• 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, GetDebugInfoNone) {
189   const std::string text = R"(
190                OpCapability Shader
191           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
192                OpMemoryModel Logical GLSL450
193                OpEntryPoint Fragment %main "main" %in_var_COLOR
194                OpExecutionMode %main OriginUpperLeft
195           %5 = OpString "ps.hlsl"
196          %14 = OpString "#line 1 \"ps.hlsl\"
197 void main(float in_var_color : COLOR) {
198   float color = in_var_color;
199 }
200 "
201          %17 = OpString "float"
202          %21 = OpString "main"
203          %24 = OpString "color"
204                OpName %in_var_COLOR "in.var.COLOR"
205                OpName %main "main"
206                OpDecorate %in_var_COLOR Location 0
207        %uint = OpTypeInt 32 0
208     %uint_32 = OpConstant %uint 32
209       %float = OpTypeFloat 32
210 %_ptr_Input_float = OpTypePointer Input %float
211        %void = OpTypeVoid
212          %27 = OpTypeFunction %void
213 %_ptr_Function_float = OpTypePointer Function %float
214 %in_var_COLOR = OpVariable %_ptr_Input_float Input
215          %13 = OpExtInst %void %1 DebugExpression
216          %15 = OpExtInst %void %1 DebugSource %5 %14
217          %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL
218          %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float
219          %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18
220          %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main
221          %12 = OpExtInst %void %1 DebugInfoNone
222          %25 = OpExtInst %void %1 DebugLocalVariable %24 %18 %15 1 20 %22 FlagIsLocal 0
223        %main = OpFunction %void None %27
224          %28 = OpLabel
225         %100 = OpVariable %_ptr_Function_float Function
226          %31 = OpLoad %float %in_var_COLOR
227                OpStore %100 %31
228          %36 = OpExtInst %void %1 DebugDeclare %25 %100 %13
229                OpReturn
230                OpFunctionEnd
231   )";
232 
233   std::unique_ptr<IRContext> context =
234       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
235                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
236   DebugInfoManager manager(context.get());
237 
238   Instruction* debug_info_none_inst = manager.GetDebugInfoNone();
239   EXPECT_NE(debug_info_none_inst, nullptr);
240   EXPECT_EQ(debug_info_none_inst->GetOpenCL100DebugOpcode(),
241             OpenCLDebugInfo100DebugInfoNone);
242   EXPECT_EQ(debug_info_none_inst->PreviousNode(), nullptr);
243 }
244 
245 TEST(DebugInfoManager, CreateDebugInfoNone) {
246   const std::string text = R"(
247                OpCapability Shader
248           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
249                OpMemoryModel Logical GLSL450
250                OpEntryPoint Fragment %main "main" %in_var_COLOR
251                OpExecutionMode %main OriginUpperLeft
252           %5 = OpString "ps.hlsl"
253          %14 = OpString "#line 1 \"ps.hlsl\"
254 void main(float in_var_color : COLOR) {
255   float color = in_var_color;
256 }
257 "
258          %17 = OpString "float"
259          %21 = OpString "main"
260          %24 = OpString "color"
261                OpName %in_var_COLOR "in.var.COLOR"
262                OpName %main "main"
263                OpDecorate %in_var_COLOR Location 0
264        %uint = OpTypeInt 32 0
265     %uint_32 = OpConstant %uint 32
266       %float = OpTypeFloat 32
267 %_ptr_Input_float = OpTypePointer Input %float
268        %void = OpTypeVoid
269          %27 = OpTypeFunction %void
270 %_ptr_Function_float = OpTypePointer Function %float
271 %in_var_COLOR = OpVariable %_ptr_Input_float Input
272          %13 = OpExtInst %void %1 DebugExpression
273          %15 = OpExtInst %void %1 DebugSource %5 %14
274          %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL
275          %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float
276          %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18
277          %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main
278          %25 = OpExtInst %void %1 DebugLocalVariable %24 %18 %15 1 20 %22 FlagIsLocal 0
279        %main = OpFunction %void None %27
280          %28 = OpLabel
281         %100 = OpVariable %_ptr_Function_float Function
282          %31 = OpLoad %float %in_var_COLOR
283                OpStore %100 %31
284          %36 = OpExtInst %void %1 DebugDeclare %25 %100 %13
285                OpReturn
286                OpFunctionEnd
287   )";
288 
289   std::unique_ptr<IRContext> context =
290       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
291                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
292   DebugInfoManager manager(context.get());
293 
294   Instruction* debug_info_none_inst = manager.GetDebugInfoNone();
295   EXPECT_NE(debug_info_none_inst, nullptr);
296   EXPECT_EQ(debug_info_none_inst->GetOpenCL100DebugOpcode(),
297             OpenCLDebugInfo100DebugInfoNone);
298   EXPECT_EQ(debug_info_none_inst->PreviousNode(), nullptr);
299 }
300 
301 TEST(DebugInfoManager, GetDebugFunction) {
302   const std::string text = R"(
303                OpCapability Shader
304           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
305                OpMemoryModel Logical GLSL450
306                OpEntryPoint Fragment %200 "200" %in_var_COLOR
307                OpExecutionMode %200 OriginUpperLeft
308           %5 = OpString "ps.hlsl"
309          %14 = OpString "#line 1 \"ps.hlsl\"
310 void 200(float in_var_color : COLOR) {
311   float color = in_var_color;
312 }
313 "
314          %17 = OpString "float"
315          %21 = OpString "200"
316          %24 = OpString "color"
317                OpName %in_var_COLOR "in.var.COLOR"
318                OpName %200 "200"
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 %200
334          %25 = OpExtInst %void %1 DebugLocalVariable %24 %18 %15 1 20 %22 FlagIsLocal 0
335        %200 = OpFunction %void None %27
336          %28 = OpLabel
337         %100 = OpVariable %_ptr_Function_float Function
338          %31 = OpLoad %float %in_var_COLOR
339                OpStore %100 %31
340          %36 = OpExtInst %void %1 DebugDeclare %25 %100 %13
341                OpReturn
342                OpFunctionEnd
343   )";
344 
345   std::unique_ptr<IRContext> context =
346       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
347                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
348   DebugInfoManager manager(context.get());
349 
350   EXPECT_EQ(manager.GetDebugFunction(100), nullptr);
351   EXPECT_EQ(manager.GetDebugFunction(150), nullptr);
352 
353   Instruction* dbg_fn = manager.GetDebugFunction(200);
354 
355   EXPECT_EQ(dbg_fn->GetOpenCL100DebugOpcode(), OpenCLDebugInfo100DebugFunction);
356   EXPECT_EQ(dbg_fn->GetSingleWordOperand(kDebugFunctionOperandFunctionIndex),
357             200);
358 }
359 
360 TEST(DebugInfoManager, GetDebugFunction_InlinedAway) {
361   // struct PS_INPUT
362   // {
363   //   float4 iColor : COLOR;
364   // };
365   //
366   // struct PS_OUTPUT
367   // {
368   //   float4 oColor : SV_Target0;
369   // };
370   //
371   // float4 foo(float4 ic)
372   // {
373   //   float4 c = ic / 2.0;
374   //   return c;
375   // }
376   //
377   // PS_OUTPUT MainPs(PS_INPUT i)
378   // {
379   //   PS_OUTPUT ps_output;
380   //   float4 ic = i.iColor;
381   //   ps_output.oColor = foo(ic);
382   //   return ps_output;
383   // }
384   const std::string text = R"(
385                OpCapability Shader
386           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
387                OpMemoryModel Logical GLSL450
388                OpEntryPoint Fragment %MainPs "MainPs" %in_var_COLOR %out_var_SV_Target0
389                OpExecutionMode %MainPs OriginUpperLeft
390          %15 = OpString "foo2.frag"
391          %19 = OpString "PS_OUTPUT"
392          %23 = OpString "float"
393          %26 = OpString "oColor"
394          %28 = OpString "PS_INPUT"
395          %31 = OpString "iColor"
396          %33 = OpString "foo"
397          %37 = OpString "c"
398          %39 = OpString "ic"
399          %42 = OpString "src.MainPs"
400          %47 = OpString "ps_output"
401          %50 = OpString "i"
402                OpName %in_var_COLOR "in.var.COLOR"
403                OpName %out_var_SV_Target0 "out.var.SV_Target0"
404                OpName %MainPs "MainPs"
405                OpDecorate %in_var_COLOR Location 0
406                OpDecorate %out_var_SV_Target0 Location 0
407         %int = OpTypeInt 32 1
408       %int_0 = OpConstant %int 0
409       %float = OpTypeFloat 32
410     %v4float = OpTypeVector %float 4
411        %uint = OpTypeInt 32 0
412     %uint_32 = OpConstant %uint 32
413 %_ptr_Input_v4float = OpTypePointer Input %v4float
414 %_ptr_Output_v4float = OpTypePointer Output %v4float
415        %void = OpTypeVoid
416    %uint_128 = OpConstant %uint 128
417      %uint_0 = OpConstant %uint 0
418          %52 = OpTypeFunction %void
419 %in_var_COLOR = OpVariable %_ptr_Input_v4float Input
420 %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output
421   %float_0_5 = OpConstant %float 0.5
422         %130 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
423         %115 = OpExtInst %void %1 DebugInfoNone
424          %49 = OpExtInst %void %1 DebugExpression
425          %17 = OpExtInst %void %1 DebugSource %15
426          %18 = OpExtInst %void %1 DebugCompilationUnit 1 4 %17 HLSL
427          %21 = OpExtInst %void %1 DebugTypeComposite %19 Structure %17 6 1 %18 %19 %uint_128 FlagIsProtected|FlagIsPrivate %22
428          %24 = OpExtInst %void %1 DebugTypeBasic %23 %uint_32 Float
429          %25 = OpExtInst %void %1 DebugTypeVector %24 4
430          %22 = OpExtInst %void %1 DebugTypeMember %26 %25 %17 8 5 %21 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
431          %29 = OpExtInst %void %1 DebugTypeComposite %28 Structure %17 1 1 %18 %28 %uint_128 FlagIsProtected|FlagIsPrivate %30
432          %30 = OpExtInst %void %1 DebugTypeMember %31 %25 %17 3 5 %29 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate
433          %32 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %25 %25
434          %34 = OpExtInst %void %1 DebugFunction %33 %32 %17 11 1 %18 %33 FlagIsProtected|FlagIsPrivate 12 %115
435          %36 = OpExtInst %void %1 DebugLexicalBlock %17 12 1 %34
436          %38 = OpExtInst %void %1 DebugLocalVariable %37 %25 %17 13 12 %36 FlagIsLocal
437          %41 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %21 %29
438          %43 = OpExtInst %void %1 DebugFunction %42 %41 %17 17 1 %18 %42 FlagIsProtected|FlagIsPrivate 18 %115
439          %45 = OpExtInst %void %1 DebugLexicalBlock %17 18 1 %43
440          %46 = OpExtInst %void %1 DebugLocalVariable %39 %25 %17 20 12 %45 FlagIsLocal
441          %48 = OpExtInst %void %1 DebugLocalVariable %47 %21 %17 19 15 %45 FlagIsLocal
442         %107 = OpExtInst %void %1 DebugInlinedAt 21 %45
443      %MainPs = OpFunction %void None %52
444          %53 = OpLabel
445          %57 = OpLoad %v4float %in_var_COLOR
446         %131 = OpExtInst %void %1 DebugScope %45
447                OpLine %15 20 12
448         %117 = OpExtInst %void %1 DebugValue %46 %57 %49
449         %132 = OpExtInst %void %1 DebugScope %36 %107
450                OpLine %15 13 19
451         %112 = OpFMul %v4float %57 %130
452                OpLine %15 13 12
453         %116 = OpExtInst %void %1 DebugValue %38 %112 %49
454         %133 = OpExtInst %void %1 DebugScope %45
455         %128 = OpExtInst %void %1 DebugValue %48 %112 %49 %int_0
456         %134 = OpExtInst %void %1 DebugNoScope
457                OpStore %out_var_SV_Target0 %112
458                OpReturn
459                OpFunctionEnd
460   )";
461 
462   std::unique_ptr<IRContext> context =
463       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
464                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
465   DebugInfoManager manager(context.get());
466 
467   EXPECT_EQ(manager.GetDebugFunction(115), nullptr);
468 }
469 
470 TEST(DebugInfoManager, CloneDebugInlinedAt) {
471   const std::string text = R"(
472                OpCapability Shader
473           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
474                OpMemoryModel Logical GLSL450
475                OpEntryPoint Fragment %main "main" %in_var_COLOR
476                OpExecutionMode %main OriginUpperLeft
477           %5 = OpString "ps.hlsl"
478          %14 = OpString "#line 1 \"ps.hlsl\"
479 void main(float in_var_color : COLOR) {
480   float color = in_var_color;
481 }
482 "
483          %17 = OpString "float"
484          %21 = OpString "main"
485          %24 = OpString "color"
486                OpName %in_var_COLOR "in.var.COLOR"
487                OpName %main "main"
488                OpDecorate %in_var_COLOR Location 0
489        %uint = OpTypeInt 32 0
490     %uint_32 = OpConstant %uint 32
491       %float = OpTypeFloat 32
492 %_ptr_Input_float = OpTypePointer Input %float
493        %void = OpTypeVoid
494          %27 = OpTypeFunction %void
495 %_ptr_Function_float = OpTypePointer Function %float
496 %in_var_COLOR = OpVariable %_ptr_Input_float Input
497          %13 = OpExtInst %void %1 DebugExpression
498          %15 = OpExtInst %void %1 DebugSource %5 %14
499          %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL
500          %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float
501          %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18
502          %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main
503         %100 = OpExtInst %void %1 DebugInlinedAt 7 %22
504        %main = OpFunction %void None %27
505          %28 = OpLabel
506          %31 = OpLoad %float %in_var_COLOR
507                OpStore %100 %31
508                OpReturn
509                OpFunctionEnd
510   )";
511 
512   std::unique_ptr<IRContext> context =
513       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
514                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
515   DebugInfoManager manager(context.get());
516 
517   EXPECT_EQ(manager.CloneDebugInlinedAt(150), nullptr);
518   EXPECT_EQ(manager.CloneDebugInlinedAt(22), nullptr);
519 
520   auto* inst = manager.CloneDebugInlinedAt(100);
521   EXPECT_EQ(inst->GetSingleWordOperand(kDebugInlinedAtOperandLineIndex), 7);
522   EXPECT_EQ(inst->GetSingleWordOperand(kDebugInlinedAtOperandScopeIndex), 22);
523   EXPECT_EQ(inst->NumOperands(), kDebugInlinedAtOperandScopeIndex + 1);
524 
525   Instruction* before_100 = nullptr;
526   for (auto it = context->module()->ext_inst_debuginfo_begin();
527        it != context->module()->ext_inst_debuginfo_end(); ++it) {
528     if (it->result_id() == 100) break;
529     before_100 = &*it;
530   }
531   EXPECT_NE(inst, before_100);
532 
533   inst = manager.CloneDebugInlinedAt(100, manager.GetDebugInlinedAt(100));
534   EXPECT_EQ(inst->GetSingleWordOperand(kDebugInlinedAtOperandLineIndex), 7);
535   EXPECT_EQ(inst->GetSingleWordOperand(kDebugInlinedAtOperandScopeIndex), 22);
536   EXPECT_EQ(inst->NumOperands(), kDebugInlinedAtOperandScopeIndex + 1);
537 
538   before_100 = nullptr;
539   for (auto it = context->module()->ext_inst_debuginfo_begin();
540        it != context->module()->ext_inst_debuginfo_end(); ++it) {
541     if (it->result_id() == 100) break;
542     before_100 = &*it;
543   }
544   EXPECT_EQ(inst, before_100);
545 }
546 
547 TEST(DebugInfoManager, KillDebugDeclares) {
548   const std::string text = R"(
549                OpCapability Shader
550           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
551                OpMemoryModel Logical GLSL450
552                OpEntryPoint Fragment %main "main" %in_var_COLOR
553                OpExecutionMode %main OriginUpperLeft
554           %5 = OpString "ps.hlsl"
555          %14 = OpString "#line 1 \"ps.hlsl\"
556 void main(float in_var_color : COLOR) {
557   float color = in_var_color;
558 }
559 "
560          %17 = OpString "float"
561          %21 = OpString "main"
562          %24 = OpString "color"
563                OpName %in_var_COLOR "in.var.COLOR"
564                OpName %main "main"
565                OpDecorate %in_var_COLOR Location 0
566        %uint = OpTypeInt 32 0
567     %uint_32 = OpConstant %uint 32
568       %float = OpTypeFloat 32
569 %_ptr_Input_float = OpTypePointer Input %float
570        %void = OpTypeVoid
571          %27 = OpTypeFunction %void
572 %_ptr_Function_float = OpTypePointer Function %float
573 %in_var_COLOR = OpVariable %_ptr_Input_float Input
574          %13 = OpExtInst %void %1 DebugExpression
575          %15 = OpExtInst %void %1 DebugSource %5 %14
576          %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL
577          %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float
578          %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18
579          %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main
580          %12 = OpExtInst %void %1 DebugInfoNone
581          %25 = OpExtInst %void %1 DebugLocalVariable %24 %18 %15 1 20 %22 FlagIsLocal 0
582        %main = OpFunction %void None %27
583          %28 = OpLabel
584         %100 = OpVariable %_ptr_Function_float Function
585          %31 = OpLoad %float %in_var_COLOR
586                OpStore %100 %31
587          %36 = OpExtInst %void %1 DebugDeclare %25 %100 %13
588          %37 = OpExtInst %void %1 DebugDeclare %25 %100 %13
589          %38 = OpExtInst %void %1 DebugDeclare %25 %100 %13
590                OpReturn
591                OpFunctionEnd
592   )";
593 
594   std::unique_ptr<IRContext> context =
595       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
596                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
597   auto* dbg_info_mgr = context->get_debug_info_mgr();
598   auto* def_use_mgr = context->get_def_use_mgr();
599 
600   EXPECT_TRUE(dbg_info_mgr->IsVariableDebugDeclared(100));
601   EXPECT_EQ(def_use_mgr->GetDef(36)->GetOpenCL100DebugOpcode(),
602             OpenCLDebugInfo100DebugDeclare);
603   EXPECT_EQ(def_use_mgr->GetDef(37)->GetOpenCL100DebugOpcode(),
604             OpenCLDebugInfo100DebugDeclare);
605   EXPECT_EQ(def_use_mgr->GetDef(38)->GetOpenCL100DebugOpcode(),
606             OpenCLDebugInfo100DebugDeclare);
607 
608   dbg_info_mgr->KillDebugDeclares(100);
609   EXPECT_EQ(def_use_mgr->GetDef(36), nullptr);
610   EXPECT_EQ(def_use_mgr->GetDef(37), nullptr);
611   EXPECT_EQ(def_use_mgr->GetDef(38), nullptr);
612   EXPECT_FALSE(dbg_info_mgr->IsVariableDebugDeclared(100));
613 }
614 
615 TEST(DebugInfoManager, AddDebugValueForDecl) {
616   const std::string text = R"(
617                OpCapability Shader
618           %1 = OpExtInstImport "OpenCL.DebugInfo.100"
619                OpMemoryModel Logical GLSL450
620                OpEntryPoint Fragment %main "main" %in_var_COLOR
621                OpExecutionMode %main OriginUpperLeft
622           %5 = OpString "ps.hlsl"
623          %14 = OpString "#line 1 \"ps.hlsl\"
624 void main(float in_var_color : COLOR) {
625   float color = in_var_color;
626 }
627 "
628          %17 = OpString "float"
629          %21 = OpString "main"
630          %24 = OpString "color"
631                OpName %in_var_COLOR "in.var.COLOR"
632                OpName %main "main"
633                OpDecorate %in_var_COLOR Location 0
634        %uint = OpTypeInt 32 0
635     %uint_32 = OpConstant %uint 32
636       %float = OpTypeFloat 32
637 %_ptr_Input_float = OpTypePointer Input %float
638        %void = OpTypeVoid
639          %27 = OpTypeFunction %void
640 %_ptr_Function_float = OpTypePointer Function %float
641 %in_var_COLOR = OpVariable %_ptr_Input_float Input
642          %13 = OpExtInst %void %1 DebugExpression
643          %15 = OpExtInst %void %1 DebugSource %5 %14
644          %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL
645          %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float
646          %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18
647          %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main
648          %12 = OpExtInst %void %1 DebugInfoNone
649          %25 = OpExtInst %void %1 DebugLocalVariable %24 %18 %15 1 20 %22 FlagIsLocal 0
650        %main = OpFunction %void None %27
651          %28 = OpLabel
652         %100 = OpVariable %_ptr_Function_float Function
653          %31 = OpLoad %float %in_var_COLOR
654         %101 = OpExtInst %void %1 DebugScope %22
655                OpLine %5 13 7
656                OpStore %100 %31
657                OpNoLine
658         %102 = OpExtInst %void %1 DebugNoScope
659          %36 = OpExtInst %void %1 DebugDeclare %25 %100 %13
660                OpReturn
661                OpFunctionEnd
662   )";
663 
664   std::unique_ptr<IRContext> context =
665       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
666                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
667   auto* def_use_mgr = context->get_def_use_mgr();
668   auto* dbg_decl = def_use_mgr->GetDef(36);
669   EXPECT_EQ(dbg_decl->GetOpenCL100DebugOpcode(),
670             OpenCLDebugInfo100DebugDeclare);
671 
672   auto* dbg_info_mgr = context->get_debug_info_mgr();
673   Instruction* store = dbg_decl->PreviousNode();
674   auto* dbg_value =
675       dbg_info_mgr->AddDebugValueForDecl(dbg_decl, 100, dbg_decl, store);
676 
677   EXPECT_EQ(dbg_value->GetOpenCL100DebugOpcode(), OpenCLDebugInfo100DebugValue);
678   EXPECT_EQ(dbg_value->dbg_line_inst()->GetSingleWordInOperand(
679                 kOpLineInOperandFileIndex),
680             5);
681   EXPECT_EQ(dbg_value->dbg_line_inst()->GetSingleWordInOperand(
682                 kOpLineInOperandLineIndex),
683             13);
684   EXPECT_EQ(dbg_value->dbg_line_inst()->GetSingleWordInOperand(
685                 kOpLineInOperandColumnIndex),
686             7);
687 }
688 
689 }  // namespace
690 }  // namespace analysis
691 }  // namespace opt
692 }  // namespace spvtools
693