blob: d50af28a18d3358745981430a44f04e56d6bd0fc [file] [log] [blame]
Ben Claytond0f684e2019-08-30 22:36:08 +01001// Copyright (c) 2019 Google LLC
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 "test/opt/assembly_builder.h"
17#include "test/opt/pass_fixture.h"
18#include "test/opt/pass_utils.h"
19
20namespace spvtools {
21namespace opt {
22namespace {
23
24using WrapOpKillTest = PassTest<::testing::Test>;
25
26TEST_F(WrapOpKillTest, SingleOpKill) {
27 const std::string text = R"(
28; CHECK: OpEntryPoint Fragment [[main:%\w+]]
29; CHECK: [[main]] = OpFunction
30; CHECK: OpFunctionCall %void [[orig_kill:%\w+]]
31; CHECK: [[orig_kill]] = OpFunction
32; CHECK-NEXT: OpLabel
33; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
Ben Claytond552f632019-11-18 11:18:41 +000034; CHECK-NEXT: OpReturn
Ben Claytond0f684e2019-08-30 22:36:08 +010035; CHECK: [[new_kill]] = OpFunction
36; CHECK-NEXT: OpLabel
37; CHECK-NEXT: OpKill
38; CHECK-NEXT: OpFunctionEnd
39 OpCapability Shader
40 %1 = OpExtInstImport "GLSL.std.450"
41 OpMemoryModel Logical GLSL450
42 OpEntryPoint Fragment %main "main"
43 OpExecutionMode %main OriginUpperLeft
44 OpSource GLSL 330
45 OpName %main "main"
46 %void = OpTypeVoid
47 %5 = OpTypeFunction %void
48 %bool = OpTypeBool
49 %true = OpConstantTrue %bool
50 %main = OpFunction %void None %5
51 %8 = OpLabel
52 OpBranch %9
53 %9 = OpLabel
54 OpLoopMerge %10 %11 None
55 OpBranch %12
56 %12 = OpLabel
57 OpBranchConditional %true %13 %10
58 %13 = OpLabel
59 OpBranch %11
60 %11 = OpLabel
61 %14 = OpFunctionCall %void %kill_
62 OpBranch %9
63 %10 = OpLabel
64 OpReturn
65 OpFunctionEnd
66 %kill_ = OpFunction %void None %5
67 %15 = OpLabel
68 OpKill
69 OpFunctionEnd
70 )";
71
72 SinglePassRunAndMatch<WrapOpKill>(text, true);
73}
74
75TEST_F(WrapOpKillTest, MultipleOpKillInSameFunc) {
76 const std::string text = R"(
77; CHECK: OpEntryPoint Fragment [[main:%\w+]]
78; CHECK: [[main]] = OpFunction
79; CHECK: OpFunctionCall %void [[orig_kill:%\w+]]
80; CHECK: [[orig_kill]] = OpFunction
81; CHECK-NEXT: OpLabel
82; CHECK-NEXT: OpSelectionMerge
83; CHECK-NEXT: OpBranchConditional
84; CHECK-NEXT: OpLabel
85; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
Ben Claytond552f632019-11-18 11:18:41 +000086; CHECK-NEXT: OpReturn
Ben Claytond0f684e2019-08-30 22:36:08 +010087; CHECK-NEXT: OpLabel
88; CHECK-NEXT: OpFunctionCall %void [[new_kill]]
Ben Claytond552f632019-11-18 11:18:41 +000089; CHECK-NEXT: OpReturn
Ben Claytond0f684e2019-08-30 22:36:08 +010090; CHECK: [[new_kill]] = OpFunction
91; CHECK-NEXT: OpLabel
92; CHECK-NEXT: OpKill
93; CHECK-NEXT: OpFunctionEnd
94 OpCapability Shader
95 %1 = OpExtInstImport "GLSL.std.450"
96 OpMemoryModel Logical GLSL450
97 OpEntryPoint Fragment %main "main"
98 OpExecutionMode %main OriginUpperLeft
99 OpSource GLSL 330
100 OpName %main "main"
101 %void = OpTypeVoid
102 %5 = OpTypeFunction %void
103 %bool = OpTypeBool
104 %true = OpConstantTrue %bool
105 %main = OpFunction %void None %5
106 %8 = OpLabel
107 OpBranch %9
108 %9 = OpLabel
109 OpLoopMerge %10 %11 None
110 OpBranch %12
111 %12 = OpLabel
112 OpBranchConditional %true %13 %10
113 %13 = OpLabel
114 OpBranch %11
115 %11 = OpLabel
116 %14 = OpFunctionCall %void %kill_
117 OpBranch %9
118 %10 = OpLabel
119 OpReturn
120 OpFunctionEnd
121 %kill_ = OpFunction %void None %5
122 %15 = OpLabel
123 OpSelectionMerge %16 None
124 OpBranchConditional %true %17 %18
125 %17 = OpLabel
126 OpKill
127 %18 = OpLabel
128 OpKill
129 %16 = OpLabel
130 OpReturn
131 OpFunctionEnd
132 )";
133
134 SinglePassRunAndMatch<WrapOpKill>(text, true);
135}
136
137TEST_F(WrapOpKillTest, MultipleOpKillInDifferentFunc) {
138 const std::string text = R"(
139; CHECK: OpEntryPoint Fragment [[main:%\w+]]
140; CHECK: [[main]] = OpFunction
141; CHECK: OpFunctionCall %void [[orig_kill1:%\w+]]
142; CHECK-NEXT: OpFunctionCall %void [[orig_kill2:%\w+]]
143; CHECK: [[orig_kill1]] = OpFunction
144; CHECK-NEXT: OpLabel
145; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
Ben Claytond552f632019-11-18 11:18:41 +0000146; CHECK-NEXT: OpReturn
Ben Claytond0f684e2019-08-30 22:36:08 +0100147; CHECK: [[orig_kill2]] = OpFunction
148; CHECK-NEXT: OpLabel
149; CHECK-NEXT: OpFunctionCall %void [[new_kill]]
Ben Claytond552f632019-11-18 11:18:41 +0000150; CHECK-NEXT: OpReturn
Ben Claytond0f684e2019-08-30 22:36:08 +0100151; CHECK: [[new_kill]] = OpFunction
152; CHECK-NEXT: OpLabel
153; CHECK-NEXT: OpKill
154; CHECK-NEXT: OpFunctionEnd
155 OpCapability Shader
156 %1 = OpExtInstImport "GLSL.std.450"
157 OpMemoryModel Logical GLSL450
158 OpEntryPoint Fragment %main "main"
159 OpExecutionMode %main OriginUpperLeft
160 OpSource GLSL 330
161 OpName %main "main"
162 %void = OpTypeVoid
163 %4 = OpTypeFunction %void
164 %bool = OpTypeBool
165 %true = OpConstantTrue %bool
166 %main = OpFunction %void None %4
167 %7 = OpLabel
168 OpBranch %8
169 %8 = OpLabel
170 OpLoopMerge %9 %10 None
171 OpBranch %11
172 %11 = OpLabel
173 OpBranchConditional %true %12 %9
174 %12 = OpLabel
175 OpBranch %10
176 %10 = OpLabel
177 %13 = OpFunctionCall %void %14
178 %15 = OpFunctionCall %void %16
179 OpBranch %8
180 %9 = OpLabel
181 OpReturn
182 OpFunctionEnd
183 %14 = OpFunction %void None %4
184 %17 = OpLabel
185 OpKill
186 OpFunctionEnd
187 %16 = OpFunction %void None %4
188 %18 = OpLabel
189 OpKill
190 OpFunctionEnd
191 )";
192
193 SinglePassRunAndMatch<WrapOpKill>(text, true);
194}
195
Ben Claytond552f632019-11-18 11:18:41 +0000196TEST_F(WrapOpKillTest, FuncWithReturnValue) {
197 const std::string text = R"(
198; CHECK: OpEntryPoint Fragment [[main:%\w+]]
199; CHECK: [[main]] = OpFunction
200; CHECK: OpFunctionCall %int [[orig_kill:%\w+]]
201; CHECK: [[orig_kill]] = OpFunction
202; CHECK-NEXT: OpLabel
203; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
204; CHECK-NEXT: [[undef:%\w+]] = OpUndef %int
205; CHECK-NEXT: OpReturnValue [[undef]]
206; CHECK: [[new_kill]] = OpFunction
207; CHECK-NEXT: OpLabel
208; CHECK-NEXT: OpKill
209; CHECK-NEXT: OpFunctionEnd
210 OpCapability Shader
211 %1 = OpExtInstImport "GLSL.std.450"
212 OpMemoryModel Logical GLSL450
213 OpEntryPoint Fragment %main "main"
214 OpExecutionMode %main OriginUpperLeft
215 OpSource GLSL 330
216 OpName %main "main"
217 %void = OpTypeVoid
218 %5 = OpTypeFunction %void
219 %int = OpTypeInt 32 1
220 %func_type = OpTypeFunction %int
221 %bool = OpTypeBool
222 %true = OpConstantTrue %bool
223 %main = OpFunction %void None %5
224 %8 = OpLabel
225 OpBranch %9
226 %9 = OpLabel
227 OpLoopMerge %10 %11 None
228 OpBranch %12
229 %12 = OpLabel
230 OpBranchConditional %true %13 %10
231 %13 = OpLabel
232 OpBranch %11
233 %11 = OpLabel
234 %14 = OpFunctionCall %int %kill_
235 OpBranch %9
236 %10 = OpLabel
237 OpReturn
238 OpFunctionEnd
239 %kill_ = OpFunction %int None %func_type
240 %15 = OpLabel
241 OpKill
242 OpFunctionEnd
243 )";
244
245 SinglePassRunAndMatch<WrapOpKill>(text, true);
246}
247
Ben Claytond0f684e2019-08-30 22:36:08 +0100248TEST_F(WrapOpKillTest, IdBoundOverflow1) {
249 const std::string text = R"(
250OpCapability GeometryStreams
251OpMemoryModel Logical GLSL450
Ben Claytond552f632019-11-18 11:18:41 +0000252OpEntryPoint Fragment %main "main"
253OpExecutionMode %main OriginUpperLeft
Ben Claytond0f684e2019-08-30 22:36:08 +0100254%2 = OpTypeVoid
255%3 = OpTypeFunction %2
Ben Claytond552f632019-11-18 11:18:41 +0000256%bool = OpTypeBool
257%true = OpConstantTrue %bool
258%main = OpFunction %2 None %3
259%8 = OpLabel
260OpBranch %9
261%9 = OpLabel
262OpLoopMerge %10 %11 None
263OpBranch %12
264%12 = OpLabel
265OpBranchConditional %true %13 %10
266%13 = OpLabel
267OpBranch %11
268%11 = OpLabel
269%14 = OpFunctionCall %void %kill_
270OpBranch %9
271%10 = OpLabel
272OpReturn
273OpFunctionEnd
274%kill_ = OpFunction %2 Pure|Const %3
Ben Claytond0f684e2019-08-30 22:36:08 +0100275%4194302 = OpLabel
276OpKill
277OpFunctionEnd
Ben Claytond552f632019-11-18 11:18:41 +0000278)";
Ben Claytond0f684e2019-08-30 22:36:08 +0100279
280 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
281
282 std::vector<Message> messages = {
283 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
284 SetMessageConsumer(GetTestMessageConsumer(messages));
285 auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
286 EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
287}
288
289TEST_F(WrapOpKillTest, IdBoundOverflow2) {
290 const std::string text = R"(
291OpCapability GeometryStreams
292OpMemoryModel Logical GLSL450
Ben Claytond552f632019-11-18 11:18:41 +0000293OpEntryPoint Fragment %main "main"
294OpExecutionMode %main OriginUpperLeft
Ben Claytond0f684e2019-08-30 22:36:08 +0100295%2 = OpTypeVoid
296%3 = OpTypeFunction %2
Ben Claytond552f632019-11-18 11:18:41 +0000297%bool = OpTypeBool
298%true = OpConstantTrue %bool
299%main = OpFunction %2 None %3
300%8 = OpLabel
301OpBranch %9
302%9 = OpLabel
303OpLoopMerge %10 %11 None
304OpBranch %12
305%12 = OpLabel
306OpBranchConditional %true %13 %10
307%13 = OpLabel
308OpBranch %11
309%11 = OpLabel
310%14 = OpFunctionCall %void %kill_
311OpBranch %9
312%10 = OpLabel
313OpReturn
314OpFunctionEnd
315%kill_ = OpFunction %2 Pure|Const %3
Ben Claytond0f684e2019-08-30 22:36:08 +0100316%4194301 = OpLabel
317OpKill
318OpFunctionEnd
Ben Claytond552f632019-11-18 11:18:41 +0000319)";
Ben Claytond0f684e2019-08-30 22:36:08 +0100320
321 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
322
323 std::vector<Message> messages = {
324 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
325 SetMessageConsumer(GetTestMessageConsumer(messages));
326 auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
327 EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
328}
329
330TEST_F(WrapOpKillTest, IdBoundOverflow3) {
331 const std::string text = R"(
332OpCapability GeometryStreams
333OpMemoryModel Logical GLSL450
Ben Claytond552f632019-11-18 11:18:41 +0000334OpEntryPoint Fragment %main "main"
335OpExecutionMode %main OriginUpperLeft
Ben Claytond0f684e2019-08-30 22:36:08 +0100336%2 = OpTypeVoid
337%3 = OpTypeFunction %2
Ben Claytond552f632019-11-18 11:18:41 +0000338%bool = OpTypeBool
339%true = OpConstantTrue %bool
340%main = OpFunction %2 None %3
341%8 = OpLabel
342OpBranch %9
343%9 = OpLabel
344OpLoopMerge %10 %11 None
345OpBranch %12
346%12 = OpLabel
347OpBranchConditional %true %13 %10
348%13 = OpLabel
349OpBranch %11
350%11 = OpLabel
351%14 = OpFunctionCall %void %kill_
352OpBranch %9
353%10 = OpLabel
354OpReturn
355OpFunctionEnd
356%kill_ = OpFunction %2 Pure|Const %3
Ben Claytond0f684e2019-08-30 22:36:08 +0100357%4194300 = OpLabel
358OpKill
359OpFunctionEnd
Ben Claytond552f632019-11-18 11:18:41 +0000360)";
Ben Claytond0f684e2019-08-30 22:36:08 +0100361
362 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
363
364 std::vector<Message> messages = {
365 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
366 SetMessageConsumer(GetTestMessageConsumer(messages));
367 auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
368 EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
369}
370
Ben Claytond552f632019-11-18 11:18:41 +0000371TEST_F(WrapOpKillTest, IdBoundOverflow4) {
372 const std::string text = R"(
373OpCapability DerivativeControl
374OpMemoryModel Logical GLSL450
375OpEntryPoint Fragment %main "main"
376OpExecutionMode %main OriginUpperLeft
377OpDecorate %2 Location 539091968
378%2 = OpTypeVoid
379%3 = OpTypeFunction %2
380%bool = OpTypeBool
381%true = OpConstantTrue %bool
382%main = OpFunction %2 None %3
383%8 = OpLabel
384OpBranch %9
385%9 = OpLabel
386OpLoopMerge %10 %11 None
387OpBranch %12
388%12 = OpLabel
389OpBranchConditional %true %13 %10
390%13 = OpLabel
391OpBranch %11
392%11 = OpLabel
393%14 = OpFunctionCall %void %kill_
394OpBranch %9
395%10 = OpLabel
396OpReturn
397OpFunctionEnd
398%kill_ = OpFunction %2 Inline|Pure|Const %3
399%4194302 = OpLabel
400OpKill
401OpFunctionEnd
402)";
403
404 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
405
406 std::vector<Message> messages = {
407 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
408 SetMessageConsumer(GetTestMessageConsumer(messages));
409 auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
410 EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
411}
412
413TEST_F(WrapOpKillTest, IdBoundOverflow5) {
414 const std::string text = R"(
415 OpCapability Shader
416 OpMemoryModel Logical GLSL450
417 OpEntryPoint Fragment %1 "main"
418 OpExecutionMode %1 OriginUpperLeft
419 OpDecorate %void Location 539091968
420 %void = OpTypeVoid
421 %3 = OpTypeFunction %void
422 %float = OpTypeFloat 32
423 %_struct_5 = OpTypeStruct %float %float
424 %_struct_6 = OpTypeStruct %_struct_5
425%_ptr_Function__struct_6 = OpTypePointer Function %_struct_6
426%_ptr_Output_float = OpTypePointer Output %float
427 %9 = OpTypeFunction %_struct_5 %_ptr_Function__struct_6
428 %bool = OpTypeBool
429 %true = OpConstantTrue %bool
430 %1 = OpFunction %void None %3
431 %12 = OpLabel
432 %13 = OpVariable %_ptr_Function__struct_6 Function
433 OpBranch %14
434 %14 = OpLabel
435 OpLoopMerge %15 %16 None
436 OpBranch %17
437 %17 = OpLabel
438 OpBranchConditional %true %18 %15
439 %18 = OpLabel
440 OpBranch %16
441 %16 = OpLabel
442 %19 = OpFunctionCall %void %20
443 %21 = OpFunctionCall %_struct_5 %22 %13
444 OpBranch %14
445 %15 = OpLabel
446 OpReturn
447 OpFunctionEnd
448 %20 = OpFunction %void Inline|Pure|Const %3
449 %23 = OpLabel
450 %24 = OpVariable %_ptr_Function__struct_6 Function
451 %25 = OpFunctionCall %_struct_5 %26 %24
452 OpKill
453 OpFunctionEnd
454 %26 = OpFunction %_struct_5 None %9
455 %27 = OpLabel
456 OpUnreachable
457 OpFunctionEnd
458 %22 = OpFunction %_struct_5 Inline %9
459 %4194295 = OpLabel
460 OpKill
461 OpFunctionEnd
462)";
463
464 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
465
466 std::vector<Message> messages = {
467 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
468 SetMessageConsumer(GetTestMessageConsumer(messages));
469 auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
470 EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
471}
472
473TEST_F(WrapOpKillTest, SkipEntryPoint) {
474 const std::string text = R"(
475OpCapability GeometryStreams
476OpMemoryModel Logical GLSL450
477OpEntryPoint Fragment %4 "main"
478OpExecutionMode %4 OriginUpperLeft
479%2 = OpTypeVoid
480%3 = OpTypeFunction %2
481%4 = OpFunction %2 Pure|Const %3
482%5 = OpLabel
483OpKill
484OpFunctionEnd
485)";
486
487 auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
488 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
489}
490
491TEST_F(WrapOpKillTest, SkipFunctionNotInContinue) {
492 const std::string text = R"(
493OpCapability GeometryStreams
494OpMemoryModel Logical GLSL450
495OpEntryPoint Fragment %main "main"
496OpExecutionMode %main OriginUpperLeft
497%2 = OpTypeVoid
498%3 = OpTypeFunction %2
499%bool = OpTypeBool
500%true = OpConstantTrue %bool
501%main = OpFunction %2 None %3
502%6 = OpLabel
503%7 = OpFunctionCall %void %4
504OpReturn
505OpFunctionEnd
506%4 = OpFunction %2 Pure|Const %3
507%5 = OpLabel
508OpKill
509OpFunctionEnd
510)";
511
512 auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
513 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
514}
515
Ben Claytond0f684e2019-08-30 22:36:08 +0100516} // namespace
517} // namespace opt
518} // namespace spvtools