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