1 // Copyright (c) 2020 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 "source/opt/debug_info_manager.h"
16
17 #include <memory>
18 #include <vector>
19
20 #include "gtest/gtest.h"
21 #include "source/opt/build_module.h"
22 #include "source/opt/instruction.h"
23 #include "spirv-tools/libspirv.hpp"
24
25 // Constants for OpenCL.DebugInfo.100 extension instructions.
26
27 static const uint32_t kDebugFunctionOperandFunctionIndex = 13;
28 static const uint32_t kDebugInlinedAtOperandLineIndex = 4;
29 static const uint32_t kDebugInlinedAtOperandScopeIndex = 5;
30 static const uint32_t kDebugInlinedAtOperandInlinedIndex = 6;
31 static const uint32_t kOpLineInOperandFileIndex = 0;
32 static const uint32_t kOpLineInOperandLineIndex = 1;
33 static const uint32_t kOpLineInOperandColumnIndex = 2;
34
35 namespace spvtools {
36 namespace opt {
37 namespace analysis {
38 namespace {
39
TEST(DebugInfoManager,GetDebugInlinedAt)40 TEST(DebugInfoManager, GetDebugInlinedAt) {
41 const std::string text = R"(
42 OpCapability Shader
43 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
44 OpMemoryModel Logical GLSL450
45 OpEntryPoint Fragment %main "main" %in_var_COLOR
46 OpExecutionMode %main OriginUpperLeft
47 %5 = OpString "ps.hlsl"
48 %14 = OpString "#line 1 \"ps.hlsl\"
49 void main(float in_var_color : COLOR) {
50 float color = in_var_color;
51 }
52 "
53 %17 = OpString "float"
54 %21 = OpString "main"
55 %24 = OpString "color"
56 OpName %in_var_COLOR "in.var.COLOR"
57 OpName %main "main"
58 OpDecorate %in_var_COLOR Location 0
59 %uint = OpTypeInt 32 0
60 %uint_32 = OpConstant %uint 32
61 %float = OpTypeFloat 32
62 %_ptr_Input_float = OpTypePointer Input %float
63 %void = OpTypeVoid
64 %27 = OpTypeFunction %void
65 %_ptr_Function_float = OpTypePointer Function %float
66 %in_var_COLOR = OpVariable %_ptr_Input_float Input
67 %13 = OpExtInst %void %1 DebugExpression
68 %15 = OpExtInst %void %1 DebugSource %5 %14
69 %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL
70 %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float
71 %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18
72 %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main
73 %100 = OpExtInst %void %1 DebugInlinedAt 7 %22
74 %main = OpFunction %void None %27
75 %28 = OpLabel
76 %31 = OpLoad %float %in_var_COLOR
77 OpStore %100 %31
78 OpReturn
79 OpFunctionEnd
80 )";
81
82 std::unique_ptr<IRContext> context =
83 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
84 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
85 DebugInfoManager manager(context.get());
86
87 EXPECT_EQ(manager.GetDebugInlinedAt(150), nullptr);
88 EXPECT_EQ(manager.GetDebugInlinedAt(31), nullptr);
89 EXPECT_EQ(manager.GetDebugInlinedAt(22), nullptr);
90
91 auto* inst = manager.GetDebugInlinedAt(100);
92 EXPECT_EQ(inst->GetSingleWordOperand(kDebugInlinedAtOperandLineIndex), 7);
93 EXPECT_EQ(inst->GetSingleWordOperand(kDebugInlinedAtOperandScopeIndex), 22);
94 }
95
96 TEST(DebugInfoManager, CreateDebugInlinedAt) {
97 const std::string text = R"(
98 OpCapability Shader
99 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
100 OpMemoryModel Logical GLSL450
101 OpEntryPoint Fragment %main "main" %in_var_COLOR
102 OpExecutionMode %main OriginUpperLeft
103 %5 = OpString "ps.hlsl"
104 %14 = OpString "#line 1 \"ps.hlsl\"
105 void main(float in_var_color : COLOR) {
106 float color = in_var_color;
107 }
108 "
109 %17 = OpString "float"
110 %21 = OpString "main"
111 %24 = OpString "color"
112 OpName %in_var_COLOR "in.var.COLOR"
113 OpName %main "main"
114 OpDecorate %in_var_COLOR Location 0
115 %uint = OpTypeInt 32 0
116 %uint_32 = OpConstant %uint 32
117 %float = OpTypeFloat 32
118 %_ptr_Input_float = OpTypePointer Input %float
119 %void = OpTypeVoid
120 %27 = OpTypeFunction %void
121 %_ptr_Function_float = OpTypePointer Function %float
122 %in_var_COLOR = OpVariable %_ptr_Input_float Input
123 %13 = OpExtInst %void %1 DebugExpression
124 %15 = OpExtInst %void %1 DebugSource %5 %14
125 %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL
126 %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float
127 %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18
128 %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main
129 %100 = OpExtInst %void %1 DebugInlinedAt 7 %22
130 %main = OpFunction %void None %27
131 %28 = OpLabel
132 %31 = OpLoad %float %in_var_COLOR
133 OpStore %100 %31
134 OpReturn
135 OpFunctionEnd
136 )";
137
138 DebugScope scope(22U, 0U);
139
140 std::unique_ptr<IRContext> context =
141 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
142 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
143 DebugInfoManager manager(context.get());
144
145 uint32_t inlined_at_id = manager.CreateDebugInlinedAt(nullptr, scope);
146 auto* inlined_at = manager.GetDebugInlinedAt(inlined_at_id);
147 EXPECT_NE(inlined_at, nullptr);
148 EXPECT_EQ(inlined_at->GetSingleWordOperand(kDebugInlinedAtOperandLineIndex),
149 1);
150 EXPECT_EQ(inlined_at->GetSingleWordOperand(kDebugInlinedAtOperandScopeIndex),
151 22);
152 EXPECT_EQ(inlined_at->NumOperands(), kDebugInlinedAtOperandScopeIndex + 1);
153
154 const uint32_t line_number = 77U;
155 Instruction line(context.get(), spv::Op::OpLine);
156 line.SetInOperands({
157 {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {5U}},
158 {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {line_number}},
159 {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {0U}},
160 });
161
162 inlined_at_id = manager.CreateDebugInlinedAt(&line, scope);
163 inlined_at = manager.GetDebugInlinedAt(inlined_at_id);
164 EXPECT_NE(inlined_at, nullptr);
165 EXPECT_EQ(inlined_at->GetSingleWordOperand(kDebugInlinedAtOperandLineIndex),
166 line_number);
167 EXPECT_EQ(inlined_at->GetSingleWordOperand(kDebugInlinedAtOperandScopeIndex),
168 22);
169 EXPECT_EQ(inlined_at->NumOperands(), kDebugInlinedAtOperandScopeIndex + 1);
170
171 scope.SetInlinedAt(100U);
172 inlined_at_id = manager.CreateDebugInlinedAt(&line, scope);
173 inlined_at = manager.GetDebugInlinedAt(inlined_at_id);
174 EXPECT_NE(inlined_at, nullptr);
175 EXPECT_EQ(inlined_at->GetSingleWordOperand(kDebugInlinedAtOperandLineIndex),
176 line_number);
177 EXPECT_EQ(inlined_at->GetSingleWordOperand(kDebugInlinedAtOperandScopeIndex),
178 22);
179 EXPECT_EQ(inlined_at->NumOperands(), kDebugInlinedAtOperandInlinedIndex + 1);
180 EXPECT_EQ(
181 inlined_at->GetSingleWordOperand(kDebugInlinedAtOperandInlinedIndex),
182 100U);
183 }
184
185 TEST(DebugInfoManager, CreateDebugInlinedAtWithConstantManager) {
186 // Show that CreateDebugInlinedAt will use the Constant manager to generate
187 // its line operand if the Constant and DefUse managers are valid. This is
188 // proven by checking that the id for the line operand 7 is the same as the
189 // existing constant 7.
190 //
191 // int function1() {
192 // return 1;
193 // }
194 //
195 // void main() {
196 // function1();
197 // }
198 const std::string text = R"(OpCapability Shader
199 OpExtension "SPV_KHR_non_semantic_info"
200 %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100"
201 OpMemoryModel Logical GLSL450
202 OpEntryPoint Fragment %main "main"
203 OpExecutionMode %main OriginUpperLeft
204 %3 = OpString "parent3.hlsl"
205 %8 = OpString "int"
206 %19 = OpString "function1"
207 %20 = OpString ""
208 %26 = OpString "main"
209 OpName %main "main"
210 OpName %src_main "src.main"
211 OpName %bb_entry "bb.entry"
212 OpName %function1 "function1"
213 OpName %bb_entry_0 "bb.entry"
214 %int = OpTypeInt 32 1
215 %int_1 = OpConstant %int 1
216 %uint = OpTypeInt 32 0
217 %uint_32 = OpConstant %uint 32
218 %void = OpTypeVoid
219 %uint_4 = OpConstant %uint 4
220 %uint_0 = OpConstant %uint 0
221 %uint_3 = OpConstant %uint 3
222 %uint_1 = OpConstant %uint 1
223 %uint_5 = OpConstant %uint 5
224 %uint_2 = OpConstant %uint 2
225 %uint_17 = OpConstant %uint 17
226 %uint_6 = OpConstant %uint 6
227 %uint_13 = OpConstant %uint 13
228 %100 = OpConstant %uint 7
229 %31 = OpTypeFunction %void
230 %42 = OpTypeFunction %int
231 %10 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_4 %uint_0
232 %13 = OpExtInst %void %1 DebugTypeFunction %uint_3 %10
233 %15 = OpExtInst %void %1 DebugSource %3
234 %16 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %15 %uint_5
235 %21 = OpExtInst %void %1 DebugFunction %19 %13 %15 %uint_2 %uint_1 %16 %20 %uint_3 %uint_2
236 %23 = OpExtInst %void %1 DebugLexicalBlock %15 %uint_2 %uint_17 %21
237 %25 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void
238 %27 = OpExtInst %void %1 DebugFunction %26 %25 %15 %uint_6 %uint_1 %16 %20 %uint_3 %uint_6
239 %29 = OpExtInst %void %1 DebugLexicalBlock %15 %uint_6 %uint_13 %27
240 %main = OpFunction %void None %31
241 %32 = OpLabel
242 %33 = OpFunctionCall %void %src_main
243 OpLine %3 8 1
244 OpReturn
245 OpFunctionEnd
246 OpLine %3 6 1
247 %src_main = OpFunction %void None %31
248 OpNoLine
249 %bb_entry = OpLabel
250 %47 = OpExtInst %void %1 DebugScope %27
251 %37 = OpExtInst %void %1 DebugFunctionDefinition %27 %src_main
252 %48 = OpExtInst %void %1 DebugScope %29
253 OpLine %3 7 3
254 %39 = OpFunctionCall %int %function1
255 %49 = OpExtInst %void %1 DebugScope %27
256 OpLine %3 8 1
257 OpReturn
258 %50 = OpExtInst %void %1 DebugNoScope
259 OpFunctionEnd
260 OpLine %3 2 1
261 %function1 = OpFunction %int None %42
262 OpNoLine
263 %bb_entry_0 = OpLabel
264 %51 = OpExtInst %void %1 DebugScope %21
265 %45 = OpExtInst %void %1 DebugFunctionDefinition %21 %function1
266 %52 = OpExtInst %void %1 DebugScope %23
267 OpLine %3 3 3
268 OpReturnValue %int_1
269 %53 = OpExtInst %void %1 DebugNoScope
270 OpFunctionEnd
271 )";
272
273 std::unique_ptr<IRContext> context =
274 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
275 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
276
277 const uint32_t line_number = 7U;
278 Instruction line(context.get(), spv::Op::OpLine);
279 line.SetInOperands({
280 {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {5U}},
281 {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {line_number}},
282 {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {0U}},
283 });
284
285 DebugScope scope(29U, 0U);
286
287 auto db_manager = context.get()->get_debug_info_mgr();
288 auto du_manager = context.get()->get_def_use_mgr();
289 auto c_manager = context.get()->get_constant_mgr();
290
291 (void)du_manager;
292 (void)c_manager;
293
294 uint32_t inlined_at_id = db_manager->CreateDebugInlinedAt(&line, scope);
295 auto* inlined_at = db_manager->GetDebugInlinedAt(inlined_at_id);
296 EXPECT_NE(inlined_at, nullptr);
297 EXPECT_EQ(inlined_at->GetSingleWordOperand(kDebugInlinedAtOperandLineIndex),
298 100);
299 }
300
301 TEST(DebugInfoManager, GetDebugInfoNone) {
302 const std::string text = R"(
303 OpCapability Shader
304 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
305 OpMemoryModel Logical GLSL450
306 OpEntryPoint Fragment %main "main" %in_var_COLOR
307 OpExecutionMode %main OriginUpperLeft
308 %5 = OpString "ps.hlsl"
309 %14 = OpString "#line 1 \"ps.hlsl\"
310 void main(float in_var_color : COLOR) {
311 float color = in_var_color;
312 }
313 "
314 %17 = OpString "float"
315 %21 = OpString "main"
316 %24 = OpString "color"
317 OpName %in_var_COLOR "in.var.COLOR"
318 OpName %main "main"
319 OpDecorate %in_var_COLOR Location 0
320 %uint = OpTypeInt 32 0
321 %uint_32 = OpConstant %uint 32
322 %float = OpTypeFloat 32
323 %_ptr_Input_float = OpTypePointer Input %float
324 %void = OpTypeVoid
325 %27 = OpTypeFunction %void
326 %_ptr_Function_float = OpTypePointer Function %float
327 %in_var_COLOR = OpVariable %_ptr_Input_float Input
328 %13 = OpExtInst %void %1 DebugExpression
329 %15 = OpExtInst %void %1 DebugSource %5 %14
330 %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL
331 %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float
332 %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18
333 %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main
334 %12 = OpExtInst %void %1 DebugInfoNone
335 %25 = OpExtInst %void %1 DebugLocalVariable %24 %18 %15 1 20 %22 FlagIsLocal 0
336 %main = OpFunction %void None %27
337 %28 = OpLabel
338 %100 = OpVariable %_ptr_Function_float Function
339 %31 = OpLoad %float %in_var_COLOR
340 OpStore %100 %31
341 %36 = OpExtInst %void %1 DebugDeclare %25 %100 %13
342 OpReturn
343 OpFunctionEnd
344 )";
345
346 std::unique_ptr<IRContext> context =
347 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
348 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
349 DebugInfoManager manager(context.get());
350
351 Instruction* debug_info_none_inst = manager.GetDebugInfoNone();
352 EXPECT_NE(debug_info_none_inst, nullptr);
353 EXPECT_EQ(debug_info_none_inst->GetOpenCL100DebugOpcode(),
354 OpenCLDebugInfo100DebugInfoNone);
355 EXPECT_EQ(debug_info_none_inst->PreviousNode(), nullptr);
356 }
357
358 TEST(DebugInfoManager, CreateDebugInfoNone) {
359 const std::string text = R"(
360 OpCapability Shader
361 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
362 OpMemoryModel Logical GLSL450
363 OpEntryPoint Fragment %main "main" %in_var_COLOR
364 OpExecutionMode %main OriginUpperLeft
365 %5 = OpString "ps.hlsl"
366 %14 = OpString "#line 1 \"ps.hlsl\"
367 void main(float in_var_color : COLOR) {
368 float color = in_var_color;
369 }
370 "
371 %17 = OpString "float"
372 %21 = OpString "main"
373 %24 = OpString "color"
374 OpName %in_var_COLOR "in.var.COLOR"
375 OpName %main "main"
376 OpDecorate %in_var_COLOR Location 0
377 %uint = OpTypeInt 32 0
378 %uint_32 = OpConstant %uint 32
379 %float = OpTypeFloat 32
380 %_ptr_Input_float = OpTypePointer Input %float
381 %void = OpTypeVoid
382 %27 = OpTypeFunction %void
383 %_ptr_Function_float = OpTypePointer Function %float
384 %in_var_COLOR = OpVariable %_ptr_Input_float Input
385 %13 = OpExtInst %void %1 DebugExpression
386 %15 = OpExtInst %void %1 DebugSource %5 %14
387 %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL
388 %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float
389 %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18
390 %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main
391 %25 = OpExtInst %void %1 DebugLocalVariable %24 %18 %15 1 20 %22 FlagIsLocal 0
392 %main = OpFunction %void None %27
393 %28 = OpLabel
394 %100 = OpVariable %_ptr_Function_float Function
395 %31 = OpLoad %float %in_var_COLOR
396 OpStore %100 %31
397 %36 = OpExtInst %void %1 DebugDeclare %25 %100 %13
398 OpReturn
399 OpFunctionEnd
400 )";
401
402 std::unique_ptr<IRContext> context =
403 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
404 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
405 DebugInfoManager manager(context.get());
406
407 Instruction* debug_info_none_inst = manager.GetDebugInfoNone();
408 EXPECT_NE(debug_info_none_inst, nullptr);
409 EXPECT_EQ(debug_info_none_inst->GetOpenCL100DebugOpcode(),
410 OpenCLDebugInfo100DebugInfoNone);
411 EXPECT_EQ(debug_info_none_inst->PreviousNode(), nullptr);
412 }
413
414 TEST(DebugInfoManager, GetDebugFunction) {
415 const std::string text = R"(
416 OpCapability Shader
417 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
418 OpMemoryModel Logical GLSL450
419 OpEntryPoint Fragment %200 "200" %in_var_COLOR
420 OpExecutionMode %200 OriginUpperLeft
421 %5 = OpString "ps.hlsl"
422 %14 = OpString "#line 1 \"ps.hlsl\"
423 void 200(float in_var_color : COLOR) {
424 float color = in_var_color;
425 }
426 "
427 %17 = OpString "float"
428 %21 = OpString "200"
429 %24 = OpString "color"
430 OpName %in_var_COLOR "in.var.COLOR"
431 OpName %200 "200"
432 OpDecorate %in_var_COLOR Location 0
433 %uint = OpTypeInt 32 0
434 %uint_32 = OpConstant %uint 32
435 %float = OpTypeFloat 32
436 %_ptr_Input_float = OpTypePointer Input %float
437 %void = OpTypeVoid
438 %27 = OpTypeFunction %void
439 %_ptr_Function_float = OpTypePointer Function %float
440 %in_var_COLOR = OpVariable %_ptr_Input_float Input
441 %13 = OpExtInst %void %1 DebugExpression
442 %15 = OpExtInst %void %1 DebugSource %5 %14
443 %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL
444 %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float
445 %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18
446 %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %200
447 %25 = OpExtInst %void %1 DebugLocalVariable %24 %18 %15 1 20 %22 FlagIsLocal 0
448 %200 = OpFunction %void None %27
449 %28 = OpLabel
450 %100 = OpVariable %_ptr_Function_float Function
451 %31 = OpLoad %float %in_var_COLOR
452 OpStore %100 %31
453 %36 = OpExtInst %void %1 DebugDeclare %25 %100 %13
454 OpReturn
455 OpFunctionEnd
456 )";
457
458 std::unique_ptr<IRContext> context =
459 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
460 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
461 DebugInfoManager manager(context.get());
462
463 EXPECT_EQ(manager.GetDebugFunction(100), nullptr);
464 EXPECT_EQ(manager.GetDebugFunction(150), nullptr);
465
466 Instruction* dbg_fn = manager.GetDebugFunction(200);
467
468 EXPECT_EQ(dbg_fn->GetOpenCL100DebugOpcode(), OpenCLDebugInfo100DebugFunction);
469 EXPECT_EQ(dbg_fn->GetSingleWordOperand(kDebugFunctionOperandFunctionIndex),
470 200);
471 }
472
473 TEST(DebugInfoManager, GetDebugFunction_InlinedAway) {
474 // struct PS_INPUT
475 // {
476 // float4 iColor : COLOR;
477 // };
478 //
479 // struct PS_OUTPUT
480 // {
481 // float4 oColor : SV_Target0;
482 // };
483 //
484 // float4 foo(float4 ic)
485 // {
486 // float4 c = ic / 2.0;
487 // return c;
488 // }
489 //
490 // PS_OUTPUT MainPs(PS_INPUT i)
491 // {
492 // PS_OUTPUT ps_output;
493 // float4 ic = i.iColor;
494 // ps_output.oColor = foo(ic);
495 // return ps_output;
496 // }
497 const std::string text = R"(
498 OpCapability Shader
499 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
500 OpMemoryModel Logical GLSL450
501 OpEntryPoint Fragment %MainPs "MainPs" %in_var_COLOR %out_var_SV_Target0
502 OpExecutionMode %MainPs OriginUpperLeft
503 %15 = OpString "foo2.frag"
504 %19 = OpString "PS_OUTPUT"
505 %23 = OpString "float"
506 %26 = OpString "oColor"
507 %28 = OpString "PS_INPUT"
508 %31 = OpString "iColor"
509 %33 = OpString "foo"
510 %37 = OpString "c"
511 %39 = OpString "ic"
512 %42 = OpString "src.MainPs"
513 %47 = OpString "ps_output"
514 %50 = OpString "i"
515 OpName %in_var_COLOR "in.var.COLOR"
516 OpName %out_var_SV_Target0 "out.var.SV_Target0"
517 OpName %MainPs "MainPs"
518 OpDecorate %in_var_COLOR Location 0
519 OpDecorate %out_var_SV_Target0 Location 0
520 %int = OpTypeInt 32 1
521 %int_0 = OpConstant %int 0
522 %float = OpTypeFloat 32
523 %v4float = OpTypeVector %float 4
524 %uint = OpTypeInt 32 0
525 %uint_32 = OpConstant %uint 32
526 %_ptr_Input_v4float = OpTypePointer Input %v4float
527 %_ptr_Output_v4float = OpTypePointer Output %v4float
528 %void = OpTypeVoid
529 %uint_128 = OpConstant %uint 128
530 %uint_0 = OpConstant %uint 0
531 %52 = OpTypeFunction %void
532 %in_var_COLOR = OpVariable %_ptr_Input_v4float Input
533 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
534 %float_0_5 = OpConstant %float 0.5
535 %130 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
536 %115 = OpExtInst %void %1 DebugInfoNone
537 %49 = OpExtInst %void %1 DebugExpression
538 %17 = OpExtInst %void %1 DebugSource %15
539 %18 = OpExtInst %void %1 DebugCompilationUnit 1 4 %17 HLSL
540 %21 = OpExtInst %void %1 DebugTypeComposite %19 Structure %17 6 1 %18 %19 %uint_128 FlagIsProtected|FlagIsPrivate %22
541 %24 = OpExtInst %void %1 DebugTypeBasic %23 %uint_32 Float
542 %25 = OpExtInst %void %1 DebugTypeVector %24 4
543 %22 = OpExtInst %void %1 DebugTypeMember %26 %25 %17 8 5 %21 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
544 %29 = OpExtInst %void %1 DebugTypeComposite %28 Structure %17 1 1 %18 %28 %uint_128 FlagIsProtected|FlagIsPrivate %30
545 %30 = OpExtInst %void %1 DebugTypeMember %31 %25 %17 3 5 %29 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
546 %32 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %25 %25
547 %34 = OpExtInst %void %1 DebugFunction %33 %32 %17 11 1 %18 %33 FlagIsProtected|FlagIsPrivate 12 %115
548 %36 = OpExtInst %void %1 DebugLexicalBlock %17 12 1 %34
549 %38 = OpExtInst %void %1 DebugLocalVariable %37 %25 %17 13 12 %36 FlagIsLocal
550 %41 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %21 %29
551 %43 = OpExtInst %void %1 DebugFunction %42 %41 %17 17 1 %18 %42 FlagIsProtected|FlagIsPrivate 18 %115
552 %45 = OpExtInst %void %1 DebugLexicalBlock %17 18 1 %43
553 %46 = OpExtInst %void %1 DebugLocalVariable %39 %25 %17 20 12 %45 FlagIsLocal
554 %48 = OpExtInst %void %1 DebugLocalVariable %47 %21 %17 19 15 %45 FlagIsLocal
555 %107 = OpExtInst %void %1 DebugInlinedAt 21 %45
556 %MainPs = OpFunction %void None %52
557 %53 = OpLabel
558 %57 = OpLoad %v4float %in_var_COLOR
559 %131 = OpExtInst %void %1 DebugScope %45
560 OpLine %15 20 12
561 %117 = OpExtInst %void %1 DebugValue %46 %57 %49
562 %132 = OpExtInst %void %1 DebugScope %36 %107
563 OpLine %15 13 19
564 %112 = OpFMul %v4float %57 %130
565 OpLine %15 13 12
566 %116 = OpExtInst %void %1 DebugValue %38 %112 %49
567 %133 = OpExtInst %void %1 DebugScope %45
568 %128 = OpExtInst %void %1 DebugValue %48 %112 %49 %int_0
569 %134 = OpExtInst %void %1 DebugNoScope
570 OpStore %out_var_SV_Target0 %112
571 OpReturn
572 OpFunctionEnd
573 )";
574
575 std::unique_ptr<IRContext> context =
576 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
577 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
578 DebugInfoManager manager(context.get());
579
580 EXPECT_EQ(manager.GetDebugFunction(115), nullptr);
581 }
582
583 TEST(DebugInfoManager, CloneDebugInlinedAt) {
584 const std::string text = R"(
585 OpCapability Shader
586 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
587 OpMemoryModel Logical GLSL450
588 OpEntryPoint Fragment %main "main" %in_var_COLOR
589 OpExecutionMode %main OriginUpperLeft
590 %5 = OpString "ps.hlsl"
591 %14 = OpString "#line 1 \"ps.hlsl\"
592 void main(float in_var_color : COLOR) {
593 float color = in_var_color;
594 }
595 "
596 %17 = OpString "float"
597 %21 = OpString "main"
598 %24 = OpString "color"
599 OpName %in_var_COLOR "in.var.COLOR"
600 OpName %main "main"
601 OpDecorate %in_var_COLOR Location 0
602 %uint = OpTypeInt 32 0
603 %uint_32 = OpConstant %uint 32
604 %float = OpTypeFloat 32
605 %_ptr_Input_float = OpTypePointer Input %float
606 %void = OpTypeVoid
607 %27 = OpTypeFunction %void
608 %_ptr_Function_float = OpTypePointer Function %float
609 %in_var_COLOR = OpVariable %_ptr_Input_float Input
610 %13 = OpExtInst %void %1 DebugExpression
611 %15 = OpExtInst %void %1 DebugSource %5 %14
612 %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL
613 %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float
614 %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18
615 %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main
616 %100 = OpExtInst %void %1 DebugInlinedAt 7 %22
617 %main = OpFunction %void None %27
618 %28 = OpLabel
619 %31 = OpLoad %float %in_var_COLOR
620 OpStore %100 %31
621 OpReturn
622 OpFunctionEnd
623 )";
624
625 std::unique_ptr<IRContext> context =
626 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
627 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
628 DebugInfoManager manager(context.get());
629
630 EXPECT_EQ(manager.CloneDebugInlinedAt(150), nullptr);
631 EXPECT_EQ(manager.CloneDebugInlinedAt(22), nullptr);
632
633 auto* inst = manager.CloneDebugInlinedAt(100);
634 EXPECT_EQ(inst->GetSingleWordOperand(kDebugInlinedAtOperandLineIndex), 7);
635 EXPECT_EQ(inst->GetSingleWordOperand(kDebugInlinedAtOperandScopeIndex), 22);
636 EXPECT_EQ(inst->NumOperands(), kDebugInlinedAtOperandScopeIndex + 1);
637
638 Instruction* before_100 = nullptr;
639 for (auto it = context->module()->ext_inst_debuginfo_begin();
640 it != context->module()->ext_inst_debuginfo_end(); ++it) {
641 if (it->result_id() == 100) break;
642 before_100 = &*it;
643 }
644 EXPECT_NE(inst, before_100);
645
646 inst = manager.CloneDebugInlinedAt(100, manager.GetDebugInlinedAt(100));
647 EXPECT_EQ(inst->GetSingleWordOperand(kDebugInlinedAtOperandLineIndex), 7);
648 EXPECT_EQ(inst->GetSingleWordOperand(kDebugInlinedAtOperandScopeIndex), 22);
649 EXPECT_EQ(inst->NumOperands(), kDebugInlinedAtOperandScopeIndex + 1);
650
651 before_100 = nullptr;
652 for (auto it = context->module()->ext_inst_debuginfo_begin();
653 it != context->module()->ext_inst_debuginfo_end(); ++it) {
654 if (it->result_id() == 100) break;
655 before_100 = &*it;
656 }
657 EXPECT_EQ(inst, before_100);
658 }
659
660 TEST(DebugInfoManager, KillDebugDeclares) {
661 const std::string text = R"(
662 OpCapability Shader
663 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
664 OpMemoryModel Logical GLSL450
665 OpEntryPoint Fragment %main "main" %in_var_COLOR
666 OpExecutionMode %main OriginUpperLeft
667 %5 = OpString "ps.hlsl"
668 %14 = OpString "#line 1 \"ps.hlsl\"
669 void main(float in_var_color : COLOR) {
670 float color = in_var_color;
671 }
672 "
673 %17 = OpString "float"
674 %21 = OpString "main"
675 %24 = OpString "color"
676 OpName %in_var_COLOR "in.var.COLOR"
677 OpName %main "main"
678 OpDecorate %in_var_COLOR Location 0
679 %uint = OpTypeInt 32 0
680 %uint_32 = OpConstant %uint 32
681 %float = OpTypeFloat 32
682 %_ptr_Input_float = OpTypePointer Input %float
683 %void = OpTypeVoid
684 %27 = OpTypeFunction %void
685 %_ptr_Function_float = OpTypePointer Function %float
686 %in_var_COLOR = OpVariable %_ptr_Input_float Input
687 %13 = OpExtInst %void %1 DebugExpression
688 %15 = OpExtInst %void %1 DebugSource %5 %14
689 %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL
690 %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float
691 %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18
692 %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main
693 %12 = OpExtInst %void %1 DebugInfoNone
694 %25 = OpExtInst %void %1 DebugLocalVariable %24 %18 %15 1 20 %22 FlagIsLocal 0
695 %main = OpFunction %void None %27
696 %28 = OpLabel
697 %100 = OpVariable %_ptr_Function_float Function
698 %31 = OpLoad %float %in_var_COLOR
699 OpStore %100 %31
700 %36 = OpExtInst %void %1 DebugDeclare %25 %100 %13
701 %37 = OpExtInst %void %1 DebugDeclare %25 %100 %13
702 %38 = OpExtInst %void %1 DebugDeclare %25 %100 %13
703 OpReturn
704 OpFunctionEnd
705 )";
706
707 std::unique_ptr<IRContext> context =
708 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
709 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
710 auto* dbg_info_mgr = context->get_debug_info_mgr();
711 auto* def_use_mgr = context->get_def_use_mgr();
712
713 EXPECT_TRUE(dbg_info_mgr->IsVariableDebugDeclared(100));
714 EXPECT_EQ(def_use_mgr->GetDef(36)->GetOpenCL100DebugOpcode(),
715 OpenCLDebugInfo100DebugDeclare);
716 EXPECT_EQ(def_use_mgr->GetDef(37)->GetOpenCL100DebugOpcode(),
717 OpenCLDebugInfo100DebugDeclare);
718 EXPECT_EQ(def_use_mgr->GetDef(38)->GetOpenCL100DebugOpcode(),
719 OpenCLDebugInfo100DebugDeclare);
720
721 dbg_info_mgr->KillDebugDeclares(100);
722 EXPECT_EQ(def_use_mgr->GetDef(36), nullptr);
723 EXPECT_EQ(def_use_mgr->GetDef(37), nullptr);
724 EXPECT_EQ(def_use_mgr->GetDef(38), nullptr);
725 EXPECT_FALSE(dbg_info_mgr->IsVariableDebugDeclared(100));
726 }
727
728 TEST(DebugInfoManager, AddDebugValueForDecl) {
729 const std::string text = R"(
730 OpCapability Shader
731 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
732 OpMemoryModel Logical GLSL450
733 OpEntryPoint Fragment %main "main" %in_var_COLOR
734 OpExecutionMode %main OriginUpperLeft
735 %5 = OpString "ps.hlsl"
736 %14 = OpString "#line 1 \"ps.hlsl\"
737 void main(float in_var_color : COLOR) {
738 float color = in_var_color;
739 }
740 "
741 %17 = OpString "float"
742 %21 = OpString "main"
743 %24 = OpString "color"
744 OpName %in_var_COLOR "in.var.COLOR"
745 OpName %main "main"
746 OpDecorate %in_var_COLOR Location 0
747 %uint = OpTypeInt 32 0
748 %uint_32 = OpConstant %uint 32
749 %float = OpTypeFloat 32
750 %_ptr_Input_float = OpTypePointer Input %float
751 %void = OpTypeVoid
752 %27 = OpTypeFunction %void
753 %_ptr_Function_float = OpTypePointer Function %float
754 %in_var_COLOR = OpVariable %_ptr_Input_float Input
755 %13 = OpExtInst %void %1 DebugExpression
756 %15 = OpExtInst %void %1 DebugSource %5 %14
757 %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL
758 %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float
759 %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18
760 %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main
761 %12 = OpExtInst %void %1 DebugInfoNone
762 %25 = OpExtInst %void %1 DebugLocalVariable %24 %18 %15 1 20 %22 FlagIsLocal 0
763 %main = OpFunction %void None %27
764 %28 = OpLabel
765 %100 = OpVariable %_ptr_Function_float Function
766 %31 = OpLoad %float %in_var_COLOR
767 %101 = OpExtInst %void %1 DebugScope %22
768 OpLine %5 13 7
769 OpStore %100 %31
770 OpNoLine
771 %102 = OpExtInst %void %1 DebugNoScope
772 %36 = OpExtInst %void %1 DebugDeclare %25 %100 %13
773 OpReturn
774 OpFunctionEnd
775 )";
776
777 std::unique_ptr<IRContext> context =
778 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
779 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
780 auto* def_use_mgr = context->get_def_use_mgr();
781 auto* dbg_decl = def_use_mgr->GetDef(36);
782 EXPECT_EQ(dbg_decl->GetOpenCL100DebugOpcode(),
783 OpenCLDebugInfo100DebugDeclare);
784
785 auto* dbg_info_mgr = context->get_debug_info_mgr();
786 Instruction* store = dbg_decl->PreviousNode();
787 auto* dbg_value =
788 dbg_info_mgr->AddDebugValueForDecl(dbg_decl, 100, dbg_decl, store);
789
790 EXPECT_EQ(dbg_value->GetOpenCL100DebugOpcode(), OpenCLDebugInfo100DebugValue);
791 EXPECT_EQ(dbg_value->dbg_line_inst()->GetSingleWordInOperand(
792 kOpLineInOperandFileIndex),
793 5);
794 EXPECT_EQ(dbg_value->dbg_line_inst()->GetSingleWordInOperand(
795 kOpLineInOperandLineIndex),
796 13);
797 EXPECT_EQ(dbg_value->dbg_line_inst()->GetSingleWordInOperand(
798 kOpLineInOperandColumnIndex),
799 7);
800 }
801
802 } // namespace
803 } // namespace analysis
804 } // namespace opt
805 } // namespace spvtools
806