mirror of
https://github.com/RPCSX/SPIRV-Tools.git
synced 2024-12-03 17:01:06 +00:00
Generate constants directly in CreateDebugInlinedAt (#4572)
Do this if Constant or DefUse managers are invalid. Using the ConstantManager attempts to regenerate the DefUseManager which is not valid during inlining.
This commit is contained in:
parent
7a7a69037e
commit
001604bd4a
@ -146,6 +146,25 @@ void DebugInfoManager::RegisterDbgDeclare(uint32_t var_id,
|
||||
}
|
||||
}
|
||||
|
||||
// Create new constant directly into global value area, bypassing the
|
||||
// Constant manager. This is used when the DefUse or Constant managers
|
||||
// are invalid and cannot be regenerated due to the module being in an
|
||||
// inconsistant state e.g. in the middle of significant modification
|
||||
// such as inlining. Invalidate Constant and DefUse managers if used.
|
||||
uint32_t AddNewConstInGlobals(IRContext* context, uint32_t const_value) {
|
||||
uint32_t id = context->TakeNextId();
|
||||
std::unique_ptr<Instruction> new_const(new Instruction(
|
||||
context, SpvOpConstant, context->get_type_mgr()->GetUIntTypeId(), id,
|
||||
{
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
|
||||
{const_value}},
|
||||
}));
|
||||
context->module()->AddGlobalValue(std::move(new_const));
|
||||
context->InvalidateAnalyses(IRContext::kAnalysisConstants);
|
||||
context->InvalidateAnalyses(IRContext::kAnalysisDefUse);
|
||||
return id;
|
||||
}
|
||||
|
||||
uint32_t DebugInfoManager::CreateDebugInlinedAt(const Instruction* line,
|
||||
const DebugScope& scope) {
|
||||
uint32_t setId = GetDbgSetImportId();
|
||||
@ -194,10 +213,18 @@ uint32_t DebugInfoManager::CreateDebugInlinedAt(const Instruction* line,
|
||||
line_number = line->GetSingleWordOperand(kOpLineOperandLineIndex);
|
||||
|
||||
// If we need the line number as an ID, generate that constant now.
|
||||
// If Constant or DefUse managers are invalid, generate constant
|
||||
// directly into the global value section of the module; do not
|
||||
// use Constant manager which may attempt to invoke building of the
|
||||
// DefUse manager which cannot be done during inlining. The extra
|
||||
// constants that may be generated here is likely not significant
|
||||
// and will likely be cleaned up in later passes.
|
||||
if (line_number_type == spv_operand_type_t::SPV_OPERAND_TYPE_ID) {
|
||||
uint32_t line_id =
|
||||
context()->get_constant_mgr()->GetUIntConst(line_number);
|
||||
line_number = line_id;
|
||||
if (!context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse) ||
|
||||
!context()->AreAnalysesValid(IRContext::Analysis::kAnalysisConstants))
|
||||
line_number = AddNewConstInGlobals(context(), line_number);
|
||||
else
|
||||
line_number = context()->get_constant_mgr()->GetUIntConst(line_number);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,6 +185,122 @@ void main(float in_var_color : COLOR) {
|
||||
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(), SpvOpLine);
|
||||
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
|
||||
|
@ -4236,6 +4236,105 @@ OpFunctionEnd
|
||||
SinglePassRunAndMatch<InlineExhaustivePass>(text, true);
|
||||
}
|
||||
|
||||
TEST_F(InlineTest, CreateConstantForInlinedAt) {
|
||||
// This shader causes CreateDebugInlinedAt to generate a constant.
|
||||
// Using the Constant manager would attempt to build the invalidated
|
||||
// DefUse manager during inlining which could cause an assert because
|
||||
// the function is in an inconsistant state. This test verifies that
|
||||
// CreateDebugInlinedAt detects that the DefUse manager is disabled
|
||||
// and creates a duplicate constant safely without the Constant manager.
|
||||
//
|
||||
// int function1() {
|
||||
// return 1;
|
||||
// }
|
||||
//
|
||||
// void main() {
|
||||
// function1();
|
||||
// }
|
||||
|
||||
const std::string text = R"(OpCapability Shader
|
||||
; CHECK: %uint_7 = OpConstant %uint 7
|
||||
; CHECK: %uint_7_0 = OpConstant %uint 7
|
||||
; CHECK: OpExtInst %void %1 DebugInlinedAt %uint_7_0
|
||||
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
|
||||
%uint_7 = 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
|
||||
)";
|
||||
|
||||
SetTargetEnv(SPV_ENV_VULKAN_1_2);
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndMatch<InlineExhaustivePass>(text, true);
|
||||
}
|
||||
|
||||
// TODO(greg-lunarg): Add tests to verify handling of these cases:
|
||||
//
|
||||
// Empty modules
|
||||
|
Loading…
Reference in New Issue
Block a user