mirror of
https://github.com/open-goal/jak-project.git
synced 2024-11-23 14:20:07 +00:00
[decompiler] Jak 2 modifications, new all-types code (#1553)
* temp * look at old game types * clean up
This commit is contained in:
parent
c9de15ba64
commit
91fa0122d8
@ -1,6 +1,7 @@
|
||||
add_library(
|
||||
decomp
|
||||
|
||||
analysis/analyze_inspect_method.cpp
|
||||
analysis/atomic_op_builder.cpp
|
||||
analysis/cfg_builder.cpp
|
||||
analysis/expression_build.cpp
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "Function.h"
|
||||
|
||||
#include "common/goos/PrettyPrinter.h"
|
||||
#include "common/symbols.h"
|
||||
#include "common/util/Assert.h"
|
||||
|
||||
#include "decompiler/Disasm/InstructionMatching.h"
|
||||
@ -2559,13 +2560,14 @@ void ControlFlowGraph::flag_early_exit(const std::vector<BasicBlock>& blocks) {
|
||||
}
|
||||
}
|
||||
|
||||
CfgVtx::DelaySlotKind get_delay_slot(const Instruction& i) {
|
||||
CfgVtx::DelaySlotKind get_delay_slot(const Instruction& i, GameVersion version) {
|
||||
if (is_nop(i)) {
|
||||
return CfgVtx::DelaySlotKind::NOP;
|
||||
} else if (is_gpr_3(i, InstructionKind::OR, {}, Register(Reg::GPR, Reg::S7),
|
||||
Register(Reg::GPR, Reg::R0))) {
|
||||
return CfgVtx::DelaySlotKind::SET_REG_FALSE;
|
||||
} else if (is_gpr_2_imm_int(i, InstructionKind::DADDIU, {}, Register(Reg::GPR, Reg::S7), 8)) {
|
||||
} else if (is_gpr_2_imm_int(i, InstructionKind::DADDIU, {}, Register(Reg::GPR, Reg::S7),
|
||||
true_symbol_offset(version))) {
|
||||
return CfgVtx::DelaySlotKind::SET_REG_TRUE;
|
||||
} else {
|
||||
return CfgVtx::DelaySlotKind::OTHER;
|
||||
@ -2576,7 +2578,7 @@ namespace {
|
||||
/*!
|
||||
* Is this instruction possible in the delay slot, without using inline assembly?
|
||||
*/
|
||||
bool branch_delay_asm(const Instruction& i) {
|
||||
bool branch_delay_asm(const Instruction& i, GameVersion version) {
|
||||
if (is_nop(i)) {
|
||||
// nop can be used as a delay
|
||||
return false;
|
||||
@ -2584,7 +2586,8 @@ bool branch_delay_asm(const Instruction& i) {
|
||||
Register(Reg::GPR, Reg::R0))) {
|
||||
// set false is used in ifs, etc
|
||||
return false;
|
||||
} else if (is_gpr_2_imm_int(i, InstructionKind::DADDIU, {}, Register(Reg::GPR, Reg::S7), 8)) {
|
||||
} else if (is_gpr_2_imm_int(i, InstructionKind::DADDIU, {}, Register(Reg::GPR, Reg::S7),
|
||||
true_symbol_offset(version))) {
|
||||
// set true is used in sc
|
||||
return false;
|
||||
} else if (is_gpr_3(i, InstructionKind::OR, {}, {}, Register(Reg::GPR, Reg::R0))) {
|
||||
@ -2609,12 +2612,12 @@ bool branch_delay_asm(const Instruction& i) {
|
||||
/*!
|
||||
* Build and resolve a Control Flow Graph as much as possible.
|
||||
*/
|
||||
std::shared_ptr<ControlFlowGraph> build_cfg(
|
||||
const LinkedObjectFile& file,
|
||||
int seg,
|
||||
Function& func,
|
||||
const CondWithElseLengthHack& cond_with_else_hack,
|
||||
const std::unordered_set<int>& blocks_ending_in_asm_br) {
|
||||
std::shared_ptr<ControlFlowGraph> build_cfg(const LinkedObjectFile& file,
|
||||
int seg,
|
||||
Function& func,
|
||||
const CondWithElseLengthHack& cond_with_else_hack,
|
||||
const std::unordered_set<int>& blocks_ending_in_asm_br,
|
||||
GameVersion version) {
|
||||
// fmt::print("START {}\n", func.guessed_name.to_string());
|
||||
auto cfg = std::make_shared<ControlFlowGraph>();
|
||||
|
||||
@ -2708,7 +2711,7 @@ std::shared_ptr<ControlFlowGraph> build_cfg(
|
||||
if (is_branch(branch_candidate, false)) {
|
||||
blocks.at(i)->end_branch.has_branch = true;
|
||||
blocks.at(i)->end_branch.branch_likely = false;
|
||||
blocks.at(i)->end_branch.kind = get_delay_slot(delay_slot_candidate);
|
||||
blocks.at(i)->end_branch.kind = get_delay_slot(delay_slot_candidate, version);
|
||||
bool branch_always = is_always_branch(branch_candidate);
|
||||
|
||||
// need to find block target
|
||||
@ -2779,7 +2782,7 @@ std::shared_ptr<ControlFlowGraph> build_cfg(
|
||||
if (is_branch(likely_branch_candidate, true)) {
|
||||
// likely branch!
|
||||
auto following = func.instructions.at(likely_branch_idx + 1);
|
||||
if (branch_delay_asm(following)) {
|
||||
if (branch_delay_asm(following, version)) {
|
||||
b->end_branch.asm_branch = true;
|
||||
if (debug_asm_branch) {
|
||||
fmt::print("LIKELY ASM BRANCH: {} and {}\n",
|
||||
@ -2795,7 +2798,7 @@ std::shared_ptr<ControlFlowGraph> build_cfg(
|
||||
auto& branch_candidate = func.instructions.at(idx);
|
||||
auto& delay_slot_candidate = func.instructions.at(idx + 1);
|
||||
if (is_branch(branch_candidate, false)) {
|
||||
if (branch_delay_asm(delay_slot_candidate)) {
|
||||
if (branch_delay_asm(delay_slot_candidate, version)) {
|
||||
b->end_branch.asm_branch = true;
|
||||
if (debug_asm_branch) {
|
||||
fmt::print("NORMAL ASM BRANCH: {} and {}\n", branch_candidate.to_string(file.labels),
|
||||
|
@ -393,5 +393,6 @@ std::shared_ptr<ControlFlowGraph> build_cfg(const LinkedObjectFile& file,
|
||||
int seg,
|
||||
Function& func,
|
||||
const CondWithElseLengthHack& cond_with_else_hack,
|
||||
const std::unordered_set<int>& blocks_ending_in_asm_br);
|
||||
const std::unordered_set<int>& blocks_ending_in_asm_br,
|
||||
GameVersion version);
|
||||
} // namespace decompiler
|
||||
|
@ -34,8 +34,10 @@ Register get_expected_fpr_backup(int n, int total) {
|
||||
|
||||
} // namespace
|
||||
|
||||
Function::Function(int _start_word, int _end_word) : start_word(_start_word), end_word(_end_word) {
|
||||
Function::Function(int _start_word, int _end_word, GameVersion version)
|
||||
: start_word(_start_word), end_word(_end_word) {
|
||||
ir2.form_pool.reset(new FormPool());
|
||||
ir2.env.version = version;
|
||||
}
|
||||
|
||||
Function::~Function() {}
|
||||
|
@ -99,7 +99,7 @@ struct FunctionName {
|
||||
|
||||
class Function {
|
||||
public:
|
||||
Function(int _start_word, int _end_word);
|
||||
Function(int _start_word, int _end_word, GameVersion version);
|
||||
~Function();
|
||||
void analyze_prologue(const LinkedObjectFile& file);
|
||||
void find_global_function_defs(LinkedObjectFile& file, DecompilerTypeSystem& dts);
|
||||
|
@ -1842,4 +1842,44 @@ RegisterAccess StackSpillLoadOp::get_set_destination() const {
|
||||
throw std::runtime_error("StackSpillLoadOp cannot be treated as a set! operation");
|
||||
}
|
||||
|
||||
bool is_op_2(AtomicOp* op,
|
||||
MatchParam<SimpleExpression::Kind> kind,
|
||||
MatchParam<Register> dst,
|
||||
MatchParam<Register> src0,
|
||||
Register* dst_out,
|
||||
Register* src0_out) {
|
||||
// should be a set reg to int math 2 ir
|
||||
auto set = dynamic_cast<SetVarOp*>(op);
|
||||
if (!set) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// destination should be a register
|
||||
auto dest = set->dst();
|
||||
if (dst != dest.reg()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto math = set->src();
|
||||
if (kind != math.kind()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto arg = math.get_arg(0);
|
||||
|
||||
if (!arg.is_var() || src0 != arg.var().reg()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// it's a match!
|
||||
if (dst_out) {
|
||||
*dst_out = dest.reg();
|
||||
}
|
||||
|
||||
if (src0_out) {
|
||||
*src0_out = arg.var().reg();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace decompiler
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "decompiler/Disasm/Instruction.h"
|
||||
#include "decompiler/Disasm/Register.h"
|
||||
#include "decompiler/IR2/IR2_common.h"
|
||||
#include "decompiler/util/MatchParam.h"
|
||||
|
||||
namespace decompiler {
|
||||
class FormElement;
|
||||
@ -807,4 +808,11 @@ class StackSpillLoadOp : public AtomicOp {
|
||||
};
|
||||
|
||||
bool get_as_reg_offset(const SimpleExpression& expr, IR2_RegOffset* out);
|
||||
|
||||
bool is_op_2(AtomicOp* op,
|
||||
MatchParam<SimpleExpression::Kind> kind,
|
||||
MatchParam<Register> dst,
|
||||
MatchParam<Register> src0,
|
||||
Register* dst_out = nullptr,
|
||||
Register* src0_out = nullptr);
|
||||
} // namespace decompiler
|
||||
|
@ -188,6 +188,11 @@ TP_Type SimpleExpression::get_type(const TypeState& input,
|
||||
// GOAL is smart enough to use binary 0b0 as floating point 0.
|
||||
return TP_Type::make_from_ts("float");
|
||||
}
|
||||
// new for jak 2:
|
||||
if (env.version == GameVersion::Jak2 && in_type.is_integer_constant() &&
|
||||
in_type.get_integer_constant() <= UINT32_MAX) {
|
||||
return TP_Type::make_from_ts("float");
|
||||
}
|
||||
return in_type;
|
||||
}
|
||||
case Kind::FPR_TO_GPR:
|
||||
@ -398,6 +403,9 @@ TP_Type SimpleExpression::get_type_int2(const TypeState& input,
|
||||
}
|
||||
|
||||
if (m_kind == Kind::RIGHT_SHIFT_ARITH) {
|
||||
if (env.version == GameVersion::Jak2 && arg0_type.typespec().base_type() == "float") {
|
||||
return TP_Type::make_from_ts(TypeSpec("float"));
|
||||
}
|
||||
return TP_Type::make_from_ts(TypeSpec("int"));
|
||||
}
|
||||
} break;
|
||||
|
@ -58,6 +58,7 @@ struct FunctionVariableDefinitions {
|
||||
*/
|
||||
class Env {
|
||||
public:
|
||||
GameVersion version = GameVersion::Jak1;
|
||||
bool types_succeeded = false;
|
||||
bool has_local_vars() const { return m_has_local_vars; }
|
||||
bool has_type_analysis() const { return m_has_types; }
|
||||
|
@ -801,6 +801,7 @@ class UntilElement : public FormElement {
|
||||
bool allow_in_if() const override { return false; }
|
||||
Form* condition = nullptr;
|
||||
Form* body = nullptr;
|
||||
std::optional<RegisterAccess> false_destination; // used in jak 2, sometimes.
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -708,10 +708,28 @@ void SimpleExpressionElement::update_from_stack_gpr_to_fpr(const Env& env,
|
||||
result->push_back(x);
|
||||
}
|
||||
} else {
|
||||
// converting something else to an FPR, put an expression around it.
|
||||
result->push_back(pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_fixed(FixedOperatorKind::GPR_TO_FPR),
|
||||
pool.alloc_sequence_form(nullptr, src_fes)));
|
||||
if (env.version != GameVersion::Jak1) {
|
||||
auto frm = pool.alloc_sequence_form(nullptr, src_fes);
|
||||
if (src_fes.size() == 1) {
|
||||
auto int_constant = get_goal_integer_constant(frm, env);
|
||||
|
||||
if (int_constant && (*int_constant <= UINT32_MAX)) {
|
||||
float flt;
|
||||
|
||||
memcpy(&flt, &int_constant.value(), sizeof(float));
|
||||
|
||||
result->push_back(pool.alloc_element<ConstantFloatElement>(flt));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// converting something else to an FPR, put an expression around it.
|
||||
result->push_back(pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_fixed(FixedOperatorKind::GPR_TO_FPR), frm));
|
||||
} else {
|
||||
result->push_back(pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_fixed(FixedOperatorKind::GPR_TO_FPR),
|
||||
pool.alloc_sequence_form(nullptr, src_fes)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3538,6 +3556,22 @@ void UntilElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stac
|
||||
}
|
||||
|
||||
stack.push_form_element(this, true);
|
||||
if (false_destination) {
|
||||
env.func->warnings.general_warning("new jak 2 until loop case, check carefully");
|
||||
stack.push_value_to_reg(*false_destination,
|
||||
pool.form<SimpleAtomElement>(SimpleAtom::make_sym_val("#f")), true,
|
||||
TypeSpec("symbol"));
|
||||
RegAccessSet accessed_regs;
|
||||
body->collect_vars(accessed_regs, true);
|
||||
condition->collect_vars(accessed_regs, true);
|
||||
auto check_name = env.get_variable_name(*false_destination);
|
||||
for (auto& reg : accessed_regs) {
|
||||
if (env.get_variable_name(reg) == check_name) {
|
||||
ASSERT_MSG(false, fmt::format("Jak 2 loop uses delay slot variable improperly: {} {}\n",
|
||||
env.func->name(), check_name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WhileElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
|
@ -400,7 +400,7 @@ void LinkedObjectFile::find_code() {
|
||||
/*!
|
||||
* Find all the functions in each segment.
|
||||
*/
|
||||
void LinkedObjectFile::find_functions() {
|
||||
void LinkedObjectFile::find_functions(GameVersion version) {
|
||||
if (segments == 1) {
|
||||
// it's a v2 file, shouldn't have any functions
|
||||
ASSERT(offset_of_data_zone_by_seg.at(0) == 0);
|
||||
@ -427,7 +427,7 @@ void LinkedObjectFile::find_functions() {
|
||||
// mark this as a function, and try again from the current function start
|
||||
ASSERT(found_function_tag_loc);
|
||||
stats.function_count++;
|
||||
functions_by_seg.at(seg).emplace_back(function_tag_loc, function_end);
|
||||
functions_by_seg.at(seg).emplace_back(function_tag_loc, function_end, version);
|
||||
function_end = function_tag_loc;
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ class LinkedObjectFile {
|
||||
uint32_t set_ordered_label_names();
|
||||
void find_code();
|
||||
std::string print_words();
|
||||
void find_functions();
|
||||
void find_functions(GameVersion version);
|
||||
void disassemble_functions();
|
||||
void process_fp_relative_links();
|
||||
std::string print_scripts();
|
||||
|
@ -589,7 +589,7 @@ void ObjectFileDB::find_code(const Config& config) {
|
||||
for_each_obj([&](ObjectFileData& obj) {
|
||||
// printf("fc %s\n", obj.record.to_unique_name().c_str());
|
||||
obj.linked_data.find_code();
|
||||
obj.linked_data.find_functions();
|
||||
obj.linked_data.find_functions(config.game_version);
|
||||
obj.linked_data.disassemble_functions();
|
||||
|
||||
if (config.game_version == GameVersion::Jak1 || obj.to_unique_name() != "effect-control-v0") {
|
||||
|
@ -158,7 +158,6 @@ class ObjectFileDB {
|
||||
void extract_art_info();
|
||||
void dump_art_info(const std::string& output_dir);
|
||||
void dump_raw_objects(const std::string& output_dir);
|
||||
|
||||
void write_object_file_words(const std::string& output_dir, bool dump_data, bool dump_code);
|
||||
void write_disassembly(const std::string& output_dir,
|
||||
bool disassemble_data,
|
||||
@ -192,6 +191,9 @@ class ObjectFileDB {
|
||||
void ir2_do_segment_analysis_phase2(int seg, const Config& config, ObjectFileData& data);
|
||||
void ir2_setup_labels(const Config& config, ObjectFileData& data);
|
||||
void ir2_run_mips2c(const Config& config, ObjectFileData& data);
|
||||
void 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);
|
||||
std::string ir2_to_file(ObjectFileData& data, const Config& config);
|
||||
std::string ir2_function_to_string(ObjectFileData& data, Function& function, int seg);
|
||||
std::string ir2_final_out(ObjectFileData& data,
|
||||
|
@ -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;
|
||||
|
988
decompiler/analysis/analyze_inspect_method.cpp
Normal file
988
decompiler/analysis/analyze_inspect_method.cpp
Normal file
@ -0,0 +1,988 @@
|
||||
#include "analyze_inspect_method.h"
|
||||
#include "decompiler/Disasm/InstructionMatching.h"
|
||||
#include "decompiler/ObjectFile/LinkedObjectFile.h"
|
||||
|
||||
namespace decompiler {
|
||||
|
||||
struct TypeInspectorResult {
|
||||
bool success = false;
|
||||
int type_size = -1;
|
||||
int type_method_count = -1;
|
||||
int parent_method_count = 9;
|
||||
int type_heap_base = -1;
|
||||
|
||||
std::string warnings;
|
||||
std::vector<Field> fields_of_type;
|
||||
bool is_basic = false;
|
||||
bool found_flags = false;
|
||||
|
||||
std::string type_name;
|
||||
std::string parent_type_name;
|
||||
u64 flags = 0;
|
||||
|
||||
std::string print_as_deftype(StructureType* old_game_type);
|
||||
};
|
||||
|
||||
bool is_set_reg_to_int(AtomicOp* op, Register dst, s64 value) {
|
||||
// should be a set reg to int math 2 ir
|
||||
auto set = dynamic_cast<SetVarOp*>(op);
|
||||
if (!set) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// destination should be a register
|
||||
auto dest = set->dst();
|
||||
if (dst != dest.reg()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto math = set->src();
|
||||
if (SimpleExpression::Kind::IDENTITY != math.kind()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto arg = math.get_arg(0);
|
||||
|
||||
if (!arg.is_int() || value != arg.get_int()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_set_reg_to_symbol_value(AtomicOp* op, Register dst, const std::string& value) {
|
||||
// should be a set reg to int math 2 ir
|
||||
auto set = dynamic_cast<SetVarOp*>(op);
|
||||
if (!set) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// destination should be a register
|
||||
auto dest = set->dst();
|
||||
if (dst != dest.reg()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto math = set->src();
|
||||
if (SimpleExpression::Kind::IDENTITY != math.kind()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto arg = math.get_arg(0);
|
||||
|
||||
if (!arg.is_sym_val(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_set_reg_to_symbol_ptr(AtomicOp* op, Register dst, const std::string& value) {
|
||||
// should be a set reg to int math 2 ir
|
||||
auto set = dynamic_cast<SetVarOp*>(op);
|
||||
if (!set) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// destination should be a register
|
||||
auto dest = set->dst();
|
||||
if (dst != dest.reg()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto math = set->src();
|
||||
if (SimpleExpression::Kind::IDENTITY != math.kind()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto arg = math.get_arg(0);
|
||||
|
||||
if (!arg.is_sym_ptr(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<std::string> get_string_loaded_to_reg(AtomicOp* op,
|
||||
Register reg,
|
||||
LinkedObjectFile& file) {
|
||||
// should be a set reg to int math 2 ir
|
||||
auto set = dynamic_cast<SetVarOp*>(op);
|
||||
if (!set) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// destination should be a register
|
||||
auto dest = set->dst();
|
||||
if (reg != dest.reg()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto math = set->src();
|
||||
if (SimpleExpression::Kind::IDENTITY != math.kind()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto& src_atom = set->src().get_arg(0);
|
||||
if (!src_atom.is_label()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return file.get_goal_string_by_label(src_atom.label());
|
||||
}
|
||||
|
||||
struct FieldPrint {
|
||||
char format = '\0';
|
||||
std::string field_name;
|
||||
std::string field_type_name;
|
||||
bool has_array = false;
|
||||
int array_size = -1;
|
||||
};
|
||||
|
||||
FieldPrint get_field_print(const std::string& str) {
|
||||
int idx = 0;
|
||||
auto next = [&]() { return str.at(idx++); };
|
||||
|
||||
auto peek = [&](int off) { return str.at(idx + off); };
|
||||
|
||||
FieldPrint field_print;
|
||||
|
||||
// first is ~T
|
||||
char c0 = next();
|
||||
ASSERT(c0 == '~');
|
||||
char c1 = next();
|
||||
if (c1 == '1') {
|
||||
c1 = next();
|
||||
}
|
||||
ASSERT(c1 == 'T');
|
||||
|
||||
// next the name:
|
||||
char name_char = next();
|
||||
while (name_char != ':' && name_char != '[') {
|
||||
field_print.field_name.push_back(name_char);
|
||||
name_char = next();
|
||||
}
|
||||
|
||||
// possibly array thing
|
||||
if (name_char == '[') {
|
||||
int size = 0;
|
||||
char num_char = next();
|
||||
while (num_char >= '0' && num_char <= '9') {
|
||||
size = size * 10 + (num_char - '0');
|
||||
num_char = next();
|
||||
}
|
||||
field_print.has_array = true;
|
||||
field_print.array_size = size;
|
||||
|
||||
ASSERT(num_char == ']');
|
||||
char c = next();
|
||||
ASSERT(c == ' ');
|
||||
c = next();
|
||||
ASSERT(c == '@');
|
||||
c = next();
|
||||
ASSERT(c == ' ');
|
||||
c = next();
|
||||
ASSERT(c == '#');
|
||||
c = next();
|
||||
ASSERT(c == 'x');
|
||||
} else {
|
||||
// next a space
|
||||
char space_char = next();
|
||||
ASSERT(space_char == ' ');
|
||||
}
|
||||
|
||||
// next the format
|
||||
char fmt1 = next();
|
||||
if (fmt1 == '~' && peek(0) != '`') { // normal ~_~%
|
||||
char fmt_code = next();
|
||||
field_print.format = fmt_code;
|
||||
char end1 = next();
|
||||
ASSERT(end1 == '~');
|
||||
char end2 = next();
|
||||
ASSERT(end2 == '%');
|
||||
ASSERT(idx == (int)str.size());
|
||||
} else if (fmt1 == '#' && peek(0) == '<') { // struct #<my-struct @ #x~X>~%
|
||||
next();
|
||||
char type_name_c = next();
|
||||
while (type_name_c != ' ') {
|
||||
field_print.field_type_name += type_name_c;
|
||||
type_name_c = next();
|
||||
}
|
||||
|
||||
std::string expect_end = "@ #x~X>~%";
|
||||
for (char i : expect_end) {
|
||||
char c = next();
|
||||
ASSERT(i == c);
|
||||
}
|
||||
field_print.format = 'X';
|
||||
|
||||
ASSERT(idx == (int)str.size());
|
||||
} else if (fmt1 == '#' && peek(0) == 'x') { // #x~X~%
|
||||
next();
|
||||
std::string expect_end = "~X~%";
|
||||
for (char i : expect_end) {
|
||||
char c = next();
|
||||
ASSERT(i == c);
|
||||
}
|
||||
field_print.format = 'X';
|
||||
} else if (fmt1 == '~' && peek(0) == '`') { // ~`my-type-with-overriden-print`P~%
|
||||
next();
|
||||
char type_name_c = next();
|
||||
while (type_name_c != '`') {
|
||||
field_print.field_type_name += type_name_c;
|
||||
type_name_c = next();
|
||||
}
|
||||
|
||||
std::string expect_end = "P~%";
|
||||
for (char i : expect_end) {
|
||||
char c = next();
|
||||
ASSERT(i == c);
|
||||
}
|
||||
field_print.format = 'P';
|
||||
|
||||
ASSERT(idx == (int)str.size());
|
||||
} else if (str.substr(idx - 1) == "(meters ~m)~%") {
|
||||
field_print.format = 'm';
|
||||
} else if (str.substr(idx - 1) == "(deg ~r)~%") {
|
||||
field_print.format = 'r';
|
||||
} else if (str.substr(idx - 1) == "(seconds ~e)~%") {
|
||||
field_print.format = 'e';
|
||||
}
|
||||
|
||||
else {
|
||||
throw std::runtime_error("other format nyi in get_field_print " + str.substr(idx));
|
||||
}
|
||||
|
||||
return field_print;
|
||||
}
|
||||
|
||||
int get_start_idx(Function& function,
|
||||
LinkedObjectFile& file,
|
||||
TypeInspectorResult* result,
|
||||
const std::string& parent_type,
|
||||
const std::string& type_name,
|
||||
Env& env) {
|
||||
if (function.basic_blocks.size() != 5) {
|
||||
fmt::print("[iim] inspect {} had {} basic blocks, expected 5\n", function.name(),
|
||||
function.basic_blocks.size());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!function.ir2.atomic_ops) {
|
||||
fmt::print("[iim] no atomic ops in {}\n", function.name());
|
||||
return -1;
|
||||
}
|
||||
auto& aos = *function.ir2.atomic_ops;
|
||||
|
||||
int op_idx = 0;
|
||||
// block 0:
|
||||
/*
|
||||
* (set! gp a0)
|
||||
* (b! (truthy gp) L370 (set! v1 #f))
|
||||
*/
|
||||
|
||||
if (aos.block_id_to_end_atomic_op.at(0) != 2) {
|
||||
fmt::print("[iim] block 0 had the wrong number of ops: {} for {}\n",
|
||||
aos.block_id_to_end_atomic_op.at(0), function.name());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!is_op_2(aos.ops.at(op_idx).get(), SimpleExpression::Kind::IDENTITY,
|
||||
Register(Reg::GPR, Reg::GP), Register(Reg::GPR, Reg::A0))) {
|
||||
fmt::print("[iim] block 0 op 0 bad in {}: {}\n", aos.ops.at(op_idx)->to_string(env),
|
||||
function.name());
|
||||
return -1;
|
||||
}
|
||||
op_idx++;
|
||||
|
||||
auto br = dynamic_cast<BranchOp*>(aos.ops.at(op_idx).get());
|
||||
if (!br) {
|
||||
fmt::print("[iim] block 0 op 1 bad in {}: {} (not branch)\n", aos.ops.at(1)->to_string(env),
|
||||
function.name());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (br->likely() || br->condition().kind() != IR2_Condition::Kind::TRUTHY ||
|
||||
!br->condition().src(0).is_var() ||
|
||||
br->condition().src(0).var().reg() != Register(Reg::GPR, Reg::GP) ||
|
||||
br->branch_delay().kind() != IR2_BranchDelay::Kind::SET_REG_FALSE ||
|
||||
br->branch_delay().var(0).reg() != Register(Reg::GPR, Reg::V1)) {
|
||||
fmt::print("[iim] block 0 op 1 bad in {}: {} (bad branch)\n", aos.ops.at(1)->to_string(env),
|
||||
function.name());
|
||||
return -1;
|
||||
}
|
||||
op_idx++;
|
||||
|
||||
// block 1:
|
||||
/*
|
||||
* (set! gp gp)
|
||||
* (b! #t L371 (nop!))
|
||||
*/
|
||||
if (aos.block_id_to_end_atomic_op.at(1) != 4) {
|
||||
fmt::print("[iim] block 1 had the wrong number of ops: {} for {}\n",
|
||||
aos.block_id_to_end_atomic_op.at(1), function.name());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!is_op_2(aos.ops.at(op_idx).get(), SimpleExpression::Kind ::IDENTITY,
|
||||
Register(Reg::GPR, Reg::GP), Register(Reg::GPR, Reg::GP))) {
|
||||
fmt::print("[iim] op 2 bad in {}: {}\n", aos.ops.at(op_idx)->to_string(env), function.name());
|
||||
return -1;
|
||||
}
|
||||
op_idx++;
|
||||
|
||||
auto br2 = dynamic_cast<BranchOp*>(aos.ops.at(op_idx).get());
|
||||
if (!br2) {
|
||||
fmt::print("[iim] op 3 bad in {}: {} (not branch)\n", aos.ops.at(op_idx)->to_string(env),
|
||||
function.name());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (br2->likely() || br2->condition().kind() != IR2_Condition::Kind::ALWAYS ||
|
||||
br2->branch_delay().kind() != IR2_BranchDelay::Kind::NOP) {
|
||||
fmt::print("[iim] op3 bad in {}: {} (bad branch)\n", aos.ops.at(op_idx)->to_string(env),
|
||||
function.name());
|
||||
return -1;
|
||||
}
|
||||
op_idx++;
|
||||
|
||||
// setup
|
||||
/*
|
||||
(set! v1 0)
|
||||
(set! t9 format)
|
||||
(set! a0 #t)
|
||||
(set! a1 L386)
|
||||
(set! a2 gp)
|
||||
(set! a3 'vector) (also can be (set! a3 (l.wu (+ gp -4))))
|
||||
(call!)
|
||||
*/
|
||||
|
||||
if (!is_set_reg_to_int(aos.ops.at(op_idx).get(), Register(Reg::GPR, Reg::V1), 0)) {
|
||||
fmt::print("[iim] op4 bad in {}: {} (bad set 0)\n", aos.ops.at(op_idx)->to_string(env),
|
||||
function.name());
|
||||
}
|
||||
op_idx++;
|
||||
|
||||
if (!is_set_reg_to_symbol_value(aos.ops.at(op_idx).get(), Register(Reg::GPR, Reg::T9),
|
||||
"format")) {
|
||||
fmt::print("[iim] op5 bad in {}: {} (bad set format)\n", aos.ops.at(op_idx)->to_string(env),
|
||||
function.name());
|
||||
}
|
||||
op_idx++;
|
||||
|
||||
if (!is_set_reg_to_symbol_ptr(aos.ops.at(op_idx).get(), Register(Reg::GPR, Reg::A0), "#t")) {
|
||||
fmt::print("[iim] op6 bad in {}: {} (bad set #t)\n", aos.ops.at(op_idx)->to_string(env),
|
||||
function.name());
|
||||
}
|
||||
op_idx++;
|
||||
|
||||
auto type_name_str =
|
||||
get_string_loaded_to_reg(aos.ops.at(op_idx).get(), Register(Reg::GPR, Reg::A1), file);
|
||||
if (!type_name_str) {
|
||||
fmt::print("[iim] op7 bad in {}: {} (bad string)\n", aos.ops.at(op_idx)->to_string(env),
|
||||
function.name());
|
||||
}
|
||||
if (type_name_str != "[~8x] ~A~%") {
|
||||
fmt::print("[iim] op7 bad in {}: {} (bad string: {})\n", aos.ops.at(op_idx)->to_string(env),
|
||||
function.name(), *type_name_str);
|
||||
}
|
||||
op_idx++;
|
||||
|
||||
if (!is_op_2(aos.ops.at(op_idx).get(), SimpleExpression::Kind ::IDENTITY,
|
||||
Register(Reg::GPR, Reg::A2), Register(Reg::GPR, Reg::GP))) {
|
||||
fmt::print("[iim] op 8 bad in {}: {}\n", aos.ops.at(op_idx)->to_string(env), function.name());
|
||||
return -1;
|
||||
}
|
||||
op_idx++;
|
||||
|
||||
if (is_set_reg_to_symbol_ptr(aos.ops.at(op_idx).get(), Register(Reg::GPR, Reg::A3), type_name)) {
|
||||
result->is_basic = false;
|
||||
} else if (aos.ops.at(op_idx)->to_string(env) == "(set! a3 (l.wu (+ gp -4)))") {
|
||||
result->is_basic = true;
|
||||
} else {
|
||||
fmt::print("[iim] op 9 bad in {}: {}\n", aos.ops.at(op_idx)->to_string(env), function.name());
|
||||
return -1;
|
||||
}
|
||||
op_idx++;
|
||||
|
||||
if (!dynamic_cast<CallOp*>(aos.ops.at(op_idx).get())) {
|
||||
fmt::print("[iim] op 10 bad in {}: {}\n", aos.ops.at(op_idx)->to_string(env), function.name());
|
||||
return -1;
|
||||
}
|
||||
op_idx++;
|
||||
|
||||
return op_idx;
|
||||
}
|
||||
|
||||
std::pair<Register, int> get_base_of_load(const SimpleExpression& load_addr) {
|
||||
if (load_addr.kind() == SimpleExpression::Kind::IDENTITY) {
|
||||
const auto& src = load_addr.get_arg(0);
|
||||
if (src.is_var()) {
|
||||
return {src.var().reg(), 0};
|
||||
}
|
||||
}
|
||||
|
||||
if (load_addr.kind() == SimpleExpression::Kind::ADD) {
|
||||
const auto& src0 = load_addr.get_arg(0);
|
||||
const auto& src1 = load_addr.get_arg(1);
|
||||
if (src1.get_kind() == SimpleAtom::Kind::INTEGER_CONSTANT &&
|
||||
src0.get_kind() == SimpleAtom::Kind::VARIABLE) {
|
||||
return {src0.var().reg(), src1.get_int()};
|
||||
}
|
||||
}
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
bool is_load_with_base(const SimpleExpression& expr, Register base) {
|
||||
return get_base_of_load(expr).first == base;
|
||||
}
|
||||
|
||||
bool is_get_load(AtomicOp* ir, Register dst, Register base) {
|
||||
auto as_set = dynamic_cast<LoadVarOp*>(ir);
|
||||
return as_set && as_set->get_set_destination().reg() == dst &&
|
||||
is_load_with_base(as_set->src(), base);
|
||||
}
|
||||
|
||||
struct LoadInfo {
|
||||
int offset = 0;
|
||||
int size = 0;
|
||||
LoadVarOp::Kind kind;
|
||||
};
|
||||
|
||||
LoadInfo get_load_info_from_set(AtomicOp* load) {
|
||||
auto as_load = dynamic_cast<LoadVarOp*>(load);
|
||||
ASSERT(as_load);
|
||||
LoadInfo info;
|
||||
info.kind = as_load->kind();
|
||||
info.size = as_load->size();
|
||||
auto base = get_base_of_load(as_load->src());
|
||||
info.offset = base.second;
|
||||
return info;
|
||||
}
|
||||
|
||||
int identify_int_field(int idx,
|
||||
Function& function,
|
||||
TypeInspectorResult* result,
|
||||
FieldPrint& print_info) {
|
||||
auto load_info = get_load_info_from_set(function.ir2.atomic_ops->ops.at(idx++).get());
|
||||
|
||||
std::string field_type_name;
|
||||
if (load_info.kind == LoadVarOp::Kind::UNSIGNED) {
|
||||
field_type_name += "u";
|
||||
} else if (load_info.kind == LoadVarOp::Kind::FLOAT) {
|
||||
ASSERT(false); // ...
|
||||
}
|
||||
field_type_name += "int";
|
||||
|
||||
switch (load_info.size) {
|
||||
case 1:
|
||||
field_type_name += "8";
|
||||
break;
|
||||
case 2:
|
||||
field_type_name += "16";
|
||||
break;
|
||||
case 4:
|
||||
field_type_name += "32";
|
||||
break;
|
||||
case 8:
|
||||
field_type_name += "64";
|
||||
break;
|
||||
case 16:
|
||||
field_type_name += "128";
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("unknown load op size in identify int field " +
|
||||
std::to_string((int)load_info.size));
|
||||
}
|
||||
|
||||
if (print_info.format == 'e') {
|
||||
field_type_name = "seconds";
|
||||
ASSERT(load_info.size == 8);
|
||||
}
|
||||
|
||||
int offset = load_info.offset;
|
||||
if (result->is_basic) {
|
||||
offset += BASIC_OFFSET;
|
||||
}
|
||||
|
||||
Field field(print_info.field_name, TypeSpec(field_type_name), offset);
|
||||
result->fields_of_type.push_back(field);
|
||||
|
||||
return idx;
|
||||
}
|
||||
int identify_float_field(int idx,
|
||||
Function& function,
|
||||
TypeInspectorResult* result,
|
||||
FieldPrint& print_info) {
|
||||
auto load_info = get_load_info_from_set(function.ir2.atomic_ops->ops.at(idx++).get());
|
||||
ASSERT(load_info.size == 4);
|
||||
ASSERT(load_info.kind == LoadVarOp::Kind::FLOAT);
|
||||
|
||||
auto& float_move = function.ir2.atomic_ops->ops.at(idx++);
|
||||
if (!is_op_2(float_move.get(), SimpleExpression::Kind::FPR_TO_GPR, make_gpr(Reg::A2),
|
||||
make_fpr(0))) {
|
||||
printf("bad float move: %s\n", float_move->to_string(function.ir2.env).c_str());
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
std::string type;
|
||||
switch (print_info.format) {
|
||||
case 'f':
|
||||
type = "float";
|
||||
break;
|
||||
case 'm':
|
||||
type = "meters";
|
||||
break;
|
||||
case 'r':
|
||||
type = "deg";
|
||||
break;
|
||||
case 'X':
|
||||
type = "float";
|
||||
result->warnings += "field " + print_info.field_name + " is a float printed as hex? ";
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
}
|
||||
int offset = load_info.offset;
|
||||
if (result->is_basic) {
|
||||
offset += BASIC_OFFSET;
|
||||
}
|
||||
|
||||
Field field(print_info.field_name, TypeSpec(type), offset);
|
||||
result->fields_of_type.push_back(field);
|
||||
return idx;
|
||||
}
|
||||
|
||||
int identify_pointer_field(int idx,
|
||||
Function& function,
|
||||
TypeInspectorResult* result,
|
||||
FieldPrint& print_info) {
|
||||
auto load_info = get_load_info_from_set(function.ir2.atomic_ops->ops.at(idx++).get());
|
||||
ASSERT(load_info.size == 4);
|
||||
ASSERT(load_info.kind == LoadVarOp::Kind::UNSIGNED);
|
||||
|
||||
int offset = load_info.offset;
|
||||
if (result->is_basic) {
|
||||
offset += BASIC_OFFSET;
|
||||
}
|
||||
|
||||
Field field(print_info.field_name, TypeSpec("pointer"), offset);
|
||||
result->fields_of_type.push_back(field);
|
||||
return idx;
|
||||
}
|
||||
|
||||
bool get_ptr_offset_constant_nonzero(const SimpleExpression& math, Register base, int* result) {
|
||||
// if (!is_reg(math->arg0.get(), base)) {
|
||||
if (!math.get_arg(0).is_var() || math.get_arg(0).var().reg() != base) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!math.get_arg(1).is_int()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*result = math.get_arg(1).get_int();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_ptr_offset(AtomicOp* ir, Register dst, Register base, int* result) {
|
||||
auto as_set = dynamic_cast<SetVarOp*>(ir);
|
||||
if (!as_set) {
|
||||
return false;
|
||||
}
|
||||
if (as_set->dst().reg() != dst) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return get_ptr_offset_constant_nonzero(as_set->src(), base, result);
|
||||
}
|
||||
|
||||
int identify_array_field(int idx,
|
||||
Function& function,
|
||||
TypeInspectorResult* result,
|
||||
FieldPrint& print_info) {
|
||||
auto& get_op = function.ir2.atomic_ops->ops.at(idx++);
|
||||
int offset = 0;
|
||||
if (!get_ptr_offset(get_op.get(), make_gpr(Reg::A2), make_gpr(Reg::GP), &offset)) {
|
||||
printf("bad get ptr offset %s\n", get_op->to_string(function.ir2.env).c_str());
|
||||
ASSERT(false);
|
||||
}
|
||||
if (result->is_basic) {
|
||||
offset += BASIC_OFFSET;
|
||||
}
|
||||
|
||||
Field field(print_info.field_name, TypeSpec("UNKNOWN"), offset);
|
||||
if (print_info.array_size) {
|
||||
field.set_array(print_info.array_size);
|
||||
} else {
|
||||
field.set_dynamic();
|
||||
}
|
||||
result->fields_of_type.push_back(field);
|
||||
return idx;
|
||||
}
|
||||
|
||||
int identify_struct_not_inline_field(int idx,
|
||||
Function& function,
|
||||
TypeInspectorResult* result,
|
||||
FieldPrint& print_info) {
|
||||
auto load_info = get_load_info_from_set(function.ir2.atomic_ops->ops.at(idx++).get());
|
||||
|
||||
if (!(load_info.size == 4 && load_info.kind == LoadVarOp::Kind::UNSIGNED)) {
|
||||
result->warnings += "field " + print_info.field_type_name + " is likely a value type";
|
||||
}
|
||||
int offset = load_info.offset;
|
||||
if (result->is_basic) {
|
||||
offset += BASIC_OFFSET;
|
||||
}
|
||||
|
||||
Field field(print_info.field_name, TypeSpec(print_info.field_type_name), offset);
|
||||
result->fields_of_type.push_back(field);
|
||||
return idx;
|
||||
}
|
||||
|
||||
int identify_struct_inline_field(int idx,
|
||||
Function& function,
|
||||
TypeInspectorResult* result,
|
||||
FieldPrint& print_info) {
|
||||
auto& get_op = function.ir2.atomic_ops->ops.at(idx++);
|
||||
int offset = 0;
|
||||
if (!get_ptr_offset(get_op.get(), make_gpr(Reg::A2), make_gpr(Reg::GP), &offset)) {
|
||||
printf("bad get ptr offset %s\n", get_op->to_string(function.ir2.env).c_str());
|
||||
ASSERT(false);
|
||||
}
|
||||
if (result->is_basic) {
|
||||
offset += BASIC_OFFSET;
|
||||
}
|
||||
|
||||
Field field(print_info.field_name, TypeSpec(print_info.field_type_name), offset);
|
||||
field.set_inline();
|
||||
result->fields_of_type.push_back(field);
|
||||
return idx;
|
||||
}
|
||||
|
||||
int identify_basic_field(int idx,
|
||||
Function& function,
|
||||
LinkedObjectFile& file,
|
||||
TypeInspectorResult* result,
|
||||
FieldPrint& print_info) {
|
||||
(void)file;
|
||||
auto load_info = get_load_info_from_set(function.ir2.atomic_ops->ops.at(idx++).get());
|
||||
ASSERT(load_info.size == 4);
|
||||
ASSERT(load_info.kind == LoadVarOp::Kind::UNSIGNED || load_info.kind == LoadVarOp::Kind::SIGNED);
|
||||
|
||||
if (load_info.kind == LoadVarOp::Kind::SIGNED) {
|
||||
result->warnings += "field " + print_info.field_name + " is a basic loaded with a signed load ";
|
||||
}
|
||||
|
||||
int offset = load_info.offset;
|
||||
if (result->is_basic) {
|
||||
offset += BASIC_OFFSET;
|
||||
}
|
||||
|
||||
Field field(print_info.field_name, TypeSpec("basic"), offset);
|
||||
result->fields_of_type.push_back(field);
|
||||
return idx;
|
||||
}
|
||||
|
||||
int detect(int idx, Function& function, LinkedObjectFile& file, TypeInspectorResult* result) {
|
||||
auto& get_format_op = function.ir2.atomic_ops->ops.at(idx++);
|
||||
if (!is_set_reg_to_symbol_value(get_format_op.get(), make_gpr(Reg::T9), "format")) {
|
||||
ASSERT_MSG(false,
|
||||
fmt::format("bad get format: {}\n", get_format_op->to_string(function.ir2.env)));
|
||||
}
|
||||
|
||||
auto& get_true = function.ir2.atomic_ops->ops.at(idx++);
|
||||
if (!is_set_reg_to_symbol_ptr(get_true.get(), make_gpr(Reg::A0), "#t")) {
|
||||
ASSERT_MSG(false, "bad get true");
|
||||
}
|
||||
|
||||
auto sstr = get_string_loaded_to_reg(function.ir2.atomic_ops->ops.at(idx++).get(),
|
||||
make_gpr(Reg::A1), file);
|
||||
if (!sstr) {
|
||||
ASSERT_MSG(false, "bad sstr");
|
||||
}
|
||||
|
||||
auto info = get_field_print(*sstr);
|
||||
|
||||
auto& first_get_op = function.ir2.atomic_ops->ops.at(idx);
|
||||
|
||||
if (is_get_load(first_get_op.get(), make_gpr(Reg::A2), make_gpr(Reg::GP)) &&
|
||||
(info.format == 'D' || info.format == 'X' || info.format == 'e') && !info.has_array &&
|
||||
info.field_type_name.empty()) {
|
||||
idx = identify_int_field(idx, function, result, info);
|
||||
// it's a load!
|
||||
} else if (is_get_load(first_get_op.get(), make_fpr(0), make_gpr(Reg::GP)) &&
|
||||
(info.format == 'f' || info.format == 'm' || info.format == 'r' ||
|
||||
info.format == 'X') &&
|
||||
!info.has_array && info.field_type_name.empty()) {
|
||||
idx = identify_float_field(idx, function, result, info);
|
||||
} else if (is_get_load(first_get_op.get(), make_gpr(Reg::A2), make_gpr(Reg::GP)) &&
|
||||
info.format == 'A' && !info.has_array && info.field_type_name.empty()) {
|
||||
idx = identify_basic_field(idx, function, file, result, info);
|
||||
} else if (is_get_load(first_get_op.get(), make_gpr(Reg::A2), make_gpr(Reg::GP)) &&
|
||||
info.format == 'X' && !info.has_array && info.field_type_name.empty()) {
|
||||
idx = identify_pointer_field(idx, function, result, info);
|
||||
} else if (info.has_array && (info.format == 'X' || info.format == 'P') &&
|
||||
info.field_type_name.empty()) {
|
||||
idx = identify_array_field(idx, function, result, info);
|
||||
} else if (!info.has_array && (info.format == 'X' || info.format == 'P') &&
|
||||
!info.field_type_name.empty()) {
|
||||
// structure.
|
||||
if (is_get_load(first_get_op.get(), make_gpr(Reg::A2), make_gpr(Reg::GP))) {
|
||||
// not inline
|
||||
idx = identify_struct_not_inline_field(idx, function, result, info);
|
||||
} else {
|
||||
idx = identify_struct_inline_field(idx, function, result, info);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
printf("couldn't do %s, %s\n", sstr->c_str(),
|
||||
first_get_op->to_string(function.ir2.env).c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!dynamic_cast<CallOp*>(function.ir2.atomic_ops->ops.at(idx++).get())) {
|
||||
printf("bad call\n");
|
||||
ASSERT(false);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
std::string inspect_inspect_method(Function& inspect_method,
|
||||
const std::string& type_name,
|
||||
DecompilerTypeSystem& dts,
|
||||
LinkedObjectFile& file,
|
||||
TypeSystem& previous_game_ts) {
|
||||
fmt::print(" iim: {}\n", inspect_method.name());
|
||||
TypeInspectorResult result;
|
||||
ASSERT(type_name == inspect_method.guessed_name.type_name);
|
||||
TypeFlags flags;
|
||||
flags.flag = 0;
|
||||
result.found_flags = dts.lookup_flags(type_name, &flags.flag);
|
||||
result.type_name = type_name;
|
||||
result.parent_type_name = dts.lookup_parent_from_inspects(type_name);
|
||||
result.flags = flags.flag;
|
||||
result.type_size = flags.size;
|
||||
result.type_method_count = flags.methods;
|
||||
result.type_heap_base = flags.heap_base;
|
||||
|
||||
{
|
||||
TypeFlags parent_flags;
|
||||
parent_flags.flag = 0;
|
||||
if (result.parent_type_name != "UNKNOWN" &&
|
||||
dts.lookup_flags(result.parent_type_name, &parent_flags.flag)) {
|
||||
result.parent_method_count = parent_flags.methods;
|
||||
}
|
||||
}
|
||||
if (!result.found_flags) {
|
||||
fmt::print("[iim] no flags found for {}, maybe defined in the kernel\n", type_name);
|
||||
}
|
||||
|
||||
result.parent_type_name = dts.lookup_parent_from_inspects(type_name);
|
||||
int idx = get_start_idx(inspect_method, file, &result, result.parent_type_name, type_name,
|
||||
inspect_method.ir2.env);
|
||||
StructureType* old_game_type = nullptr;
|
||||
if (previous_game_ts.fully_defined_type_exists(type_name)) {
|
||||
old_game_type = dynamic_cast<StructureType*>(previous_game_ts.lookup_type(type_name));
|
||||
}
|
||||
if (idx <= 0) {
|
||||
// can't get any field...
|
||||
result.warnings += "Failed to read fields. ";
|
||||
idx = -2;
|
||||
return result.print_as_deftype(old_game_type);
|
||||
}
|
||||
while (idx < int(inspect_method.ir2.atomic_ops->ops.size()) - 2 && idx != -1) {
|
||||
idx = detect(idx, inspect_method, file, &result);
|
||||
}
|
||||
|
||||
if (idx == -1) {
|
||||
result.warnings += "Failed to read some fields. ";
|
||||
}
|
||||
|
||||
return result.print_as_deftype(old_game_type);
|
||||
}
|
||||
|
||||
std::string old_method_string(const MethodInfo& info) {
|
||||
if (info.type.arg_count() > 0) {
|
||||
if (info.type.base_type() == "function" || info.type.base_type() == "state") {
|
||||
std::string result = fmt::format(" ;; ({} (", info.name);
|
||||
bool add = false;
|
||||
for (int i = 0; i < (int)info.type.arg_count() - 1; i++) {
|
||||
result += info.type.get_arg(i).print();
|
||||
result += ' ';
|
||||
add = true;
|
||||
}
|
||||
if (add) {
|
||||
result.pop_back();
|
||||
}
|
||||
result += ") ";
|
||||
result += info.type.get_arg(info.type.arg_count() - 1).print();
|
||||
if (info.type.base_type() == "state") {
|
||||
result += " :state";
|
||||
}
|
||||
result += fmt::format(" {})", info.id);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return fmt::format(" ;; ({} {}) weird method", info.name, info.type.print());
|
||||
}
|
||||
|
||||
/*
|
||||
* old_game_type may be null
|
||||
*/
|
||||
std::string TypeInspectorResult::print_as_deftype(StructureType* old_game_type) {
|
||||
std::string result;
|
||||
|
||||
result += fmt::format("(deftype {} ({})\n (", type_name, parent_type_name);
|
||||
|
||||
int longest_field_name = 0;
|
||||
int longest_type_name = 0;
|
||||
int longest_mods = 0;
|
||||
|
||||
std::string inline_string = ":inline";
|
||||
std::string dynamic_string = ":dynamic";
|
||||
|
||||
for (auto& field : fields_of_type) {
|
||||
longest_field_name = std::max(longest_field_name, int(field.name().size()));
|
||||
longest_type_name = std::max(longest_type_name, int(field.type().print().size()));
|
||||
|
||||
int mods = 0;
|
||||
// mods are array size, :inline, :dynamic
|
||||
if (field.is_array() && !field.is_dynamic()) {
|
||||
mods += std::to_string(field.array_size()).size();
|
||||
}
|
||||
|
||||
if (field.is_inline()) {
|
||||
if (mods) {
|
||||
mods++; // space
|
||||
}
|
||||
mods += inline_string.size();
|
||||
}
|
||||
|
||||
if (field.is_dynamic()) {
|
||||
if (mods) {
|
||||
mods++; // space
|
||||
}
|
||||
mods += dynamic_string.size();
|
||||
}
|
||||
longest_mods = std::max(longest_mods, mods);
|
||||
}
|
||||
|
||||
for (auto& field : fields_of_type) {
|
||||
result += "(";
|
||||
result += field.name();
|
||||
result.append(1 + (longest_field_name - int(field.name().size())), ' ');
|
||||
result += field.type().print();
|
||||
result.append(1 + (longest_type_name - int(field.type().print().size())), ' ');
|
||||
|
||||
std::string mods;
|
||||
if (field.is_array() && !field.is_dynamic()) {
|
||||
mods += std::to_string(field.array_size());
|
||||
mods += " ";
|
||||
}
|
||||
|
||||
if (field.is_inline()) {
|
||||
mods += inline_string;
|
||||
mods += " ";
|
||||
}
|
||||
|
||||
if (field.is_dynamic()) {
|
||||
mods += dynamic_string;
|
||||
mods += " ";
|
||||
}
|
||||
result.append(mods);
|
||||
result.append(longest_mods - int(mods.size() - 1), ' ');
|
||||
|
||||
result.append(":offset-assert ");
|
||||
result.append(std::to_string(field.offset()));
|
||||
result.append(")");
|
||||
if (old_game_type) {
|
||||
Field old_field;
|
||||
if (old_game_type->lookup_field(field.name(), &old_field)) {
|
||||
if (old_field.type() != field.type()) {
|
||||
result += fmt::format(" ;; {}", old_field.type().print());
|
||||
if (old_field.is_array() && !old_field.is_dynamic()) {
|
||||
result += fmt::format(" {}", old_field.array_size());
|
||||
}
|
||||
if (old_field.is_inline()) {
|
||||
result += " :inline";
|
||||
}
|
||||
if (old_field.is_dynamic()) {
|
||||
result += " :dynamic";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result.append("\n ");
|
||||
}
|
||||
result.append(")\n");
|
||||
|
||||
result.append(fmt::format(" :method-count-assert {}\n", type_method_count));
|
||||
result.append(fmt::format(" :size-assert #x{:x}\n", type_size));
|
||||
result.append(fmt::format(" :flag-assert #x{:x}\n ", flags));
|
||||
if (!warnings.empty()) {
|
||||
result.append(";; ");
|
||||
result.append(warnings);
|
||||
result.append("\n ");
|
||||
}
|
||||
|
||||
if (type_method_count > 9) {
|
||||
result.append("(:methods\n ");
|
||||
MethodInfo old_new_method;
|
||||
if (old_game_type && old_game_type->get_my_new_method(&old_new_method)) {
|
||||
result.append(old_method_string(old_new_method));
|
||||
result.append("\n ");
|
||||
}
|
||||
for (int i = parent_method_count; i < type_method_count; i++) {
|
||||
result.append(fmt::format("(dummy-{} () none {})", i, i));
|
||||
if (old_game_type) {
|
||||
MethodInfo info;
|
||||
if (old_game_type->get_my_method(i, &info)) {
|
||||
result += old_method_string(info);
|
||||
}
|
||||
}
|
||||
result.append("\n ");
|
||||
}
|
||||
result.append(")\n ");
|
||||
}
|
||||
result.append(")\n");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string inspect_top_level_symbol_defines(std::unordered_set<std::string>& already_seen,
|
||||
Function& top_level,
|
||||
LinkedObjectFile& file,
|
||||
DecompilerTypeSystem& dts,
|
||||
DecompilerTypeSystem& previous_game_ts) {
|
||||
if (!top_level.ir2.atomic_ops) {
|
||||
return {};
|
||||
}
|
||||
std::string result;
|
||||
for (auto& aop : top_level.ir2.atomic_ops->ops) {
|
||||
auto* as_store = dynamic_cast<StoreOp*>(aop.get());
|
||||
if (as_store && as_store->addr().kind() == SimpleExpression::Kind::IDENTITY &&
|
||||
as_store->addr().get_arg(0).is_sym_val()) {
|
||||
auto& sym_name = as_store->addr().get_arg(0).get_str();
|
||||
if (already_seen.find(sym_name) == already_seen.end()) {
|
||||
already_seen.insert(sym_name);
|
||||
if (dts.ts.partially_defined_type_exists(sym_name)) {
|
||||
continue;
|
||||
}
|
||||
result += fmt::format(";; (define-extern {} object)", sym_name);
|
||||
auto it = previous_game_ts.symbol_types.find(sym_name);
|
||||
if (it != previous_game_ts.symbol_types.end()) {
|
||||
result += fmt::format(" ;; {}", it->second.print());
|
||||
}
|
||||
result += '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace decompiler
|
23
decompiler/analysis/analyze_inspect_method.h
Normal file
23
decompiler/analysis/analyze_inspect_method.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "decompiler/Function/Function.h"
|
||||
#include "decompiler/util/DecompilerTypeSystem.h"
|
||||
|
||||
namespace decompiler {
|
||||
|
||||
std::string inspect_inspect_method(Function& inspect_method,
|
||||
const std::string& type_name,
|
||||
DecompilerTypeSystem& dts,
|
||||
LinkedObjectFile& file,
|
||||
TypeSystem& previous_game_ts);
|
||||
|
||||
std::string inspect_top_level_symbol_defines(std::unordered_set<std::string>& already_seen,
|
||||
Function& top_level,
|
||||
LinkedObjectFile& file,
|
||||
DecompilerTypeSystem& dts,
|
||||
DecompilerTypeSystem& previous_game_ts);
|
||||
|
||||
} // namespace decompiler
|
@ -1746,11 +1746,23 @@ std::unique_ptr<AtomicOp> convert_5(const Instruction& i0,
|
||||
const Instruction& i2,
|
||||
const Instruction& i3,
|
||||
const Instruction& i4,
|
||||
int idx) {
|
||||
int idx,
|
||||
GameVersion version) {
|
||||
auto s6 = make_gpr(Reg::S6);
|
||||
|
||||
int process_offset = -1;
|
||||
switch (version) {
|
||||
case GameVersion::Jak1:
|
||||
process_offset = 44;
|
||||
break;
|
||||
case GameVersion::Jak2:
|
||||
process_offset = 48;
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
}
|
||||
if (i0.kind == InstructionKind::LWU && i0.get_dst(0).is_reg(s6) &&
|
||||
i0.get_src(0).get_imm() == 44 && i0.get_src(1).is_reg(s6) &&
|
||||
i0.get_src(0).get_imm() == process_offset && i0.get_src(1).is_reg(s6) &&
|
||||
i1.kind == InstructionKind::MTLO1 && i1.get_src(0).is_reg(s6) &&
|
||||
i2.kind == InstructionKind::LWU && i2.get_dst(0).is_reg(s6) &&
|
||||
i2.get_src(0).get_imm() == 12 && i2.get_src(1).is_reg(s6) &&
|
||||
@ -2111,7 +2123,7 @@ int convert_block_to_atomic_ops(int begin_idx,
|
||||
|
||||
if (!converted && n_instr >= 5) {
|
||||
// try 5 instructions
|
||||
op = convert_5(instr[0], instr[1], instr[2], instr[3], instr[4], op_idx);
|
||||
op = convert_5(instr[0], instr[1], instr[2], instr[3], instr[4], op_idx, version);
|
||||
if (op) {
|
||||
converted = true;
|
||||
length = 5;
|
||||
|
@ -110,12 +110,12 @@ void clean_up_until_loop(FormPool& pool, UntilElement* ir, const Env& env) {
|
||||
ASSERT(condition_branch.first);
|
||||
if (condition_branch.first->op()->branch_delay().kind() != IR2_BranchDelay::Kind::NOP) {
|
||||
ASSERT_MSG(
|
||||
false,
|
||||
condition_branch.first->op()->branch_delay().kind() == IR2_BranchDelay::Kind::SET_REG_FALSE,
|
||||
fmt::format(
|
||||
"bad delay slot in until loop: {} in {}\n", env.func->name(),
|
||||
condition_branch.first->op()->branch_delay().to_form(env.file->labels, env).print()));
|
||||
ir->false_destination = condition_branch.first->op()->branch_delay().var(0);
|
||||
}
|
||||
ASSERT(condition_branch.first->op()->branch_delay().kind() == IR2_BranchDelay::Kind::NOP);
|
||||
auto replacement = condition_branch.first->op()->get_condition_as_form(pool, env);
|
||||
replacement->invert();
|
||||
*(condition_branch.second) = replacement;
|
||||
@ -573,7 +573,7 @@ bool try_splitting_nested_sc(FormPool& pool, Function& func, ShortCircuitElement
|
||||
ASSERT(ir->entries.at(i).branch_delay.has_value());
|
||||
bool is_and = delay_slot_sets_false(branch.first, *ir->entries.at(i).branch_delay);
|
||||
bool is_or = delay_slot_sets_truthy(branch.first, *ir->entries.at(i).branch_delay);
|
||||
ASSERT(is_and != is_or);
|
||||
ASSERT_MSG(is_and != is_or, fmt::format("bad nested sc in {}", func.name()));
|
||||
|
||||
if (first_different == -1) {
|
||||
// haven't seen a change yet.
|
||||
@ -925,47 +925,6 @@ bool is_op_3(AtomicOp* op,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_op_2(AtomicOp* op,
|
||||
MatchParam<SimpleExpression::Kind> kind,
|
||||
MatchParam<Register> dst,
|
||||
MatchParam<Register> src0,
|
||||
Register* dst_out = nullptr,
|
||||
Register* src0_out = nullptr) {
|
||||
// should be a set reg to int math 2 ir
|
||||
auto set = dynamic_cast<SetVarOp*>(op);
|
||||
if (!set) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// destination should be a register
|
||||
auto dest = set->dst();
|
||||
if (dst != dest.reg()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto math = set->src();
|
||||
if (kind != math.kind()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto arg = math.get_arg(0);
|
||||
|
||||
if (!arg.is_var() || src0 != arg.var().reg()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// it's a match!
|
||||
if (dst_out) {
|
||||
*dst_out = dest.reg();
|
||||
}
|
||||
|
||||
if (src0_out) {
|
||||
*src0_out = arg.var().reg();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_op_2(FormElement* ir,
|
||||
MatchParam<SimpleExpression::Kind> kind,
|
||||
MatchParam<Register> dst,
|
||||
|
@ -76,7 +76,10 @@ Config read_config_file(const std::string& path_to_config_file,
|
||||
config.is_pal = cfg.at("is_pal").get<bool>();
|
||||
config.rip_levels = cfg.at("levels_convert_to_obj").get<bool>();
|
||||
config.extract_collision = cfg.at("extract_collision").get<bool>();
|
||||
|
||||
config.generate_all_types = cfg.at("generate_all_types").get<bool>();
|
||||
if (cfg.contains("old_all_types_file")) {
|
||||
config.old_all_types_file = cfg.at("old_all_types_file").get<std::string>();
|
||||
}
|
||||
auto allowed = cfg.at("allowed_objects").get<std::vector<std::string>>();
|
||||
for (const auto& x : allowed) {
|
||||
config.allowed_objects.insert(x);
|
||||
|
@ -123,6 +123,9 @@ struct Config {
|
||||
|
||||
bool generate_symbol_definition_map = false;
|
||||
|
||||
bool generate_all_types = false;
|
||||
std::optional<std::string> old_all_types_file;
|
||||
|
||||
bool is_pal = false;
|
||||
|
||||
bool write_patches = false;
|
||||
|
@ -13,4 +13,7 @@
|
||||
(declare-type sparticle-launch-group basic)
|
||||
(declare-type lightning-spec basic)
|
||||
(declare-type sparticle-launcher basic)
|
||||
(declare-type state basic)
|
||||
(declare-type state basic)
|
||||
|
||||
;; debug
|
||||
(define-extern looping-code (function symbol))
|
||||
|
@ -51,6 +51,9 @@
|
||||
// this is a guess at where each symbol is first defined/used.
|
||||
"generate_symbol_definition_map": false,
|
||||
|
||||
// genreate the all-types file
|
||||
"generate_all_types" : false,
|
||||
|
||||
// debug option for instruction decoder
|
||||
"write_hex_near_instructions": false,
|
||||
|
||||
|
@ -4,7 +4,9 @@
|
||||
////////////////////////////
|
||||
|
||||
"types_with_bad_inspect_methods": [
|
||||
|
||||
"game-task-event",
|
||||
"game-task-control",
|
||||
"predator-edge"
|
||||
],
|
||||
|
||||
"no_type_analysis_functions_by_name": [],
|
||||
@ -55,7 +57,8 @@
|
||||
"(anon-function 2 scene)", "progress-trans", "(method 10 bigmap)", "(method 9 editable-region)", "(method 57 enemy)",
|
||||
"(anon-function 10 meet-brutter)", "(method 154 vehicle-racer)", "(method 188 predator)", "(anon-function 13 sig0-course)",
|
||||
"(method 228 hal-sewer)", "(method 154 vehicle-city-racer)", "(method 53 squid)", "(anon-function 11 fort-floor-spike)",
|
||||
"(method 29 gun-dummy)", "vehicle-explode-post", "(method 158 vehicle-guard)", "(method 207 metalhead-predator)"
|
||||
"(method 29 gun-dummy)", "vehicle-explode-post", "(method 158 vehicle-guard)", "(method 207 metalhead-predator)",
|
||||
"(anon-function 4 gun-states)", "(anon-function 28 grenadier)", "(anon-function 24 grenadier)"
|
||||
],
|
||||
|
||||
// these functions use pairs and the decompiler
|
||||
|
@ -8,159 +8,159 @@
|
||||
// the DGOs will be processed in this order. Usually it's best to have KERNEL, ENGINE, then the levels when
|
||||
// you want to run on the entire game.
|
||||
"dgo_names": [
|
||||
"./CGO/ART.CGO",
|
||||
"./CGO/KERNEL.CGO",
|
||||
"./CGO/ENGINE.CGO",
|
||||
"./CGO/GAME.CGO",
|
||||
"./CGO/COMMON.CGO",
|
||||
"./DGO/LWIDEB.DGO",
|
||||
"./DGO/LMEETBRT.DGO",
|
||||
"./DGO/CTA.DGO",
|
||||
"./DGO/PALOUT.DGO",
|
||||
"./DGO/STD.DGO",
|
||||
"./DGO/FOR.DGO",
|
||||
"./DGO/CASEXT.DGO",
|
||||
"./DGO/HIDEOUT.DGO",
|
||||
"./DGO/LWIDESTA.DGO",
|
||||
"./DGO/LRACELIT.DGO",
|
||||
"./DGO/CTB.DGO",
|
||||
"./DGO/KIOSK.DGO",
|
||||
"./DGO/DG1.DGO",
|
||||
"./DGO/FEB.DGO",
|
||||
"./DGO/DMI.DGO",
|
||||
"./DGO/ORACLE.DGO",
|
||||
"./DGO/LERLTESS.DGO",
|
||||
"./DGO/DRI.DGO",
|
||||
"./DGO/LBRNERMK.DGO",
|
||||
"./DGO/LRACECF.DGO",
|
||||
"./DGO/CTC.DGO",
|
||||
"./DGO/LTHRNOUT.DGO",
|
||||
"./DGO/FRA.DGO",
|
||||
"./DGO/LGARCSTA.DGO",
|
||||
"./DGO/MTN.DGO",
|
||||
"./DGO/INTROCST.DGO",
|
||||
"./DGO/DRB.DGO",
|
||||
"./DGO/ATE.DGO",
|
||||
"./DGO/LERROL.DGO",
|
||||
"./DGO/LTRNYSAM.DGO",
|
||||
"./DGO/LOUTCSTB.DGO",
|
||||
"./DGO/LASHTHRN.DGO",
|
||||
"./DGO/TOC.DGO",
|
||||
"./DGO/CFB.DGO",
|
||||
"./DGO/CAB.DGO",
|
||||
"./DGO/STC.DGO",
|
||||
"./DGO/STR.DGO",
|
||||
"./DGO/ATO.DGO",
|
||||
"./DGO/SEB.DGO",
|
||||
"./DGO/LPRSNCST.DGO",
|
||||
"./DGO/SWB.DGO",
|
||||
"./DGO/LPOWER.DGO",
|
||||
"./DGO/FOB.DGO",
|
||||
"./DGO/CIB.DGO",
|
||||
"./DGO/LSHUTTLE.DGO",
|
||||
"./DGO/LJAKDAX.DGO",
|
||||
"./DGO/FORDUMPC.DGO",
|
||||
"./DGO/LTRNTESS.DGO",
|
||||
"./DGO/TBO.DGO",
|
||||
"./DGO/THR.DGO",
|
||||
"./DGO/PRI.DGO",
|
||||
"./DGO/LKIDDOGE.DGO",
|
||||
"./DGO/NESTT.DGO",
|
||||
"./DGO/LWIDEC.DGO",
|
||||
"./DGO/SAG.DGO",
|
||||
"./DGO/NEB.DGO",
|
||||
"./DGO/COB.DGO",
|
||||
"./DGO/LBOMBBOT.DGO",
|
||||
"./DGO/DEMO.DGO",
|
||||
"./DGO/LRACEDF.DGO",
|
||||
"./DGO/LERLCHAL.DGO",
|
||||
"./DGO/LHIPOUT.DGO",
|
||||
"./DGO/OUTROCST.DGO",
|
||||
"./DGO/NES.DGO",
|
||||
"./DGO/PAR.DGO",
|
||||
"./DGO/LERBRNGD.DGO",
|
||||
"./DGO/MTX.DGO",
|
||||
"./DGO/FDA.DGO",
|
||||
"./DGO/LKEIRIFT.DGO",
|
||||
"./DGO/LWHACK.DGO",
|
||||
"./DGO/LJKDXASH.DGO",
|
||||
"./DGO/CAS.DGO",
|
||||
"./DGO/COA.DGO",
|
||||
"./DGO/LTESS.DGO",
|
||||
"./DGO/CFA.DGO",
|
||||
"./DGO/TOMBEXT.DGO",
|
||||
"./DGO/LCGUARD.DGO",
|
||||
"./DGO/TOE.DGO",
|
||||
"./DGO/PALBOSS.DGO",
|
||||
"./DGO/FRB.DGO",
|
||||
"./DGO/PAE.DGO",
|
||||
"./DGO/TITLE.DGO",
|
||||
"./DGO/FORDUMPD.DGO",
|
||||
"./DGO/D3A.DGO",
|
||||
"./DGO/DRILLMTN.DGO",
|
||||
"./DGO/PAC.DGO",
|
||||
"./DGO/LTENTOB.DGO",
|
||||
"./DGO/LRACEBF.DGO",
|
||||
"./DGO/LPROTECT.DGO",
|
||||
"./DGO/FEA.DGO",
|
||||
"./DGO/ONINTENT.DGO",
|
||||
"./DGO/STA.DGO",
|
||||
"./DGO/CGC.DGO",
|
||||
"./DGO/CMA.DGO",
|
||||
"./DGO/FDB.DGO",
|
||||
"./DGO/SKA.DGO",
|
||||
"./DGO/LTRNKRKD.DGO",
|
||||
"./DGO/CIA.DGO",
|
||||
"./DGO/TOB.DGO",
|
||||
"./DGO/LRACEDB.DGO",
|
||||
"./DGO/LDJAKBRN.DGO",
|
||||
"./DGO/TOA.DGO",
|
||||
"./DGO/STADBLMP.DGO",
|
||||
"./DGO/UND.DGO",
|
||||
"./DGO/LYSKDCD.DGO",
|
||||
"./DGO/HALFPIPE.DGO",
|
||||
"./DGO/LSAMERGD.DGO",
|
||||
"./DGO/PAS.DGO",
|
||||
"./DGO/LBBUSH.DGO",
|
||||
"./DGO/LPACKAGE.DGO",
|
||||
"./DGO/LINTCSTB.DGO",
|
||||
"./DGO/LPORTRUN.DGO",
|
||||
"./DGO/LASHGRD.DGO",
|
||||
"./DGO/CGB.DGO",
|
||||
"./DGO/D3B.DGO",
|
||||
"./DGO/STB.DGO",
|
||||
"./DGO/GARAGE.DGO",
|
||||
"./DGO/PORTWALL.DGO",
|
||||
"./DGO/LHELLDOG.DGO",
|
||||
"./DGO/SWE.DGO",
|
||||
"./DGO/LRACECB.DGO",
|
||||
"./DGO/GGA.DGO",
|
||||
"./DGO/TOD.DGO",
|
||||
"./DGO/MCN.DGO",
|
||||
"./DGO/SEW.DGO",
|
||||
"./DGO/VIN.DGO",
|
||||
"./DGO/CGA.DGO",
|
||||
"./DGO/CMB.DGO",
|
||||
"./DGO/LGUARD.DGO",
|
||||
"./DGO/CPA.DGO",
|
||||
"./DGO/LCITYLOW.DGO",
|
||||
"./DGO/LTENTOUT.DGO",
|
||||
"./DGO/UNB.DGO",
|
||||
"./DGO/CPO.DGO",
|
||||
"./DGO/CAP.DGO",
|
||||
"./DGO/CWI.DGO",
|
||||
"./DGO/CTYKORA.DGO",
|
||||
"./DGO/RUI.DGO",
|
||||
"./DGO/LSACK.DGO",
|
||||
"./DGO/CTYASHA.DGO",
|
||||
"./DGO/LPRTRACE.DGO",
|
||||
"./DGO/LWIDEA.DGO",
|
||||
"./DGO/HIPHOG.DGO",
|
||||
"./DGO/LSMYSBRT.DGO",
|
||||
"./DGO/LRACEBB.DGO",
|
||||
"./DGO/CASCITY.DGO",
|
||||
"./DGO/LYSAMSAM.DGO",
|
||||
"./DGO/VI1.DGO"
|
||||
"CGO/ART.CGO",
|
||||
"CGO/KERNEL.CGO",
|
||||
"CGO/ENGINE.CGO",
|
||||
"CGO/GAME.CGO",
|
||||
"CGO/COMMON.CGO",
|
||||
"DGO/LWIDEB.DGO",
|
||||
"DGO/LMEETBRT.DGO",
|
||||
"DGO/CTA.DGO",
|
||||
"DGO/PALOUT.DGO",
|
||||
"DGO/STD.DGO",
|
||||
"DGO/FOR.DGO",
|
||||
"DGO/CASEXT.DGO",
|
||||
"DGO/HIDEOUT.DGO",
|
||||
"DGO/LWIDESTA.DGO",
|
||||
"DGO/LRACELIT.DGO",
|
||||
"DGO/CTB.DGO",
|
||||
"DGO/KIOSK.DGO",
|
||||
"DGO/DG1.DGO",
|
||||
"DGO/FEB.DGO",
|
||||
"DGO/DMI.DGO",
|
||||
"DGO/ORACLE.DGO",
|
||||
"DGO/LERLTESS.DGO",
|
||||
"DGO/DRI.DGO",
|
||||
"DGO/LBRNERMK.DGO",
|
||||
"DGO/LRACECF.DGO",
|
||||
"DGO/CTC.DGO",
|
||||
"DGO/LTHRNOUT.DGO",
|
||||
"DGO/FRA.DGO",
|
||||
"DGO/LGARCSTA.DGO",
|
||||
"DGO/MTN.DGO",
|
||||
"DGO/INTROCST.DGO",
|
||||
"DGO/DRB.DGO",
|
||||
"DGO/ATE.DGO",
|
||||
"DGO/LERROL.DGO",
|
||||
"DGO/LTRNYSAM.DGO",
|
||||
"DGO/LOUTCSTB.DGO",
|
||||
"DGO/LASHTHRN.DGO",
|
||||
"DGO/TOC.DGO",
|
||||
"DGO/CFB.DGO",
|
||||
"DGO/CAB.DGO",
|
||||
"DGO/STC.DGO",
|
||||
"DGO/STR.DGO",
|
||||
"DGO/ATO.DGO",
|
||||
"DGO/SEB.DGO",
|
||||
"DGO/LPRSNCST.DGO",
|
||||
"DGO/SWB.DGO",
|
||||
"DGO/LPOWER.DGO",
|
||||
"DGO/FOB.DGO",
|
||||
"DGO/CIB.DGO",
|
||||
"DGO/LSHUTTLE.DGO",
|
||||
"DGO/LJAKDAX.DGO",
|
||||
"DGO/FORDUMPC.DGO",
|
||||
"DGO/LTRNTESS.DGO",
|
||||
"DGO/TBO.DGO",
|
||||
"DGO/THR.DGO",
|
||||
"DGO/PRI.DGO",
|
||||
"DGO/LKIDDOGE.DGO",
|
||||
"DGO/NESTT.DGO",
|
||||
"DGO/LWIDEC.DGO",
|
||||
"DGO/SAG.DGO",
|
||||
"DGO/NEB.DGO",
|
||||
"DGO/COB.DGO",
|
||||
"DGO/LBOMBBOT.DGO",
|
||||
"DGO/DEMO.DGO",
|
||||
"DGO/LRACEDF.DGO",
|
||||
"DGO/LERLCHAL.DGO",
|
||||
"DGO/LHIPOUT.DGO",
|
||||
"DGO/OUTROCST.DGO",
|
||||
"DGO/NES.DGO",
|
||||
"DGO/PAR.DGO",
|
||||
"DGO/LERBRNGD.DGO",
|
||||
"DGO/MTX.DGO",
|
||||
"DGO/FDA.DGO",
|
||||
"DGO/LKEIRIFT.DGO",
|
||||
"DGO/LWHACK.DGO",
|
||||
"DGO/LJKDXASH.DGO",
|
||||
"DGO/CAS.DGO",
|
||||
"DGO/COA.DGO",
|
||||
"DGO/LTESS.DGO",
|
||||
"DGO/CFA.DGO",
|
||||
"DGO/TOMBEXT.DGO",
|
||||
"DGO/LCGUARD.DGO",
|
||||
"DGO/TOE.DGO",
|
||||
"DGO/PALBOSS.DGO",
|
||||
"DGO/FRB.DGO",
|
||||
"DGO/PAE.DGO",
|
||||
"DGO/TITLE.DGO",
|
||||
"DGO/FORDUMPD.DGO",
|
||||
"DGO/D3A.DGO",
|
||||
"DGO/DRILLMTN.DGO",
|
||||
"DGO/PAC.DGO",
|
||||
"DGO/LTENTOB.DGO",
|
||||
"DGO/LRACEBF.DGO",
|
||||
"DGO/LPROTECT.DGO",
|
||||
"DGO/FEA.DGO",
|
||||
"DGO/ONINTENT.DGO",
|
||||
"DGO/STA.DGO",
|
||||
"DGO/CGC.DGO",
|
||||
"DGO/CMA.DGO",
|
||||
"DGO/FDB.DGO",
|
||||
"DGO/SKA.DGO",
|
||||
"DGO/LTRNKRKD.DGO",
|
||||
"DGO/CIA.DGO",
|
||||
"DGO/TOB.DGO",
|
||||
"DGO/LRACEDB.DGO",
|
||||
"DGO/LDJAKBRN.DGO",
|
||||
"DGO/TOA.DGO",
|
||||
"DGO/STADBLMP.DGO",
|
||||
"DGO/UND.DGO",
|
||||
"DGO/LYSKDCD.DGO",
|
||||
"DGO/HALFPIPE.DGO",
|
||||
"DGO/LSAMERGD.DGO",
|
||||
"DGO/PAS.DGO",
|
||||
"DGO/LBBUSH.DGO",
|
||||
"DGO/LPACKAGE.DGO",
|
||||
"DGO/LINTCSTB.DGO",
|
||||
"DGO/LPORTRUN.DGO",
|
||||
"DGO/LASHGRD.DGO",
|
||||
"DGO/CGB.DGO",
|
||||
"DGO/D3B.DGO",
|
||||
"DGO/STB.DGO",
|
||||
"DGO/GARAGE.DGO",
|
||||
"DGO/PORTWALL.DGO",
|
||||
"DGO/LHELLDOG.DGO",
|
||||
"DGO/SWE.DGO",
|
||||
"DGO/LRACECB.DGO",
|
||||
"DGO/GGA.DGO",
|
||||
"DGO/TOD.DGO",
|
||||
"DGO/MCN.DGO",
|
||||
"DGO/SEW.DGO",
|
||||
"DGO/VIN.DGO",
|
||||
"DGO/CGA.DGO",
|
||||
"DGO/CMB.DGO",
|
||||
"DGO/LGUARD.DGO",
|
||||
"DGO/CPA.DGO",
|
||||
"DGO/LCITYLOW.DGO",
|
||||
"DGO/LTENTOUT.DGO",
|
||||
"DGO/UNB.DGO",
|
||||
"DGO/CPO.DGO",
|
||||
"DGO/CAP.DGO",
|
||||
"DGO/CWI.DGO",
|
||||
"DGO/CTYKORA.DGO",
|
||||
"DGO/RUI.DGO",
|
||||
"DGO/LSACK.DGO",
|
||||
"DGO/CTYASHA.DGO",
|
||||
"DGO/LPRTRACE.DGO",
|
||||
"DGO/LWIDEA.DGO",
|
||||
"DGO/HIPHOG.DGO",
|
||||
"DGO/LSMYSBRT.DGO",
|
||||
"DGO/LRACEBB.DGO",
|
||||
"DGO/CASCITY.DGO",
|
||||
"DGO/LYSAMSAM.DGO",
|
||||
"DGO/VI1.DGO"
|
||||
],
|
||||
|
||||
// some objects are part of STR files (streaming data).
|
||||
|
@ -68,6 +68,13 @@
|
||||
// set to true for PAL versions. this will forcefully skip files that have some data missing at the end.
|
||||
"is_pal": false,
|
||||
|
||||
"generate_all_types": true,
|
||||
"write_patches": false,
|
||||
"apply_patches": false,
|
||||
"object_patches": [],
|
||||
// jak 1's all-types, used to generate "hints"
|
||||
"old_all_types_file": "decompiler/config/all-types.gc",
|
||||
|
||||
////////////////////////////
|
||||
// CONFIG FILES
|
||||
////////////////////////////
|
||||
|
@ -174,6 +174,13 @@ int main(int argc, char** argv) {
|
||||
db.analyze_functions_ir2(out_folder, config, {});
|
||||
}
|
||||
|
||||
if (config.generate_all_types) {
|
||||
ASSERT_MSG(config.decompile_code, "Must decompile code to generate all-types");
|
||||
db.ir2_analyze_all_types(file_util::combine_path(out_folder, "new-all-types.gc"),
|
||||
config.old_all_types_file,
|
||||
config.hacks.types_with_bad_inspect_methods);
|
||||
}
|
||||
|
||||
fmt::print("[Mem] After decomp: {} MB\n", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
// write out all symbols
|
||||
|
@ -403,8 +403,8 @@ int DecompilerTypeSystem::get_format_arg_count(const std::string& str) const {
|
||||
}
|
||||
|
||||
static const std::vector<char> single_char_ignore_list = {'%', 'T'};
|
||||
static const std::vector<std::string> multi_char_ignore_list = {"0L", "1L", "3L", "1K",
|
||||
"2j", "0k", "30L"};
|
||||
static const std::vector<std::string> multi_char_ignore_list = {"0L", "1L", "3L", "1K",
|
||||
"2j", "0k", "30L", "1T"};
|
||||
|
||||
int arg_count = 0;
|
||||
for (size_t i = 0; i < str.length(); i++) {
|
||||
|
6
scripts/shell/decomp2.sh
Executable file
6
scripts/shell/decomp2.sh
Executable file
@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Directory of this script
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
"${DIR}"/../../build/decompiler/decompiler "${DIR}"/../../decompiler/config/jak2_ntsc_v1.jsonc "${DIR}"/../../iso_data/ "${DIR}"/../../decompiler_out
|
@ -128,7 +128,7 @@ std::unique_ptr<FormRegressionTest::TestData> FormRegressionTest::make_function(
|
||||
auto program = parser->parse_program(code, string_label_names);
|
||||
|
||||
// create the test data collection
|
||||
auto test = std::make_unique<TestData>(program.instructions.size());
|
||||
auto test = std::make_unique<TestData>(program.instructions.size(), settings.version);
|
||||
// populate the LinkedObjectFile
|
||||
test->file.words_by_seg.resize(3);
|
||||
test->file.labels = program.labels;
|
||||
@ -160,7 +160,7 @@ std::unique_ptr<FormRegressionTest::TestData> FormRegressionTest::make_function(
|
||||
// analyze function prologue/epilogue
|
||||
test->func.analyze_prologue(test->file);
|
||||
// build control flow graph
|
||||
test->func.cfg = build_cfg(test->file, 0, test->func, {}, {});
|
||||
test->func.cfg = build_cfg(test->file, 0, test->func, {}, {}, settings.version);
|
||||
EXPECT_TRUE(test->func.cfg->is_fully_resolved());
|
||||
if (!test->func.cfg->is_fully_resolved()) {
|
||||
fmt::print("CFG:\n{}\n", test->func.cfg->to_dot());
|
||||
@ -176,7 +176,7 @@ std::unique_ptr<FormRegressionTest::TestData> FormRegressionTest::make_function(
|
||||
// convert instruction to atomic ops
|
||||
DecompWarnings warnings;
|
||||
auto ops = convert_function_to_atomic_ops(test->func, program.labels, warnings, false, {},
|
||||
GameVersion::Jak1);
|
||||
settings.version);
|
||||
test->func.ir2.atomic_ops = std::make_shared<FunctionAtomicOps>(std::move(ops));
|
||||
test->func.ir2.atomic_ops_succeeded = true;
|
||||
test->func.ir2.env.set_end_var(test->func.ir2.atomic_ops->end_op().return_var());
|
||||
@ -280,7 +280,7 @@ void FormRegressionTest::test(const std::string& code,
|
||||
EXPECT_TRUE(expected_form == actual_form);
|
||||
}
|
||||
|
||||
void FormRegressionTest::test_final_function(
|
||||
void FormRegressionTest::test_final_function_jak1(
|
||||
const std::string& code,
|
||||
const std::string& type,
|
||||
const std::string& expected,
|
||||
@ -311,12 +311,12 @@ void FormRegressionTest::test_final_function(
|
||||
EXPECT_TRUE(expected_form == actual_form);
|
||||
}
|
||||
|
||||
void FormRegressionTest::test_with_stack_structures(const std::string& code,
|
||||
const std::string& type,
|
||||
const std::string& expected,
|
||||
const std::string& stack_map_json,
|
||||
const std::string& cast_json,
|
||||
const std::string& var_map_json) {
|
||||
void FormRegressionTest::test_with_stack_structures_jak1(const std::string& code,
|
||||
const std::string& type,
|
||||
const std::string& expected,
|
||||
const std::string& stack_map_json,
|
||||
const std::string& cast_json,
|
||||
const std::string& var_map_json) {
|
||||
TestSettings settings;
|
||||
settings.do_expressions = true;
|
||||
settings.stack_structure_json = stack_map_json;
|
||||
|
@ -20,6 +20,7 @@ struct TestSettings {
|
||||
std::string casts_json;
|
||||
std::string var_map_json;
|
||||
std::string stack_structure_json;
|
||||
GameVersion version = GameVersion::Jak1;
|
||||
};
|
||||
|
||||
class FormRegressionTest : public ::testing::Test {
|
||||
@ -31,7 +32,7 @@ class FormRegressionTest : public ::testing::Test {
|
||||
static void TearDownTestCase();
|
||||
|
||||
struct TestData {
|
||||
explicit TestData(int instrs) : func(0, instrs) {}
|
||||
explicit TestData(int instrs, GameVersion version) : func(0, instrs, version) {}
|
||||
decompiler::Function func;
|
||||
decompiler::LinkedObjectFile file;
|
||||
|
||||
@ -41,28 +42,28 @@ class FormRegressionTest : public ::testing::Test {
|
||||
std::unique_ptr<TestData> make_function(const std::string& code,
|
||||
const TypeSpec& function_type,
|
||||
const TestSettings& settings);
|
||||
|
||||
void test(const std::string& code,
|
||||
const std::string& type,
|
||||
const std::string& expected,
|
||||
const TestSettings& settings);
|
||||
|
||||
void test_final_function(const std::string& code,
|
||||
const std::string& type,
|
||||
const std::string& expected,
|
||||
bool allow_pairs = false,
|
||||
const std::vector<std::pair<std::string, std::string>>& strings = {},
|
||||
const std::string& cast_json = "",
|
||||
const std::string& var_map_json = "");
|
||||
void test_final_function_jak1(
|
||||
const std::string& code,
|
||||
const std::string& type,
|
||||
const std::string& expected,
|
||||
bool allow_pairs = false,
|
||||
const std::vector<std::pair<std::string, std::string>>& strings = {},
|
||||
const std::string& cast_json = "",
|
||||
const std::string& var_map_json = "");
|
||||
|
||||
void test_no_expr(const std::string& code,
|
||||
const std::string& type,
|
||||
const std::string& expected,
|
||||
bool allow_pairs = false,
|
||||
const std::string& method_name = "",
|
||||
const std::vector<std::pair<std::string, std::string>>& strings = {},
|
||||
const std::string& cast_json = "",
|
||||
const std::string& var_map_json = "") {
|
||||
void test_no_expr_jak1(const std::string& code,
|
||||
const std::string& type,
|
||||
const std::string& expected,
|
||||
bool allow_pairs = false,
|
||||
const std::string& method_name = "",
|
||||
const std::vector<std::pair<std::string, std::string>>& strings = {},
|
||||
const std::string& cast_json = "",
|
||||
const std::string& var_map_json = "") {
|
||||
TestSettings settings;
|
||||
settings.allow_pairs = allow_pairs;
|
||||
settings.method_name = method_name;
|
||||
@ -73,14 +74,14 @@ class FormRegressionTest : public ::testing::Test {
|
||||
test(code, type, expected, settings);
|
||||
}
|
||||
|
||||
void test_with_expr(const std::string& code,
|
||||
const std::string& type,
|
||||
const std::string& expected,
|
||||
bool allow_pairs = false,
|
||||
const std::string& method_name = "",
|
||||
const std::vector<std::pair<std::string, std::string>>& strings = {},
|
||||
const std::string& cast_json = "",
|
||||
const std::string& var_map_json = "") {
|
||||
void test_with_expr_jak1(const std::string& code,
|
||||
const std::string& type,
|
||||
const std::string& expected,
|
||||
bool allow_pairs = false,
|
||||
const std::string& method_name = "",
|
||||
const std::vector<std::pair<std::string, std::string>>& strings = {},
|
||||
const std::string& cast_json = "",
|
||||
const std::string& var_map_json = "") {
|
||||
TestSettings settings;
|
||||
settings.allow_pairs = allow_pairs;
|
||||
settings.method_name = method_name;
|
||||
@ -91,10 +92,10 @@ class FormRegressionTest : public ::testing::Test {
|
||||
test(code, type, expected, settings);
|
||||
}
|
||||
|
||||
void test_with_stack_structures(const std::string& code,
|
||||
const std::string& type,
|
||||
const std::string& expected,
|
||||
const std::string& stack_map_json,
|
||||
const std::string& cast_json = "",
|
||||
const std::string& var_map_json = "");
|
||||
void test_with_stack_structures_jak1(const std::string& code,
|
||||
const std::string& type,
|
||||
const std::string& expected,
|
||||
const std::string& stack_map_json,
|
||||
const std::string& cast_json = "",
|
||||
const std::string& var_map_json = "");
|
||||
};
|
@ -681,17 +681,17 @@ TEST_F(FormRegressionTest, ExprDisasmVif) {
|
||||
" )\n"
|
||||
" (- gp-0 (* arg1 4))\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "",
|
||||
{{"L139", " #x~X:"},
|
||||
{"L138", " (~s :irq ~D)~%"},
|
||||
{"L137", " (~s :irq ~D :~s #x~X)~%"},
|
||||
{"L136", " (~s :irq ~D :wl ~D :cl ~D)~%"},
|
||||
{"L135", " (~s :irq ~D :~s "},
|
||||
{"L134", "#x~X #x~X #x~X #x~X)~%"},
|
||||
{"L133", " (~s :irq ~D :instructions #x~D :addr #x~X)~%"},
|
||||
{"L132", " (~s :irq ~D :qwc #x~D)~%"},
|
||||
{"L145", " #x~X: #x~8x #x~8x #x~8x #x~8x~%"},
|
||||
{"L131", " (~s :irq ~D :num ~D :addr #x~X "},
|
||||
{"L130", ":msk ~D :flg ~D :usn ~D [skip ~d])~%"},
|
||||
{"L129", " (*unknown* vif-tag #x~X)~%"}});
|
||||
test_with_expr_jak1(func, type, expected, false, "",
|
||||
{{"L139", " #x~X:"},
|
||||
{"L138", " (~s :irq ~D)~%"},
|
||||
{"L137", " (~s :irq ~D :~s #x~X)~%"},
|
||||
{"L136", " (~s :irq ~D :wl ~D :cl ~D)~%"},
|
||||
{"L135", " (~s :irq ~D :~s "},
|
||||
{"L134", "#x~X #x~X #x~X #x~X)~%"},
|
||||
{"L133", " (~s :irq ~D :instructions #x~D :addr #x~X)~%"},
|
||||
{"L132", " (~s :irq ~D :qwc #x~D)~%"},
|
||||
{"L145", " #x~X: #x~8x #x~8x #x~8x #x~8x~%"},
|
||||
{"L131", " (~s :irq ~D :num ~D :addr #x~X "},
|
||||
{"L130", ":msk ~D :flg ~D :usn ~D [skip ~d])~%"},
|
||||
{"L129", " (*unknown* vif-tag #x~X)~%"}});
|
||||
}
|
@ -28,7 +28,7 @@ TEST_F(FormRegressionTest, SimplestTest) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function object object)";
|
||||
std::string expected = "(begin (set! v0-0 a0-0) (ret-value v0-0))";
|
||||
test_no_expr(func, type, expected);
|
||||
test_no_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, Op3) {
|
||||
@ -40,7 +40,7 @@ TEST_F(FormRegressionTest, Op3) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(begin (set! v0-0 (*.si a0-0 a1-0)) (ret-value v0-0))";
|
||||
test_no_expr(func, type, expected);
|
||||
test_no_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, Division) {
|
||||
@ -53,7 +53,7 @@ TEST_F(FormRegressionTest, Division) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(begin (set! v0-0 (/.si a0-0 a1-0)) (ret-value v0-0))";
|
||||
test_no_expr(func, type, expected);
|
||||
test_no_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, Ash) {
|
||||
@ -73,7 +73,7 @@ TEST_F(FormRegressionTest, Ash) {
|
||||
" sll r0, r0, 0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(begin (set! v1-0 a0-0) (set! v0-0 (ash.si v1-0 a1-0)) (ret-value v0-0))";
|
||||
test_no_expr(func, type, expected);
|
||||
test_no_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, Abs) {
|
||||
@ -89,7 +89,7 @@ TEST_F(FormRegressionTest, Abs) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int)";
|
||||
std::string expected = "(begin (set! v0-0 a0-0) (set! v0-0 (abs v0-0)) (ret-value v0-0))";
|
||||
test_no_expr(func, type, expected);
|
||||
test_no_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, Min) {
|
||||
@ -109,7 +109,7 @@ TEST_F(FormRegressionTest, Min) {
|
||||
" (set! v0-1 (min.si v0-0 v1-0))\n"
|
||||
" (ret-value v0-1)\n"
|
||||
" )";
|
||||
test_no_expr(func, type, expected);
|
||||
test_no_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, Max) {
|
||||
@ -130,7 +130,7 @@ TEST_F(FormRegressionTest, Max) {
|
||||
" (set! v0-1 (max.si v0-0 v1-0))\n"
|
||||
" (ret-value v0-1)\n"
|
||||
" )";
|
||||
test_no_expr(func, type, expected);
|
||||
test_no_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, FormatString) {
|
||||
@ -169,7 +169,7 @@ TEST_F(FormRegressionTest, FormatString) {
|
||||
" (set! v0-1 a0-0)\n"
|
||||
" (ret-value v0-1)\n"
|
||||
" )";
|
||||
test_no_expr(func, type, expected, false, "", {{"L343", "~f"}});
|
||||
test_no_expr_jak1(func, type, expected, false, "", {{"L343", "~f"}});
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, WhileLoop) {
|
||||
@ -212,7 +212,7 @@ TEST_F(FormRegressionTest, WhileLoop) {
|
||||
" (set! v0-0 #f)\n"
|
||||
" (ret-value v0-0)\n"
|
||||
" )";
|
||||
test_no_expr(func, type, expected);
|
||||
test_no_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
// Note - this test looks weird because or's aren't fully processed at this point.
|
||||
@ -278,7 +278,7 @@ TEST_F(FormRegressionTest, Or) {
|
||||
" (set! v0-0 #f)\n"
|
||||
" (ret-value v0-0)\n"
|
||||
" )";
|
||||
test_no_expr(func, type, expected);
|
||||
test_no_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, DynamicMethodAccess) {
|
||||
@ -355,7 +355,7 @@ TEST_F(FormRegressionTest, DynamicMethodAccess) {
|
||||
" )\n"
|
||||
" (ret-value v0-0)\n"
|
||||
" )";
|
||||
test_no_expr(func, type, expected);
|
||||
test_no_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, SimpleLoopMergeCheck) {
|
||||
@ -397,7 +397,7 @@ TEST_F(FormRegressionTest, SimpleLoopMergeCheck) {
|
||||
" (set! v0-0 (car a0-0))\n"
|
||||
" (ret-value v0-0)\n"
|
||||
" )";
|
||||
test_no_expr(func, type, expected, true);
|
||||
test_no_expr_jak1(func, type, expected, true);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, And) {
|
||||
@ -467,7 +467,7 @@ TEST_F(FormRegressionTest, And) {
|
||||
" )\n"
|
||||
" )"
|
||||
"(ret-value v0-0))\n";
|
||||
test_no_expr(func, type, expected, true);
|
||||
test_no_expr_jak1(func, type, expected, true);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, FunctionCall) {
|
||||
@ -548,7 +548,7 @@ TEST_F(FormRegressionTest, FunctionCall) {
|
||||
" (set! v0-1 a1-0)\n" // not empty, so return the result
|
||||
" )" // the (set! v0 #f) from the if is added later.
|
||||
" (ret-value v0-1))\n";
|
||||
test_no_expr(func, type, expected, true);
|
||||
test_no_expr_jak1(func, type, expected, true);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, NestedAndOr) {
|
||||
@ -715,7 +715,7 @@ TEST_F(FormRegressionTest, NestedAndOr) {
|
||||
" (set! v0-1 a0-0)\n"
|
||||
" (ret-value v0-1)\n"
|
||||
" )";
|
||||
test_no_expr(func, type, expected, true);
|
||||
test_no_expr_jak1(func, type, expected, true);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, NewMethod) {
|
||||
@ -770,7 +770,7 @@ TEST_F(FormRegressionTest, NewMethod) {
|
||||
" (set! (-> v0-0 allocated-length) a2-0)\n"
|
||||
" )"
|
||||
" (ret-value v0-0))\n";
|
||||
test_no_expr(func, type, expected, false, "inline-array-class");
|
||||
test_no_expr_jak1(func, type, expected, false, "inline-array-class");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, Recursive) {
|
||||
@ -815,7 +815,7 @@ TEST_F(FormRegressionTest, Recursive) {
|
||||
" )\n"
|
||||
" )"
|
||||
" (ret-value v0-0))\n";
|
||||
test_no_expr(func, type, expected, false);
|
||||
test_no_expr_jak1(func, type, expected, false);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, TypeOf) {
|
||||
@ -851,5 +851,5 @@ TEST_F(FormRegressionTest, TypeOf) {
|
||||
" (set! v0-0 (call! a0-0))\n"
|
||||
" (ret-value v0-0)\n"
|
||||
" )";
|
||||
test_no_expr(func, type, expected, false);
|
||||
test_no_expr_jak1(func, type, expected, false);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ TEST_F(FormRegressionTest, ExprIdentity) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function object object)";
|
||||
std::string expected = "arg0";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprFloatingPoint) {
|
||||
@ -31,7 +31,7 @@ TEST_F(FormRegressionTest, ExprFloatingPoint) {
|
||||
" daddiu sp, sp, 16";
|
||||
std::string type = "(function float float)";
|
||||
std::string expected = "(/ 0.0 arg0)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprAdditionSigned) {
|
||||
@ -42,7 +42,7 @@ TEST_F(FormRegressionTest, ExprAdditionSigned) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(+ arg0 arg1)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprAdditionUnSigned) {
|
||||
@ -53,7 +53,7 @@ TEST_F(FormRegressionTest, ExprAdditionUnSigned) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function uint uint uint)";
|
||||
std::string expected = "(+ arg0 arg1)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprAdditionMixed1) {
|
||||
@ -64,7 +64,7 @@ TEST_F(FormRegressionTest, ExprAdditionMixed1) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int uint int)";
|
||||
std::string expected = "(+ arg0 arg1)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprAdditionMixed2) {
|
||||
@ -75,7 +75,7 @@ TEST_F(FormRegressionTest, ExprAdditionMixed2) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function uint int uint)";
|
||||
std::string expected = "(+ arg0 arg1)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprAdditionSignedWrongReturn) {
|
||||
@ -86,7 +86,7 @@ TEST_F(FormRegressionTest, ExprAdditionSignedWrongReturn) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int uint)";
|
||||
std::string expected = "(the-as uint (+ arg0 arg1))";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprAdditionUnSignedWrongReturn) {
|
||||
@ -97,7 +97,7 @@ TEST_F(FormRegressionTest, ExprAdditionUnSignedWrongReturn) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function uint uint int)";
|
||||
std::string expected = "(the-as int (+ arg0 arg1))";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprAdditionMixed1WrongReturn) {
|
||||
@ -108,7 +108,7 @@ TEST_F(FormRegressionTest, ExprAdditionMixed1WrongReturn) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int uint uint)";
|
||||
std::string expected = "(the-as uint (+ arg0 arg1))";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprAdditionMixed2WrongReturn) {
|
||||
@ -119,7 +119,7 @@ TEST_F(FormRegressionTest, ExprAdditionMixed2WrongReturn) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function uint int int)";
|
||||
std::string expected = "(the-as int (+ arg0 arg1))";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprSubtraction) {
|
||||
@ -130,7 +130,7 @@ TEST_F(FormRegressionTest, ExprSubtraction) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(- arg0 arg1)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMultiplication) {
|
||||
@ -141,7 +141,7 @@ TEST_F(FormRegressionTest, ExprMultiplication) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(* arg0 arg1)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMultiplicationWrong1) {
|
||||
@ -152,7 +152,7 @@ TEST_F(FormRegressionTest, ExprMultiplicationWrong1) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int uint int)";
|
||||
std::string expected = "(* arg0 (the-as int arg1))";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMultiplicationWrong2) {
|
||||
@ -163,7 +163,7 @@ TEST_F(FormRegressionTest, ExprMultiplicationWrong2) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function uint int int)";
|
||||
std::string expected = "(* (the-as int arg0) arg1)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMultiplicationWrong3) {
|
||||
@ -174,7 +174,7 @@ TEST_F(FormRegressionTest, ExprMultiplicationWrong3) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function uint uint uint)";
|
||||
std::string expected = "(the-as uint (* (the-as int arg0) (the-as int arg1)))";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprDivision1) {
|
||||
@ -186,7 +186,7 @@ TEST_F(FormRegressionTest, ExprDivision1) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(/ arg0 arg1)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprDivision2) {
|
||||
@ -198,7 +198,7 @@ TEST_F(FormRegressionTest, ExprDivision2) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function uint int int)";
|
||||
std::string expected = "(/ (the-as int arg0) arg1)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprDivision3) {
|
||||
@ -210,7 +210,7 @@ TEST_F(FormRegressionTest, ExprDivision3) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int uint int)";
|
||||
std::string expected = "(/ arg0 (the-as int arg1))";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprDivision4) {
|
||||
@ -222,7 +222,7 @@ TEST_F(FormRegressionTest, ExprDivision4) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function uint uint uint)";
|
||||
std::string expected = "(the-as uint (/ (the-as int arg0) (the-as int arg1)))";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprAsh) {
|
||||
@ -240,7 +240,7 @@ TEST_F(FormRegressionTest, ExprAsh) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(ash arg0 arg1)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMod) {
|
||||
@ -252,7 +252,7 @@ TEST_F(FormRegressionTest, ExprMod) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(mod arg0 arg1)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprAbs) {
|
||||
@ -268,7 +268,7 @@ TEST_F(FormRegressionTest, ExprAbs) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int)";
|
||||
std::string expected = "(abs arg0)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMin) {
|
||||
@ -282,7 +282,7 @@ TEST_F(FormRegressionTest, ExprMin) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(min arg0 arg1)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMax) {
|
||||
@ -296,7 +296,7 @@ TEST_F(FormRegressionTest, ExprMax) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(max arg0 arg1)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprLogior) {
|
||||
@ -307,7 +307,7 @@ TEST_F(FormRegressionTest, ExprLogior) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(logior arg0 arg1)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprLogxor) {
|
||||
@ -318,7 +318,7 @@ TEST_F(FormRegressionTest, ExprLogxor) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(logxor arg0 arg1)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprLognor) {
|
||||
@ -329,7 +329,7 @@ TEST_F(FormRegressionTest, ExprLognor) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(lognor arg0 arg1)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprLogand) {
|
||||
@ -340,7 +340,7 @@ TEST_F(FormRegressionTest, ExprLogand) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int int)";
|
||||
std::string expected = "(logand arg0 arg1)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprLognot) {
|
||||
@ -351,7 +351,7 @@ TEST_F(FormRegressionTest, ExprLognot) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function int int)";
|
||||
std::string expected = "(lognot arg0)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprFalse) {
|
||||
@ -362,7 +362,7 @@ TEST_F(FormRegressionTest, ExprFalse) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function symbol)";
|
||||
std::string expected = "#f";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprTrue) {
|
||||
@ -373,7 +373,7 @@ TEST_F(FormRegressionTest, ExprTrue) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function symbol)";
|
||||
std::string expected = "#t";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprPrintBfloat) {
|
||||
@ -403,7 +403,7 @@ TEST_F(FormRegressionTest, ExprPrintBfloat) {
|
||||
std::string type = "(function bfloat bfloat)";
|
||||
|
||||
std::string expected = "(begin (format #t \"~f\" (-> arg0 data)) arg0)";
|
||||
test_with_expr(func, type, expected, false, "", {{"L343", "~f"}});
|
||||
test_with_expr_jak1(func, type, expected, false, "", {{"L343", "~f"}});
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprSizeOfType) {
|
||||
@ -425,7 +425,7 @@ TEST_F(FormRegressionTest, ExprSizeOfType) {
|
||||
std::string type = "(function type uint)";
|
||||
|
||||
std::string expected = "(logand 3 (+ (* (-> arg0 allocated-length) 4) 43))";
|
||||
test_with_expr(func, type, expected, false, "");
|
||||
test_with_expr_jak1(func, type, expected, false, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprBasicTypeP) {
|
||||
@ -468,7 +468,7 @@ TEST_F(FormRegressionTest, ExprBasicTypeP) {
|
||||
" )\n"
|
||||
" #f\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, FinalBasicTypeP) {
|
||||
@ -511,7 +511,7 @@ TEST_F(FormRegressionTest, FinalBasicTypeP) {
|
||||
" )\n"
|
||||
" #f\n"
|
||||
" )";
|
||||
test_final_function(func, type, expected);
|
||||
test_final_function_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprTypeTypep) {
|
||||
@ -565,7 +565,7 @@ TEST_F(FormRegressionTest, ExprTypeTypep) {
|
||||
" )\n"
|
||||
" #f\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "");
|
||||
test_with_expr_jak1(func, type, expected, false, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprFindParentMethod) {
|
||||
@ -629,7 +629,7 @@ TEST_F(FormRegressionTest, ExprFindParentMethod) {
|
||||
" )\n"
|
||||
" v0-0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "");
|
||||
test_with_expr_jak1(func, type, expected, false, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprRef) {
|
||||
@ -660,7 +660,7 @@ TEST_F(FormRegressionTest, ExprRef) {
|
||||
|
||||
std::string expected =
|
||||
"(begin (dotimes (v1-0 arg1) (nop!) (nop!) (set! arg0 (cdr arg0))) (car arg0))";
|
||||
test_with_expr(func, type, expected, true, "");
|
||||
test_with_expr_jak1(func, type, expected, true, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprPairMethod4) {
|
||||
@ -728,7 +728,7 @@ TEST_F(FormRegressionTest, ExprPairMethod4) {
|
||||
" )\n"
|
||||
" v0-0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "");
|
||||
test_with_expr_jak1(func, type, expected, true, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprPairMethod5) {
|
||||
@ -741,7 +741,7 @@ TEST_F(FormRegressionTest, ExprPairMethod5) {
|
||||
std::string type = "(function pair uint)";
|
||||
|
||||
std::string expected = "(-> pair size)";
|
||||
test_with_expr(func, type, expected, false, "");
|
||||
test_with_expr_jak1(func, type, expected, false, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprLast) {
|
||||
@ -774,7 +774,7 @@ TEST_F(FormRegressionTest, ExprLast) {
|
||||
" (while (not (null? (cdr v0-0))) (nop!) (nop!) (set! v0-0 (cdr v0-0)))\n"
|
||||
" v0-0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "");
|
||||
test_with_expr_jak1(func, type, expected, true, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMember) {
|
||||
@ -826,7 +826,7 @@ TEST_F(FormRegressionTest, ExprMember) {
|
||||
" )\n"
|
||||
" (if (not (null? v1-0)) v1-0)\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "");
|
||||
test_with_expr_jak1(func, type, expected, true, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprNmember) {
|
||||
@ -888,7 +888,7 @@ TEST_F(FormRegressionTest, ExprNmember) {
|
||||
" )\n"
|
||||
" (if (not (null? arg1)) arg1)\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "");
|
||||
test_with_expr_jak1(func, type, expected, true, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprAssoc) {
|
||||
@ -939,7 +939,7 @@ TEST_F(FormRegressionTest, ExprAssoc) {
|
||||
" )\n"
|
||||
" (if (not (null? v1-0)) (car v1-0))\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "");
|
||||
test_with_expr_jak1(func, type, expected, true, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprAssoce) {
|
||||
@ -1007,7 +1007,7 @@ TEST_F(FormRegressionTest, ExprAssoce) {
|
||||
" )\n"
|
||||
" (if (not (null? v1-0)) (car v1-0))\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "");
|
||||
test_with_expr_jak1(func, type, expected, true, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprNassoc) {
|
||||
@ -1098,7 +1098,7 @@ TEST_F(FormRegressionTest, ExprNassoc) {
|
||||
" )\n"
|
||||
" (if (not (null? arg1)) (car arg1))\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "");
|
||||
test_with_expr_jak1(func, type, expected, true, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprNassoce) {
|
||||
@ -1203,7 +1203,7 @@ TEST_F(FormRegressionTest, ExprNassoce) {
|
||||
" )\n"
|
||||
" (if (not (null? arg1)) (car arg1))\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "");
|
||||
test_with_expr_jak1(func, type, expected, true, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprAppend) {
|
||||
@ -1262,7 +1262,7 @@ TEST_F(FormRegressionTest, ExprAppend) {
|
||||
" arg0\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "");
|
||||
test_with_expr_jak1(func, type, expected, true, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprDelete) {
|
||||
@ -1339,7 +1339,7 @@ TEST_F(FormRegressionTest, ExprDelete) {
|
||||
" )\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "");
|
||||
test_with_expr_jak1(func, type, expected, true, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprDeleteCar) {
|
||||
@ -1418,7 +1418,7 @@ TEST_F(FormRegressionTest, ExprDeleteCar) {
|
||||
" )\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "");
|
||||
test_with_expr_jak1(func, type, expected, true, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprInsertCons) {
|
||||
@ -1451,7 +1451,7 @@ TEST_F(FormRegressionTest, ExprInsertCons) {
|
||||
|
||||
// NOTE - this appears to _not_ be a nested call.
|
||||
std::string expected = "(let ((a3-0 (delete-car! (car arg0) arg1))) (cons arg0 a3-0))";
|
||||
test_with_expr(func, type, expected, true, "");
|
||||
test_with_expr_jak1(func, type, expected, true, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprSort) {
|
||||
@ -1587,7 +1587,7 @@ TEST_F(FormRegressionTest, ExprSort) {
|
||||
" )\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "");
|
||||
test_with_expr_jak1(func, type, expected, true, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprInlineArrayMethod0) {
|
||||
@ -1639,7 +1639,7 @@ TEST_F(FormRegressionTest, ExprInlineArrayMethod0) {
|
||||
" )\n"
|
||||
" v0-0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "inline-array-class");
|
||||
test_with_expr_jak1(func, type, expected, true, "inline-array-class");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprInlineArrayMethod4) {
|
||||
@ -1651,7 +1651,7 @@ TEST_F(FormRegressionTest, ExprInlineArrayMethod4) {
|
||||
std::string type = "(function inline-array-class int)";
|
||||
|
||||
std::string expected = "(-> arg0 length)";
|
||||
test_with_expr(func, type, expected, true, "inline-array-class");
|
||||
test_with_expr_jak1(func, type, expected, true, "inline-array-class");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprInlineArrayMethod5) {
|
||||
@ -1676,7 +1676,7 @@ TEST_F(FormRegressionTest, ExprInlineArrayMethod5) {
|
||||
" (* (-> arg0 allocated-length) (the-as int (-> arg0 type heap-base)))\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "inline-array-class");
|
||||
test_with_expr_jak1(func, type, expected, true, "inline-array-class");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprArrayMethod0) {
|
||||
@ -1758,7 +1758,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod0) {
|
||||
" (set! (-> v0-1 content-type) arg2)\n"
|
||||
" v0-1\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "array");
|
||||
test_with_expr_jak1(func, type, expected, true, "array");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprArrayMethod4) {
|
||||
@ -1771,7 +1771,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod4) {
|
||||
std::string type = "(function array int)";
|
||||
|
||||
std::string expected = "(-> arg0 length)";
|
||||
test_with_expr(func, type, expected, true, "array");
|
||||
test_with_expr_jak1(func, type, expected, true, "array");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprArrayMethod5) {
|
||||
@ -1826,7 +1826,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod5) {
|
||||
" )\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "array");
|
||||
test_with_expr_jak1(func, type, expected, true, "array");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMemCopy) {
|
||||
@ -1866,7 +1866,7 @@ TEST_F(FormRegressionTest, ExprMemCopy) {
|
||||
" )\n"
|
||||
" v0-0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMemSet32) {
|
||||
@ -1905,7 +1905,7 @@ TEST_F(FormRegressionTest, ExprMemSet32) {
|
||||
" )\n"
|
||||
" v0-0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMemOr) {
|
||||
@ -1948,7 +1948,7 @@ TEST_F(FormRegressionTest, ExprMemOr) {
|
||||
" )\n"
|
||||
" v0-0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprFact) {
|
||||
@ -1982,7 +1982,7 @@ TEST_F(FormRegressionTest, ExprFact) {
|
||||
std::string type = "(function int int)";
|
||||
|
||||
std::string expected = "(if (= arg0 1) 1 (* arg0 (fact (+ arg0 -1))))";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprPrint) {
|
||||
@ -2010,7 +2010,7 @@ TEST_F(FormRegressionTest, ExprPrint) {
|
||||
std::string type = "(function object object)";
|
||||
|
||||
std::string expected = "((method-of-type (rtype-of arg0) print) arg0)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprPrintl) {
|
||||
@ -2058,7 +2058,7 @@ TEST_F(FormRegressionTest, ExprPrintl) {
|
||||
" (format #t \"~%\")\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "", {{"L324", "~%"}});
|
||||
test_with_expr_jak1(func, type, expected, false, "", {{"L324", "~%"}});
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprInspect) {
|
||||
@ -2086,7 +2086,7 @@ TEST_F(FormRegressionTest, ExprInspect) {
|
||||
std::string type = "(function object object)";
|
||||
|
||||
std::string expected = "((method-of-type (rtype-of arg0) inspect) arg0)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprPrintTreeBitmask) {
|
||||
@ -2157,7 +2157,7 @@ TEST_F(FormRegressionTest, ExprPrintTreeBitmask) {
|
||||
" )\n"
|
||||
" #f\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "", {{"L323", " "}, {"L322", "| "}});
|
||||
test_with_expr_jak1(func, type, expected, false, "", {{"L323", " "}, {"L322", "| "}});
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprPrintName) {
|
||||
@ -2278,9 +2278,9 @@ TEST_F(FormRegressionTest, ExprPrintName) {
|
||||
"(the-as int arg0))))))\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "", {},
|
||||
"[\t\t[24, \"a1\", \"symbol\"],\n"
|
||||
"\t\t[39, \"a0\", \"symbol\"]]");
|
||||
test_with_expr_jak1(func, type, expected, false, "", {},
|
||||
"[\t\t[24, \"a1\", \"symbol\"],\n"
|
||||
"\t\t[39, \"a0\", \"symbol\"]]");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprProfileBarMethod9) {
|
||||
@ -2296,7 +2296,7 @@ TEST_F(FormRegressionTest, ExprProfileBarMethod9) {
|
||||
std::string type = "(function profile-bar int uint)";
|
||||
|
||||
std::string expected = "(-> arg0 data (+ (-> arg0 profile-frame-count) -2) time-stamp)";
|
||||
test_with_expr(func, type, expected, false, "");
|
||||
test_with_expr_jak1(func, type, expected, false, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprStopwatchElapsedSeconds) {
|
||||
@ -2326,7 +2326,7 @@ TEST_F(FormRegressionTest, ExprStopwatchElapsedSeconds) {
|
||||
std::string type = "(function int float)";
|
||||
|
||||
std::string expected = "(let ((v1-0 (abs arg0))) (* 0.0 (the float v1-0)))";
|
||||
test_with_expr(func, type, expected, false, "");
|
||||
test_with_expr_jak1(func, type, expected, false, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprCopyStringString) {
|
||||
@ -2374,7 +2374,7 @@ TEST_F(FormRegressionTest, ExprCopyStringString) {
|
||||
" )\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "");
|
||||
test_with_expr_jak1(func, type, expected, false, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, StringLt) {
|
||||
@ -2479,7 +2479,7 @@ TEST_F(FormRegressionTest, StringLt) {
|
||||
" )\n"
|
||||
" #f\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "");
|
||||
test_with_expr_jak1(func, type, expected, false, "");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprAssert) {
|
||||
@ -2510,7 +2510,7 @@ TEST_F(FormRegressionTest, ExprAssert) {
|
||||
std::string type = "(function symbol string int)";
|
||||
|
||||
std::string expected = "(begin (if (not arg0) (format #t \"A ~A\" arg1)) 0)";
|
||||
test_with_expr(func, type, expected, false, "", {{"L17", "A ~A"}});
|
||||
test_with_expr_jak1(func, type, expected, false, "", {{"L17", "A ~A"}});
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprTerminal2) {
|
||||
@ -2547,7 +2547,7 @@ TEST_F(FormRegressionTest, ExprTerminal2) {
|
||||
" ((f0-4 (sqrtf (/ (- (* 0.0 arg0) arg1) arg2))))\n"
|
||||
" (- f0-4 (+ arg1 (* arg2 (* f0-4 f0-4))))\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "", {{"L17", "A ~A"}});
|
||||
test_with_expr_jak1(func, type, expected, false, "", {{"L17", "A ~A"}});
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, MoveFalse) {
|
||||
@ -2568,7 +2568,7 @@ TEST_F(FormRegressionTest, MoveFalse) {
|
||||
std::string type = "(function int symbol)";
|
||||
|
||||
std::string expected = "(logtest? (+ arg0 12) 1)";
|
||||
test_with_expr(func, type, expected, false, "", {{"L17", "A ~A"}});
|
||||
test_with_expr_jak1(func, type, expected, false, "", {{"L17", "A ~A"}});
|
||||
}
|
||||
|
||||
// Good for testing that in-place ops (+!) check the _variable_ is the same.
|
||||
@ -2620,7 +2620,7 @@ TEST_F(FormRegressionTest, QMemCpy) {
|
||||
" )\n"
|
||||
" v0-0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, StripStripTrailingWhitespace) {
|
||||
@ -2728,7 +2728,7 @@ TEST_F(FormRegressionTest, StripStripTrailingWhitespace) {
|
||||
" )\n"
|
||||
" #f\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
// Let bug (github #328)
|
||||
@ -2782,7 +2782,7 @@ TEST_F(FormRegressionTest, TimeToGround) {
|
||||
" )\n"
|
||||
" (the-as float v0-0)\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
// Infinite loop bug (github #196)
|
||||
@ -2815,7 +2815,7 @@ TEST_F(FormRegressionTest, LoopingCode) {
|
||||
" )\n"
|
||||
" (the-as symbol #f)\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, AbsAsSideEffect) {
|
||||
@ -2869,7 +2869,7 @@ TEST_F(FormRegressionTest, AbsAsSideEffect) {
|
||||
" )\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
// for github https://github.com/water111/jak-project/issues/332
|
||||
@ -2905,7 +2905,7 @@ TEST_F(FormRegressionTest, AshPropagation) {
|
||||
" (logior! (-> arg0 bytes (/ arg1 8)) (ash 1 (logand arg1 7)))\n"
|
||||
" 0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
// for github https://github.com/water111/jak-project/issues/332
|
||||
@ -2939,5 +2939,5 @@ TEST_F(FormRegressionTest, AshPropagation2) {
|
||||
"(let ((v1-2 (-> arg0 bytes (/ arg1 8))))\n"
|
||||
" (logtest? v1-2 (ash 1 (logand arg1 7)))\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
@ -50,10 +50,10 @@ TEST_F(FormRegressionTest, MatrixPMult) {
|
||||
" )\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_stack_structures(func, type, expected,
|
||||
"[\n"
|
||||
" [16, \"matrix\"]\n"
|
||||
" ]");
|
||||
test_with_stack_structures_jak1(func, type, expected,
|
||||
"[\n"
|
||||
" [16, \"matrix\"]\n"
|
||||
" ]");
|
||||
}
|
||||
|
||||
// TODO- this should also work without the cast, but be uglier.
|
||||
@ -96,11 +96,11 @@ TEST_F(FormRegressionTest, VectorXQuaternionWithCast) {
|
||||
" )\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_stack_structures(func, type, expected,
|
||||
"[\n"
|
||||
" [16, \"matrix\"]\n"
|
||||
" ]",
|
||||
"[[10, \"v1\", \"(pointer uint128)\"]]");
|
||||
test_with_stack_structures_jak1(func, type, expected,
|
||||
"[\n"
|
||||
" [16, \"matrix\"]\n"
|
||||
" ]",
|
||||
"[[10, \"v1\", \"(pointer uint128)\"]]");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, EliminateFloatDeadSet) {
|
||||
@ -227,7 +227,7 @@ TEST_F(FormRegressionTest, EliminateFloatDeadSet) {
|
||||
" )\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_stack_structures(func, type, expected, "[]");
|
||||
test_with_stack_structures_jak1(func, type, expected, "[]");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, IterateProcessTree) {
|
||||
@ -319,7 +319,7 @@ TEST_F(FormRegressionTest, IterateProcessTree) {
|
||||
" )\n"
|
||||
" s4-0\n"
|
||||
" )";
|
||||
test_with_stack_structures(func, type, expected, "[]");
|
||||
test_with_stack_structures_jak1(func, type, expected, "[]");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, InspectVifStatBitfield) {
|
||||
@ -451,18 +451,18 @@ TEST_F(FormRegressionTest, InspectVifStatBitfield) {
|
||||
" (format #t \"~T ~D~%\" (-> arg0 fqc))\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "",
|
||||
{{"L37", "[~8x] ~A~%"},
|
||||
{"L36", "~T ~D~%"},
|
||||
{"L35", "~T ~D~%"},
|
||||
{"L34", "~T ~D~%"},
|
||||
{"L33", "~T ~D~%"},
|
||||
{"L32", "~T ~D~%"},
|
||||
{"L31", "~T ~D~%"},
|
||||
{"L30", "~T ~D~%"},
|
||||
{"L29", "~T ~D~%"},
|
||||
{"L28", "~T ~D~%"},
|
||||
{"L27", "~T ~D~%"}});
|
||||
test_with_expr_jak1(func, type, expected, false, "",
|
||||
{{"L37", "[~8x] ~A~%"},
|
||||
{"L36", "~T ~D~%"},
|
||||
{"L35", "~T ~D~%"},
|
||||
{"L34", "~T ~D~%"},
|
||||
{"L33", "~T ~D~%"},
|
||||
{"L32", "~T ~D~%"},
|
||||
{"L31", "~T ~D~%"},
|
||||
{"L30", "~T ~D~%"},
|
||||
{"L29", "~T ~D~%"},
|
||||
{"L28", "~T ~D~%"},
|
||||
{"L27", "~T ~D~%"}});
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, InspectHandleBitfield) {
|
||||
@ -512,8 +512,9 @@ TEST_F(FormRegressionTest, InspectHandleBitfield) {
|
||||
" (format #t \"~Tpid: ~D~%\" (-> arg0 pid))\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "",
|
||||
{{"L79", "[~8x] ~A~%"}, {"L32", "~Tprocess: #x~X~%"}, {"L31", "~Tpid: ~D~%"}});
|
||||
test_with_expr_jak1(
|
||||
func, type, expected, false, "",
|
||||
{{"L79", "[~8x] ~A~%"}, {"L32", "~Tprocess: #x~X~%"}, {"L31", "~Tpid: ~D~%"}});
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, InspectDmaTagBitfield) {
|
||||
@ -598,16 +599,16 @@ TEST_F(FormRegressionTest, InspectDmaTagBitfield) {
|
||||
" (format #t \"~Ta: ~D~%\" (-> arg0 spr))\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "",
|
||||
{
|
||||
{"L65", "[~8x] ~A~%"},
|
||||
{"L37", "~Ta: ~D~%"},
|
||||
{"L36", "~Ta: ~D~%"},
|
||||
{"L35", "~Ta: ~D~%"},
|
||||
{"L34", "~Ta: ~D~%"},
|
||||
{"L33", "~Ta: ~D~%"},
|
||||
{"L32", "~Ta: ~D~%"},
|
||||
});
|
||||
test_with_expr_jak1(func, type, expected, false, "",
|
||||
{
|
||||
{"L65", "[~8x] ~A~%"},
|
||||
{"L37", "~Ta: ~D~%"},
|
||||
{"L36", "~Ta: ~D~%"},
|
||||
{"L35", "~Ta: ~D~%"},
|
||||
{"L34", "~Ta: ~D~%"},
|
||||
{"L33", "~Ta: ~D~%"},
|
||||
{"L32", "~Ta: ~D~%"},
|
||||
});
|
||||
}
|
||||
|
||||
// Tests nonzero-check on bitfield
|
||||
@ -661,7 +662,7 @@ TEST_F(FormRegressionTest, DmaSyncCrash) {
|
||||
" )\n"
|
||||
" 0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, DmaSend) {
|
||||
@ -742,7 +743,7 @@ TEST_F(FormRegressionTest, DmaSend) {
|
||||
" (.sync.l)\n"
|
||||
" 0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, DmaInitialize) {
|
||||
@ -776,9 +777,9 @@ TEST_F(FormRegressionTest, DmaInitialize) {
|
||||
" (set! (-> (the-as vif-bank #x10003c00) err me0) 1)\n"
|
||||
" 0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "", {},
|
||||
"[[1, \"v1\", \"vif-bank\"], [8, \"v1\", \"vif-bank\"], [6, \"a0\", "
|
||||
"\"vif-bank\"], [13, \"a0\", \"vif-bank\"]]");
|
||||
test_with_expr_jak1(func, type, expected, false, "", {},
|
||||
"[[1, \"v1\", \"vif-bank\"], [8, \"v1\", \"vif-bank\"], [6, \"a0\", "
|
||||
"\"vif-bank\"], [13, \"a0\", \"vif-bank\"]]");
|
||||
}
|
||||
|
||||
// Dynamic bitfield stuff.
|
||||
@ -859,7 +860,7 @@ TEST_F(FormRegressionTest, SetDisplayEnv) {
|
||||
" (set! (-> arg0 bgcolor) (new 'static 'gs-bgcolor))\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, DmaBufferAddVuFunction) {
|
||||
@ -974,7 +975,7 @@ TEST_F(FormRegressionTest, DmaBufferAddVuFunction) {
|
||||
" )\n"
|
||||
" #f\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "", {}, "[[[9, 33], \"t2\", \"dma-packet\"]]");
|
||||
test_with_expr_jak1(func, type, expected, false, "", {}, "[[[9, 33], \"t2\", \"dma-packet\"]]");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, DmaBucketInsertTag) {
|
||||
@ -997,11 +998,11 @@ TEST_F(FormRegressionTest, DmaBucketInsertTag) {
|
||||
" )\n"
|
||||
" arg2\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "", {},
|
||||
"[\n"
|
||||
" [[2, 6], \"v1\", \"dma-bucket\"],\n"
|
||||
" [3, \"a0\", \"dma-bucket\"]\n"
|
||||
" ]");
|
||||
test_with_expr_jak1(func, type, expected, false, "", {},
|
||||
"[\n"
|
||||
" [[2, 6], \"v1\", \"dma-bucket\"],\n"
|
||||
" [3, \"a0\", \"dma-bucket\"]\n"
|
||||
" ]");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, StupidFloatMove) {
|
||||
@ -1109,7 +1110,7 @@ TEST_F(FormRegressionTest, StupidFloatMove) {
|
||||
" )\n"
|
||||
" 0.0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
// gpr->fpr not being propagated
|
||||
@ -1128,7 +1129,7 @@ TEST_F(FormRegressionTest, Method11FontContext) {
|
||||
" (set! (-> arg0 origin z) (the float arg1))\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
// 128-bit bitfields, also type for pextuw
|
||||
@ -1166,7 +1167,7 @@ TEST_F(FormRegressionTest, Method4ResTag) {
|
||||
" (* (-> arg0 elt-count) (-> arg0 elt-type size))\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, MakeSqrtTable) {
|
||||
@ -1240,7 +1241,7 @@ TEST_F(FormRegressionTest, MakeSqrtTable) {
|
||||
" 0\n"
|
||||
" (none)\n"
|
||||
" )";
|
||||
test_with_expr(
|
||||
test_with_expr_jak1(
|
||||
func, type, expected, false, "",
|
||||
{{"L190", "static int sqrt_table[256] =~%{~%"}, {"L189", "~D,~%"}, {"L188", "};~%"}});
|
||||
}
|
||||
@ -1288,7 +1289,7 @@ TEST_F(FormRegressionTest, Method2Vec4s) {
|
||||
" )\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "", {{"L344", "#<vector ~F ~F ~F ~F @ #x~X>"}});
|
||||
test_with_expr_jak1(func, type, expected, false, "", {{"L344", "#<vector ~F ~F ~F ~F @ #x~X>"}});
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, SoundNameEqual) {
|
||||
@ -1310,7 +1311,7 @@ TEST_F(FormRegressionTest, SoundNameEqual) {
|
||||
std::string type = "(function sound-name sound-name symbol)";
|
||||
std::string expected =
|
||||
"(and (= (the-as uint arg0) (the-as uint arg1)) (= (-> arg0 hi) (-> arg1 hi)))";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, DebugMenuFuncDecode) {
|
||||
@ -1376,7 +1377,7 @@ TEST_F(FormRegressionTest, DebugMenuFuncDecode) {
|
||||
" )\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "", {}, "[[13, \"a0\", \"symbol\"]]");
|
||||
test_with_expr_jak1(func, type, expected, false, "", {}, "[[13, \"a0\", \"symbol\"]]");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, MatrixNewInlineProp) {
|
||||
@ -1431,7 +1432,7 @@ TEST_F(FormRegressionTest, MatrixNewInlineProp) {
|
||||
" )\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_stack_structures(func, type, expected, R"([[16, "matrix"]])");
|
||||
test_with_stack_structures_jak1(func, type, expected, R"([[16, "matrix"]])");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, VectorNewInlineProp) {
|
||||
@ -1491,7 +1492,7 @@ TEST_F(FormRegressionTest, VectorNewInlineProp) {
|
||||
" )\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_stack_structures(func, type, expected, R"([[16, "vector"]])");
|
||||
test_with_stack_structures_jak1(func, type, expected, R"([[16, "vector"]])");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, Method23Trsqv) {
|
||||
@ -1517,7 +1518,7 @@ TEST_F(FormRegressionTest, Method23Trsqv) {
|
||||
std::string type = "(function trsqv vector float)";
|
||||
std::string expected =
|
||||
"(vector-y-angle (vector-! (new 'stack-no-clear 'vector) arg1 (-> arg0 trans)))";
|
||||
test_with_stack_structures(func, type, expected, R"([[16, "vector"]])");
|
||||
test_with_stack_structures_jak1(func, type, expected, R"([[16, "vector"]])");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, VectorLineDistance) {
|
||||
@ -1612,6 +1613,6 @@ TEST_F(FormRegressionTest, VectorLineDistance) {
|
||||
" )\n"
|
||||
" (vector-length (vector-! (new-stack-vector0) gp-1 v1-3))\n"
|
||||
" )";
|
||||
test_with_stack_structures(func, type, expected,
|
||||
R"([[16, "vector"], [32, "vector"], [48, "vector"], [64, "vector"]])");
|
||||
test_with_stack_structures_jak1(
|
||||
func, type, expected, R"([[16, "vector"], [32, "vector"], [48, "vector"], [64, "vector"]])");
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ TEST_F(FormRegressionTest, VectorDegToVectorRad) {
|
||||
" (none)\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_final_function(func, type, expected);
|
||||
test_final_function_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
// weird short circuit thing
|
||||
@ -141,7 +141,7 @@ TEST_F(FormRegressionTest, WeirdShortCircuit) {
|
||||
" )\n"
|
||||
" s5-0\n"
|
||||
" )";
|
||||
test_with_stack_structures(func, type, expected, "[[16, \"event-message-block\"]]");
|
||||
test_with_stack_structures_jak1(func, type, expected, "[[16, \"event-message-block\"]]");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, WeirdShortCircuit2) {
|
||||
@ -162,5 +162,5 @@ TEST_F(FormRegressionTest, WeirdShortCircuit2) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function actor-link-info object)";
|
||||
std::string expected = "(the-as object (and (-> arg0 prev) (-> arg0 prev extra process)))";
|
||||
test_with_stack_structures(func, type, expected, "[[16, \"event-message-block\"]]");
|
||||
test_with_stack_structures_jak1(func, type, expected, "[[16, \"event-message-block\"]]");
|
||||
}
|
@ -665,32 +665,32 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
|
||||
" (format #t \")\")\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "array",
|
||||
{{"L343", "~f"},
|
||||
{"L342", "#("},
|
||||
{"L341", "~D"},
|
||||
{"L340", " ~D"},
|
||||
{"L339", "#x~X"},
|
||||
{"L338", " #x~X"},
|
||||
{"L337", " ~f"},
|
||||
{"L336", "~A"},
|
||||
{"L335", " ~A"},
|
||||
{"L334", ")"}},
|
||||
"["
|
||||
"\t\t[23, \"gp\", \"(array int32)\"],\n"
|
||||
"\t\t[43, \"gp\", \"(array uint32)\"],\n"
|
||||
"\t\t[63, \"gp\", \"(array int64)\"],\n"
|
||||
"\t\t[83, \"gp\", \"(array uint64)\"],\n"
|
||||
"\t\t[102, \"gp\", \"(array int8)\"],\n"
|
||||
"\t\t[121, \"gp\", \"(array uint8)\"],\n"
|
||||
"\t\t[141, \"gp\", \"(array int16)\"],\n"
|
||||
"\t\t[161, \"gp\", \"(array uint16)\"],\n"
|
||||
"\t\t[186, \"gp\", \"(array uint128)\"],\n"
|
||||
"\t\t[204, \"gp\", \"(array int32)\"],\n"
|
||||
"\t\t[223, \"gp\", \"(array float)\"],\n"
|
||||
"\t\t[232, \"gp\", \"(array float)\"],\n"
|
||||
"\t\t[249, \"gp\", \"(array basic)\"],\n"
|
||||
"\t\t[258, \"gp\", \"(array basic)\"]]");
|
||||
test_with_expr_jak1(func, type, expected, true, "array",
|
||||
{{"L343", "~f"},
|
||||
{"L342", "#("},
|
||||
{"L341", "~D"},
|
||||
{"L340", " ~D"},
|
||||
{"L339", "#x~X"},
|
||||
{"L338", " #x~X"},
|
||||
{"L337", " ~f"},
|
||||
{"L336", "~A"},
|
||||
{"L335", " ~A"},
|
||||
{"L334", ")"}},
|
||||
"["
|
||||
"\t\t[23, \"gp\", \"(array int32)\"],\n"
|
||||
"\t\t[43, \"gp\", \"(array uint32)\"],\n"
|
||||
"\t\t[63, \"gp\", \"(array int64)\"],\n"
|
||||
"\t\t[83, \"gp\", \"(array uint64)\"],\n"
|
||||
"\t\t[102, \"gp\", \"(array int8)\"],\n"
|
||||
"\t\t[121, \"gp\", \"(array uint8)\"],\n"
|
||||
"\t\t[141, \"gp\", \"(array int16)\"],\n"
|
||||
"\t\t[161, \"gp\", \"(array uint16)\"],\n"
|
||||
"\t\t[186, \"gp\", \"(array uint128)\"],\n"
|
||||
"\t\t[204, \"gp\", \"(array int32)\"],\n"
|
||||
"\t\t[223, \"gp\", \"(array float)\"],\n"
|
||||
"\t\t[232, \"gp\", \"(array float)\"],\n"
|
||||
"\t\t[249, \"gp\", \"(array basic)\"],\n"
|
||||
"\t\t[258, \"gp\", \"(array basic)\"]]");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprArrayMethod3) {
|
||||
@ -1226,28 +1226,28 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
|
||||
" )\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true, "array",
|
||||
{{"L333", "[~8x] ~A~%"},
|
||||
{"L332", "~Tallocated-length: ~D~%"},
|
||||
{"L331", "~Tlength: ~D~%"},
|
||||
{"L330", " ~Tcontent-type: ~A~%"},
|
||||
{"L329", "~Tdata[~D]: @ #x~X~%"},
|
||||
{"L328", "~T [~D] ~D~%"},
|
||||
{"L327", "~T [~D] #x~X~%"},
|
||||
{"L326", "~T [~D] ~f~%"},
|
||||
{"L325", "~T [~D] ~A~%"}},
|
||||
"[\t\t[44, \"gp\", \"(array int32)\"],\n"
|
||||
"\t\t[62, \"gp\", \"(array uint32)\"],\n"
|
||||
"\t\t[80, \"gp\", \"(array int64)\"],\n"
|
||||
"\t\t[98, \"gp\", \"(array uint64)\"],\n"
|
||||
"\t\t[115, \"gp\", \"(array int8)\"],\n"
|
||||
"\t\t[132, \"gp\", \"(array int8)\"],\n"
|
||||
"\t\t[150, \"gp\", \"(array int16)\"],\n"
|
||||
"\t\t[168, \"gp\", \"(array uint16)\"],\n"
|
||||
"\t\t[191, \"gp\", \"(array uint128)\"],\n"
|
||||
"\t\t[207, \"gp\", \"(array int32)\"],\n"
|
||||
"\t\t[226, \"gp\", \"(array float)\"],\n"
|
||||
"\t\t[243, \"gp\", \"(array basic)\"]]");
|
||||
test_with_expr_jak1(func, type, expected, true, "array",
|
||||
{{"L333", "[~8x] ~A~%"},
|
||||
{"L332", "~Tallocated-length: ~D~%"},
|
||||
{"L331", "~Tlength: ~D~%"},
|
||||
{"L330", " ~Tcontent-type: ~A~%"},
|
||||
{"L329", "~Tdata[~D]: @ #x~X~%"},
|
||||
{"L328", "~T [~D] ~D~%"},
|
||||
{"L327", "~T [~D] #x~X~%"},
|
||||
{"L326", "~T [~D] ~f~%"},
|
||||
{"L325", "~T [~D] ~A~%"}},
|
||||
"[\t\t[44, \"gp\", \"(array int32)\"],\n"
|
||||
"\t\t[62, \"gp\", \"(array uint32)\"],\n"
|
||||
"\t\t[80, \"gp\", \"(array int64)\"],\n"
|
||||
"\t\t[98, \"gp\", \"(array uint64)\"],\n"
|
||||
"\t\t[115, \"gp\", \"(array int8)\"],\n"
|
||||
"\t\t[132, \"gp\", \"(array int8)\"],\n"
|
||||
"\t\t[150, \"gp\", \"(array int16)\"],\n"
|
||||
"\t\t[168, \"gp\", \"(array uint16)\"],\n"
|
||||
"\t\t[191, \"gp\", \"(array uint128)\"],\n"
|
||||
"\t\t[207, \"gp\", \"(array int32)\"],\n"
|
||||
"\t\t[226, \"gp\", \"(array float)\"],\n"
|
||||
"\t\t[243, \"gp\", \"(array basic)\"]]");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprValid) {
|
||||
@ -2013,7 +2013,7 @@ TEST_F(FormRegressionTest, ExprValid) {
|
||||
" )\n"
|
||||
" )\n"
|
||||
"\n";
|
||||
test_with_expr(
|
||||
test_with_expr_jak1(
|
||||
func, type, expected, false, "",
|
||||
{{"L321", "ERROR: object #x~X ~S is not a valid object (misaligned)~%"},
|
||||
{"L320", "ERROR: object #x~X ~S is not a valid object (bad address)~%"},
|
||||
@ -2397,7 +2397,7 @@ TEST_F(FormRegressionTest, ExprStringToInt) {
|
||||
" )\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_final_function(func, type, expected);
|
||||
test_final_function_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, Method19ResTag) {
|
||||
@ -2888,11 +2888,11 @@ TEST_F(FormRegressionTest, Method19ResTag) {
|
||||
" (logior (logand 0 t0-6) (shl v1-14 32))\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "", {},
|
||||
"[\n"
|
||||
" [46, \"t2\", \"(pointer uint64)\"],\n"
|
||||
" [100, \"t3\", \"(pointer uint64)\"],\n"
|
||||
" [184, \"t5\", \"(pointer uint64)\"],\n"
|
||||
" [64, \"t6\", \"(pointer uint64)\"]\n"
|
||||
" ]");
|
||||
test_with_expr_jak1(func, type, expected, false, "", {},
|
||||
"[\n"
|
||||
" [46, \"t2\", \"(pointer uint64)\"],\n"
|
||||
" [100, \"t3\", \"(pointer uint64)\"],\n"
|
||||
" [184, \"t5\", \"(pointer uint64)\"],\n"
|
||||
" [64, \"t6\", \"(pointer uint64)\"]\n"
|
||||
" ]");
|
||||
}
|
@ -12,7 +12,7 @@ TEST_F(FormRegressionTest, ExprMethod7Object) {
|
||||
" daddu sp, sp, r0\n";
|
||||
std::string type = "(function object int object)";
|
||||
std::string expected = "arg0";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprLoadPackage) {
|
||||
@ -71,7 +71,7 @@ TEST_F(FormRegressionTest, ExprLoadPackage) {
|
||||
" v0-1\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprUnloadPackage) {
|
||||
@ -110,7 +110,7 @@ TEST_F(FormRegressionTest, ExprUnloadPackage) {
|
||||
" )\n"
|
||||
" *kernel-packages*\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, true);
|
||||
test_with_expr_jak1(func, type, expected, true);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod1Thread) {
|
||||
@ -141,7 +141,7 @@ TEST_F(FormRegressionTest, ExprMethod1Thread) {
|
||||
" (set! (-> arg0 process top-thread) (-> arg0 previous))\n"
|
||||
" (none)\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false);
|
||||
test_with_expr_jak1(func, type, expected, false);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod2Thread) {
|
||||
@ -187,7 +187,8 @@ TEST_F(FormRegressionTest, ExprMethod2Thread) {
|
||||
" )\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "", {{"L343", "#<~A ~S of ~S pc: #x~X @ #x~X>"}});
|
||||
test_with_expr_jak1(func, type, expected, false, "",
|
||||
{{"L343", "#<~A ~S of ~S pc: #x~X @ #x~X>"}});
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod9Thread) {
|
||||
@ -288,7 +289,7 @@ TEST_F(FormRegressionTest, ExprMethod9Thread) {
|
||||
" 0\n"
|
||||
" (none)\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "", {{"L342", "1 ~A ~%"}, {"L341", "2 ~A ~%"}});
|
||||
test_with_expr_jak1(func, type, expected, false, "", {{"L342", "1 ~A ~%"}, {"L341", "2 ~A ~%"}});
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod0Thread) {
|
||||
@ -363,9 +364,9 @@ TEST_F(FormRegressionTest, ExprMethod0Thread) {
|
||||
" (set! (-> obj stack-size) arg4)\n"
|
||||
" (the-as cpu-thread obj)\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "cpu-thread", {},
|
||||
"[[[13, 28], \"v0\", \"cpu-thread\"]]",
|
||||
"{\"vars\":{\"v0-0\":[\"obj\", \"cpu-thread\"]}}");
|
||||
test_with_expr_jak1(func, type, expected, false, "cpu-thread", {},
|
||||
"[[[13, 28], \"v0\", \"cpu-thread\"]]",
|
||||
"{\"vars\":{\"v0-0\":[\"obj\", \"cpu-thread\"]}}");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod5CpuThread) {
|
||||
@ -380,7 +381,7 @@ TEST_F(FormRegressionTest, ExprMethod5CpuThread) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function cpu-thread int)";
|
||||
std::string expected = "(the-as int (+ (-> arg0 type size) (-> arg0 stack-size)))";
|
||||
test_with_expr(func, type, expected, false);
|
||||
test_with_expr_jak1(func, type, expected, false);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, RemoveExit) {
|
||||
@ -406,7 +407,7 @@ TEST_F(FormRegressionTest, RemoveExit) {
|
||||
" v0-0\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false);
|
||||
test_with_expr_jak1(func, type, expected, false);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, RemoveMethod0ProcessTree) {
|
||||
@ -451,7 +452,7 @@ TEST_F(FormRegressionTest, RemoveMethod0ProcessTree) {
|
||||
" (set! (-> v0-0 ppointer) (the-as (pointer process) (&-> v0-0 self)))\n"
|
||||
" v0-0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "process-tree");
|
||||
test_with_expr_jak1(func, type, expected, false, "process-tree");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, RemoveMethod3ProcessTree) {
|
||||
@ -547,13 +548,13 @@ TEST_F(FormRegressionTest, RemoveMethod3ProcessTree) {
|
||||
" (format #t \"~Tchild: ~A~%\" (ppointer->process (-> arg0 child)))\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "process-tree",
|
||||
{{"L340", "[~8x] ~A~%"},
|
||||
{"L339", "~Tname: ~S~%"},
|
||||
{"L338", "~Tmask: #x~X~%"},
|
||||
{"L337", "~Tparent: ~A~%"},
|
||||
{"L336", "~Tbrother: ~A~%"},
|
||||
{"L335", "~Tchild: ~A~%"}});
|
||||
test_with_expr_jak1(func, type, expected, false, "process-tree",
|
||||
{{"L340", "[~8x] ~A~%"},
|
||||
{"L339", "~Tname: ~S~%"},
|
||||
{"L338", "~Tmask: #x~X~%"},
|
||||
{"L337", "~Tparent: ~A~%"},
|
||||
{"L336", "~Tbrother: ~A~%"},
|
||||
{"L335", "~Tchild: ~A~%"}});
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod0Process) {
|
||||
@ -666,9 +667,9 @@ TEST_F(FormRegressionTest, ExprMethod0Process) {
|
||||
" )\n"
|
||||
" (the-as process v0-0)\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "process", {},
|
||||
"[\t\t[12, \"a0\", \"int\"],\n"
|
||||
"\t\t[[13, 43], \"v0\", \"process\"]]");
|
||||
test_with_expr_jak1(func, type, expected, false, "process", {},
|
||||
"[\t\t[12, \"a0\", \"int\"],\n"
|
||||
"\t\t[[13, 43], \"v0\", \"process\"]]");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprInspectProcessHeap) {
|
||||
@ -731,10 +732,10 @@ TEST_F(FormRegressionTest, ExprInspectProcessHeap) {
|
||||
" )\n"
|
||||
" #f\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "", {},
|
||||
"[\t\t[[4,11], \"s5\", \"basic\"],\n"
|
||||
"\t\t[[17,20], \"s5\", \"pointer\"]]",
|
||||
"{\"vars\":{\"s5-0\":[\"obj\", \"pointer\"]}}");
|
||||
test_with_expr_jak1(func, type, expected, false, "", {},
|
||||
"[\t\t[[4,11], \"s5\", \"basic\"],\n"
|
||||
"\t\t[[17,20], \"s5\", \"pointer\"]]",
|
||||
"{\"vars\":{\"s5-0\":[\"obj\", \"pointer\"]}}");
|
||||
}
|
||||
|
||||
// note: skipped method 3 process
|
||||
@ -750,7 +751,7 @@ TEST_F(FormRegressionTest, ExprMethod5Process) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function process int)";
|
||||
std::string expected = "(the-as int (+ (-> process size) (-> arg0 allocated-length)))";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod2Process) {
|
||||
@ -831,8 +832,9 @@ TEST_F(FormRegressionTest, ExprMethod2Process) {
|
||||
" )\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "",
|
||||
{{"L317", "#<~A ~S ~A :state ~S "}, {"L316", ":stack ~D/~D :heap ~D/~D @ #x~X>"}});
|
||||
test_with_expr_jak1(
|
||||
func, type, expected, false, "",
|
||||
{{"L317", "#<~A ~S ~A :state ~S "}, {"L316", ":stack ~D/~D :heap ~D/~D @ #x~X>"}});
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod0DeadPool) {
|
||||
@ -945,7 +947,7 @@ TEST_F(FormRegressionTest, ExprMethod0DeadPool) {
|
||||
" )\n"
|
||||
" s3-0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "dead-pool");
|
||||
test_with_expr_jak1(func, type, expected, false, "dead-pool");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod14DeadPool) {
|
||||
@ -1085,7 +1087,7 @@ TEST_F(FormRegressionTest, ExprMethod14DeadPool) {
|
||||
" )";
|
||||
|
||||
// note - there's likely an actual bug here.
|
||||
test_with_expr(
|
||||
test_with_expr_jak1(
|
||||
func, type, expected, false, "dead-pool",
|
||||
{{"L315", "WARNING: ~A ~A had to be allocated from the debug pool, because ~A was empty.~%"},
|
||||
{"L314", "WARNING: ~A ~A could not be allocated, because ~A was empty.~%"}},
|
||||
@ -1111,7 +1113,7 @@ TEST_F(FormRegressionTest, ExprMethod15DeadPool) {
|
||||
" daddiu sp, sp, 16";
|
||||
std::string type = "(function dead-pool process none)";
|
||||
std::string expected = "(begin (change-parent arg1 arg0) (none))";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod0DeadPoolHeap) {
|
||||
@ -1256,10 +1258,10 @@ TEST_F(FormRegressionTest, ExprMethod0DeadPoolHeap) {
|
||||
" (set! (-> obj heap top-base) (-> obj heap top))\n"
|
||||
" obj\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "dead-pool-heap", {},
|
||||
"[\t\t[60, \"v0\", \"int\"],\n"
|
||||
"\t\t[61, \"a0\", \"pointer\"], [61, \"v0\", \"dead-pool-heap\"]]",
|
||||
"{\"vars\":{\"v0-0\":[\"obj\", \"dead-pool-heap\"]}}");
|
||||
test_with_expr_jak1(func, type, expected, false, "dead-pool-heap", {},
|
||||
"[\t\t[60, \"v0\", \"int\"],\n"
|
||||
"\t\t[61, \"a0\", \"pointer\"], [61, \"v0\", \"dead-pool-heap\"]]",
|
||||
"{\"vars\":{\"v0-0\":[\"obj\", \"dead-pool-heap\"]}}");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod22DeadPoolHeap) {
|
||||
@ -1296,7 +1298,7 @@ TEST_F(FormRegressionTest, ExprMethod22DeadPoolHeap) {
|
||||
" (-> arg0 heap base)\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod21DeadPoolHeap) {
|
||||
@ -1382,10 +1384,10 @@ TEST_F(FormRegressionTest, ExprMethod21DeadPoolHeap) {
|
||||
" (&- (-> arg0 heap top) (the-as uint (-> arg0 heap base)))\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "", {},
|
||||
"[\t\t[5, \"v1\", \"pointer\"],\n"
|
||||
"\t\t[13, \"a0\", \"pointer\"],\n"
|
||||
"\t\t[25, \"v1\", \"pointer\"]]");
|
||||
test_with_expr_jak1(func, type, expected, false, "", {},
|
||||
"[\t\t[5, \"v1\", \"pointer\"],\n"
|
||||
"\t\t[13, \"a0\", \"pointer\"],\n"
|
||||
"\t\t[25, \"v1\", \"pointer\"]]");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod3DeadPoolHeap) {
|
||||
@ -1561,10 +1563,10 @@ TEST_F(FormRegressionTest, ExprMethod3DeadPoolHeap) {
|
||||
" )\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "",
|
||||
{{"L300", "~Tprocess-list[0] @ #x~X ~D/~D bytes used~%"},
|
||||
{"L299", "~T [~3D] #<dead-pool-heap-rec @ #x~X> ~A~%"},
|
||||
{"L298", "~T gap: ~D bytes @ #x~X~%"}});
|
||||
test_with_expr_jak1(func, type, expected, false, "",
|
||||
{{"L300", "~Tprocess-list[0] @ #x~X ~D/~D bytes used~%"},
|
||||
{"L299", "~T [~3D] #<dead-pool-heap-rec @ #x~X> ~A~%"},
|
||||
{"L298", "~T gap: ~D bytes @ #x~X~%"}});
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod5DeadPoolHeap) {
|
||||
@ -1579,8 +1581,8 @@ TEST_F(FormRegressionTest, ExprMethod5DeadPoolHeap) {
|
||||
std::string type = "(function dead-pool-heap int)";
|
||||
std::string expected =
|
||||
"(+ (the-as int (- -4 (the-as int arg0))) (the-as int (-> arg0 heap top)))";
|
||||
test_with_expr(func, type, expected, false, "", {},
|
||||
"[[3, \"v1\", \"int\"], [3, \"a0\", \"int\"]]");
|
||||
test_with_expr_jak1(func, type, expected, false, "", {},
|
||||
"[[3, \"v1\", \"int\"], [3, \"a0\", \"int\"]]");
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod19DeadPoolHeap) {
|
||||
@ -1632,7 +1634,7 @@ TEST_F(FormRegressionTest, ExprMethod19DeadPoolHeap) {
|
||||
" (- (memory-total arg0) (gap-size arg0 (-> arg0 alive-list prev)))\n"
|
||||
" 0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod20DeadPoolHeap) {
|
||||
@ -1645,7 +1647,7 @@ TEST_F(FormRegressionTest, ExprMethod20DeadPoolHeap) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function dead-pool-heap int)";
|
||||
std::string expected = "(&- (-> arg0 heap top) (the-as uint (-> arg0 heap base)))";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod25DeadPoolHeap) {
|
||||
@ -1688,7 +1690,7 @@ TEST_F(FormRegressionTest, ExprMethod25DeadPoolHeap) {
|
||||
" (&- v1-0 (the-as uint (-> arg0 heap base)))\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod26DeadPoolHeap) {
|
||||
@ -1699,7 +1701,7 @@ TEST_F(FormRegressionTest, ExprMethod26DeadPoolHeap) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function dead-pool-heap uint)";
|
||||
std::string expected = "(-> arg0 compact-time)";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod24DeadPoolHeap) {
|
||||
@ -1756,7 +1758,7 @@ TEST_F(FormRegressionTest, ExprMethod24DeadPoolHeap) {
|
||||
" (while (and gp-0 (< (gap-size arg0 gp-0) arg1)) (set! gp-0 (-> gp-0 next)))\n"
|
||||
" gp-0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod14DeadPoolHeap) {
|
||||
@ -2032,7 +2034,7 @@ TEST_F(FormRegressionTest, ExprMethod14DeadPoolHeap) {
|
||||
" )\n"
|
||||
" s3-0\n"
|
||||
" )";
|
||||
test_with_expr(
|
||||
test_with_expr_jak1(
|
||||
func, type, expected, false, "",
|
||||
{{"L315", "WARNING: ~A ~A had to be allocated from the debug pool, because ~A was empty.~%"},
|
||||
{"L314", "WARNING: ~A ~A could not be allocated, because ~A was empty.~%"}});
|
||||
@ -2199,8 +2201,8 @@ TEST_F(FormRegressionTest, ExprMethod15DeadPoolHeap) {
|
||||
" 0\n"
|
||||
" (none)\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "",
|
||||
{{"L297", "ERROR: process ~A does not belong to dead-pool-heap ~A.~%"}});
|
||||
test_with_expr_jak1(func, type, expected, false, "",
|
||||
{{"L297", "ERROR: process ~A does not belong to dead-pool-heap ~A.~%"}});
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod17DeadPoolHeap) {
|
||||
@ -2325,7 +2327,7 @@ TEST_F(FormRegressionTest, ExprMethod17DeadPoolHeap) {
|
||||
" )\n"
|
||||
" arg0\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprMethod16DeadPoolHeap) {
|
||||
@ -2574,7 +2576,7 @@ TEST_F(FormRegressionTest, ExprMethod16DeadPoolHeap) {
|
||||
" 0\n"
|
||||
" (none)\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected, false, "", {{"L296", "~3LLow Actor Memory~%~0L"}});
|
||||
test_with_expr_jak1(func, type, expected, false, "", {{"L296", "~3LLow Actor Memory~%~0L"}});
|
||||
}
|
||||
|
||||
// nested method calls
|
||||
@ -2771,5 +2773,5 @@ TEST_F(FormRegressionTest, ExprMethod18DeadPoolHeap) {
|
||||
" 0\n"
|
||||
" (none)\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ TEST_F(FormRegressionTest, ExprTruncate) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function float float)";
|
||||
std::string expected = "(the float (the int arg0))";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprIntegralP) {
|
||||
@ -37,7 +37,7 @@ TEST_F(FormRegressionTest, ExprIntegralP) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function float float)";
|
||||
std::string expected = "(the-as float (= (the float (the int arg0)) arg0))";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprFractionalPart) {
|
||||
@ -55,7 +55,7 @@ TEST_F(FormRegressionTest, ExprFractionalPart) {
|
||||
" daddu sp, sp, r0";
|
||||
std::string type = "(function float float)";
|
||||
std::string expected = "(- arg0 (the float (the int arg0)))";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
||||
|
||||
TEST_F(FormRegressionTest, ExprSeek) {
|
||||
@ -103,5 +103,5 @@ TEST_F(FormRegressionTest, ExprSeek) {
|
||||
" (else (- arg0 arg2))\n"
|
||||
" )\n"
|
||||
" )";
|
||||
test_with_expr(func, type, expected);
|
||||
test_with_expr_jak1(func, type, expected);
|
||||
}
|
Loading…
Reference in New Issue
Block a user