2020-11-13 22:33:57 -05:00
|
|
|
#pragma once
|
|
|
|
|
2021-08-26 20:33:00 -04:00
|
|
|
#include <memory>
|
2022-06-22 23:37:46 -04:00
|
|
|
#include <optional>
|
|
|
|
#include <string>
|
2020-11-13 22:33:57 -05:00
|
|
|
#include <unordered_map>
|
2022-06-22 23:37:46 -04:00
|
|
|
#include <vector>
|
|
|
|
|
2020-11-13 22:33:57 -05:00
|
|
|
#include "common/common_types.h"
|
2022-02-08 19:02:47 -05:00
|
|
|
#include "common/util/Assert.h"
|
2020-11-13 22:33:57 -05:00
|
|
|
|
2022-06-22 23:37:46 -04:00
|
|
|
#include "goalc/debugger/disassemble.h"
|
|
|
|
#include "goalc/emitter/Instruction.h"
|
|
|
|
|
2021-08-26 20:33:00 -04:00
|
|
|
class FunctionEnv;
|
|
|
|
|
2023-02-24 18:32:30 -05:00
|
|
|
namespace goos {
|
|
|
|
class Object;
|
|
|
|
class HeapObject;
|
|
|
|
} // namespace goos
|
|
|
|
|
2021-04-23 15:07:22 -04:00
|
|
|
/*!
|
|
|
|
* 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.
|
|
|
|
*/
|
2020-11-13 22:33:57 -05:00
|
|
|
struct FunctionDebugInfo {
|
|
|
|
u32 offset_in_seg; // not including type tag.
|
|
|
|
u32 length;
|
|
|
|
u8 seg;
|
|
|
|
std::string name;
|
2021-08-04 21:30:08 -04:00
|
|
|
std::string obj_name;
|
2020-11-13 22:33:57 -05:00
|
|
|
|
2021-04-23 15:07:22 -04:00
|
|
|
std::vector<InstructionInfo> instructions; // contains mapping to IRs
|
|
|
|
|
2023-02-24 18:32:30 -05:00
|
|
|
std::vector<std::shared_ptr<goos::HeapObject>> code_sources;
|
|
|
|
std::vector<std::string> ir_strings;
|
|
|
|
|
2021-04-23 15:07:22 -04:00
|
|
|
// the actual bytes in the object file.
|
|
|
|
std::vector<u8> generated_code;
|
2021-06-30 22:13:15 -04:00
|
|
|
std::optional<int> stack_usage;
|
2020-11-13 22:33:57 -05:00
|
|
|
|
2023-10-29 06:16:14 -04:00
|
|
|
std::string disassemble_debug_info(bool* had_failure, const goos::Reader* reader, bool omit_ir);
|
2020-11-13 22:33:57 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
class DebugInfo {
|
|
|
|
public:
|
|
|
|
explicit DebugInfo(std::string obj_name);
|
|
|
|
|
2021-08-04 21:30:08 -04:00
|
|
|
FunctionDebugInfo& add_function(const std::string& name, const std::string& obj_name) {
|
2020-11-13 22:33:57 -05:00
|
|
|
if (m_functions.find(name) != m_functions.end()) {
|
2022-02-08 19:02:47 -05:00
|
|
|
ASSERT(false);
|
2020-11-13 22:33:57 -05:00
|
|
|
}
|
|
|
|
auto& result = m_functions[name];
|
|
|
|
result.name = name;
|
2021-08-04 21:30:08 -04:00
|
|
|
result.obj_name = obj_name;
|
2020-11-13 22:33:57 -05:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool lookup_function(FunctionDebugInfo** info, std::string* name, u32 offset, u8 seg) {
|
|
|
|
for (auto& kv : m_functions) {
|
|
|
|
auto start = kv.second.offset_in_seg;
|
|
|
|
auto end = start + kv.second.length;
|
|
|
|
if (offset >= start && offset < end && seg == kv.second.seg) {
|
|
|
|
*info = &kv.second;
|
|
|
|
*name = kv.first;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-06-30 22:13:15 -04:00
|
|
|
FunctionDebugInfo& function_by_name(const std::string& name) { return m_functions.at(name); }
|
|
|
|
|
2020-11-13 22:33:57 -05:00
|
|
|
void clear() { m_functions.clear(); }
|
|
|
|
|
2023-10-29 06:16:14 -04:00
|
|
|
std::string disassemble_all_functions(bool* had_failure,
|
|
|
|
const goos::Reader* reader,
|
|
|
|
bool omit_ir);
|
2021-08-26 20:33:00 -04:00
|
|
|
std::string disassemble_function_by_name(const std::string& name,
|
|
|
|
bool* had_failure,
|
|
|
|
const goos::Reader* reader);
|
2020-11-13 22:33:57 -05:00
|
|
|
|
|
|
|
private:
|
|
|
|
std::string m_obj_name;
|
|
|
|
std::unordered_map<std::string, FunctionDebugInfo> m_functions;
|
|
|
|
};
|