diff --git a/doc/changelog.md b/doc/changelog.md index a9932e0fb4..50b88d27a7 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -134,4 +134,6 @@ - Added support for creating a static bitfield where fields may not be known at compile time. - Added support for `(size-of )` - Fixed a bug where creating a stack array of 0 sized caused a compiler assertion. It is now a normal compiler error. -- Fixed a bug where the repl history was not loaded on compiler start \ No newline at end of file +- Fixed a bug where the repl history was not loaded on compiler start +- Branch target addresses in the disassembly generated by `md`, `asm-file` with `:disassemble` and `(declare (print-asm))` are now correct +- Fixed a segfault when the `goal-library.gc` contains an `(exit)` \ No newline at end of file diff --git a/goalc/compiler/CodeGenerator.cpp b/goalc/compiler/CodeGenerator.cpp index 6cd4f6341a..0a618dce0a 100644 --- a/goalc/compiler/CodeGenerator.cpp +++ b/goalc/compiler/CodeGenerator.cpp @@ -45,7 +45,7 @@ std::vector CodeGenerator::run(const TypeSystem* ts) { do_function(m_fe->functions().at(i).get(), i); } - // generate a v3 object. TODO - support for v4 "data" objects. + // generate a v3 object. return m_gen.generate_data_v3(ts).to_vector(); } diff --git a/goalc/compiler/compilation/CompilerControl.cpp b/goalc/compiler/compilation/CompilerControl.cpp index 692c26c343..b3ad803c72 100644 --- a/goalc/compiler/compilation/CompilerControl.cpp +++ b/goalc/compiler/compilation/CompilerControl.cpp @@ -33,7 +33,9 @@ Val* Compiler::compile_exit(const goos::Object& form, const goos::Object& rest, } // flag for the REPL. m_want_exit = true; - m_repl->save_history(); + if (m_repl) { + m_repl->save_history(); + } return get_none(); } diff --git a/goalc/debugger/DebugInfo.cpp b/goalc/debugger/DebugInfo.cpp index cfc219f8b4..ee38602649 100644 --- a/goalc/debugger/DebugInfo.cpp +++ b/goalc/debugger/DebugInfo.cpp @@ -1,5 +1,4 @@ #include -#include #include "DebugInfo.h" #include "third-party/fmt/core.h" @@ -7,17 +6,8 @@ DebugInfo::DebugInfo(std::string obj_name) : m_obj_name(std::move(obj_name)) {} std::string FunctionDebugInfo::disassemble_debug_info(bool* had_failure) { std::string result = fmt::format("[{}]\n", name); - std::vector data; - u8 temp[128]; - for (const auto& x : instructions) { - auto count = x.instruction.emit(temp); - for (int i = 0; i < count; i++) { - data.push_back(temp[i]); - } - } - - result += disassemble_x86_function(data.data(), data.size(), 0x10000, 0x10000, instructions, irs, - had_failure); + result += disassemble_x86_function(generated_code.data(), generated_code.size(), 0x10000, 0x10000, + instructions, irs, had_failure); return result; } diff --git a/goalc/debugger/DebugInfo.h b/goalc/debugger/DebugInfo.h index 951d0926a0..9a81c92b4c 100644 --- a/goalc/debugger/DebugInfo.h +++ b/goalc/debugger/DebugInfo.h @@ -8,6 +8,11 @@ #include "goalc/emitter/Instruction.h" #include "goalc/debugger/disassemble.h" +/*! + * FunctionDebugInfo stores per-function debugging information. + * For now, it is pretty basic, but it will eventually contain stuff like stack frame info + * and which var is in each register at each instruction. + */ struct FunctionDebugInfo { u32 offset_in_seg; // not including type tag. u32 length; @@ -15,7 +20,10 @@ struct FunctionDebugInfo { std::string name; std::vector irs; - std::vector instructions; + std::vector instructions; // contains mapping to IRs + + // the actual bytes in the object file. + std::vector generated_code; std::string disassemble_debug_info(bool* had_failure); }; diff --git a/goalc/emitter/ObjectGenerator.cpp b/goalc/emitter/ObjectGenerator.cpp index f9f718601a..0442188f69 100644 --- a/goalc/emitter/ObjectGenerator.cpp +++ b/goalc/emitter/ObjectGenerator.cpp @@ -95,13 +95,21 @@ ObjectFileData ObjectGenerator::generate_data_v3(const TypeSystem* ts) { handle_temp_static_ptr_links(seg); } - // actual linking? + // step 4, generate the link table for (int seg = N_SEG; seg-- > 0;) { emit_link_table(seg, ts); } - // emit header + // step 4.5, collect final result of code/object generation for compiler debugging disassembly + for (int seg = 0; seg < N_SEG; seg++) { + for (auto& function : m_function_data_by_seg.at(seg)) { + auto start = m_data_by_seg.at(seg).begin() + function.instruction_to_byte_in_data.at(0); + auto end = start + function.debug->length; + function.debug->generated_code = {start, end}; + } + } + // step 5, build header and combine sections out.header = generate_header_v3(); out.segment_data = std::move(m_data_by_seg); out.link_tables = std::move(m_link_by_seg);