• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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 "gmock/gmock.h"
16 #include "src/reader/spirv/parser_impl_test_helper.h"
17 #include "src/reader/spirv/spirv_tools_helpers_test.h"
18 
19 namespace tint {
20 namespace reader {
21 namespace spirv {
22 namespace {
23 
24 using ::testing::Eq;
25 
26 using SpvParserUserNameTest = SpvParserTest;
27 
TEST_F(SpvParserUserNameTest,UserName_RespectOpName)28 TEST_F(SpvParserUserNameTest, UserName_RespectOpName) {
29   auto p = parser(test::Assemble(R"(
30      OpName %1 "the_void_type"
31      %1 = OpTypeVoid
32   )"));
33   EXPECT_TRUE(p->BuildAndParseInternalModule());
34   EXPECT_THAT(p->namer().GetName(1), Eq("the_void_type"));
35 
36   p->DeliberatelyInvalidSpirv();
37 }
38 
TEST_F(SpvParserUserNameTest,UserName_IgnoreEmptyName)39 TEST_F(SpvParserUserNameTest, UserName_IgnoreEmptyName) {
40   auto p = parser(test::Assemble(R"(
41      OpName %1 ""
42      %1 = OpTypeVoid
43   )"));
44   EXPECT_TRUE(p->BuildAndParseInternalModule());
45   EXPECT_FALSE(p->namer().HasName(1));
46 
47   p->DeliberatelyInvalidSpirv();
48 }
49 
TEST_F(SpvParserUserNameTest,UserName_DistinguishDuplicateSuggestion)50 TEST_F(SpvParserUserNameTest, UserName_DistinguishDuplicateSuggestion) {
51   auto p = parser(test::Assemble(R"(
52      OpName %1 "vanilla"
53      OpName %2 "vanilla"
54      %1 = OpTypeVoid
55      %2 = OpTypeInt 32 0
56   )"));
57   EXPECT_TRUE(p->BuildAndParseInternalModule());
58   EXPECT_THAT(p->namer().GetName(1), Eq("vanilla"));
59   EXPECT_THAT(p->namer().GetName(2), Eq("vanilla_1"));
60 
61   p->DeliberatelyInvalidSpirv();
62 }
63 
TEST_F(SpvParserUserNameTest,UserName_RespectOpMemberName)64 TEST_F(SpvParserUserNameTest, UserName_RespectOpMemberName) {
65   auto p = parser(test::Assemble(R"(
66      OpMemberName %3 0 "strawberry"
67      OpMemberName %3 1 "vanilla"
68      OpMemberName %3 2 "chocolate"
69      %2 = OpTypeInt 32 0
70      %3 = OpTypeStruct %2 %2 %2
71   )"));
72   EXPECT_TRUE(p->BuildAndParseInternalModule());
73   EXPECT_THAT(p->namer().GetMemberName(3, 0), Eq("strawberry"));
74   EXPECT_THAT(p->namer().GetMemberName(3, 1), Eq("vanilla"));
75   EXPECT_THAT(p->namer().GetMemberName(3, 2), Eq("chocolate"));
76 
77   p->DeliberatelyInvalidSpirv();
78 }
79 
TEST_F(SpvParserUserNameTest,UserName_IgnoreEmptyMemberName)80 TEST_F(SpvParserUserNameTest, UserName_IgnoreEmptyMemberName) {
81   auto p = parser(test::Assemble(R"(
82      OpMemberName %3 0 ""
83      %2 = OpTypeInt 32 0
84      %3 = OpTypeStruct %2
85   )"));
86   EXPECT_TRUE(p->BuildAndParseInternalModule());
87   EXPECT_THAT(p->namer().GetMemberName(3, 0), Eq("field0"));
88 
89   p->DeliberatelyInvalidSpirv();
90 }
91 
TEST_F(SpvParserUserNameTest,UserName_SynthesizeMemberNames)92 TEST_F(SpvParserUserNameTest, UserName_SynthesizeMemberNames) {
93   auto p = parser(test::Assemble(R"(
94      %2 = OpTypeInt 32 0
95      %3 = OpTypeStruct %2 %2 %2
96   )"));
97   EXPECT_TRUE(p->BuildAndParseInternalModule());
98   EXPECT_THAT(p->namer().GetMemberName(3, 0), Eq("field0"));
99   EXPECT_THAT(p->namer().GetMemberName(3, 1), Eq("field1"));
100   EXPECT_THAT(p->namer().GetMemberName(3, 2), Eq("field2"));
101 
102   p->DeliberatelyInvalidSpirv();
103 }
104 
TEST_F(SpvParserUserNameTest,UserName_MemberNamesMixUserAndSynthesized)105 TEST_F(SpvParserUserNameTest, UserName_MemberNamesMixUserAndSynthesized) {
106   auto p = parser(test::Assemble(R"(
107      OpMemberName %3 1 "vanilla"
108      %2 = OpTypeInt 32 0
109      %3 = OpTypeStruct %2 %2 %2
110   )"));
111   EXPECT_TRUE(p->BuildAndParseInternalModule());
112   EXPECT_THAT(p->namer().GetMemberName(3, 0), Eq("field0"));
113   EXPECT_THAT(p->namer().GetMemberName(3, 1), Eq("vanilla"));
114   EXPECT_THAT(p->namer().GetMemberName(3, 2), Eq("field2"));
115 
116   p->DeliberatelyInvalidSpirv();
117 }
118 
TEST_F(SpvParserUserNameTest,EntryPointNames_AlwaysTakePrecedence)119 TEST_F(SpvParserUserNameTest, EntryPointNames_AlwaysTakePrecedence) {
120   const std::string assembly = R"(
121    OpCapability Shader
122    OpMemoryModel Logical Simple
123    OpEntryPoint Vertex %100 "main"
124    OpEntryPoint Fragment %100 "main_1"
125    OpExecutionMode %100 OriginUpperLeft
126 
127    ; attempt to grab the "main_1" that would be the derived name
128    ; for the second entry point.
129    OpName %1 "main_1"
130 
131    %void = OpTypeVoid
132    %voidfn = OpTypeFunction %void
133    %uint = OpTypeInt 32 0
134    %uint_0 = OpConstant %uint 0
135 
136    %100 = OpFunction %void None %voidfn
137    %100_entry = OpLabel
138    %1 = OpCopyObject %uint %uint_0
139    OpReturn
140    OpFunctionEnd
141 )";
142   auto p = parser(test::Assemble(assembly));
143   EXPECT_TRUE(p->BuildAndParseInternalModule());
144   // The first entry point grabs the best name, "main"
145   EXPECT_THAT(p->namer().Name(100), Eq("main"));
146   // The OpName on %1 is overriden because the second entry point
147   // has grabbed "main_1" first.
148   EXPECT_THAT(p->namer().Name(1), Eq("main_1_1"));
149 
150   const auto& ep_info = p->GetEntryPointInfo(100);
151   ASSERT_EQ(2u, ep_info.size());
152   EXPECT_EQ(ep_info[0].name, "main");
153   EXPECT_EQ(ep_info[1].name, "main_1");
154 
155   // This test checks two entry point with the same implementation function.
156   // But for the shader stages supported by WGSL, the SPIR-V rules require
157   // conflicting execution modes be applied to them.
158   // I still want to test the name disambiguation behaviour, but the cases
159   // are rejected by SPIR-V validation. This is true at least for the current
160   // WGSL feature set.
161   p->DeliberatelyInvalidSpirv();
162 }
163 
TEST_F(SpvParserUserNameTest,EntryPointNames_DistinctFromInnerNames)164 TEST_F(SpvParserUserNameTest, EntryPointNames_DistinctFromInnerNames) {
165   const std::string assembly = R"(
166    OpCapability Shader
167    OpMemoryModel Logical Simple
168    OpEntryPoint Vertex %100 "main"
169    OpEntryPoint Fragment %100 "main_1"
170    OpExecutionMode %100 OriginUpperLeft
171 
172    ; attempt to grab the "main_1" that would be the derived name
173    ; for the second entry point.
174    OpName %1 "main_1"
175 
176    %void = OpTypeVoid
177    %voidfn = OpTypeFunction %void
178    %uint = OpTypeInt 32 0
179    %uint_0 = OpConstant %uint 0
180 
181    %100 = OpFunction %void None %voidfn
182    %100_entry = OpLabel
183    %1 = OpCopyObject %uint %uint_0
184    OpReturn
185    OpFunctionEnd
186 )";
187   auto p = parser(test::Assemble(assembly));
188 
189   EXPECT_TRUE(p->BuildAndParseInternalModule());
190   // The first entry point grabs the best name, "main"
191   EXPECT_THAT(p->namer().Name(100), Eq("main"));
192   EXPECT_THAT(p->namer().Name(1), Eq("main_1_1"));
193 
194   const auto ep_info = p->GetEntryPointInfo(100);
195   ASSERT_EQ(2u, ep_info.size());
196   EXPECT_EQ(ep_info[0].name, "main");
197   EXPECT_EQ(ep_info[0].inner_name, "main_2");
198   // The second entry point retains its name...
199   EXPECT_EQ(ep_info[1].name, "main_1");
200   // ...but will use the same implementation function.
201   EXPECT_EQ(ep_info[1].inner_name, "main_2");
202 
203   // This test checks two entry point with the same implementation function.
204   // But for the shader stages supported by WGSL, the SPIR-V rules require
205   // conflicting execution modes be applied to them.
206   // I still want to test the name disambiguation behaviour, but the cases
207   // are rejected by SPIR-V validation. This is true at least for the current
208   // WGSL feature set.
209   p->DeliberatelyInvalidSpirv();
210 }
211 
212 }  // namespace
213 }  // namespace spirv
214 }  // namespace reader
215 }  // namespace tint
216