mirror of
https://github.com/open-goal/jak-project.git
synced 2024-11-23 06:09:57 +00:00
[compiler] asm-only disasm output + fix spacing bug (#3104)
This commit is contained in:
parent
7c74b0c999
commit
09536c68ac
@ -17,6 +17,14 @@
|
||||
)
|
||||
)
|
||||
|
||||
(defmacro mda (file &rest path)
|
||||
"Make Debug Asm Only: make + print disassembly (asm-only mode) for a file"
|
||||
(if (null? path)
|
||||
`(asm-file ,file :color :write :disassemble :disasm-code-only)
|
||||
`(asm-file ,file :color :write :disassemble :disasm-code-only ,(first path))
|
||||
)
|
||||
)
|
||||
|
||||
(defmacro ml (file)
|
||||
"Make Load: make and load the file through the listener"
|
||||
`(asm-file ,file :color :load :write)
|
||||
|
@ -324,13 +324,14 @@ std::vector<u8> Compiler::codegen_object_file(FileEnv* env) {
|
||||
|
||||
bool Compiler::codegen_and_disassemble_object_file(FileEnv* env,
|
||||
std::vector<u8>* data_out,
|
||||
std::string* asm_out) {
|
||||
std::string* asm_out,
|
||||
bool omit_ir) {
|
||||
auto debug_info = &m_debugger.get_debug_info_for_object(env->name());
|
||||
debug_info->clear();
|
||||
CodeGenerator gen(env, debug_info, m_version);
|
||||
*data_out = gen.run(&m_ts);
|
||||
bool ok = true;
|
||||
*asm_out = debug_info->disassemble_all_functions(&ok, &m_goos.reader);
|
||||
*asm_out = debug_info->disassemble_all_functions(&ok, &m_goos.reader, omit_ir);
|
||||
return ok;
|
||||
}
|
||||
|
||||
@ -482,7 +483,7 @@ void Compiler::asm_file(const CompilationOptions& options) {
|
||||
std::vector<u8> data;
|
||||
std::string disasm;
|
||||
if (options.disassemble) {
|
||||
codegen_and_disassemble_object_file(obj_file, &data, &disasm);
|
||||
codegen_and_disassemble_object_file(obj_file, &data, &disasm, options.disasm_code_only);
|
||||
if (options.disassembly_output_file.empty()) {
|
||||
printf("%s\n", disasm.c_str());
|
||||
} else {
|
||||
|
@ -34,6 +34,7 @@ struct CompilationOptions {
|
||||
bool write = false; // write object file to out/obj
|
||||
bool no_code = false; // file shouldn't generate code, throw error if it does
|
||||
bool disassemble = false; // either print disassembly to stdout or output_file
|
||||
bool disasm_code_only = false; // if on, IR and source lines are not printed
|
||||
bool print_time = false; // print timing statistics
|
||||
};
|
||||
|
||||
@ -210,7 +211,8 @@ class Compiler {
|
||||
std::vector<u8> codegen_object_file(FileEnv* env);
|
||||
bool codegen_and_disassemble_object_file(FileEnv* env,
|
||||
std::vector<u8>* data_out,
|
||||
std::string* asm_out);
|
||||
std::string* asm_out,
|
||||
bool omit_ir);
|
||||
|
||||
void for_each_in_list(const goos::Object& list,
|
||||
const std::function<void(const goos::Object&)>& f);
|
||||
|
@ -161,6 +161,8 @@ Val* Compiler::compile_asm_file(const goos::Object& form, const goos::Object& re
|
||||
} else if (setting == ":disassemble") {
|
||||
options.disassemble = true;
|
||||
last_was_disasm = true;
|
||||
} else if (setting == ":disasm-code-only") {
|
||||
options.disasm_code_only = true;
|
||||
} else {
|
||||
throw_compiler_error(form, "The option {} was not recognized for asm-file.", setting);
|
||||
}
|
||||
|
@ -7,19 +7,22 @@
|
||||
DebugInfo::DebugInfo(std::string obj_name) : m_obj_name(std::move(obj_name)) {}
|
||||
|
||||
std::string FunctionDebugInfo::disassemble_debug_info(bool* had_failure,
|
||||
const goos::Reader* reader) {
|
||||
const goos::Reader* reader,
|
||||
bool omit_ir) {
|
||||
std::string result = fmt::format("[{}]\n", name);
|
||||
result +=
|
||||
disassemble_x86_function(generated_code.data(), generated_code.size(), reader, 0x10000,
|
||||
0x10000, instructions, code_sources, ir_strings, had_failure, true);
|
||||
result += disassemble_x86_function(generated_code.data(), generated_code.size(), reader, 0x10000,
|
||||
0x10000, instructions, code_sources, ir_strings, had_failure,
|
||||
true, omit_ir);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string DebugInfo::disassemble_all_functions(bool* had_failure, const goos::Reader* reader) {
|
||||
std::string DebugInfo::disassemble_all_functions(bool* had_failure,
|
||||
const goos::Reader* reader,
|
||||
bool omit_ir) {
|
||||
std::string result;
|
||||
for (auto& kv : m_functions) {
|
||||
result += kv.second.disassemble_debug_info(had_failure, reader) + "\n\n";
|
||||
result += kv.second.disassemble_debug_info(had_failure, reader, omit_ir) + "\n\n";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -30,7 +33,7 @@ std::string DebugInfo::disassemble_function_by_name(const std::string& name,
|
||||
std::string result;
|
||||
for (auto& kv : m_functions) {
|
||||
if (kv.second.name == name) {
|
||||
result += kv.second.disassemble_debug_info(had_failure, reader) + "\n\n";
|
||||
result += kv.second.disassemble_debug_info(had_failure, reader, false) + "\n\n";
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -40,7 +40,7 @@ struct FunctionDebugInfo {
|
||||
std::vector<u8> generated_code;
|
||||
std::optional<int> stack_usage;
|
||||
|
||||
std::string disassemble_debug_info(bool* had_failure, const goos::Reader* reader);
|
||||
std::string disassemble_debug_info(bool* had_failure, const goos::Reader* reader, bool omit_ir);
|
||||
};
|
||||
|
||||
class DebugInfo {
|
||||
@ -74,7 +74,9 @@ class DebugInfo {
|
||||
|
||||
void clear() { m_functions.clear(); }
|
||||
|
||||
std::string disassemble_all_functions(bool* had_failure, const goos::Reader* reader);
|
||||
std::string disassemble_all_functions(bool* had_failure,
|
||||
const goos::Reader* reader,
|
||||
bool omit_ir);
|
||||
std::string disassemble_function_by_name(const std::string& name,
|
||||
bool* had_failure,
|
||||
const goos::Reader* reader);
|
||||
|
@ -428,7 +428,7 @@ Disassembly Debugger::disassemble_at_rip(const InstructionPointerInfo& info) {
|
||||
function_mem.data(), function_mem.size(), m_reader,
|
||||
m_debug_context.base + info.map_entry->start_addr + func_info->offset_in_seg,
|
||||
rip + rip_offset, func_info->instructions, func_info->code_sources, func_info->ir_strings,
|
||||
&result.failed, false);
|
||||
&result.failed, false, false);
|
||||
}
|
||||
} else {
|
||||
result.failed = true;
|
||||
|
@ -76,6 +76,8 @@ std::string disassemble_x86(u8* data, int len, u64 base_addr, u64 highlight_addr
|
||||
// how many "forms" to look at ahead of / behind rip when stopping
|
||||
static constexpr int FORM_DUMP_SIZE_REV = 4;
|
||||
static constexpr int FORM_DUMP_SIZE_FWD = 4;
|
||||
// how long the bytecode part of the disassembly is, IR comes after this
|
||||
static constexpr int DISASM_LINE_LEN = 60;
|
||||
|
||||
std::string disassemble_x86_function(
|
||||
u8* data,
|
||||
@ -87,7 +89,8 @@ std::string disassemble_x86_function(
|
||||
const std::vector<std::shared_ptr<goos::HeapObject>>& code_sources,
|
||||
const std::vector<std::string>& ir_strings,
|
||||
bool* had_failure,
|
||||
bool print_whole_function) {
|
||||
bool print_whole_function,
|
||||
bool omit_ir) {
|
||||
std::string result;
|
||||
ZydisDecoder decoder;
|
||||
ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64);
|
||||
@ -145,7 +148,8 @@ std::string disassemble_x86_function(
|
||||
}
|
||||
}
|
||||
|
||||
if (current_instruction_idx >= 0 && current_instruction_idx < int(x86_instructions.size())) {
|
||||
if (!omit_ir && current_instruction_idx >= 0 &&
|
||||
current_instruction_idx < int(x86_instructions.size())) {
|
||||
const auto& debug_instr = x86_instructions.at(current_instruction_idx);
|
||||
if (debug_instr.kind == InstructionInfo::Kind::IR && debug_instr.ir_idx != current_ir_idx) {
|
||||
current_ir_idx = debug_instr.ir_idx;
|
||||
@ -154,8 +158,9 @@ std::string disassemble_x86_function(
|
||||
}
|
||||
|
||||
std::string line;
|
||||
size_t line_size_offset = 0;
|
||||
|
||||
if (current_ir_idx >= 0 && current_ir_idx < int(ir_strings.size())) {
|
||||
if (!omit_ir && current_ir_idx >= 0 && current_ir_idx < int(ir_strings.size())) {
|
||||
auto source = reader->db.try_get_short_info(code_sources.at(current_ir_idx));
|
||||
if (source) {
|
||||
if (source->filename != current_filename ||
|
||||
@ -171,6 +176,7 @@ std::string disassemble_x86_function(
|
||||
std::string pointer(current_offset_in_line + 3, ' ');
|
||||
pointer += "^\n";
|
||||
line += fmt::format(fmt::emphasis::bold | fg(fmt::color::lime_green), "{}", pointer);
|
||||
line_size_offset = line.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -188,8 +194,8 @@ std::string disassemble_x86_function(
|
||||
line += print_buff;
|
||||
|
||||
if (print_ir && current_ir_idx >= 0 && current_ir_idx < int(ir_strings.size())) {
|
||||
if (line.size() < 50) {
|
||||
line.append(50 - line.size(), ' ');
|
||||
if (line.size() - line_size_offset < DISASM_LINE_LEN) {
|
||||
line.append(DISASM_LINE_LEN - (line.size() - line_size_offset), ' ');
|
||||
}
|
||||
line += " ";
|
||||
line += ir_strings.at(current_ir_idx);
|
||||
|
@ -42,4 +42,5 @@ std::string disassemble_x86_function(
|
||||
const std::vector<std::shared_ptr<goos::HeapObject>>& code_sources,
|
||||
const std::vector<std::string>& ir_strings,
|
||||
bool* had_failure,
|
||||
bool print_whole_function);
|
||||
bool print_whole_function,
|
||||
bool omit_ir);
|
@ -292,7 +292,8 @@ TEST_F(WithGameTests, DebuggerMemoryMap) {
|
||||
TEST_F(WithGameTests, DebuggerDisassemble) {
|
||||
auto di = shared_compiler->compiler.get_debugger().get_debug_info_for_object("gcommon");
|
||||
bool fail = false;
|
||||
auto result = di.disassemble_all_functions(&fail, &shared_compiler->compiler.get_goos().reader);
|
||||
auto result =
|
||||
di.disassemble_all_functions(&fail, &shared_compiler->compiler.get_goos().reader, false);
|
||||
// printf("Got\n%s\n", result.c_str());
|
||||
EXPECT_FALSE(fail);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user