[decompiler] Jak 2 modifications, new all-types code (#1553)

* temp

* look at old game types

* clean up
This commit is contained in:
water111 2022-06-25 21:26:15 -04:00 committed by GitHub
parent c9de15ba64
commit 91fa0122d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 1762 additions and 586 deletions

View File

@ -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

View File

@ -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),

View File

@ -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

View File

@ -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() {}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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; }

View File

@ -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.
};
/*!

View File

@ -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) {

View File

@ -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;
}

View File

@ -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();

View File

@ -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") {

View File

@ -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,

View File

@ -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;

View 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

View 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

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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;

View File

@ -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))

View File

@ -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,

View File

@ -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

View File

@ -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).

View File

@ -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
////////////////////////////

View File

@ -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

View File

@ -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
View 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

View File

@ -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;

View File

@ -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 = "");
};

View File

@ -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)~%"}});
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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"]])");
}

View File

@ -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\"]]");
}

View File

@ -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"
" ]");
}

View File

@ -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);
}

View File

@ -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);
}