diff --git a/source/opt/constants.cpp b/source/opt/constants.cpp index 19ca6008d..a3dac5d77 100644 --- a/source/opt/constants.cpp +++ b/source/opt/constants.cpp @@ -432,6 +432,12 @@ uint32_t ConstantManager::GetSIntConst(int32_t val) { return GetDefiningInstruction(c)->result_id(); } +uint32_t ConstantManager::GetUIntConst(uint32_t val) { + Type* uint_type = context()->get_type_mgr()->GetUIntType(); + const Constant* c = GetConstant(uint_type, {val}); + return GetDefiningInstruction(c)->result_id(); +} + std::vector Constant::GetVectorComponents( analysis::ConstantManager* const_mgr) const { std::vector components; diff --git a/source/opt/constants.h b/source/opt/constants.h index 95d984fcd..52bd809ab 100644 --- a/source/opt/constants.h +++ b/source/opt/constants.h @@ -642,6 +642,9 @@ class ConstantManager { // Returns the id of a 32-bit signed integer constant with value |val|. uint32_t GetSIntConst(int32_t val); + // Returns the id of a 32-bit unsigned integer constant with value |val|. + uint32_t GetUIntConst(uint32_t val); + private: // Creates a Constant instance with the given type and a vector of constant // defining words. Returns a unique pointer to the created Constant instance diff --git a/source/opt/debug_info_manager.cpp b/source/opt/debug_info_manager.cpp index e782641f2..2e8e13279 100644 --- a/source/opt/debug_info_manager.cpp +++ b/source/opt/debug_info_manager.cpp @@ -18,12 +18,15 @@ #include "source/opt/ir_context.h" -// Constants for OpenCL.DebugInfo.100 extension instructions. +// Constants for OpenCL.DebugInfo.100 & NonSemantic.Vulkan.DebugInfo.100 +// extension instructions. static const uint32_t kOpLineOperandLineIndex = 1; static const uint32_t kLineOperandIndexDebugFunction = 7; static const uint32_t kLineOperandIndexDebugLexicalBlock = 5; static const uint32_t kDebugFunctionOperandFunctionIndex = 13; +static const uint32_t kDebugFunctionDefinitionOperandDebugFunctionIndex = 4; +static const uint32_t kDebugFunctionDefinitionOperandOpFunctionIndex = 5; static const uint32_t kDebugFunctionOperandParentIndex = 9; static const uint32_t kDebugTypeCompositeOperandParentIndex = 9; static const uint32_t kDebugLexicalBlockOperandParentIndex = 7; @@ -46,8 +49,8 @@ namespace { void SetInlinedOperand(Instruction* dbg_inlined_at, uint32_t inlined_operand) { assert(dbg_inlined_at); - assert(dbg_inlined_at->GetOpenCL100DebugOpcode() == - OpenCLDebugInfo100DebugInlinedAt); + assert(dbg_inlined_at->GetCommonDebugOpcode() == + CommonDebugInfoDebugInlinedAt); if (dbg_inlined_at->NumOperands() <= kDebugInlinedAtOperandInlinedIndex) { dbg_inlined_at->AddOperand( {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {inlined_operand}}); @@ -59,8 +62,8 @@ void SetInlinedOperand(Instruction* dbg_inlined_at, uint32_t inlined_operand) { uint32_t GetInlinedOperand(Instruction* dbg_inlined_at) { assert(dbg_inlined_at); - assert(dbg_inlined_at->GetOpenCL100DebugOpcode() == - OpenCLDebugInfo100DebugInlinedAt); + assert(dbg_inlined_at->GetCommonDebugOpcode() == + CommonDebugInfoDebugInlinedAt); if (dbg_inlined_at->NumOperands() <= kDebugInlinedAtOperandInlinedIndex) return kNoInlinedAt; return dbg_inlined_at->GetSingleWordOperand( @@ -68,8 +71,7 @@ uint32_t GetInlinedOperand(Instruction* dbg_inlined_at) { } bool IsEmptyDebugExpression(Instruction* instr) { - return instr->GetOpenCL100DebugOpcode() == - OpenCLDebugInfo100DebugExpression && + return (instr->GetCommonDebugOpcode() == CommonDebugInfoDebugExpression) && instr->NumOperands() == kDebugExpressOperandOperationIndex; } @@ -79,43 +81,63 @@ DebugInfoManager::DebugInfoManager(IRContext* c) : context_(c) { AnalyzeDebugInsts(*c->module()); } +uint32_t DebugInfoManager::GetDbgSetImportId() { + uint32_t setId = + context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo(); + if (setId == 0) { + setId = + context()->get_feature_mgr()->GetExtInstImportId_Vulkan100DebugInfo(); + } + return setId; +} + Instruction* DebugInfoManager::GetDbgInst(uint32_t id) { auto dbg_inst_it = id_to_dbg_inst_.find(id); return dbg_inst_it == id_to_dbg_inst_.end() ? nullptr : dbg_inst_it->second; } void DebugInfoManager::RegisterDbgInst(Instruction* inst) { - assert( - inst->NumInOperands() != 0 && - context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo() == - inst->GetInOperand(0).words[0] && - "Given instruction is not a debug instruction"); + assert(inst->NumInOperands() != 0 && + (GetDbgSetImportId() == inst->GetInOperand(0).words[0]) && + "Given instruction is not a debug instruction"); id_to_dbg_inst_[inst->result_id()] = inst; } void DebugInfoManager::RegisterDbgFunction(Instruction* inst) { - assert(inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugFunction && - "inst is not a DebugFunction"); - auto fn_id = inst->GetSingleWordOperand(kDebugFunctionOperandFunctionIndex); - // Do not register function that has been optimized away - auto fn_inst = GetDbgInst(fn_id); - if (fn_inst != nullptr) { - assert(GetDbgInst(fn_id)->GetOpenCL100DebugOpcode() == - OpenCLDebugInfo100DebugInfoNone); - return; + if (inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugFunction) { + auto fn_id = inst->GetSingleWordOperand(kDebugFunctionOperandFunctionIndex); + // Do not register function that has been optimized away. + auto fn_inst = GetDbgInst(fn_id); + if (fn_inst != nullptr) { + assert(GetDbgInst(fn_id)->GetOpenCL100DebugOpcode() == + OpenCLDebugInfo100DebugInfoNone); + return; + } + assert( + fn_id_to_dbg_fn_.find(fn_id) == fn_id_to_dbg_fn_.end() && + "Register DebugFunction for a function that already has DebugFunction"); + fn_id_to_dbg_fn_[fn_id] = inst; + } else if (inst->GetVulkan100DebugOpcode() == + NonSemanticVulkanDebugInfo100DebugFunctionDefinition) { + auto fn_id = inst->GetSingleWordOperand( + kDebugFunctionDefinitionOperandOpFunctionIndex); + auto fn_inst = GetDbgInst(inst->GetSingleWordOperand( + kDebugFunctionDefinitionOperandDebugFunctionIndex)); + assert(fn_inst && fn_inst->GetVulkan100DebugOpcode() == + NonSemanticVulkanDebugInfo100DebugFunction); + assert(fn_id_to_dbg_fn_.find(fn_id) == fn_id_to_dbg_fn_.end() && + "Register DebugFunctionDefinition for a function that already has " + "DebugFunctionDefinition"); + fn_id_to_dbg_fn_[fn_id] = fn_inst; + } else { + assert(false && "inst is not a DebugFunction"); } - assert( - fn_id_to_dbg_fn_.find(fn_id) == fn_id_to_dbg_fn_.end() && - "Register DebugFunction for a function that already has DebugFunction"); - fn_id_to_dbg_fn_[fn_id] = inst; } void DebugInfoManager::RegisterDbgDeclare(uint32_t var_id, Instruction* dbg_declare) { - assert(dbg_declare->GetOpenCL100DebugOpcode() == - OpenCLDebugInfo100DebugDeclare || - dbg_declare->GetOpenCL100DebugOpcode() == - OpenCLDebugInfo100DebugValue); + assert(dbg_declare->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare || + dbg_declare->GetCommonDebugOpcode() == CommonDebugInfoDebugValue); auto dbg_decl_itr = var_id_to_dbg_decl_.find(var_id); if (dbg_decl_itr == var_id_to_dbg_decl_.end()) { var_id_to_dbg_decl_[var_id] = {dbg_declare}; @@ -126,27 +148,36 @@ void DebugInfoManager::RegisterDbgDeclare(uint32_t var_id, uint32_t DebugInfoManager::CreateDebugInlinedAt(const Instruction* line, const DebugScope& scope) { - if (context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo() == - 0) - return kNoInlinedAt; + uint32_t setId = GetDbgSetImportId(); + + if (setId == 0) return kNoInlinedAt; + + spv_operand_type_t line_number_type = + spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER; + + // In NonSemantic.Vulkan.DebugInfo.100, all constants are IDs of OpConstant, + // not literals. + if (setId == + context()->get_feature_mgr()->GetExtInstImportId_Vulkan100DebugInfo()) + line_number_type = spv_operand_type_t::SPV_OPERAND_TYPE_ID; uint32_t line_number = 0; if (line == nullptr) { auto* lexical_scope_inst = GetDbgInst(scope.GetLexicalScope()); if (lexical_scope_inst == nullptr) return kNoInlinedAt; - OpenCLDebugInfo100Instructions debug_opcode = - lexical_scope_inst->GetOpenCL100DebugOpcode(); + CommonDebugInfoInstructions debug_opcode = + lexical_scope_inst->GetCommonDebugOpcode(); switch (debug_opcode) { - case OpenCLDebugInfo100DebugFunction: + case CommonDebugInfoDebugFunction: line_number = lexical_scope_inst->GetSingleWordOperand( kLineOperandIndexDebugFunction); break; - case OpenCLDebugInfo100DebugLexicalBlock: + case CommonDebugInfoDebugLexicalBlock: line_number = lexical_scope_inst->GetSingleWordOperand( kLineOperandIndexDebugLexicalBlock); break; - case OpenCLDebugInfo100DebugTypeComposite: - case OpenCLDebugInfo100DebugCompilationUnit: + case CommonDebugInfoDebugTypeComposite: + case CommonDebugInfoDebugCompilationUnit: assert(false && "DebugTypeComposite and DebugCompilationUnit are lexical " "scopes, but we inline functions into a function or a block " @@ -161,6 +192,13 @@ uint32_t DebugInfoManager::CreateDebugInlinedAt(const Instruction* line, } } else { line_number = line->GetSingleWordOperand(kOpLineOperandLineIndex); + + // If we need the line number as an ID, generate that constant now. + 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; + } } uint32_t result_id = context()->TakeNextId(); @@ -168,13 +206,10 @@ uint32_t DebugInfoManager::CreateDebugInlinedAt(const Instruction* line, context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(), result_id, { - {spv_operand_type_t::SPV_OPERAND_TYPE_ID, - {context() - ->get_feature_mgr() - ->GetExtInstImportId_OpenCL100DebugInfo()}}, + {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {setId}}, {spv_operand_type_t::SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER, - {static_cast(OpenCLDebugInfo100DebugInlinedAt)}}, - {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {line_number}}, + {static_cast(CommonDebugInfoDebugInlinedAt)}}, + {line_number_type, {line_number}}, {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {scope.GetLexicalScope()}}, })); // |scope| already has DebugInlinedAt. We put the existing DebugInlinedAt @@ -257,19 +292,34 @@ Instruction* DebugInfoManager::GetDebugOperationWithDeref() { if (deref_operation_ != nullptr) return deref_operation_; uint32_t result_id = context()->TakeNextId(); - std::unique_ptr deref_operation(new Instruction( - context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(), - result_id, - { - {SPV_OPERAND_TYPE_ID, - {context() - ->get_feature_mgr() - ->GetExtInstImportId_OpenCL100DebugInfo()}}, - {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER, - {static_cast(OpenCLDebugInfo100DebugOperation)}}, - {SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION, - {static_cast(OpenCLDebugInfo100Deref)}}, - })); + std::unique_ptr deref_operation; + + if (context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo()) { + deref_operation = std::unique_ptr(new Instruction( + context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(), + result_id, + { + {SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}}, + {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER, + {static_cast(OpenCLDebugInfo100DebugOperation)}}, + {SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION, + {static_cast(OpenCLDebugInfo100Deref)}}, + })); + } else { + uint32_t deref_id = context()->get_constant_mgr()->GetUIntConst( + NonSemanticVulkanDebugInfo100Deref); + + deref_operation = std::unique_ptr( + new Instruction(context(), SpvOpExtInst, + context()->get_type_mgr()->GetVoidTypeId(), result_id, + { + {SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}}, + {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER, + {static_cast( + NonSemanticVulkanDebugInfo100DebugOperation)}}, + {SPV_OPERAND_TYPE_ID, {deref_id}}, + })); + } // Add to the front of |ext_inst_debuginfo_|. deref_operation_ = @@ -283,8 +333,7 @@ Instruction* DebugInfoManager::GetDebugOperationWithDeref() { } Instruction* DebugInfoManager::DerefDebugExpression(Instruction* dbg_expr) { - assert(dbg_expr->GetOpenCL100DebugOpcode() == - OpenCLDebugInfo100DebugExpression); + assert(dbg_expr->GetCommonDebugOpcode() == CommonDebugInfoDebugExpression); std::unique_ptr deref_expr(dbg_expr->Clone(context())); deref_expr->SetResultId(context()->TakeNextId()); deref_expr->InsertOperand( @@ -306,12 +355,9 @@ Instruction* DebugInfoManager::GetDebugInfoNone() { context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(), result_id, { - {spv_operand_type_t::SPV_OPERAND_TYPE_ID, - {context() - ->get_feature_mgr() - ->GetExtInstImportId_OpenCL100DebugInfo()}}, + {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}}, {spv_operand_type_t::SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER, - {static_cast(OpenCLDebugInfo100DebugInfoNone)}}, + {static_cast(CommonDebugInfoDebugInfoNone)}}, })); // Add to the front of |ext_inst_debuginfo_|. @@ -333,12 +379,9 @@ Instruction* DebugInfoManager::GetEmptyDebugExpression() { context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(), result_id, { - {spv_operand_type_t::SPV_OPERAND_TYPE_ID, - {context() - ->get_feature_mgr() - ->GetExtInstImportId_OpenCL100DebugInfo()}}, + {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}}, {spv_operand_type_t::SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER, - {static_cast(OpenCLDebugInfo100DebugExpression)}}, + {static_cast(CommonDebugInfoDebugExpression)}}, })); // Add to the front of |ext_inst_debuginfo_|. @@ -355,8 +398,7 @@ Instruction* DebugInfoManager::GetEmptyDebugExpression() { Instruction* DebugInfoManager::GetDebugInlinedAt(uint32_t dbg_inlined_at_id) { auto* inlined_at = GetDbgInst(dbg_inlined_at_id); if (inlined_at == nullptr) return nullptr; - if (inlined_at->GetOpenCL100DebugOpcode() != - OpenCLDebugInfo100DebugInlinedAt) { + if (inlined_at->GetCommonDebugOpcode() != CommonDebugInfoDebugInlinedAt) { return nullptr; } return inlined_at; @@ -403,23 +445,23 @@ bool DebugInfoManager::KillDebugDeclares(uint32_t variable_id) { uint32_t DebugInfoManager::GetParentScope(uint32_t child_scope) { auto dbg_scope_itr = id_to_dbg_inst_.find(child_scope); assert(dbg_scope_itr != id_to_dbg_inst_.end()); - OpenCLDebugInfo100Instructions debug_opcode = - dbg_scope_itr->second->GetOpenCL100DebugOpcode(); + CommonDebugInfoInstructions debug_opcode = + dbg_scope_itr->second->GetCommonDebugOpcode(); uint32_t parent_scope = kNoDebugScope; switch (debug_opcode) { - case OpenCLDebugInfo100DebugFunction: + case CommonDebugInfoDebugFunction: parent_scope = dbg_scope_itr->second->GetSingleWordOperand( kDebugFunctionOperandParentIndex); break; - case OpenCLDebugInfo100DebugLexicalBlock: + case CommonDebugInfoDebugLexicalBlock: parent_scope = dbg_scope_itr->second->GetSingleWordOperand( kDebugLexicalBlockOperandParentIndex); break; - case OpenCLDebugInfo100DebugTypeComposite: + case CommonDebugInfoDebugTypeComposite: parent_scope = dbg_scope_itr->second->GetSingleWordOperand( kDebugTypeCompositeOperandParentIndex); break; - case OpenCLDebugInfo100DebugCompilationUnit: + case CommonDebugInfoDebugCompilationUnit: // DebugCompilationUnit does not have a parent scope. break; default: @@ -513,8 +555,7 @@ Instruction* DebugInfoManager::AddDebugValueForDecl( std::unique_ptr dbg_val(dbg_decl->Clone(context())); dbg_val->SetResultId(context()->TakeNextId()); - dbg_val->SetInOperand(kExtInstInstructionInIdx, - {OpenCLDebugInfo100DebugValue}); + dbg_val->SetInOperand(kExtInstInstructionInIdx, {CommonDebugInfoDebugValue}); dbg_val->SetOperand(kDebugDeclareOperandVariableIndex, {value_id}); dbg_val->SetOperand(kDebugValueOperandExpressionIndex, {GetEmptyDebugExpression()->result_id()}); @@ -532,9 +573,20 @@ Instruction* DebugInfoManager::AddDebugValueForDecl( return added_dbg_val; } +uint32_t DebugInfoManager::GetVulkanDebugOperation(Instruction* inst) { + assert(inst->GetVulkan100DebugOpcode() == + NonSemanticVulkanDebugInfo100DebugOperation && + "inst must be Vulkan DebugOperation"); + return context() + ->get_constant_mgr() + ->GetConstantFromInst(context()->get_def_use_mgr()->GetDef( + inst->GetSingleWordOperand(kDebugOperationOperandOperationIndex))) + ->GetU32(); +} + uint32_t DebugInfoManager::GetVariableIdOfDebugValueUsedForDeclare( Instruction* inst) { - if (inst->GetOpenCL100DebugOpcode() != OpenCLDebugInfo100DebugValue) return 0; + if (inst->GetCommonDebugOpcode() != CommonDebugInfoDebugValue) return 0; auto* expr = GetDbgInst(inst->GetSingleWordOperand(kDebugValueOperandExpressionIndex)); @@ -544,9 +596,19 @@ uint32_t DebugInfoManager::GetVariableIdOfDebugValueUsedForDeclare( auto* operation = GetDbgInst( expr->GetSingleWordOperand(kDebugExpressOperandOperationIndex)); if (operation == nullptr) return 0; - if (operation->GetSingleWordOperand(kDebugOperationOperandOperationIndex) != - OpenCLDebugInfo100Deref) { - return 0; + + // OpenCL.DebugInfo.100 contains a literal for the operation, Vulkan uses an + // OpConstant. + if (inst->IsOpenCL100DebugInstr()) { + if (operation->GetSingleWordOperand(kDebugOperationOperandOperationIndex) != + OpenCLDebugInfo100Deref) { + return 0; + } + } else { + uint32_t operation_const = GetVulkanDebugOperation(operation); + if (operation_const != NonSemanticVulkanDebugInfo100Deref) { + return 0; + } } uint32_t var_id = @@ -567,8 +629,8 @@ uint32_t DebugInfoManager::GetVariableIdOfDebugValueUsedForDeclare( } bool DebugInfoManager::IsDebugDeclare(Instruction* instr) { - if (!instr->IsOpenCL100DebugInstr()) return false; - return instr->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugDeclare || + if (!instr->IsCommonDebugInstr()) return false; + return instr->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare || GetVariableIdOfDebugValueUsedForDeclare(instr) != 0; } @@ -615,14 +677,13 @@ void DebugInfoManager::AnalyzeDebugInst(Instruction* inst) { users.insert(inst); } - if (!inst->IsOpenCL100DebugInstr()) return; + if (!inst->IsCommonDebugInstr()) return; RegisterDbgInst(inst); - if (inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugFunction) { - assert(GetDebugFunction(inst->GetSingleWordOperand( - kDebugFunctionOperandFunctionIndex)) == nullptr && - "Two DebugFunction instruction exists for a single OpFunction."); + if (inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugFunction || + inst->GetVulkan100DebugOpcode() == + NonSemanticVulkanDebugInfo100DebugFunctionDefinition) { RegisterDbgFunction(inst); } @@ -633,8 +694,17 @@ void DebugInfoManager::AnalyzeDebugInst(Instruction* inst) { deref_operation_ = inst; } + if (deref_operation_ == nullptr && + inst->GetVulkan100DebugOpcode() == + NonSemanticVulkanDebugInfo100DebugOperation) { + uint32_t operation_const = GetVulkanDebugOperation(inst); + if (operation_const == NonSemanticVulkanDebugInfo100Deref) { + deref_operation_ = inst; + } + } + if (debug_info_none_inst_ == nullptr && - inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugInfoNone) { + inst->GetCommonDebugOpcode() == CommonDebugInfoDebugInfoNone) { debug_info_none_inst_ = inst; } @@ -642,7 +712,7 @@ void DebugInfoManager::AnalyzeDebugInst(Instruction* inst) { empty_debug_expr_inst_ = inst; } - if (inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugDeclare) { + if (inst->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare) { uint32_t var_id = inst->GetSingleWordOperand(kDebugDeclareOperandVariableIndex); RegisterDbgDeclare(var_id, inst); @@ -655,8 +725,8 @@ void DebugInfoManager::AnalyzeDebugInst(Instruction* inst) { void DebugInfoManager::ConvertDebugGlobalToLocalVariable( Instruction* dbg_global_var, Instruction* local_var) { - if (dbg_global_var->GetOpenCL100DebugOpcode() != - OpenCLDebugInfo100DebugGlobalVariable) { + if (dbg_global_var->GetCommonDebugOpcode() != + CommonDebugInfoDebugGlobalVariable) { return; } assert(local_var->opcode() == SpvOpVariable || @@ -664,7 +734,7 @@ void DebugInfoManager::ConvertDebugGlobalToLocalVariable( // Convert |dbg_global_var| to DebugLocalVariable dbg_global_var->SetInOperand(kExtInstInstructionInIdx, - {OpenCLDebugInfo100DebugLocalVariable}); + {CommonDebugInfoDebugLocalVariable}); auto flags = dbg_global_var->GetSingleWordOperand( kDebugGlobalVariableOperandFlagsIndex); for (uint32_t i = dbg_global_var->NumInOperands() - 1; @@ -680,12 +750,9 @@ void DebugInfoManager::ConvertDebugGlobalToLocalVariable( context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(), context()->TakeNextId(), { - {spv_operand_type_t::SPV_OPERAND_TYPE_ID, - {context() - ->get_feature_mgr() - ->GetExtInstImportId_OpenCL100DebugInfo()}}, + {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}}, {spv_operand_type_t::SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER, - {static_cast(OpenCLDebugInfo100DebugDeclare)}}, + {static_cast(CommonDebugInfoDebugDeclare)}}, {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {dbg_global_var->result_id()}}, {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {local_var->result_id()}}, @@ -713,7 +780,7 @@ void DebugInfoManager::AnalyzeDebugInsts(Module& module) { // list. if (empty_debug_expr_inst_ != nullptr && empty_debug_expr_inst_->PreviousNode() != nullptr && - empty_debug_expr_inst_->PreviousNode()->IsOpenCL100DebugInstr()) { + empty_debug_expr_inst_->PreviousNode()->IsCommonDebugInstr()) { empty_debug_expr_inst_->InsertBefore( &*context()->module()->ext_inst_debuginfo_begin()); } @@ -722,7 +789,7 @@ void DebugInfoManager::AnalyzeDebugInsts(Module& module) { // list. if (debug_info_none_inst_ != nullptr && debug_info_none_inst_->PreviousNode() != nullptr && - debug_info_none_inst_->PreviousNode()->IsOpenCL100DebugInstr()) { + debug_info_none_inst_->PreviousNode()->IsCommonDebugInstr()) { debug_info_none_inst_->InsertBefore( &*context()->module()->ext_inst_debuginfo_begin()); } @@ -740,7 +807,7 @@ void DebugInfoManager::ClearDebugInfo(Instruction* instr) { inlinedat_id_to_users_itr->second.erase(instr); } - if (instr == nullptr || !instr->IsOpenCL100DebugInstr()) { + if (instr == nullptr || !instr->IsCommonDebugInstr()) { return; } @@ -751,9 +818,15 @@ void DebugInfoManager::ClearDebugInfo(Instruction* instr) { instr->GetSingleWordOperand(kDebugFunctionOperandFunctionIndex); fn_id_to_dbg_fn_.erase(fn_id); } + if (instr->GetVulkan100DebugOpcode() == + NonSemanticVulkanDebugInfo100DebugFunction) { + auto fn_id = instr->GetSingleWordOperand( + kDebugFunctionDefinitionOperandOpFunctionIndex); + fn_id_to_dbg_fn_.erase(fn_id); + } - if (instr->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugDeclare || - instr->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugValue) { + if (instr->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare || + instr->GetCommonDebugOpcode() == CommonDebugInfoDebugValue) { auto var_or_value_id = instr->GetSingleWordOperand(kDebugDeclareOperandVariableIndex); auto dbg_decl_itr = var_id_to_dbg_decl_.find(var_or_value_id); @@ -767,6 +840,8 @@ void DebugInfoManager::ClearDebugInfo(Instruction* instr) { for (auto dbg_instr_itr = context()->module()->ext_inst_debuginfo_begin(); dbg_instr_itr != context()->module()->ext_inst_debuginfo_end(); ++dbg_instr_itr) { + // OpenCL.DebugInfo.100 contains the operation as a literal operand, in + // Vulkan it's referenced as an OpConstant. if (instr != &*dbg_instr_itr && dbg_instr_itr->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugOperation && @@ -775,6 +850,15 @@ void DebugInfoManager::ClearDebugInfo(Instruction* instr) { OpenCLDebugInfo100Deref) { deref_operation_ = &*dbg_instr_itr; break; + } else if (instr != &*dbg_instr_itr && + dbg_instr_itr->GetVulkan100DebugOpcode() == + NonSemanticVulkanDebugInfo100DebugOperation) { + uint32_t operation_const = GetVulkanDebugOperation(&*dbg_instr_itr); + + if (operation_const == NonSemanticVulkanDebugInfo100Deref) { + deref_operation_ = &*dbg_instr_itr; + break; + } } } } @@ -784,9 +868,8 @@ void DebugInfoManager::ClearDebugInfo(Instruction* instr) { for (auto dbg_instr_itr = context()->module()->ext_inst_debuginfo_begin(); dbg_instr_itr != context()->module()->ext_inst_debuginfo_end(); ++dbg_instr_itr) { - if (instr != &*dbg_instr_itr && - dbg_instr_itr->GetOpenCL100DebugOpcode() == - OpenCLDebugInfo100DebugInfoNone) { + if (instr != &*dbg_instr_itr && dbg_instr_itr->GetCommonDebugOpcode() == + CommonDebugInfoDebugInfoNone) { debug_info_none_inst_ = &*dbg_instr_itr; break; } diff --git a/source/opt/debug_info_manager.h b/source/opt/debug_info_manager.h index 776e9baab..679ae138e 100644 --- a/source/opt/debug_info_manager.h +++ b/source/opt/debug_info_manager.h @@ -67,8 +67,8 @@ class DebugInlinedAtContext { std::unordered_map callee_inlined_at2chain_; }; -// A class for analyzing, managing, and creating OpenCL.DebugInfo.100 extension -// instructions. +// A class for analyzing, managing, and creating OpenCL.DebugInfo.100 and +// NonSemantic.Vulkan.DebugInfo.100 extension instructions. class DebugInfoManager { public: // Constructs a debug information manager from the given |context|. @@ -85,7 +85,7 @@ class DebugInfoManager { return !(lhs == rhs); } - // Analyzes OpenCL.DebugInfo.100 instruction |dbg_inst|. + // Analyzes DebugInfo instruction |dbg_inst|. void AnalyzeDebugInst(Instruction* dbg_inst); // Creates new DebugInlinedAt and returns its id. Its line operand is the @@ -164,6 +164,9 @@ class DebugInfoManager { // Erases |instr| from data structures of this class. void ClearDebugInfo(Instruction* instr); + // Return the opcode for the Vulkan DebugOperation inst + uint32_t GetVulkanDebugOperation(Instruction* inst); + // Returns the id of Value operand if |inst| is DebugValue who has Deref // operation and its Value operand is a result id of OpVariable with // Function storage class. Otherwise, returns 0. @@ -190,10 +193,13 @@ class DebugInfoManager { private: IRContext* context() { return context_; } - // Analyzes OpenCL.DebugInfo.100 instructions in the given |module| and + // Analyzes DebugInfo instructions in the given |module| and // populates data structures in this class. void AnalyzeDebugInsts(Module& module); + // Get the DebugInfo ExtInstImport Id, or 0 if no DebugInfo is available. + uint32_t GetDbgSetImportId(); + // Returns the debug instruction whose id is |id|. Returns |nullptr| if one // does not exists. Instruction* GetDbgInst(uint32_t id); @@ -230,7 +236,7 @@ class DebugInfoManager { IRContext* context_; - // Mapping from ids of OpenCL.DebugInfo.100 extension instructions + // Mapping from ids of DebugInfo extension instructions. // to their Instruction instances. std::unordered_map id_to_dbg_inst_;