• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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