• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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