mirror of
https://github.com/open-goal/jak-project
synced 2026-05-23 06:54:31 -04:00
[decompiler] Jak 2 modifications, new all-types code (#1553)
* temp * look at old game types * clean up
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
#include "common/util/Timer.h"
|
||||
|
||||
#include "decompiler/IR2/Form.h"
|
||||
#include "decompiler/analysis/analyze_inspect_method.h"
|
||||
#include "decompiler/analysis/cfg_builder.h"
|
||||
#include "decompiler/analysis/expression_build.h"
|
||||
#include "decompiler/analysis/final_output.h"
|
||||
@@ -103,7 +104,22 @@ void ObjectFileDB::analyze_functions_ir2(
|
||||
data.full_output = ir2_final_out(data, imports, {});
|
||||
}
|
||||
|
||||
for_each_function_def_order_in_obj(data, [&](Function& f, int) { f.ir2 = {}; });
|
||||
if (!config.generate_all_types) {
|
||||
// this frees ir2 memory, but means future passes can't look back on this function.
|
||||
for_each_function_def_order_in_obj(data, [&](Function& f, int) { f.ir2 = {}; });
|
||||
} else {
|
||||
for_each_function_def_order_in_obj(data, [&](Function& f, int seg) {
|
||||
if (seg == 0) {
|
||||
return; // keep top-levels
|
||||
}
|
||||
if (f.guessed_name.kind == FunctionName::FunctionKind::METHOD &&
|
||||
f.guessed_name.method_id == GOAL_INSPECT_METHOD) {
|
||||
return; // keep inspects
|
||||
}
|
||||
// otherwise free memory
|
||||
f.ir2 = {};
|
||||
});
|
||||
}
|
||||
|
||||
fmt::print("Done in {:.2f}ms\n", file_timer.getMs());
|
||||
});
|
||||
@@ -280,6 +296,61 @@ void ObjectFileDB::ir2_top_level_pass(const Config& config) {
|
||||
lg::info("{:4d} logins {:.2f}%\n", total_top_levels, 100.f * total_top_levels / total_functions);
|
||||
}
|
||||
|
||||
void ObjectFileDB::ir2_analyze_all_types(const std::string& output_file,
|
||||
const std::optional<std::string>& previous_game_types,
|
||||
const std::unordered_set<std::string>& bad_types) {
|
||||
struct PerObject {
|
||||
std::string object_name;
|
||||
std::vector<std::string> type_defs;
|
||||
std::string symbol_defs;
|
||||
};
|
||||
|
||||
std::vector<PerObject> per_object;
|
||||
|
||||
DecompilerTypeSystem previous_game_ts;
|
||||
if (previous_game_types) {
|
||||
previous_game_ts.parse_type_defs({*previous_game_types});
|
||||
}
|
||||
|
||||
std::unordered_set<std::string> already_seen;
|
||||
for_each_obj([&](ObjectFileData& data) {
|
||||
if (data.obj_version != 3) {
|
||||
return;
|
||||
}
|
||||
auto& object_result = per_object.emplace_back();
|
||||
object_result.object_name = data.to_unique_name();
|
||||
|
||||
for_each_function_def_order_in_obj(data, [&](Function& f, int seg) {
|
||||
if (seg == TOP_LEVEL_SEGMENT) {
|
||||
object_result.symbol_defs += inspect_top_level_symbol_defines(
|
||||
already_seen, f, data.linked_data, dts, previous_game_ts);
|
||||
} else {
|
||||
if (f.is_inspect_method && bad_types.find(f.guessed_name.type_name) == bad_types.end()) {
|
||||
object_result.type_defs.push_back(inspect_inspect_method(
|
||||
f, f.guessed_name.type_name, dts, data.linked_data, previous_game_ts.ts));
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
std::string result;
|
||||
result += ";; All Types\n\n";
|
||||
|
||||
for (auto& obj : per_object) {
|
||||
result += fmt::format(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n");
|
||||
result += fmt::format(";; {:30s} ;;\n", obj.object_name);
|
||||
result += fmt::format(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n");
|
||||
for (auto& t : obj.type_defs) {
|
||||
result += t;
|
||||
result += "\n";
|
||||
}
|
||||
result += obj.symbol_defs;
|
||||
result += "\n";
|
||||
}
|
||||
|
||||
file_util::write_text_file(output_file, result);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Initial Function Analysis Pass to build the control flow graph.
|
||||
* - Find basic blocks
|
||||
@@ -322,7 +393,7 @@ void ObjectFileDB::ir2_basic_block_pass(int seg, const Config& config, ObjectFil
|
||||
asm_br_blocks = asm_lookup->second;
|
||||
}
|
||||
|
||||
func.cfg = build_cfg(data.linked_data, seg, func, hack, asm_br_blocks);
|
||||
func.cfg = build_cfg(data.linked_data, seg, func, hack, asm_br_blocks, config.game_version);
|
||||
if (!func.cfg->is_fully_resolved()) {
|
||||
lg::warn("Function {} from {} failed to build control flow graph!", func.name(),
|
||||
data.to_unique_name());
|
||||
@@ -548,23 +619,6 @@ void ObjectFileDB::ir2_cfg_build_pass(int seg, ObjectFileData& data) {
|
||||
});
|
||||
}
|
||||
|
||||
// void ObjectFileDB::ir2_store_current_forms(int seg) {
|
||||
// Timer timer;
|
||||
// int total = 0;
|
||||
//
|
||||
// for_each_function_in_seg(seg, [&](Function& func, ObjectFileData& data) {
|
||||
// (void)data;
|
||||
//
|
||||
// if (func.ir2.top_form) {
|
||||
// total++;
|
||||
// func.ir2.debug_form_string =
|
||||
// pretty_print::to_string(func.ir2.top_form->to_form(func.ir2.env));
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// lg::info("Stored debug forms for {} functions in {:.2f} ms\n", total, timer.getMs());
|
||||
//}
|
||||
//
|
||||
void ObjectFileDB::ir2_build_expressions(int seg, const Config& config, ObjectFileData& data) {
|
||||
for_each_function_in_seg_in_obj(seg, data, [&](Function& func) {
|
||||
(void)data;
|
||||
|
||||
Reference in New Issue
Block a user