| // Copyright (c) 2020 Google LLC | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| #include "source/opt/debug_info_manager.h" | |
| #include <memory> | |
| #include <vector> | |
| #include "gtest/gtest.h" | |
| #include "source/opt/build_module.h" | |
| #include "source/opt/instruction.h" | |
| #include "spirv-tools/libspirv.hpp" | |
| // Constants for OpenCL.DebugInfo.100 extension instructions. | |
| static const uint32_t kDebugFunctionOperandFunctionIndex = 13; | |
| static const uint32_t kDebugInlinedAtOperandLineIndex = 4; | |
| static const uint32_t kDebugInlinedAtOperandScopeIndex = 5; | |
| static const uint32_t kDebugInlinedAtOperandInlinedIndex = 6; | |
| static const uint32_t kOpLineInOperandFileIndex = 0; | |
| static const uint32_t kOpLineInOperandLineIndex = 1; | |
| static const uint32_t kOpLineInOperandColumnIndex = 2; | |
| namespace spvtools { | |
| namespace opt { | |
| namespace analysis { | |
| namespace { | |
| TEST(DebugInfoManager, GetDebugInlinedAt) { | |
| const std::string text = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "OpenCL.DebugInfo.100" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %in_var_COLOR | |
| OpExecutionMode %main OriginUpperLeft | |
| %5 = OpString "ps.hlsl" | |
| %14 = OpString "#line 1 \"ps.hlsl\" | |
| void main(float in_var_color : COLOR) { | |
| float color = in_var_color; | |
| } | |
| " | |
| %17 = OpString "float" | |
| %21 = OpString "main" | |
| %24 = OpString "color" | |
| OpName %in_var_COLOR "in.var.COLOR" | |
| OpName %main "main" | |
| OpDecorate %in_var_COLOR Location 0 | |
| %uint = OpTypeInt 32 0 | |
| %uint_32 = OpConstant %uint 32 | |
| %float = OpTypeFloat 32 | |
| %_ptr_Input_float = OpTypePointer Input %float | |
| %void = OpTypeVoid | |
| %27 = OpTypeFunction %void | |
| %_ptr_Function_float = OpTypePointer Function %float | |
| %in_var_COLOR = OpVariable %_ptr_Input_float Input | |
| %13 = OpExtInst %void %1 DebugExpression | |
| %15 = OpExtInst %void %1 DebugSource %5 %14 | |
| %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL | |
| %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float | |
| %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18 | |
| %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main | |
| %100 = OpExtInst %void %1 DebugInlinedAt 7 %22 | |
| %main = OpFunction %void None %27 | |
| %28 = OpLabel | |
| %31 = OpLoad %float %in_var_COLOR | |
| OpStore %100 %31 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| std::unique_ptr<IRContext> context = | |
| BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, | |
| SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); | |
| DebugInfoManager manager(context.get()); | |
| EXPECT_EQ(manager.GetDebugInlinedAt(150), nullptr); | |
| EXPECT_EQ(manager.GetDebugInlinedAt(31), nullptr); | |
| EXPECT_EQ(manager.GetDebugInlinedAt(22), nullptr); | |
| auto* inst = manager.GetDebugInlinedAt(100); | |
| EXPECT_EQ(inst->GetSingleWordOperand(kDebugInlinedAtOperandLineIndex), 7); | |
| EXPECT_EQ(inst->GetSingleWordOperand(kDebugInlinedAtOperandScopeIndex), 22); | |
| } | |
| TEST(DebugInfoManager, CreateDebugInlinedAt) { | |
| const std::string text = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "OpenCL.DebugInfo.100" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %in_var_COLOR | |
| OpExecutionMode %main OriginUpperLeft | |
| %5 = OpString "ps.hlsl" | |
| %14 = OpString "#line 1 \"ps.hlsl\" | |
| void main(float in_var_color : COLOR) { | |
| float color = in_var_color; | |
| } | |
| " | |
| %17 = OpString "float" | |
| %21 = OpString "main" | |
| %24 = OpString "color" | |
| OpName %in_var_COLOR "in.var.COLOR" | |
| OpName %main "main" | |
| OpDecorate %in_var_COLOR Location 0 | |
| %uint = OpTypeInt 32 0 | |
| %uint_32 = OpConstant %uint 32 | |
| %float = OpTypeFloat 32 | |
| %_ptr_Input_float = OpTypePointer Input %float | |
| %void = OpTypeVoid | |
| %27 = OpTypeFunction %void | |
| %_ptr_Function_float = OpTypePointer Function %float | |
| %in_var_COLOR = OpVariable %_ptr_Input_float Input | |
| %13 = OpExtInst %void %1 DebugExpression | |
| %15 = OpExtInst %void %1 DebugSource %5 %14 | |
| %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL | |
| %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float | |
| %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18 | |
| %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main | |
| %100 = OpExtInst %void %1 DebugInlinedAt 7 %22 | |
| %main = OpFunction %void None %27 | |
| %28 = OpLabel | |
| %31 = OpLoad %float %in_var_COLOR | |
| OpStore %100 %31 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| DebugScope scope(22U, 0U); | |
| std::unique_ptr<IRContext> context = | |
| BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, | |
| SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); | |
| DebugInfoManager manager(context.get()); | |
| uint32_t inlined_at_id = manager.CreateDebugInlinedAt(nullptr, scope); | |
| auto* inlined_at = manager.GetDebugInlinedAt(inlined_at_id); | |
| EXPECT_NE(inlined_at, nullptr); | |
| EXPECT_EQ(inlined_at->GetSingleWordOperand(kDebugInlinedAtOperandLineIndex), | |
| 1); | |
| EXPECT_EQ(inlined_at->GetSingleWordOperand(kDebugInlinedAtOperandScopeIndex), | |
| 22); | |
| EXPECT_EQ(inlined_at->NumOperands(), kDebugInlinedAtOperandScopeIndex + 1); | |
| const uint32_t line_number = 77U; | |
| Instruction line(context.get(), spv::Op::OpLine); | |
| line.SetInOperands({ | |
| {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {5U}}, | |
| {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {line_number}}, | |
| {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {0U}}, | |
| }); | |
| inlined_at_id = manager.CreateDebugInlinedAt(&line, scope); | |
| inlined_at = manager.GetDebugInlinedAt(inlined_at_id); | |
| EXPECT_NE(inlined_at, nullptr); | |
| EXPECT_EQ(inlined_at->GetSingleWordOperand(kDebugInlinedAtOperandLineIndex), | |
| line_number); | |
| EXPECT_EQ(inlined_at->GetSingleWordOperand(kDebugInlinedAtOperandScopeIndex), | |
| 22); | |
| EXPECT_EQ(inlined_at->NumOperands(), kDebugInlinedAtOperandScopeIndex + 1); | |
| scope.SetInlinedAt(100U); | |
| inlined_at_id = manager.CreateDebugInlinedAt(&line, scope); | |
| inlined_at = manager.GetDebugInlinedAt(inlined_at_id); | |
| EXPECT_NE(inlined_at, nullptr); | |
| EXPECT_EQ(inlined_at->GetSingleWordOperand(kDebugInlinedAtOperandLineIndex), | |
| line_number); | |
| EXPECT_EQ(inlined_at->GetSingleWordOperand(kDebugInlinedAtOperandScopeIndex), | |
| 22); | |
| EXPECT_EQ(inlined_at->NumOperands(), kDebugInlinedAtOperandInlinedIndex + 1); | |
| EXPECT_EQ( | |
| inlined_at->GetSingleWordOperand(kDebugInlinedAtOperandInlinedIndex), | |
| 100U); | |
| } | |
| TEST(DebugInfoManager, CreateDebugInlinedAtWithConstantManager) { | |
| // Show that CreateDebugInlinedAt will use the Constant manager to generate | |
| // its line operand if the Constant and DefUse managers are valid. This is | |
| // proven by checking that the id for the line operand 7 is the same as the | |
| // existing constant 7. | |
| // | |
| // int function1() { | |
| // return 1; | |
| // } | |
| // | |
| // void main() { | |
| // function1(); | |
| // } | |
| const std::string text = R"(OpCapability Shader | |
| OpExtension "SPV_KHR_non_semantic_info" | |
| %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" | |
| OpExecutionMode %main OriginUpperLeft | |
| %3 = OpString "parent3.hlsl" | |
| %8 = OpString "int" | |
| %19 = OpString "function1" | |
| %20 = OpString "" | |
| %26 = OpString "main" | |
| OpName %main "main" | |
| OpName %src_main "src.main" | |
| OpName %bb_entry "bb.entry" | |
| OpName %function1 "function1" | |
| OpName %bb_entry_0 "bb.entry" | |
| %int = OpTypeInt 32 1 | |
| %int_1 = OpConstant %int 1 | |
| %uint = OpTypeInt 32 0 | |
| %uint_32 = OpConstant %uint 32 | |
| %void = OpTypeVoid | |
| %uint_4 = OpConstant %uint 4 | |
| %uint_0 = OpConstant %uint 0 | |
| %uint_3 = OpConstant %uint 3 | |
| %uint_1 = OpConstant %uint 1 | |
| %uint_5 = OpConstant %uint 5 | |
| %uint_2 = OpConstant %uint 2 | |
| %uint_17 = OpConstant %uint 17 | |
| %uint_6 = OpConstant %uint 6 | |
| %uint_13 = OpConstant %uint 13 | |
| %100 = OpConstant %uint 7 | |
| %31 = OpTypeFunction %void | |
| %42 = OpTypeFunction %int | |
| %10 = OpExtInst %void %1 DebugTypeBasic %8 %uint_32 %uint_4 %uint_0 | |
| %13 = OpExtInst %void %1 DebugTypeFunction %uint_3 %10 | |
| %15 = OpExtInst %void %1 DebugSource %3 | |
| %16 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %15 %uint_5 | |
| %21 = OpExtInst %void %1 DebugFunction %19 %13 %15 %uint_2 %uint_1 %16 %20 %uint_3 %uint_2 | |
| %23 = OpExtInst %void %1 DebugLexicalBlock %15 %uint_2 %uint_17 %21 | |
| %25 = OpExtInst %void %1 DebugTypeFunction %uint_3 %void | |
| %27 = OpExtInst %void %1 DebugFunction %26 %25 %15 %uint_6 %uint_1 %16 %20 %uint_3 %uint_6 | |
| %29 = OpExtInst %void %1 DebugLexicalBlock %15 %uint_6 %uint_13 %27 | |
| %main = OpFunction %void None %31 | |
| %32 = OpLabel | |
| %33 = OpFunctionCall %void %src_main | |
| OpLine %3 8 1 | |
| OpReturn | |
| OpFunctionEnd | |
| OpLine %3 6 1 | |
| %src_main = OpFunction %void None %31 | |
| OpNoLine | |
| %bb_entry = OpLabel | |
| %47 = OpExtInst %void %1 DebugScope %27 | |
| %37 = OpExtInst %void %1 DebugFunctionDefinition %27 %src_main | |
| %48 = OpExtInst %void %1 DebugScope %29 | |
| OpLine %3 7 3 | |
| %39 = OpFunctionCall %int %function1 | |
| %49 = OpExtInst %void %1 DebugScope %27 | |
| OpLine %3 8 1 | |
| OpReturn | |
| %50 = OpExtInst %void %1 DebugNoScope | |
| OpFunctionEnd | |
| OpLine %3 2 1 | |
| %function1 = OpFunction %int None %42 | |
| OpNoLine | |
| %bb_entry_0 = OpLabel | |
| %51 = OpExtInst %void %1 DebugScope %21 | |
| %45 = OpExtInst %void %1 DebugFunctionDefinition %21 %function1 | |
| %52 = OpExtInst %void %1 DebugScope %23 | |
| OpLine %3 3 3 | |
| OpReturnValue %int_1 | |
| %53 = OpExtInst %void %1 DebugNoScope | |
| OpFunctionEnd | |
| )"; | |
| std::unique_ptr<IRContext> context = | |
| BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, | |
| SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); | |
| const uint32_t line_number = 7U; | |
| Instruction line(context.get(), spv::Op::OpLine); | |
| line.SetInOperands({ | |
| {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {5U}}, | |
| {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {line_number}}, | |
| {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {0U}}, | |
| }); | |
| DebugScope scope(29U, 0U); | |
| auto db_manager = context.get()->get_debug_info_mgr(); | |
| auto du_manager = context.get()->get_def_use_mgr(); | |
| auto c_manager = context.get()->get_constant_mgr(); | |
| (void)du_manager; | |
| (void)c_manager; | |
| uint32_t inlined_at_id = db_manager->CreateDebugInlinedAt(&line, scope); | |
| auto* inlined_at = db_manager->GetDebugInlinedAt(inlined_at_id); | |
| EXPECT_NE(inlined_at, nullptr); | |
| EXPECT_EQ(inlined_at->GetSingleWordOperand(kDebugInlinedAtOperandLineIndex), | |
| 100); | |
| } | |
| TEST(DebugInfoManager, GetDebugInfoNone) { | |
| const std::string text = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "OpenCL.DebugInfo.100" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %in_var_COLOR | |
| OpExecutionMode %main OriginUpperLeft | |
| %5 = OpString "ps.hlsl" | |
| %14 = OpString "#line 1 \"ps.hlsl\" | |
| void main(float in_var_color : COLOR) { | |
| float color = in_var_color; | |
| } | |
| " | |
| %17 = OpString "float" | |
| %21 = OpString "main" | |
| %24 = OpString "color" | |
| OpName %in_var_COLOR "in.var.COLOR" | |
| OpName %main "main" | |
| OpDecorate %in_var_COLOR Location 0 | |
| %uint = OpTypeInt 32 0 | |
| %uint_32 = OpConstant %uint 32 | |
| %float = OpTypeFloat 32 | |
| %_ptr_Input_float = OpTypePointer Input %float | |
| %void = OpTypeVoid | |
| %27 = OpTypeFunction %void | |
| %_ptr_Function_float = OpTypePointer Function %float | |
| %in_var_COLOR = OpVariable %_ptr_Input_float Input | |
| %13 = OpExtInst %void %1 DebugExpression | |
| %15 = OpExtInst %void %1 DebugSource %5 %14 | |
| %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL | |
| %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float | |
| %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18 | |
| %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main | |
| %12 = OpExtInst %void %1 DebugInfoNone | |
| %25 = OpExtInst %void %1 DebugLocalVariable %24 %18 %15 1 20 %22 FlagIsLocal 0 | |
| %main = OpFunction %void None %27 | |
| %28 = OpLabel | |
| %100 = OpVariable %_ptr_Function_float Function | |
| %31 = OpLoad %float %in_var_COLOR | |
| OpStore %100 %31 | |
| %36 = OpExtInst %void %1 DebugDeclare %25 %100 %13 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| std::unique_ptr<IRContext> context = | |
| BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, | |
| SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); | |
| DebugInfoManager manager(context.get()); | |
| Instruction* debug_info_none_inst = manager.GetDebugInfoNone(); | |
| EXPECT_NE(debug_info_none_inst, nullptr); | |
| EXPECT_EQ(debug_info_none_inst->GetOpenCL100DebugOpcode(), | |
| OpenCLDebugInfo100DebugInfoNone); | |
| EXPECT_EQ(debug_info_none_inst->PreviousNode(), nullptr); | |
| } | |
| TEST(DebugInfoManager, CreateDebugInfoNone) { | |
| const std::string text = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "OpenCL.DebugInfo.100" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %in_var_COLOR | |
| OpExecutionMode %main OriginUpperLeft | |
| %5 = OpString "ps.hlsl" | |
| %14 = OpString "#line 1 \"ps.hlsl\" | |
| void main(float in_var_color : COLOR) { | |
| float color = in_var_color; | |
| } | |
| " | |
| %17 = OpString "float" | |
| %21 = OpString "main" | |
| %24 = OpString "color" | |
| OpName %in_var_COLOR "in.var.COLOR" | |
| OpName %main "main" | |
| OpDecorate %in_var_COLOR Location 0 | |
| %uint = OpTypeInt 32 0 | |
| %uint_32 = OpConstant %uint 32 | |
| %float = OpTypeFloat 32 | |
| %_ptr_Input_float = OpTypePointer Input %float | |
| %void = OpTypeVoid | |
| %27 = OpTypeFunction %void | |
| %_ptr_Function_float = OpTypePointer Function %float | |
| %in_var_COLOR = OpVariable %_ptr_Input_float Input | |
| %13 = OpExtInst %void %1 DebugExpression | |
| %15 = OpExtInst %void %1 DebugSource %5 %14 | |
| %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL | |
| %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float | |
| %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18 | |
| %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main | |
| %25 = OpExtInst %void %1 DebugLocalVariable %24 %18 %15 1 20 %22 FlagIsLocal 0 | |
| %main = OpFunction %void None %27 | |
| %28 = OpLabel | |
| %100 = OpVariable %_ptr_Function_float Function | |
| %31 = OpLoad %float %in_var_COLOR | |
| OpStore %100 %31 | |
| %36 = OpExtInst %void %1 DebugDeclare %25 %100 %13 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| std::unique_ptr<IRContext> context = | |
| BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, | |
| SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); | |
| DebugInfoManager manager(context.get()); | |
| Instruction* debug_info_none_inst = manager.GetDebugInfoNone(); | |
| EXPECT_NE(debug_info_none_inst, nullptr); | |
| EXPECT_EQ(debug_info_none_inst->GetOpenCL100DebugOpcode(), | |
| OpenCLDebugInfo100DebugInfoNone); | |
| EXPECT_EQ(debug_info_none_inst->PreviousNode(), nullptr); | |
| } | |
| TEST(DebugInfoManager, GetDebugFunction) { | |
| const std::string text = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "OpenCL.DebugInfo.100" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %200 "200" %in_var_COLOR | |
| OpExecutionMode %200 OriginUpperLeft | |
| %5 = OpString "ps.hlsl" | |
| %14 = OpString "#line 1 \"ps.hlsl\" | |
| void 200(float in_var_color : COLOR) { | |
| float color = in_var_color; | |
| } | |
| " | |
| %17 = OpString "float" | |
| %21 = OpString "200" | |
| %24 = OpString "color" | |
| OpName %in_var_COLOR "in.var.COLOR" | |
| OpName %200 "200" | |
| OpDecorate %in_var_COLOR Location 0 | |
| %uint = OpTypeInt 32 0 | |
| %uint_32 = OpConstant %uint 32 | |
| %float = OpTypeFloat 32 | |
| %_ptr_Input_float = OpTypePointer Input %float | |
| %void = OpTypeVoid | |
| %27 = OpTypeFunction %void | |
| %_ptr_Function_float = OpTypePointer Function %float | |
| %in_var_COLOR = OpVariable %_ptr_Input_float Input | |
| %13 = OpExtInst %void %1 DebugExpression | |
| %15 = OpExtInst %void %1 DebugSource %5 %14 | |
| %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL | |
| %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float | |
| %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18 | |
| %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %200 | |
| %25 = OpExtInst %void %1 DebugLocalVariable %24 %18 %15 1 20 %22 FlagIsLocal 0 | |
| %200 = OpFunction %void None %27 | |
| %28 = OpLabel | |
| %100 = OpVariable %_ptr_Function_float Function | |
| %31 = OpLoad %float %in_var_COLOR | |
| OpStore %100 %31 | |
| %36 = OpExtInst %void %1 DebugDeclare %25 %100 %13 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| std::unique_ptr<IRContext> context = | |
| BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, | |
| SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); | |
| DebugInfoManager manager(context.get()); | |
| EXPECT_EQ(manager.GetDebugFunction(100), nullptr); | |
| EXPECT_EQ(manager.GetDebugFunction(150), nullptr); | |
| Instruction* dbg_fn = manager.GetDebugFunction(200); | |
| EXPECT_EQ(dbg_fn->GetOpenCL100DebugOpcode(), OpenCLDebugInfo100DebugFunction); | |
| EXPECT_EQ(dbg_fn->GetSingleWordOperand(kDebugFunctionOperandFunctionIndex), | |
| 200); | |
| } | |
| TEST(DebugInfoManager, GetDebugFunction_InlinedAway) { | |
| // struct PS_INPUT | |
| // { | |
| // float4 iColor : COLOR; | |
| // }; | |
| // | |
| // struct PS_OUTPUT | |
| // { | |
| // float4 oColor : SV_Target0; | |
| // }; | |
| // | |
| // float4 foo(float4 ic) | |
| // { | |
| // float4 c = ic / 2.0; | |
| // return c; | |
| // } | |
| // | |
| // PS_OUTPUT MainPs(PS_INPUT i) | |
| // { | |
| // PS_OUTPUT ps_output; | |
| // float4 ic = i.iColor; | |
| // ps_output.oColor = foo(ic); | |
| // return ps_output; | |
| // } | |
| const std::string text = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "OpenCL.DebugInfo.100" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %MainPs "MainPs" %in_var_COLOR %out_var_SV_Target0 | |
| OpExecutionMode %MainPs OriginUpperLeft | |
| %15 = OpString "foo2.frag" | |
| %19 = OpString "PS_OUTPUT" | |
| %23 = OpString "float" | |
| %26 = OpString "oColor" | |
| %28 = OpString "PS_INPUT" | |
| %31 = OpString "iColor" | |
| %33 = OpString "foo" | |
| %37 = OpString "c" | |
| %39 = OpString "ic" | |
| %42 = OpString "src.MainPs" | |
| %47 = OpString "ps_output" | |
| %50 = OpString "i" | |
| OpName %in_var_COLOR "in.var.COLOR" | |
| OpName %out_var_SV_Target0 "out.var.SV_Target0" | |
| OpName %MainPs "MainPs" | |
| OpDecorate %in_var_COLOR Location 0 | |
| OpDecorate %out_var_SV_Target0 Location 0 | |
| %int = OpTypeInt 32 1 | |
| %int_0 = OpConstant %int 0 | |
| %float = OpTypeFloat 32 | |
| %v4float = OpTypeVector %float 4 | |
| %uint = OpTypeInt 32 0 | |
| %uint_32 = OpConstant %uint 32 | |
| %_ptr_Input_v4float = OpTypePointer Input %v4float | |
| %_ptr_Output_v4float = OpTypePointer Output %v4float | |
| %void = OpTypeVoid | |
| %uint_128 = OpConstant %uint 128 | |
| %uint_0 = OpConstant %uint 0 | |
| %52 = OpTypeFunction %void | |
| %in_var_COLOR = OpVariable %_ptr_Input_v4float Input | |
| %out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output | |
| %float_0_5 = OpConstant %float 0.5 | |
| %130 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5 | |
| %115 = OpExtInst %void %1 DebugInfoNone | |
| %49 = OpExtInst %void %1 DebugExpression | |
| %17 = OpExtInst %void %1 DebugSource %15 | |
| %18 = OpExtInst %void %1 DebugCompilationUnit 1 4 %17 HLSL | |
| %21 = OpExtInst %void %1 DebugTypeComposite %19 Structure %17 6 1 %18 %19 %uint_128 FlagIsProtected|FlagIsPrivate %22 | |
| %24 = OpExtInst %void %1 DebugTypeBasic %23 %uint_32 Float | |
| %25 = OpExtInst %void %1 DebugTypeVector %24 4 | |
| %22 = OpExtInst %void %1 DebugTypeMember %26 %25 %17 8 5 %21 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate | |
| %29 = OpExtInst %void %1 DebugTypeComposite %28 Structure %17 1 1 %18 %28 %uint_128 FlagIsProtected|FlagIsPrivate %30 | |
| %30 = OpExtInst %void %1 DebugTypeMember %31 %25 %17 3 5 %29 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate | |
| %32 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %25 %25 | |
| %34 = OpExtInst %void %1 DebugFunction %33 %32 %17 11 1 %18 %33 FlagIsProtected|FlagIsPrivate 12 %115 | |
| %36 = OpExtInst %void %1 DebugLexicalBlock %17 12 1 %34 | |
| %38 = OpExtInst %void %1 DebugLocalVariable %37 %25 %17 13 12 %36 FlagIsLocal | |
| %41 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %21 %29 | |
| %43 = OpExtInst %void %1 DebugFunction %42 %41 %17 17 1 %18 %42 FlagIsProtected|FlagIsPrivate 18 %115 | |
| %45 = OpExtInst %void %1 DebugLexicalBlock %17 18 1 %43 | |
| %46 = OpExtInst %void %1 DebugLocalVariable %39 %25 %17 20 12 %45 FlagIsLocal | |
| %48 = OpExtInst %void %1 DebugLocalVariable %47 %21 %17 19 15 %45 FlagIsLocal | |
| %107 = OpExtInst %void %1 DebugInlinedAt 21 %45 | |
| %MainPs = OpFunction %void None %52 | |
| %53 = OpLabel | |
| %57 = OpLoad %v4float %in_var_COLOR | |
| %131 = OpExtInst %void %1 DebugScope %45 | |
| OpLine %15 20 12 | |
| %117 = OpExtInst %void %1 DebugValue %46 %57 %49 | |
| %132 = OpExtInst %void %1 DebugScope %36 %107 | |
| OpLine %15 13 19 | |
| %112 = OpFMul %v4float %57 %130 | |
| OpLine %15 13 12 | |
| %116 = OpExtInst %void %1 DebugValue %38 %112 %49 | |
| %133 = OpExtInst %void %1 DebugScope %45 | |
| %128 = OpExtInst %void %1 DebugValue %48 %112 %49 %int_0 | |
| %134 = OpExtInst %void %1 DebugNoScope | |
| OpStore %out_var_SV_Target0 %112 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| std::unique_ptr<IRContext> context = | |
| BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, | |
| SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); | |
| DebugInfoManager manager(context.get()); | |
| EXPECT_EQ(manager.GetDebugFunction(115), nullptr); | |
| } | |
| TEST(DebugInfoManager, CloneDebugInlinedAt) { | |
| const std::string text = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "OpenCL.DebugInfo.100" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %in_var_COLOR | |
| OpExecutionMode %main OriginUpperLeft | |
| %5 = OpString "ps.hlsl" | |
| %14 = OpString "#line 1 \"ps.hlsl\" | |
| void main(float in_var_color : COLOR) { | |
| float color = in_var_color; | |
| } | |
| " | |
| %17 = OpString "float" | |
| %21 = OpString "main" | |
| %24 = OpString "color" | |
| OpName %in_var_COLOR "in.var.COLOR" | |
| OpName %main "main" | |
| OpDecorate %in_var_COLOR Location 0 | |
| %uint = OpTypeInt 32 0 | |
| %uint_32 = OpConstant %uint 32 | |
| %float = OpTypeFloat 32 | |
| %_ptr_Input_float = OpTypePointer Input %float | |
| %void = OpTypeVoid | |
| %27 = OpTypeFunction %void | |
| %_ptr_Function_float = OpTypePointer Function %float | |
| %in_var_COLOR = OpVariable %_ptr_Input_float Input | |
| %13 = OpExtInst %void %1 DebugExpression | |
| %15 = OpExtInst %void %1 DebugSource %5 %14 | |
| %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL | |
| %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float | |
| %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18 | |
| %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main | |
| %100 = OpExtInst %void %1 DebugInlinedAt 7 %22 | |
| %main = OpFunction %void None %27 | |
| %28 = OpLabel | |
| %31 = OpLoad %float %in_var_COLOR | |
| OpStore %100 %31 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| std::unique_ptr<IRContext> context = | |
| BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, | |
| SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); | |
| DebugInfoManager manager(context.get()); | |
| EXPECT_EQ(manager.CloneDebugInlinedAt(150), nullptr); | |
| EXPECT_EQ(manager.CloneDebugInlinedAt(22), nullptr); | |
| auto* inst = manager.CloneDebugInlinedAt(100); | |
| EXPECT_EQ(inst->GetSingleWordOperand(kDebugInlinedAtOperandLineIndex), 7); | |
| EXPECT_EQ(inst->GetSingleWordOperand(kDebugInlinedAtOperandScopeIndex), 22); | |
| EXPECT_EQ(inst->NumOperands(), kDebugInlinedAtOperandScopeIndex + 1); | |
| Instruction* before_100 = nullptr; | |
| for (auto it = context->module()->ext_inst_debuginfo_begin(); | |
| it != context->module()->ext_inst_debuginfo_end(); ++it) { | |
| if (it->result_id() == 100) break; | |
| before_100 = &*it; | |
| } | |
| EXPECT_NE(inst, before_100); | |
| inst = manager.CloneDebugInlinedAt(100, manager.GetDebugInlinedAt(100)); | |
| EXPECT_EQ(inst->GetSingleWordOperand(kDebugInlinedAtOperandLineIndex), 7); | |
| EXPECT_EQ(inst->GetSingleWordOperand(kDebugInlinedAtOperandScopeIndex), 22); | |
| EXPECT_EQ(inst->NumOperands(), kDebugInlinedAtOperandScopeIndex + 1); | |
| before_100 = nullptr; | |
| for (auto it = context->module()->ext_inst_debuginfo_begin(); | |
| it != context->module()->ext_inst_debuginfo_end(); ++it) { | |
| if (it->result_id() == 100) break; | |
| before_100 = &*it; | |
| } | |
| EXPECT_EQ(inst, before_100); | |
| } | |
| TEST(DebugInfoManager, KillDebugDeclares) { | |
| const std::string text = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "OpenCL.DebugInfo.100" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %in_var_COLOR | |
| OpExecutionMode %main OriginUpperLeft | |
| %5 = OpString "ps.hlsl" | |
| %14 = OpString "#line 1 \"ps.hlsl\" | |
| void main(float in_var_color : COLOR) { | |
| float color = in_var_color; | |
| } | |
| " | |
| %17 = OpString "float" | |
| %21 = OpString "main" | |
| %24 = OpString "color" | |
| OpName %in_var_COLOR "in.var.COLOR" | |
| OpName %main "main" | |
| OpDecorate %in_var_COLOR Location 0 | |
| %uint = OpTypeInt 32 0 | |
| %uint_32 = OpConstant %uint 32 | |
| %float = OpTypeFloat 32 | |
| %_ptr_Input_float = OpTypePointer Input %float | |
| %void = OpTypeVoid | |
| %27 = OpTypeFunction %void | |
| %_ptr_Function_float = OpTypePointer Function %float | |
| %in_var_COLOR = OpVariable %_ptr_Input_float Input | |
| %13 = OpExtInst %void %1 DebugExpression | |
| %15 = OpExtInst %void %1 DebugSource %5 %14 | |
| %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL | |
| %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float | |
| %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18 | |
| %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main | |
| %12 = OpExtInst %void %1 DebugInfoNone | |
| %25 = OpExtInst %void %1 DebugLocalVariable %24 %18 %15 1 20 %22 FlagIsLocal 0 | |
| %main = OpFunction %void None %27 | |
| %28 = OpLabel | |
| %100 = OpVariable %_ptr_Function_float Function | |
| %31 = OpLoad %float %in_var_COLOR | |
| OpStore %100 %31 | |
| %36 = OpExtInst %void %1 DebugDeclare %25 %100 %13 | |
| %37 = OpExtInst %void %1 DebugDeclare %25 %100 %13 | |
| %38 = OpExtInst %void %1 DebugDeclare %25 %100 %13 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| std::unique_ptr<IRContext> context = | |
| BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, | |
| SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); | |
| auto* dbg_info_mgr = context->get_debug_info_mgr(); | |
| auto* def_use_mgr = context->get_def_use_mgr(); | |
| EXPECT_TRUE(dbg_info_mgr->IsVariableDebugDeclared(100)); | |
| EXPECT_EQ(def_use_mgr->GetDef(36)->GetOpenCL100DebugOpcode(), | |
| OpenCLDebugInfo100DebugDeclare); | |
| EXPECT_EQ(def_use_mgr->GetDef(37)->GetOpenCL100DebugOpcode(), | |
| OpenCLDebugInfo100DebugDeclare); | |
| EXPECT_EQ(def_use_mgr->GetDef(38)->GetOpenCL100DebugOpcode(), | |
| OpenCLDebugInfo100DebugDeclare); | |
| dbg_info_mgr->KillDebugDeclares(100); | |
| EXPECT_EQ(def_use_mgr->GetDef(36), nullptr); | |
| EXPECT_EQ(def_use_mgr->GetDef(37), nullptr); | |
| EXPECT_EQ(def_use_mgr->GetDef(38), nullptr); | |
| EXPECT_FALSE(dbg_info_mgr->IsVariableDebugDeclared(100)); | |
| } | |
| TEST(DebugInfoManager, AddDebugValueForDecl) { | |
| const std::string text = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "OpenCL.DebugInfo.100" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %in_var_COLOR | |
| OpExecutionMode %main OriginUpperLeft | |
| %5 = OpString "ps.hlsl" | |
| %14 = OpString "#line 1 \"ps.hlsl\" | |
| void main(float in_var_color : COLOR) { | |
| float color = in_var_color; | |
| } | |
| " | |
| %17 = OpString "float" | |
| %21 = OpString "main" | |
| %24 = OpString "color" | |
| OpName %in_var_COLOR "in.var.COLOR" | |
| OpName %main "main" | |
| OpDecorate %in_var_COLOR Location 0 | |
| %uint = OpTypeInt 32 0 | |
| %uint_32 = OpConstant %uint 32 | |
| %float = OpTypeFloat 32 | |
| %_ptr_Input_float = OpTypePointer Input %float | |
| %void = OpTypeVoid | |
| %27 = OpTypeFunction %void | |
| %_ptr_Function_float = OpTypePointer Function %float | |
| %in_var_COLOR = OpVariable %_ptr_Input_float Input | |
| %13 = OpExtInst %void %1 DebugExpression | |
| %15 = OpExtInst %void %1 DebugSource %5 %14 | |
| %16 = OpExtInst %void %1 DebugCompilationUnit 1 4 %15 HLSL | |
| %18 = OpExtInst %void %1 DebugTypeBasic %17 %uint_32 Float | |
| %20 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %18 %18 | |
| %22 = OpExtInst %void %1 DebugFunction %21 %20 %15 1 1 %16 %21 FlagIsProtected|FlagIsPrivate 1 %main | |
| %12 = OpExtInst %void %1 DebugInfoNone | |
| %25 = OpExtInst %void %1 DebugLocalVariable %24 %18 %15 1 20 %22 FlagIsLocal 0 | |
| %main = OpFunction %void None %27 | |
| %28 = OpLabel | |
| %100 = OpVariable %_ptr_Function_float Function | |
| %31 = OpLoad %float %in_var_COLOR | |
| %101 = OpExtInst %void %1 DebugScope %22 | |
| OpLine %5 13 7 | |
| OpStore %100 %31 | |
| %36 = OpExtInst %void %1 DebugDeclare %25 %100 %13 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| std::unique_ptr<IRContext> context = | |
| BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, | |
| SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); | |
| auto* def_use_mgr = context->get_def_use_mgr(); | |
| auto* dbg_decl = def_use_mgr->GetDef(36); | |
| EXPECT_EQ(dbg_decl->GetOpenCL100DebugOpcode(), | |
| OpenCLDebugInfo100DebugDeclare); | |
| auto* dbg_info_mgr = context->get_debug_info_mgr(); | |
| Instruction* store = dbg_decl->PreviousNode(); | |
| auto* dbg_value = | |
| dbg_info_mgr->AddDebugValueForDecl(dbg_decl, 100, dbg_decl, store); | |
| EXPECT_EQ(dbg_value->GetOpenCL100DebugOpcode(), OpenCLDebugInfo100DebugValue); | |
| EXPECT_EQ(dbg_value->dbg_line_inst()->GetSingleWordInOperand( | |
| kOpLineInOperandFileIndex), | |
| 5); | |
| EXPECT_EQ(dbg_value->dbg_line_inst()->GetSingleWordInOperand( | |
| kOpLineInOperandLineIndex), | |
| 13); | |
| EXPECT_EQ(dbg_value->dbg_line_inst()->GetSingleWordInOperand( | |
| kOpLineInOperandColumnIndex), | |
| 7); | |
| } | |
| TEST(DebugInfoManager, ConvertGlobalToLocal) { | |
| const std::string text = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %2 "PSMain" %3 | |
| OpExecutionMode %2 OriginUpperLeft | |
| %4 = OpString "C:\\local\\Temp\\2528091a-6811-4e62-9ed5-02f1547c2016.hlsl" | |
| %5 = OpString "float" | |
| %6 = OpString "Pi" | |
| %float = OpTypeFloat 32 | |
| %float_3_1415 = OpConstant %float 3.1415 | |
| %uint = OpTypeInt 32 0 | |
| %uint_32 = OpConstant %uint 32 | |
| %_ptr_Private_float = OpTypePointer Private %float | |
| %_ptr_Function_float = OpTypePointer Function %float | |
| %void = OpTypeVoid | |
| %uint_3 = OpConstant %uint 3 | |
| %uint_0 = OpConstant %uint 0 | |
| %uint_4 = OpConstant %uint 4 | |
| %uint_1 = OpConstant %uint 1 | |
| %uint_5 = OpConstant %uint 5 | |
| %uint_8 = OpConstant %uint 8 | |
| %uint_6 = OpConstant %uint 6 | |
| %uint_20 = OpConstant %uint 20 | |
| %25 = OpTypeFunction %void | |
| %uint_11 = OpConstant %uint 11 | |
| %3 = OpVariable %_ptr_Private_float Private | |
| %8 = OpExtInst %void %1 DebugTypeBasic %5 %uint_32 %uint_3 %uint_0 | |
| %12 = OpExtInst %void %1 DebugSource %4 | |
| %13 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %12 %uint_5 | |
| %17 = OpExtInst %void %1 DebugGlobalVariable %6 %8 %12 %uint_6 %uint_20 %13 %6 %3 %uint_8 | |
| %2 = OpFunction %void None %25 | |
| %27 = OpLabel | |
| %29 = OpVariable %_ptr_Function_float Function | |
| OpStore %3 %float_3_1415 | |
| %28 = OpExtInst %void %1 DebugLine %12 %uint_11 %uint_11 %uint_1 %uint_1 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| std::unique_ptr<IRContext> context = | |
| BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, | |
| SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); | |
| auto* def_use_mgr = context->get_def_use_mgr(); | |
| auto* dbg_var = def_use_mgr->GetDef(17); | |
| EXPECT_EQ(dbg_var->GetCommonDebugOpcode(), | |
| OpenCLDebugInfo100DebugGlobalVariable); | |
| EXPECT_EQ(dbg_var->NumInOperands(), 11); | |
| std::vector<Operand> originalOperands; | |
| for (uint32_t i = 0; i < dbg_var->NumInOperands(); ++i) { | |
| originalOperands.emplace_back(dbg_var->GetInOperand((i))); | |
| } | |
| auto* local_var = def_use_mgr->GetDef(29); | |
| auto* dbg_info_mgr = context->get_debug_info_mgr(); | |
| dbg_info_mgr->ConvertDebugGlobalToLocalVariable(dbg_var, local_var); | |
| EXPECT_EQ(dbg_var->NumInOperands(), 9); | |
| // This checks that the first two inoperands are correct. | |
| EXPECT_EQ(dbg_var->GetCommonDebugOpcode(), | |
| OpenCLDebugInfo100DebugLocalVariable); | |
| // Then next 6 operands should be the same as the original instruction. | |
| EXPECT_EQ(dbg_var->GetInOperand(2), originalOperands[2]); | |
| EXPECT_EQ(dbg_var->GetInOperand(3), originalOperands[3]); | |
| EXPECT_EQ(dbg_var->GetInOperand(4), originalOperands[4]); | |
| EXPECT_EQ(dbg_var->GetInOperand(5), originalOperands[5]); | |
| EXPECT_EQ(dbg_var->GetInOperand(6), originalOperands[6]); | |
| EXPECT_EQ(dbg_var->GetInOperand(7), originalOperands[7]); | |
| // The flags operand should have shifted because operand 8 and 9 in the global | |
| // instruction are not relevant. | |
| EXPECT_EQ(dbg_var->GetInOperand(8), originalOperands[10]); | |
| } | |
| } // namespace | |
| } // namespace analysis | |
| } // namespace opt | |
| } // namespace spvtools |