1 // Copyright 2021 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/resolver/resolver.h"
16
17 #include "src/resolver/resolver_test_helper.h"
18
19 namespace tint {
20 namespace resolver {
21 namespace {
22
23 class ResolverPipelineOverridableConstantTest : public ResolverTest {
24 protected:
25 /// Verify that the AST node `var` was resolved to an overridable constant
26 /// with an ID equal to `id`.
27 /// @param var the overridable constant AST node
28 /// @param id the expected constant ID
ExpectConstantId(const ast::Variable * var,uint16_t id)29 void ExpectConstantId(const ast::Variable* var, uint16_t id) {
30 auto* sem = Sem().Get<sem::GlobalVariable>(var);
31 ASSERT_NE(sem, nullptr);
32 EXPECT_EQ(sem->Declaration(), var);
33 EXPECT_TRUE(sem->IsOverridable());
34 EXPECT_EQ(sem->ConstantId(), id);
35 EXPECT_FALSE(sem->ConstantValue());
36 }
37 };
38
TEST_F(ResolverPipelineOverridableConstantTest,NonOverridable)39 TEST_F(ResolverPipelineOverridableConstantTest, NonOverridable) {
40 auto* a = GlobalConst("a", ty.f32(), Expr(1.f));
41
42 EXPECT_TRUE(r()->Resolve()) << r()->error();
43
44 auto* sem_a = Sem().Get<sem::GlobalVariable>(a);
45 ASSERT_NE(sem_a, nullptr);
46 EXPECT_EQ(sem_a->Declaration(), a);
47 EXPECT_FALSE(sem_a->IsOverridable());
48 EXPECT_TRUE(sem_a->ConstantValue());
49 }
50
TEST_F(ResolverPipelineOverridableConstantTest,WithId)51 TEST_F(ResolverPipelineOverridableConstantTest, WithId) {
52 auto* a = GlobalConst("a", ty.f32(), Expr(1.f), {Override(7u)});
53
54 EXPECT_TRUE(r()->Resolve()) << r()->error();
55
56 ExpectConstantId(a, 7u);
57 }
58
TEST_F(ResolverPipelineOverridableConstantTest,WithoutId)59 TEST_F(ResolverPipelineOverridableConstantTest, WithoutId) {
60 auto* a = GlobalConst("a", ty.f32(), Expr(1.f), {Override()});
61
62 EXPECT_TRUE(r()->Resolve()) << r()->error();
63
64 ExpectConstantId(a, 0u);
65 }
66
TEST_F(ResolverPipelineOverridableConstantTest,WithAndWithoutIds)67 TEST_F(ResolverPipelineOverridableConstantTest, WithAndWithoutIds) {
68 std::vector<ast::Variable*> variables;
69 auto* a = GlobalConst("a", ty.f32(), Expr(1.f), {Override()});
70 auto* b = GlobalConst("b", ty.f32(), Expr(1.f), {Override()});
71 auto* c = GlobalConst("c", ty.f32(), Expr(1.f), {Override(2u)});
72 auto* d = GlobalConst("d", ty.f32(), Expr(1.f), {Override(4u)});
73 auto* e = GlobalConst("e", ty.f32(), Expr(1.f), {Override()});
74 auto* f = GlobalConst("f", ty.f32(), Expr(1.f), {Override(1u)});
75
76 EXPECT_TRUE(r()->Resolve()) << r()->error();
77
78 // Verify that constant id allocation order is deterministic.
79 ExpectConstantId(a, 0u);
80 ExpectConstantId(b, 3u);
81 ExpectConstantId(c, 2u);
82 ExpectConstantId(d, 4u);
83 ExpectConstantId(e, 5u);
84 ExpectConstantId(f, 1u);
85 }
86
TEST_F(ResolverPipelineOverridableConstantTest,DuplicateIds)87 TEST_F(ResolverPipelineOverridableConstantTest, DuplicateIds) {
88 GlobalConst("a", ty.f32(), Expr(1.f), {Override(Source{{12, 34}}, 7u)});
89 GlobalConst("b", ty.f32(), Expr(1.f), {Override(Source{{56, 78}}, 7u)});
90
91 EXPECT_FALSE(r()->Resolve());
92
93 EXPECT_EQ(r()->error(), R"(56:78 error: pipeline constant IDs must be unique
94 12:34 note: a pipeline constant with an ID of 7 was previously declared here:)");
95 }
96
TEST_F(ResolverPipelineOverridableConstantTest,IdTooLarge)97 TEST_F(ResolverPipelineOverridableConstantTest, IdTooLarge) {
98 GlobalConst("a", ty.f32(), Expr(1.f), {Override(Source{{12, 34}}, 65536u)});
99
100 EXPECT_FALSE(r()->Resolve());
101
102 EXPECT_EQ(r()->error(),
103 "12:34 error: pipeline constant IDs must be between 0 and 65535");
104 }
105
106 } // namespace
107 } // namespace resolver
108 } // namespace tint
109