1 // Copyright (c) 2016 Google Inc.
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 <vector>
16 
17 #include "test/opt/pass_fixture.h"
18 #include "test/opt/pass_utils.h"
19 
20 namespace spvtools {
21 namespace opt {
22 namespace {
23 
24 using StripLineDebugInfoTest = PassTest<::testing::Test>;
25 
TEST_F(StripLineDebugInfoTest,LineNoLine)26 TEST_F(StripLineDebugInfoTest, LineNoLine) {
27   std::vector<const char*> text = {
28       // clang-format off
29                "OpCapability Shader",
30           "%1 = OpExtInstImport \"GLSL.std.450\"",
31                "OpMemoryModel Logical GLSL450",
32                "OpEntryPoint Vertex %2 \"main\"",
33           "%3 = OpString \"minimal.vert\"",
34                "OpModuleProcessed \"42\"",
35                "OpModuleProcessed \"43\"",
36                "OpModuleProcessed \"44\"",
37                "OpNoLine",
38                "OpLine %3 10 10",
39        "%void = OpTypeVoid",
40                "OpLine %3 100 100",
41           "%5 = OpTypeFunction %void",
42           "%2 = OpFunction %void None %5",
43                "OpLine %3 1 1",
44                "OpNoLine",
45                "OpLine %3 2 2",
46                "OpLine %3 3 3",
47           "%6 = OpLabel",
48                "OpLine %3 4 4",
49                "OpNoLine",
50                "OpReturn",
51                "OpLine %3 4 4",
52                "OpNoLine",
53                "OpFunctionEnd",
54                "OpNoLine",
55                "OpLine %3 4 5"
56       // clang-format on
57   };
58   SinglePassRunAndCheck<StripDebugInfoPass>(JoinAllInsts(text),
59                                             JoinNonDebugInsts(text),
60                                             /* skip_nop = */ false);
61 
62   // Let's add more debug instruction before the "OpString" instruction.
63   const std::vector<const char*> more_text = {
64       "OpSourceContinued \"I'm a happy shader! Yay! ;)\"",
65       "OpSourceContinued \"wahahaha\"",
66       "OpSource ESSL 310",
67       "OpSource ESSL 310",
68       "OpSourceContinued \"wahahaha\"",
69       "OpSourceContinued \"wahahaha\"",
70       "OpSourceExtension \"save-the-world-extension\"",
71       "OpName %2 \"main\"",
72   };
73   text.insert(text.begin() + 4, more_text.cbegin(), more_text.cend());
74   SinglePassRunAndCheck<StripDebugInfoPass>(JoinAllInsts(text),
75                                             JoinNonDebugInsts(text),
76                                             /* skip_nop = */ false);
77 }
78 
79 using StripDebugStringTest = PassTest<::testing::Test>;
80 
TEST_F(StripDebugStringTest,OpDecorateRemoved)81 TEST_F(StripDebugStringTest, OpDecorateRemoved) {
82   std::vector<const char*> input{
83       // clang-format off
84                      "OpCapability Shader",
85                 "%1 = OpExtInstImport \"GLSL.std.450\"",
86                      "OpMemoryModel Logical GLSL450",
87                      "OpEntryPoint Vertex %2 \"main\"",
88                 "%3 = OpString \"minimal.vert\"",
89                      "OpDecorate %3 Location 1337",
90              "%void = OpTypeVoid",
91                 "%5 = OpTypeFunction %void",
92                 "%2 = OpFunction %void None %5",
93                 "%6 = OpLabel",
94                      "OpReturn",
95                      "OpFunctionEnd",
96       // clang-format on
97   };
98   std::vector<const char*> output{
99       // clang-format off
100                      "OpCapability Shader",
101                 "%1 = OpExtInstImport \"GLSL.std.450\"",
102                      "OpMemoryModel Logical GLSL450",
103                      "OpEntryPoint Vertex %2 \"main\"",
104              "%void = OpTypeVoid",
105                 "%5 = OpTypeFunction %void",
106                 "%2 = OpFunction %void None %5",
107                 "%6 = OpLabel",
108                      "OpReturn",
109                      "OpFunctionEnd",
110       // clang-format on
111   };
112   SinglePassRunAndCheck<StripDebugInfoPass>(JoinAllInsts(input),
113                                             JoinAllInsts(output),
114                                             /* skip_nop = */ false,
115                                             /* do_validation */ true);
116 }
117 
TEST_F(StripDebugStringTest,OpNameRemoved)118 TEST_F(StripDebugStringTest, OpNameRemoved) {
119   std::vector<const char*> input{
120       // clang-format off
121                      "OpCapability Shader",
122                 "%1 = OpExtInstImport \"GLSL.std.450\"",
123                      "OpMemoryModel Logical GLSL450",
124                      "OpEntryPoint Vertex %2 \"main\"",
125                 "%3 = OpString \"minimal.vert\"",
126                      "OpName %3 \"bob\"",
127              "%void = OpTypeVoid",
128                 "%5 = OpTypeFunction %void",
129                 "%2 = OpFunction %void None %5",
130                 "%6 = OpLabel",
131                      "OpReturn",
132                      "OpFunctionEnd",
133       // clang-format on
134   };
135   std::vector<const char*> output{
136       // clang-format off
137                      "OpCapability Shader",
138                 "%1 = OpExtInstImport \"GLSL.std.450\"",
139                      "OpMemoryModel Logical GLSL450",
140                      "OpEntryPoint Vertex %2 \"main\"",
141              "%void = OpTypeVoid",
142                 "%5 = OpTypeFunction %void",
143                 "%2 = OpFunction %void None %5",
144                 "%6 = OpLabel",
145                      "OpReturn",
146                      "OpFunctionEnd",
147       // clang-format on
148   };
149   SinglePassRunAndCheck<StripDebugInfoPass>(JoinAllInsts(input),
150                                             JoinAllInsts(output),
151                                             /* skip_nop = */ false,
152                                             /* do_validation */ true);
153 }
154 
TEST_F(StripDebugStringTest,OpStringRemovedWithNonSemantic)155 TEST_F(StripDebugStringTest, OpStringRemovedWithNonSemantic) {
156   std::vector<const char*> input{
157       // clang-format off
158                      "OpCapability Shader",
159                      "OpExtension \"SPV_KHR_non_semantic_info\"",
160                 "%1 = OpExtInstImport \"NonSemantic.Testing.Set\"",
161                      "OpMemoryModel Logical GLSL450",
162                      "OpEntryPoint Vertex %2 \"main\"",
163                 // this string is not referenced, should be removed fully
164                 "%3 = OpString \"minimal.vert\"",
165                      "OpName %3 \"bob\"",
166                 // this string is referenced and cannot be removed,
167                 // but the name should be
168                 "%4 = OpString \"secondary.inc\"",
169                      "OpName %4 \"sue\"",
170              "%void = OpTypeVoid",
171                 "%6 = OpTypeFunction %void",
172                 "%2 = OpFunction %void None %6",
173                 "%7 = OpLabel",
174                 "%8 = OpExtInst %void %1 5 %4",
175                      "OpReturn",
176                      "OpFunctionEnd",
177       // clang-format on
178   };
179   std::vector<const char*> output{
180       // clang-format off
181                      "OpCapability Shader",
182                      "OpExtension \"SPV_KHR_non_semantic_info\"",
183                 "%1 = OpExtInstImport \"NonSemantic.Testing.Set\"",
184                      "OpMemoryModel Logical GLSL450",
185                      "OpEntryPoint Vertex %2 \"main\"",
186                 "%4 = OpString \"secondary.inc\"",
187              "%void = OpTypeVoid",
188                 "%6 = OpTypeFunction %void",
189                 "%2 = OpFunction %void None %6",
190                 "%7 = OpLabel",
191                 "%8 = OpExtInst %void %1 5 %4",
192                      "OpReturn",
193                      "OpFunctionEnd",
194       // clang-format on
195   };
196   SinglePassRunAndCheck<StripDebugInfoPass>(JoinAllInsts(input),
197                                             JoinAllInsts(output),
198                                             /* skip_nop = */ false,
199                                             /* do_validation */ true);
200 }
201 
202 using StripDebugInfoTest = PassTest<::testing::TestWithParam<const char*>>;
203 
TEST_P(StripDebugInfoTest,Kind)204 TEST_P(StripDebugInfoTest, Kind) {
205   std::vector<const char*> text = {
206       "OpCapability Shader",
207       "OpMemoryModel Logical GLSL450",
208       GetParam(),
209   };
210   SinglePassRunAndCheck<StripDebugInfoPass>(JoinAllInsts(text),
211                                             JoinNonDebugInsts(text),
212                                             /* skip_nop = */ false);
213 }
214 
215 // Test each possible non-line debug instruction.
216 // clang-format off
217 INSTANTIATE_TEST_SUITE_P(
218     SingleKindDebugInst, StripDebugInfoTest,
219     ::testing::ValuesIn(std::vector<const char*>({
220         "OpSourceContinued \"I'm a happy shader! Yay! ;)\"",
221         "OpSource ESSL 310",
222         "OpSourceExtension \"save-the-world-extension\"",
223         "OpName %main \"main\"",
224         "OpMemberName %struct 0 \"field\"",
225         "%1 = OpString \"name.vert\"",
226         "OpModuleProcessed \"42\"",
227     })));
228 // clang-format on
229 
230 }  // namespace
231 }  // namespace opt
232 }  // namespace spvtools
233