diff --git a/src/amd/compiler/aco_assembler.cpp b/src/amd/compiler/aco_assembler.cpp index 9f50c3f5982..7256687198f 100644 --- a/src/amd/compiler/aco_assembler.cpp +++ b/src/amd/compiler/aco_assembler.cpp @@ -1216,6 +1216,11 @@ emit_instruction(asm_context& ctx, std::vector& out, Instruction* inst instr->opcode = aco_opcode::s_mov_b32; /* in case it's an inline constant, make it a literal */ instr->operands[0] = Operand::literal32(0); + } else if (instr->opcode == aco_opcode::p_debug_info) { + assert(instr->operands[0].isConstant()); + uint32_t index = instr->operands[0].constantValue(); + ctx.program->debug_info[index].offset = (out.size() - 1) * 4; + return; } /* Promote VOP12C to VOP3 if necessary. */ diff --git a/src/amd/compiler/aco_instruction_selection.cpp b/src/amd/compiler/aco_instruction_selection.cpp index 79e41ad0632..03dbb4b266f 100644 --- a/src/amd/compiler/aco_instruction_selection.cpp +++ b/src/amd/compiler/aco_instruction_selection.cpp @@ -10539,6 +10539,30 @@ visit_jump(isel_context* ctx, nir_jump_instr* instr) } } +void +visit_debug_info(isel_context* ctx, nir_debug_info_instr* instr) +{ + ac_shader_debug_info info; + memset(&info, 0, sizeof(info)); + + switch (instr->type) { + case nir_debug_info_src_loc: + info.type = ac_shader_debug_info_src_loc; + info.src_loc.file = strdup(nir_src_as_string(instr->src_loc.filename)); + info.src_loc.line = instr->src_loc.line; + info.src_loc.column = instr->src_loc.column; + info.src_loc.spirv_offset = instr->src_loc.spirv_offset; + break; + default: + return; + } + + Builder bld(ctx->program, ctx->block); + bld.pseudo(aco_opcode::p_debug_info, Operand::c32(ctx->program->debug_info.size())); + + ctx->program->debug_info.push_back(info); +} + void visit_block(isel_context* ctx, nir_block* block) { @@ -10562,6 +10586,7 @@ visit_block(isel_context* ctx, nir_block* block) case nir_instr_type_undef: visit_undef(ctx, nir_instr_as_undef(instr)); break; case nir_instr_type_deref: break; case nir_instr_type_jump: visit_jump(ctx, nir_instr_as_jump(instr)); break; + case nir_instr_type_debug_info: visit_debug_info(ctx, nir_instr_as_debug_info(instr)); break; default: isel_err(instr, "Unknown NIR instr type"); } } diff --git a/src/amd/compiler/aco_ir.h b/src/amd/compiler/aco_ir.h index a0fbbf6672d..b5a26489b33 100644 --- a/src/amd/compiler/aco_ir.h +++ b/src/amd/compiler/aco_ir.h @@ -15,6 +15,7 @@ #include "ac_binary.h" #include "ac_hw_stage.h" +#include "ac_shader_debug_info.h" #include "ac_shader_util.h" #include "amd_family.h" #include @@ -2131,6 +2132,8 @@ public: bool is_prolog = false; bool is_epilog = false; + std::vector debug_info; + std::vector constant_data; Temp private_segment_buffer; Temp scratch_offset; diff --git a/src/amd/compiler/aco_lower_to_hw_instr.cpp b/src/amd/compiler/aco_lower_to_hw_instr.cpp index 93bc4450118..6562d9e25d0 100644 --- a/src/amd/compiler/aco_lower_to_hw_instr.cpp +++ b/src/amd/compiler/aco_lower_to_hw_instr.cpp @@ -2246,7 +2246,8 @@ lower_to_hw_instr(Program* program) } aco_ptr mov; - if (instr->isPseudo() && instr->opcode != aco_opcode::p_unit_test) { + if (instr->isPseudo() && instr->opcode != aco_opcode::p_unit_test && + instr->opcode != aco_opcode::p_debug_info) { Pseudo_instruction* pi = &instr->pseudo(); switch (instr->opcode) { @@ -2908,7 +2909,7 @@ lower_to_hw_instr(Program* program) inst->isLDSDIR()) { // TODO: GFX6-9 can use vskip can_remove = prefer_remove; - } else { + } else if (inst->opcode != aco_opcode::p_debug_info) { can_remove = false; assert(false && "Pseudo instructions should be lowered by this point."); } diff --git a/src/amd/compiler/aco_opcodes.py b/src/amd/compiler/aco_opcodes.py index 6e37ee6fad6..41a23748a86 100644 --- a/src/amd/compiler/aco_opcodes.py +++ b/src/amd/compiler/aco_opcodes.py @@ -439,6 +439,8 @@ insn("p_end_with_regs") insn("p_shader_cycles_hi_lo_hi") +insn("p_debug_info") + # SOP2 instructions: 2 scalar inputs, 1 scalar output (+optional scc) SOP2 = { ("s_add_u32", dst(1, SCC), src(1, 1), op(0x00)), diff --git a/src/amd/compiler/aco_print_ir.cpp b/src/amd/compiler/aco_print_ir.cpp index 9aeaac5b1e2..c2aad045b46 100644 --- a/src/amd/compiler/aco_print_ir.cpp +++ b/src/amd/compiler/aco_print_ir.cpp @@ -899,6 +899,24 @@ print_stage(Stage stage, FILE* output) fprintf(output, ")\n"); } +void +print_debug_info(const Program* program, const Instruction* instr, FILE* output) +{ + fprintf(output, "// "); + + assert(instr->operands[0].isConstant()); + const auto& info = program->debug_info[instr->operands[0].constantValue()]; + switch (info.type) { + case ac_shader_debug_info_src_loc: + if (info.src_loc.spirv_offset) + fprintf(output, "0x%x ", info.src_loc.spirv_offset); + fprintf(output, "%s:%u:%u", info.src_loc.file, info.src_loc.line, info.src_loc.column); + break; + } + + fprintf(output, "\n"); +} + void aco_print_block(enum amd_gfx_level gfx_level, const Block* block, FILE* output, unsigned flags, const Program* program) @@ -926,6 +944,10 @@ aco_print_block(enum amd_gfx_level gfx_level, const Block* block, FILE* output, for (auto const& instr : block->instructions) { fprintf(output, "\t"); + if (instr->opcode == aco_opcode::p_debug_info) { + print_debug_info(program, instr.get(), output); + continue; + } if (flags & print_live_vars) { RegisterDemand demand = instr->register_demand; fprintf(output, "(%3u vgpr, %3u sgpr) ", demand.vgpr, demand.sgpr);