mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 19:40:10 +01:00
aco,radv: support symbol relocation in aco
Reviewed-by: Rhys Perry <pendingchaos02@gmail.com> Signed-off-by: Qiang Yu <yuq825@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22727>
This commit is contained in:
parent
3fc4ddd628
commit
360176b671
8 changed files with 50 additions and 13 deletions
|
|
@ -46,10 +46,12 @@ struct asm_context {
|
|||
enum amd_gfx_level gfx_level;
|
||||
std::vector<std::pair<int, SOPP_instruction*>> branches;
|
||||
std::map<unsigned, constaddr_info> constaddrs;
|
||||
std::vector<struct aco_symbol>* symbols;
|
||||
const int16_t* opcode;
|
||||
// TODO: keep track of branch instructions referring blocks
|
||||
// and, when emitting the block, correct the offset in instr
|
||||
asm_context(Program* program_) : program(program_), gfx_level(program->gfx_level)
|
||||
asm_context(Program* program_, std::vector<struct aco_symbol>* symbols_)
|
||||
: program(program_), gfx_level(program->gfx_level), symbols(symbols_)
|
||||
{
|
||||
if (gfx_level <= GFX7)
|
||||
opcode = &instr_info.opcode_gfx7[0];
|
||||
|
|
@ -136,6 +138,18 @@ emit_instruction(asm_context& ctx, std::vector<uint32_t>& out, Instruction* inst
|
|||
assert(instr->operands[1].isConstant());
|
||||
/* in case it's an inline constant, make it a literal */
|
||||
instr->operands[1] = Operand::literal32(instr->operands[1].constantValue());
|
||||
} else if (instr->opcode == aco_opcode::p_load_symbol) {
|
||||
assert(instr->operands[0].isConstant());
|
||||
assert(ctx.symbols);
|
||||
|
||||
struct aco_symbol info;
|
||||
info.id = (enum aco_symbol_id)instr->operands[0].constantValue();
|
||||
info.offset = out.size() + 1;
|
||||
ctx.symbols->push_back(info);
|
||||
|
||||
instr->opcode = aco_opcode::s_mov_b32;
|
||||
/* in case it's an inline constant, make it a literal */
|
||||
instr->operands[0] = Operand::literal32(0);
|
||||
}
|
||||
|
||||
/* Promote VOP12C to VOP3 if necessary. */
|
||||
|
|
@ -1036,6 +1050,13 @@ insert_code(asm_context& ctx, std::vector<uint32_t>& out, unsigned insert_before
|
|||
if (info.add_literal >= insert_before)
|
||||
info.add_literal += insert_count;
|
||||
}
|
||||
|
||||
if (ctx.symbols) {
|
||||
for (auto& symbol : *ctx.symbols) {
|
||||
if (symbol.offset >= insert_before)
|
||||
symbol.offset += insert_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1171,9 +1192,10 @@ fix_constaddrs(asm_context& ctx, std::vector<uint32_t>& out)
|
|||
}
|
||||
|
||||
unsigned
|
||||
emit_program(Program* program, std::vector<uint32_t>& code)
|
||||
emit_program(Program* program, std::vector<uint32_t>& code,
|
||||
std::vector<struct aco_symbol>* symbols)
|
||||
{
|
||||
asm_context ctx(program);
|
||||
asm_context ctx(program, symbols);
|
||||
|
||||
if (program->stage.hw == HWStage::VS || program->stage.hw == HWStage::FS ||
|
||||
program->stage.hw == HWStage::NGG)
|
||||
|
|
|
|||
|
|
@ -236,7 +236,8 @@ aco_compile_shader(const struct aco_compiler_options* options,
|
|||
|
||||
/* assembly */
|
||||
std::vector<uint32_t> code;
|
||||
unsigned exec_size = aco::emit_program(program.get(), code);
|
||||
std::vector<struct aco_symbol> symbols;
|
||||
unsigned exec_size = aco::emit_program(program.get(), code, &symbols);
|
||||
|
||||
if (program->collect_statistics)
|
||||
aco::collect_postasm_stats(program.get(), code);
|
||||
|
|
@ -252,7 +253,8 @@ aco_compile_shader(const struct aco_compiler_options* options,
|
|||
stats_size = aco_num_statistics * sizeof(uint32_t);
|
||||
|
||||
(*build_binary)(binary, &config, llvm_ir.c_str(), llvm_ir.size(), disasm.c_str(), disasm.size(),
|
||||
program->statistics, stats_size, exec_size, code.data(), code.size());
|
||||
program->statistics, stats_size, exec_size, code.data(), code.size(),
|
||||
symbols.data(), symbols.size());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -282,7 +284,7 @@ aco_compile_rt_prolog(const struct aco_compiler_options* options,
|
|||
/* assembly */
|
||||
std::vector<uint32_t> code;
|
||||
code.reserve(align(program->blocks[0].instructions.size() * 2, 16));
|
||||
unsigned exec_size = aco::emit_program(program.get(), code);
|
||||
unsigned exec_size = aco::emit_program(program.get(), code, NULL);
|
||||
|
||||
bool get_disasm = options->dump_shader || options->record_ir;
|
||||
|
||||
|
|
@ -291,7 +293,7 @@ aco_compile_rt_prolog(const struct aco_compiler_options* options,
|
|||
disasm = get_disasm_string(program.get(), code, exec_size);
|
||||
|
||||
(*build_prolog)(binary, &config, NULL, 0, disasm.c_str(), disasm.size(), program->statistics, 0,
|
||||
exec_size, code.data(), code.size());
|
||||
exec_size, code.data(), code.size(), NULL, 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -319,7 +321,7 @@ aco_compile_vs_prolog(const struct aco_compiler_options* options,
|
|||
/* assembly */
|
||||
std::vector<uint32_t> code;
|
||||
code.reserve(align(program->blocks[0].instructions.size() * 2, 16));
|
||||
unsigned exec_size = aco::emit_program(program.get(), code);
|
||||
unsigned exec_size = aco::emit_program(program.get(), code, NULL);
|
||||
|
||||
bool get_disasm = options->dump_shader || options->record_ir;
|
||||
|
||||
|
|
@ -361,7 +363,7 @@ aco_compile_ps_epilog(const struct aco_compiler_options* options,
|
|||
|
||||
/* assembly */
|
||||
std::vector<uint32_t> code;
|
||||
unsigned exec_size = aco::emit_program(program.get(), code);
|
||||
unsigned exec_size = aco::emit_program(program.get(), code, NULL);
|
||||
|
||||
bool get_disasm = options->dump_shader || options->record_ir;
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,8 @@ struct aco_compiler_statistic_info {
|
|||
typedef void(aco_callback)(void** priv_ptr, const struct ac_shader_config* config,
|
||||
const char* llvm_ir_str, unsigned llvm_ir_size, const char* disasm_str,
|
||||
unsigned disasm_size, uint32_t* statistics, uint32_t stats_size,
|
||||
uint32_t exec_size, const uint32_t* code, uint32_t code_dw);
|
||||
uint32_t exec_size, const uint32_t* code, uint32_t code_dw,
|
||||
const struct aco_symbol *symbols, unsigned num_symbols);
|
||||
|
||||
typedef void (aco_shader_part_callback)(void **priv_ptr,
|
||||
uint32_t num_sgprs,
|
||||
|
|
|
|||
|
|
@ -2226,7 +2226,8 @@ void insert_wait_states(Program* program);
|
|||
bool dealloc_vgprs(Program* program);
|
||||
void insert_NOPs(Program* program);
|
||||
void form_hard_clauses(Program* program);
|
||||
unsigned emit_program(Program* program, std::vector<uint32_t>& code);
|
||||
unsigned emit_program(Program* program, std::vector<uint32_t>& code,
|
||||
std::vector<struct aco_symbol> *symbols);
|
||||
/**
|
||||
* Returns true if print_asm can disassemble the given program for the current build/runtime
|
||||
* configuration
|
||||
|
|
|
|||
|
|
@ -530,6 +530,7 @@ SOP1 = {
|
|||
( -1, -1, -1, -1, -1, 0x4d, "s_sendmsg_rtn_b64"),
|
||||
# actually a pseudo-instruction. it's lowered to SALU during assembly though, so it's useful to identify it as a SOP1.
|
||||
( -1, -1, -1, -1, -1, -1, "p_constaddr_getpc"),
|
||||
( -1, -1, -1, -1, -1, -1, "p_load_symbol"),
|
||||
}
|
||||
for (gfx6, gfx7, gfx8, gfx9, gfx10, gfx11, name, cls) in default_class(SOP1, InstrClass.Salu):
|
||||
opcode(name, gfx7, gfx9, gfx10, gfx11, Format.SOP1, cls)
|
||||
|
|
|
|||
|
|
@ -160,6 +160,15 @@ enum aco_statistic {
|
|||
aco_num_statistics
|
||||
};
|
||||
|
||||
enum aco_symbol_id {
|
||||
aco_symbol_invalid,
|
||||
};
|
||||
|
||||
struct aco_symbol {
|
||||
enum aco_symbol_id id;
|
||||
unsigned offset;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ void finish_assembler_test()
|
|||
{
|
||||
finish_program(program.get());
|
||||
std::vector<uint32_t> binary;
|
||||
unsigned exec_size = emit_program(program.get(), binary);
|
||||
unsigned exec_size = emit_program(program.get(), binary, NULL);
|
||||
|
||||
/* we could use CLRX for disassembly but that would require it to be
|
||||
* installed */
|
||||
|
|
|
|||
|
|
@ -2070,7 +2070,8 @@ static void
|
|||
radv_aco_build_shader_binary(void **bin, const struct ac_shader_config *config,
|
||||
const char *llvm_ir_str, unsigned llvm_ir_size, const char *disasm_str,
|
||||
unsigned disasm_size, uint32_t *statistics, uint32_t stats_size,
|
||||
uint32_t exec_size, const uint32_t *code, uint32_t code_dw)
|
||||
uint32_t exec_size, const uint32_t *code, uint32_t code_dw,
|
||||
const struct aco_symbol *symbols, unsigned num_symbols)
|
||||
{
|
||||
struct radv_shader_binary **binary = (struct radv_shader_binary **)bin;
|
||||
size_t size = llvm_ir_size;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue