mirror of
https://github.com/open-goal/jak-project.git
synced 2024-11-23 14:20:07 +00:00
[Decompilation] Fixes to compiler/decompiler for gcommon (#227)
* fix shift naming issue * fix bad argument variable names * fix missing variable issue * small missing things * wip * cleanup * wip * fix conditions * small bug fix in rewriter * fix incredibly stupid printing bug
This commit is contained in:
parent
65206823ef
commit
ddffda1e8c
@ -70,7 +70,7 @@ bool create_dir_if_needed(const std::string& path) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_binary_file(const std::string& name, void* data, size_t size) {
|
void write_binary_file(const std::string& name, const void* data, size_t size) {
|
||||||
FILE* fp = fopen(name.c_str(), "wb");
|
FILE* fp = fopen(name.c_str(), "wb");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
throw std::runtime_error("couldn't open file " + name);
|
throw std::runtime_error("couldn't open file " + name);
|
||||||
|
@ -12,7 +12,7 @@ namespace file_util {
|
|||||||
std::string get_project_path();
|
std::string get_project_path();
|
||||||
std::string get_file_path(const std::vector<std::string>& input);
|
std::string get_file_path(const std::vector<std::string>& input);
|
||||||
bool create_dir_if_needed(const std::string& path);
|
bool create_dir_if_needed(const std::string& path);
|
||||||
void write_binary_file(const std::string& name, void* data, size_t size);
|
void write_binary_file(const std::string& name, const void* data, size_t size);
|
||||||
void write_rgba_png(const std::string& name, void* data, int w, int h);
|
void write_rgba_png(const std::string& name, void* data, int w, int h);
|
||||||
void write_text_file(const std::string& file_name, const std::string& text);
|
void write_text_file(const std::string& file_name, const std::string& text);
|
||||||
std::vector<uint8_t> read_binary_file(const std::string& filename);
|
std::vector<uint8_t> read_binary_file(const std::string& filename);
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
namespace versions {
|
namespace versions {
|
||||||
// language version (OpenGOAL)
|
// language version (OpenGOAL)
|
||||||
constexpr s32 GOAL_VERSION_MAJOR = 0;
|
constexpr s32 GOAL_VERSION_MAJOR = 0;
|
||||||
constexpr s32 GOAL_VERSION_MINOR = 5;
|
constexpr s32 GOAL_VERSION_MINOR = 6;
|
||||||
|
|
||||||
// these versions are from the game
|
// these versions are from the game
|
||||||
constexpr u32 ART_FILE_VERSION = 6;
|
constexpr u32 ART_FILE_VERSION = 6;
|
||||||
|
@ -355,10 +355,13 @@ class IR2_Condition {
|
|||||||
const SimpleAtom& src(int i) const { return m_src[i]; }
|
const SimpleAtom& src(int i) const { return m_src[i]; }
|
||||||
ConditionElement* get_as_form(FormPool& pool, const Env& env, int my_idx) const;
|
ConditionElement* get_as_form(FormPool& pool, const Env& env, int my_idx) const;
|
||||||
void collect_vars(VariableSet& vars) const;
|
void collect_vars(VariableSet& vars) const;
|
||||||
|
void make_flipped() { m_flipped_eval = true; }
|
||||||
|
bool flipped() const { return m_flipped_eval; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Kind m_kind = Kind::INVALID;
|
Kind m_kind = Kind::INVALID;
|
||||||
SimpleAtom m_src[2];
|
SimpleAtom m_src[2];
|
||||||
|
bool m_flipped_eval = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string get_condition_kind_name(IR2_Condition::Kind kind);
|
std::string get_condition_kind_name(IR2_Condition::Kind kind);
|
||||||
|
@ -45,7 +45,7 @@ ConditionElement* IR2_Condition::get_as_form(FormPool& pool, const Env& env, int
|
|||||||
for (int i = 0; i < get_condition_num_args(m_kind); i++) {
|
for (int i = 0; i < get_condition_num_args(m_kind); i++) {
|
||||||
vars[i] = m_src[i];
|
vars[i] = m_src[i];
|
||||||
}
|
}
|
||||||
return pool.alloc_element<ConditionElement>(m_kind, vars[0], vars[1], consumed);
|
return pool.alloc_element<ConditionElement>(m_kind, vars[0], vars[1], consumed, m_flipped_eval);
|
||||||
}
|
}
|
||||||
|
|
||||||
FormElement* SetVarOp::get_as_form(FormPool& pool, const Env& env) const {
|
FormElement* SetVarOp::get_as_form(FormPool& pool, const Env& env) const {
|
||||||
@ -90,6 +90,13 @@ FormElement* SetVarConditionOp::get_as_form(FormPool& pool, const Env& env) cons
|
|||||||
|
|
||||||
FormElement* StoreOp::get_as_form(FormPool& pool, const Env& env) const {
|
FormElement* StoreOp::get_as_form(FormPool& pool, const Env& env) const {
|
||||||
if (env.has_type_analysis()) {
|
if (env.has_type_analysis()) {
|
||||||
|
if (m_addr.is_identity() && m_addr.get_arg(0).is_sym_val()) {
|
||||||
|
auto val = pool.alloc_single_element_form<SimpleExpressionElement>(nullptr, m_value.as_expr(),
|
||||||
|
m_my_idx);
|
||||||
|
auto src = pool.alloc_single_element_form<SimpleExpressionElement>(nullptr, m_addr, m_my_idx);
|
||||||
|
return pool.alloc_element<SetFormFormElement>(src, val);
|
||||||
|
}
|
||||||
|
|
||||||
IR2_RegOffset ro;
|
IR2_RegOffset ro;
|
||||||
if (get_as_reg_offset(m_addr, &ro)) {
|
if (get_as_reg_offset(m_addr, &ro)) {
|
||||||
auto& input_type = env.get_types_before_op(m_my_idx).get(ro.reg);
|
auto& input_type = env.get_types_before_op(m_my_idx).get(ro.reg);
|
||||||
@ -238,8 +245,10 @@ FormElement* LoadVarOp::get_as_form(FormPool& pool, const Env& env) const {
|
|||||||
}
|
}
|
||||||
assert(rd.tokens.back().kind == FieldReverseLookupOutput::Token::Kind::VAR_IDX);
|
assert(rd.tokens.back().kind == FieldReverseLookupOutput::Token::Kind::VAR_IDX);
|
||||||
|
|
||||||
auto load = pool.alloc_single_element_form<ArrayFieldAccess>(nullptr, ro.var, tokens,
|
// we pass along the register offset because code generation seems to be a bit
|
||||||
input_type.get_multiplier());
|
// different in different cases.
|
||||||
|
auto load = pool.alloc_single_element_form<ArrayFieldAccess>(
|
||||||
|
nullptr, ro.var, tokens, input_type.get_multiplier(), ro.offset);
|
||||||
return pool.alloc_element<SetVarElement>(m_dst, load, true);
|
return pool.alloc_element<SetVarElement>(m_dst, load, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,67 +57,6 @@ std::string Env::print_local_var_types(const Form* top_level_form) const {
|
|||||||
entries.push_back(fmt::format("{}: {}", x.name(), x.type.typespec().print()));
|
entries.push_back(fmt::format("{}: {}", x.name(), x.type.typespec().print()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (top_level_form) {
|
|
||||||
VariableSet var_set;
|
|
||||||
top_level_form->collect_vars(var_set);
|
|
||||||
|
|
||||||
// we want to sort them for easier reading:
|
|
||||||
std::vector<std::pair<RegId, Variable>> vars;
|
|
||||||
|
|
||||||
for (auto& x : var_set) {
|
|
||||||
vars.push_back(std::make_pair(get_ssa_var(x), x));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::sort(vars.begin(), vars.end(),
|
|
||||||
[](const std::pair<RegId, Variable>& a, const std::pair<RegId, Variable>& b) {
|
|
||||||
return a.first < b.first;
|
|
||||||
});
|
|
||||||
|
|
||||||
RegId* prev = nullptr;
|
|
||||||
for (auto& x : vars) {
|
|
||||||
// sorted by ssa var and there are likely duplicates of Variables and SSA vars, only print
|
|
||||||
// unique ssa variables.
|
|
||||||
if (prev && x.first == *prev) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
prev = &x.first;
|
|
||||||
auto& map = x.second.mode() == VariableMode::WRITE ? m_var_names.write_vars.at(x.second.reg())
|
|
||||||
: m_var_names.read_vars.at(x.second.reg());
|
|
||||||
auto& info = map.at(x.first.id);
|
|
||||||
|
|
||||||
if (info.initialized) {
|
|
||||||
entries.push_back(fmt::format("{}: {}", info.name(), info.type.typespec().print()));
|
|
||||||
} else {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std::unordered_map<Register, std::unordered_set<int>, Register::hash> printed;
|
|
||||||
|
|
||||||
for (auto& reg_info : m_var_names.read_vars) {
|
|
||||||
auto& reg_printed = printed[reg_info.first];
|
|
||||||
for (int var_id = 0; var_id < int(reg_info.second.size()); var_id++) {
|
|
||||||
auto& info = reg_info.second.at(var_id);
|
|
||||||
if (info.initialized) {
|
|
||||||
reg_printed.insert(var_id);
|
|
||||||
entries.push_back(fmt::format("{}: {}", info.name(), info.type.typespec().print()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& reg_info : m_var_names.write_vars) {
|
|
||||||
auto& reg_printed = printed[reg_info.first];
|
|
||||||
for (int var_id = 0; var_id < int(reg_info.second.size()); var_id++) {
|
|
||||||
auto& info = reg_info.second.at(var_id);
|
|
||||||
if (info.initialized) {
|
|
||||||
if (reg_printed.find(var_id) == reg_printed.end()) {
|
|
||||||
entries.push_back(fmt::format("{}: {}", info.name(), info.type.typespec().print()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int max_len = 0;
|
int max_len = 0;
|
||||||
for (auto& entry : entries) {
|
for (auto& entry : entries) {
|
||||||
if (int(entry.length()) > max_len) {
|
if (int(entry.length()) > max_len) {
|
||||||
@ -228,7 +167,7 @@ goos::Object Env::local_var_type_list(const Form* top_level_form,
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
for (auto& x : vars) {
|
for (auto& x : vars) {
|
||||||
if (x.reg_id.reg.get_kind() == Reg::GPR && x.reg_id.reg.get_gpr() < Reg::A0 + nargs_to_ignore &&
|
if (x.reg_id.reg.get_kind() == Reg::GPR && x.reg_id.reg.get_gpr() < Reg::A0 + nargs_to_ignore &&
|
||||||
x.reg_id.reg.get_gpr() >= Reg::A0) {
|
x.reg_id.reg.get_gpr() >= Reg::A0 && x.reg_id.id == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
|
@ -356,8 +356,9 @@ void AtomicOpElement::get_modified_regs(RegSet& regs) const {
|
|||||||
ConditionElement::ConditionElement(IR2_Condition::Kind kind,
|
ConditionElement::ConditionElement(IR2_Condition::Kind kind,
|
||||||
std::optional<SimpleAtom> src0,
|
std::optional<SimpleAtom> src0,
|
||||||
std::optional<SimpleAtom> src1,
|
std::optional<SimpleAtom> src1,
|
||||||
RegSet consumed)
|
RegSet consumed,
|
||||||
: m_kind(kind), m_consumed(std::move(consumed)) {
|
bool flipped)
|
||||||
|
: m_kind(kind), m_consumed(std::move(consumed)), m_flipped(flipped) {
|
||||||
m_src[0] = src0;
|
m_src[0] = src0;
|
||||||
m_src[1] = src1;
|
m_src[1] = src1;
|
||||||
}
|
}
|
||||||
@ -768,7 +769,7 @@ goos::Object CondNoElseElement::to_form(const Env& env) const {
|
|||||||
for (auto& e : entries) {
|
for (auto& e : entries) {
|
||||||
std::vector<goos::Object> entry;
|
std::vector<goos::Object> entry;
|
||||||
entry.push_back(e.condition->to_form_as_condition(env));
|
entry.push_back(e.condition->to_form_as_condition(env));
|
||||||
entries.front().body->inline_forms(list, env);
|
e.body->inline_forms(entry, env);
|
||||||
list.push_back(pretty_print::build_list(entry));
|
list.push_back(pretty_print::build_list(entry));
|
||||||
}
|
}
|
||||||
return pretty_print::build_list(list);
|
return pretty_print::build_list(list);
|
||||||
@ -1067,10 +1068,12 @@ std::string fixed_operator_to_string(FixedOperatorKind kind) {
|
|||||||
return "lognor";
|
return "lognor";
|
||||||
case FixedOperatorKind::LOGNOT:
|
case FixedOperatorKind::LOGNOT:
|
||||||
return "lognot";
|
return "lognot";
|
||||||
case FixedOperatorKind::SLL:
|
case FixedOperatorKind::SHL:
|
||||||
return "sll";
|
return "shl";
|
||||||
case FixedOperatorKind::SRL:
|
case FixedOperatorKind::SHR:
|
||||||
return "srl";
|
return "shr";
|
||||||
|
case FixedOperatorKind::SAR:
|
||||||
|
return "sar";
|
||||||
case FixedOperatorKind::CAR:
|
case FixedOperatorKind::CAR:
|
||||||
return "car";
|
return "car";
|
||||||
case FixedOperatorKind::CDR:
|
case FixedOperatorKind::CDR:
|
||||||
@ -1079,6 +1082,21 @@ std::string fixed_operator_to_string(FixedOperatorKind kind) {
|
|||||||
return "new";
|
return "new";
|
||||||
case FixedOperatorKind::OBJECT_NEW:
|
case FixedOperatorKind::OBJECT_NEW:
|
||||||
return "object-new";
|
return "object-new";
|
||||||
|
case FixedOperatorKind::TYPE_NEW:
|
||||||
|
return "type-new";
|
||||||
|
|
||||||
|
case FixedOperatorKind::LT:
|
||||||
|
return "<";
|
||||||
|
case FixedOperatorKind::GT:
|
||||||
|
return ">";
|
||||||
|
case FixedOperatorKind::LEQ:
|
||||||
|
return "<=";
|
||||||
|
case FixedOperatorKind::GEQ:
|
||||||
|
return ">=";
|
||||||
|
case FixedOperatorKind::EQ:
|
||||||
|
return "=";
|
||||||
|
case FixedOperatorKind::NEQ:
|
||||||
|
return "!=";
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
@ -1323,8 +1341,12 @@ void DynamicMethodAccess::get_modified_regs(RegSet&) const {}
|
|||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
ArrayFieldAccess::ArrayFieldAccess(Variable source,
|
ArrayFieldAccess::ArrayFieldAccess(Variable source,
|
||||||
const std::vector<DerefToken>& deref_tokens,
|
const std::vector<DerefToken>& deref_tokens,
|
||||||
int expected_stride)
|
int expected_stride,
|
||||||
: m_source(source), m_deref_tokens(deref_tokens), m_expected_stride(expected_stride) {}
|
int constant_offset)
|
||||||
|
: m_source(source),
|
||||||
|
m_deref_tokens(deref_tokens),
|
||||||
|
m_expected_stride(expected_stride),
|
||||||
|
m_constant_offset(constant_offset) {}
|
||||||
|
|
||||||
goos::Object ArrayFieldAccess::to_form(const Env& env) const {
|
goos::Object ArrayFieldAccess::to_form(const Env& env) const {
|
||||||
std::vector<goos::Object> elts;
|
std::vector<goos::Object> elts;
|
||||||
|
@ -30,13 +30,15 @@ class FormElement {
|
|||||||
virtual void collect_vars(VariableSet& vars) const = 0;
|
virtual void collect_vars(VariableSet& vars) const = 0;
|
||||||
virtual void get_modified_regs(RegSet& regs) const = 0;
|
virtual void get_modified_regs(RegSet& regs) const = 0;
|
||||||
std::string to_string(const Env& env) const;
|
std::string to_string(const Env& env) const;
|
||||||
|
bool has_side_effects();
|
||||||
|
|
||||||
// push the result of this operation to the operation stack
|
// push the result of this operation to the operation stack
|
||||||
virtual void push_to_stack(const Env& env, FormPool& pool, FormStack& stack);
|
virtual void push_to_stack(const Env& env, FormPool& pool, FormStack& stack);
|
||||||
virtual void update_from_stack(const Env& env,
|
virtual void update_from_stack(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result);
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Form;
|
friend class Form;
|
||||||
@ -59,53 +61,62 @@ class SimpleExpressionElement : public FormElement {
|
|||||||
void update_from_stack(const Env& env,
|
void update_from_stack(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result) override;
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects) override;
|
||||||
void get_modified_regs(RegSet& regs) const override;
|
void get_modified_regs(RegSet& regs) const override;
|
||||||
|
|
||||||
void update_from_stack_identity(const Env& env,
|
void update_from_stack_identity(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result);
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects);
|
||||||
void update_from_stack_gpr_to_fpr(const Env& env,
|
void update_from_stack_gpr_to_fpr(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result);
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects);
|
||||||
void update_from_stack_fpr_to_gpr(const Env& env,
|
void update_from_stack_fpr_to_gpr(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result);
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects);
|
||||||
void update_from_stack_div_s(const Env& env,
|
void update_from_stack_div_s(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result);
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects);
|
||||||
void update_from_stack_add_i(const Env& env,
|
void update_from_stack_add_i(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result);
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects);
|
||||||
void update_from_stack_mult_si(const Env& env,
|
void update_from_stack_mult_si(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result);
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects);
|
||||||
void update_from_stack_lognot(const Env& env,
|
void update_from_stack_lognot(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result);
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects);
|
||||||
void update_from_stack_force_si_2(const Env& env,
|
void update_from_stack_force_si_2(const Env& env,
|
||||||
FixedOperatorKind kind,
|
FixedOperatorKind kind,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result);
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects);
|
||||||
void update_from_stack_force_ui_2(const Env& env,
|
void update_from_stack_force_ui_2(const Env& env,
|
||||||
FixedOperatorKind kind,
|
FixedOperatorKind kind,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result);
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects);
|
||||||
void update_from_stack_copy_first_int_2(const Env& env,
|
void update_from_stack_copy_first_int_2(const Env& env,
|
||||||
FixedOperatorKind kind,
|
FixedOperatorKind kind,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result);
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects);
|
||||||
|
|
||||||
const SimpleExpression& expr() const { return m_expr; }
|
const SimpleExpression& expr() const { return m_expr; }
|
||||||
|
|
||||||
@ -151,7 +162,8 @@ class LoadSourceElement : public FormElement {
|
|||||||
void update_from_stack(const Env& env,
|
void update_from_stack(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result) override;
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects) override;
|
||||||
void get_modified_regs(RegSet& regs) const override;
|
void get_modified_regs(RegSet& regs) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -194,7 +206,8 @@ class SetVarElement : public FormElement {
|
|||||||
void update_from_stack(const Env& env,
|
void update_from_stack(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result) override;
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects) override;
|
||||||
void get_modified_regs(RegSet& regs) const override;
|
void get_modified_regs(RegSet& regs) const override;
|
||||||
|
|
||||||
const Variable& dst() const { return m_dst; }
|
const Variable& dst() const { return m_dst; }
|
||||||
@ -259,7 +272,8 @@ class ConditionElement : public FormElement {
|
|||||||
ConditionElement(IR2_Condition::Kind kind,
|
ConditionElement(IR2_Condition::Kind kind,
|
||||||
std::optional<SimpleAtom> src0,
|
std::optional<SimpleAtom> src0,
|
||||||
std::optional<SimpleAtom> src1,
|
std::optional<SimpleAtom> src1,
|
||||||
RegSet consumed);
|
RegSet consumed,
|
||||||
|
bool flipped);
|
||||||
goos::Object to_form(const Env& env) const override;
|
goos::Object to_form(const Env& env) const override;
|
||||||
goos::Object to_form_as_condition(const Env& env) const override;
|
goos::Object to_form_as_condition(const Env& env) const override;
|
||||||
void apply(const std::function<void(FormElement*)>& f) override;
|
void apply(const std::function<void(FormElement*)>& f) override;
|
||||||
@ -269,15 +283,22 @@ class ConditionElement : public FormElement {
|
|||||||
void update_from_stack(const Env& env,
|
void update_from_stack(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result) override;
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects) override;
|
||||||
void get_modified_regs(RegSet& regs) const override;
|
void get_modified_regs(RegSet& regs) const override;
|
||||||
void invert();
|
void invert();
|
||||||
const RegSet& consume() const { return m_consumed; }
|
const RegSet& consume() const { return m_consumed; }
|
||||||
|
|
||||||
|
FormElement* make_generic(const Env& env,
|
||||||
|
FormPool& pool,
|
||||||
|
const std::vector<Form*>& source_forms,
|
||||||
|
const std::vector<TypeSpec>& types);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IR2_Condition::Kind m_kind;
|
IR2_Condition::Kind m_kind;
|
||||||
std::optional<SimpleAtom> m_src[2];
|
std::optional<SimpleAtom> m_src[2];
|
||||||
RegSet m_consumed;
|
RegSet m_consumed;
|
||||||
|
bool m_flipped;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -293,7 +314,8 @@ class FunctionCallElement : public FormElement {
|
|||||||
void update_from_stack(const Env& env,
|
void update_from_stack(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result) override;
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects) override;
|
||||||
void push_to_stack(const Env& env, FormPool& pool, FormStack& stack) override;
|
void push_to_stack(const Env& env, FormPool& pool, FormStack& stack) override;
|
||||||
void get_modified_regs(RegSet& regs) const override;
|
void get_modified_regs(RegSet& regs) const override;
|
||||||
|
|
||||||
@ -395,6 +417,7 @@ class CondWithElseElement : public FormElement {
|
|||||||
};
|
};
|
||||||
std::vector<Entry> entries;
|
std::vector<Entry> entries;
|
||||||
Form* else_ir = nullptr;
|
Form* else_ir = nullptr;
|
||||||
|
bool already_rewritten = false;
|
||||||
CondWithElseElement(std::vector<Entry> _entries, Form* _else_ir)
|
CondWithElseElement(std::vector<Entry> _entries, Form* _else_ir)
|
||||||
: entries(std::move(_entries)), else_ir(_else_ir) {}
|
: entries(std::move(_entries)), else_ir(_else_ir) {}
|
||||||
goos::Object to_form(const Env& env) const override;
|
goos::Object to_form(const Env& env) const override;
|
||||||
@ -481,6 +504,7 @@ class ShortCircuitElement : public FormElement {
|
|||||||
Variable final_result;
|
Variable final_result;
|
||||||
std::vector<Entry> entries;
|
std::vector<Entry> entries;
|
||||||
std::optional<bool> used_as_value = std::nullopt;
|
std::optional<bool> used_as_value = std::nullopt;
|
||||||
|
bool already_rewritten = false;
|
||||||
|
|
||||||
explicit ShortCircuitElement(std::vector<Entry> _entries) : entries(std::move(_entries)) {}
|
explicit ShortCircuitElement(std::vector<Entry> _entries) : entries(std::move(_entries)) {}
|
||||||
goos::Object to_form(const Env& env) const override;
|
goos::Object to_form(const Env& env) const override;
|
||||||
@ -491,7 +515,8 @@ class ShortCircuitElement : public FormElement {
|
|||||||
void update_from_stack(const Env& env,
|
void update_from_stack(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result) override;
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects) override;
|
||||||
void get_modified_regs(RegSet& regs) const override;
|
void get_modified_regs(RegSet& regs) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -511,6 +536,7 @@ class CondNoElseElement : public FormElement {
|
|||||||
};
|
};
|
||||||
Variable final_destination;
|
Variable final_destination;
|
||||||
bool used_as_value = false;
|
bool used_as_value = false;
|
||||||
|
bool already_rewritten = false;
|
||||||
std::vector<Entry> entries;
|
std::vector<Entry> entries;
|
||||||
explicit CondNoElseElement(std::vector<Entry> _entries) : entries(std::move(_entries)) {}
|
explicit CondNoElseElement(std::vector<Entry> _entries) : entries(std::move(_entries)) {}
|
||||||
goos::Object to_form(const Env& env) const override;
|
goos::Object to_form(const Env& env) const override;
|
||||||
@ -534,7 +560,8 @@ class AbsElement : public FormElement {
|
|||||||
void update_from_stack(const Env& env,
|
void update_from_stack(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result) override;
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects) override;
|
||||||
void get_modified_regs(RegSet& regs) const override;
|
void get_modified_regs(RegSet& regs) const override;
|
||||||
Variable source;
|
Variable source;
|
||||||
RegSet consumed;
|
RegSet consumed;
|
||||||
@ -563,7 +590,8 @@ class AshElement : public FormElement {
|
|||||||
void update_from_stack(const Env& env,
|
void update_from_stack(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result) override;
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects) override;
|
||||||
void get_modified_regs(RegSet& regs) const override;
|
void get_modified_regs(RegSet& regs) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -584,7 +612,8 @@ class TypeOfElement : public FormElement {
|
|||||||
void update_from_stack(const Env& env,
|
void update_from_stack(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result) override;
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -681,7 +710,8 @@ class GenericElement : public FormElement {
|
|||||||
void update_from_stack(const Env& env,
|
void update_from_stack(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result) override;
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects) override;
|
||||||
void get_modified_regs(RegSet& regs) const override;
|
void get_modified_regs(RegSet& regs) const override;
|
||||||
void push_to_stack(const Env& env, FormPool& pool, FormStack& stack) override;
|
void push_to_stack(const Env& env, FormPool& pool, FormStack& stack) override;
|
||||||
const GenericOperator& op() const { return m_head; }
|
const GenericOperator& op() const { return m_head; }
|
||||||
@ -704,7 +734,8 @@ class CastElement : public FormElement {
|
|||||||
void update_from_stack(const Env& env,
|
void update_from_stack(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result) override;
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects) override;
|
||||||
const TypeSpec& type() const { return m_type; }
|
const TypeSpec& type() const { return m_type; }
|
||||||
const Form* source() const { return m_source; }
|
const Form* source() const { return m_source; }
|
||||||
Form* source() { return m_source; }
|
Form* source() { return m_source; }
|
||||||
@ -756,7 +787,8 @@ class DerefElement : public FormElement {
|
|||||||
void update_from_stack(const Env& env,
|
void update_from_stack(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result) override;
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects) override;
|
||||||
void get_modified_regs(RegSet& regs) const override;
|
void get_modified_regs(RegSet& regs) const override;
|
||||||
|
|
||||||
bool is_addr_of() const { return m_is_addr_of; }
|
bool is_addr_of() const { return m_is_addr_of; }
|
||||||
@ -780,7 +812,8 @@ class DynamicMethodAccess : public FormElement {
|
|||||||
void update_from_stack(const Env& env,
|
void update_from_stack(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result) override;
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects) override;
|
||||||
void get_modified_regs(RegSet& regs) const override;
|
void get_modified_regs(RegSet& regs) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -791,7 +824,8 @@ class ArrayFieldAccess : public FormElement {
|
|||||||
public:
|
public:
|
||||||
ArrayFieldAccess(Variable source,
|
ArrayFieldAccess(Variable source,
|
||||||
const std::vector<DerefToken>& deref_tokens,
|
const std::vector<DerefToken>& deref_tokens,
|
||||||
int expected_stride);
|
int expected_stride,
|
||||||
|
int constant_offset);
|
||||||
goos::Object to_form(const Env& env) const override;
|
goos::Object to_form(const Env& env) const override;
|
||||||
void apply(const std::function<void(FormElement*)>& f) override;
|
void apply(const std::function<void(FormElement*)>& f) override;
|
||||||
void apply_form(const std::function<void(Form*)>& f) override;
|
void apply_form(const std::function<void(Form*)>& f) override;
|
||||||
@ -799,13 +833,15 @@ class ArrayFieldAccess : public FormElement {
|
|||||||
void update_from_stack(const Env& env,
|
void update_from_stack(const Env& env,
|
||||||
FormPool& pool,
|
FormPool& pool,
|
||||||
FormStack& stack,
|
FormStack& stack,
|
||||||
std::vector<FormElement*>* result) override;
|
std::vector<FormElement*>* result,
|
||||||
|
bool allow_side_effects) override;
|
||||||
void get_modified_regs(RegSet& regs) const override;
|
void get_modified_regs(RegSet& regs) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Variable m_source;
|
Variable m_source;
|
||||||
std::vector<DerefToken> m_deref_tokens;
|
std::vector<DerefToken> m_deref_tokens;
|
||||||
int m_expected_stride = -1;
|
int m_expected_stride = -1;
|
||||||
|
int m_constant_offset = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GetMethodElement : public FormElement {
|
class GetMethodElement : public FormElement {
|
||||||
@ -888,7 +924,11 @@ class Form {
|
|||||||
void apply_form(const std::function<void(Form*)>& f);
|
void apply_form(const std::function<void(Form*)>& f);
|
||||||
void collect_vars(VariableSet& vars) const;
|
void collect_vars(VariableSet& vars) const;
|
||||||
|
|
||||||
void update_children_from_stack(const Env& env, FormPool& pool, FormStack& stack);
|
void update_children_from_stack(const Env& env,
|
||||||
|
FormPool& pool,
|
||||||
|
FormStack& stack,
|
||||||
|
bool allow_side_effects);
|
||||||
|
bool has_side_effects();
|
||||||
void get_modified_regs(RegSet& regs) const;
|
void get_modified_regs(RegSet& regs) const;
|
||||||
|
|
||||||
FormElement* parent_element = nullptr;
|
FormElement* parent_element = nullptr;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -26,6 +26,7 @@ std::string FormStack::print(const Env& env) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FormStack::push_value_to_reg(Variable var, Form* value, bool sequence_point) {
|
void FormStack::push_value_to_reg(Variable var, Form* value, bool sequence_point) {
|
||||||
|
assert(value);
|
||||||
StackEntry entry;
|
StackEntry entry;
|
||||||
entry.active = true; // by default, we should display everything!
|
entry.active = true; // by default, we should display everything!
|
||||||
entry.sequence_point = sequence_point;
|
entry.sequence_point = sequence_point;
|
||||||
@ -37,6 +38,7 @@ void FormStack::push_value_to_reg(Variable var, Form* value, bool sequence_point
|
|||||||
void FormStack::push_non_seq_reg_to_reg(const Variable& dst,
|
void FormStack::push_non_seq_reg_to_reg(const Variable& dst,
|
||||||
const Variable& src,
|
const Variable& src,
|
||||||
Form* src_as_form) {
|
Form* src_as_form) {
|
||||||
|
assert(src_as_form);
|
||||||
StackEntry entry;
|
StackEntry entry;
|
||||||
entry.active = true;
|
entry.active = true;
|
||||||
entry.sequence_point = false;
|
entry.sequence_point = false;
|
||||||
@ -64,8 +66,11 @@ void FormStack::push_form_element(FormElement* elt, bool sequence_point) {
|
|||||||
m_stack.push_back(entry);
|
m_stack.push_back(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
Form* FormStack::pop_reg(const Variable& var, const RegSet& barrier, const Env& env) {
|
Form* FormStack::pop_reg(const Variable& var,
|
||||||
return pop_reg(var.reg(), barrier, env);
|
const RegSet& barrier,
|
||||||
|
const Env& env,
|
||||||
|
bool allow_side_effects) {
|
||||||
|
return pop_reg(var.reg(), barrier, env, allow_side_effects);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -77,22 +82,30 @@ bool nonempty_intersection(const RegSet& a, const RegSet& b) {
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Form* FormStack::pop_reg(Register reg, const RegSet& barrier, const Env& env) {
|
Form* FormStack::pop_reg(Register reg,
|
||||||
|
const RegSet& barrier,
|
||||||
|
const Env& env,
|
||||||
|
bool allow_side_effects) {
|
||||||
(void)env; // keep this for easy debugging.
|
(void)env; // keep this for easy debugging.
|
||||||
RegSet modified;
|
RegSet modified;
|
||||||
for (size_t i = m_stack.size(); i-- > 0;) {
|
for (size_t i = m_stack.size(); i-- > 0;) {
|
||||||
auto& entry = m_stack.at(i);
|
auto& entry = m_stack.at(i);
|
||||||
if (entry.active) {
|
if (entry.active) {
|
||||||
if (entry.destination->reg() == reg) {
|
if (entry.destination.has_value() && entry.destination->reg() == reg) {
|
||||||
entry.source->get_modified_regs(modified);
|
entry.source->get_modified_regs(modified);
|
||||||
|
if (!allow_side_effects && entry.source->has_side_effects()) {
|
||||||
|
// the source of the set! has a side effect and that's not allowed, so abort.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
if (nonempty_intersection(modified, barrier)) {
|
if (nonempty_intersection(modified, barrier)) {
|
||||||
|
// violating the barrier registers.
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
entry.active = false;
|
entry.active = false;
|
||||||
assert(entry.source);
|
assert(entry.source);
|
||||||
if (entry.non_seq_source.has_value()) {
|
if (entry.non_seq_source.has_value()) {
|
||||||
assert(entry.sequence_point == false);
|
assert(entry.sequence_point == false);
|
||||||
auto result = pop_reg(entry.non_seq_source->reg(), barrier, env);
|
auto result = pop_reg(entry.non_seq_source->reg(), barrier, env, allow_side_effects);
|
||||||
if (result) {
|
if (result) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -108,9 +121,17 @@ Form* FormStack::pop_reg(Register reg, const RegSet& barrier, const Env& env) {
|
|||||||
if (entry.source) {
|
if (entry.source) {
|
||||||
assert(!entry.elt);
|
assert(!entry.elt);
|
||||||
entry.source->get_modified_regs(modified);
|
entry.source->get_modified_regs(modified);
|
||||||
|
if (!allow_side_effects) {
|
||||||
|
// shouldn't allow skipping past a set! (may be too conservative?)
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(entry.elt);
|
assert(entry.elt);
|
||||||
entry.elt->get_modified_regs(modified);
|
entry.elt->get_modified_regs(modified);
|
||||||
|
if (!allow_side_effects && entry.elt->has_side_effects()) {
|
||||||
|
// shouldn't allow skipping past something with a set! (also may be too conservative?)
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,11 @@ class FormStack {
|
|||||||
void push_value_to_reg(Variable var, Form* value, bool sequence_point);
|
void push_value_to_reg(Variable var, Form* value, bool sequence_point);
|
||||||
void push_non_seq_reg_to_reg(const Variable& dst, const Variable& src, Form* src_as_form);
|
void push_non_seq_reg_to_reg(const Variable& dst, const Variable& src, Form* src_as_form);
|
||||||
void push_form_element(FormElement* elt, bool sequence_point);
|
void push_form_element(FormElement* elt, bool sequence_point);
|
||||||
Form* pop_reg(const Variable& var, const RegSet& barrier, const Env& env);
|
Form* pop_reg(const Variable& var,
|
||||||
Form* pop_reg(Register reg, const RegSet& barrier, const Env& env);
|
const RegSet& barrier,
|
||||||
|
const Env& env,
|
||||||
|
bool allow_side_effects);
|
||||||
|
Form* pop_reg(Register reg, const RegSet& barrier, const Env& env, bool allow_side_effects);
|
||||||
bool is_single_expression();
|
bool is_single_expression();
|
||||||
std::vector<FormElement*> rewrite(FormPool& pool);
|
std::vector<FormElement*> rewrite(FormPool& pool);
|
||||||
std::vector<FormElement*> rewrite_to_get_var(FormPool& pool, const Variable& var, const Env& env);
|
std::vector<FormElement*> rewrite_to_get_var(FormPool& pool, const Variable& var, const Env& env);
|
||||||
|
@ -105,12 +105,20 @@ enum class FixedOperatorKind {
|
|||||||
LOGXOR,
|
LOGXOR,
|
||||||
LOGNOR,
|
LOGNOR,
|
||||||
LOGNOT,
|
LOGNOT,
|
||||||
SLL,
|
SHL,
|
||||||
SRL,
|
SHR,
|
||||||
|
SAR,
|
||||||
CAR,
|
CAR,
|
||||||
CDR,
|
CDR,
|
||||||
NEW,
|
NEW,
|
||||||
OBJECT_NEW,
|
OBJECT_NEW,
|
||||||
|
TYPE_NEW,
|
||||||
|
LT,
|
||||||
|
GT,
|
||||||
|
LEQ,
|
||||||
|
GEQ,
|
||||||
|
EQ,
|
||||||
|
NEQ,
|
||||||
INVALID
|
INVALID
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -779,6 +779,7 @@ std::unique_ptr<AtomicOp> convert_bne_2(const Instruction& i0,
|
|||||||
} else {
|
} else {
|
||||||
condition = IR2_Condition(IR2_Condition::Kind::NOT_EQUAL, make_src_atom(s0, idx),
|
condition = IR2_Condition(IR2_Condition::Kind::NOT_EQUAL, make_src_atom(s0, idx),
|
||||||
make_src_atom(s1, idx));
|
make_src_atom(s1, idx));
|
||||||
|
condition.make_flipped();
|
||||||
}
|
}
|
||||||
return make_branch(condition, i1, likely, dest, idx);
|
return make_branch(condition, i1, likely, dest, idx);
|
||||||
}
|
}
|
||||||
@ -809,6 +810,7 @@ std::unique_ptr<AtomicOp> convert_beq_2(const Instruction& i0,
|
|||||||
} else {
|
} else {
|
||||||
condition =
|
condition =
|
||||||
IR2_Condition(IR2_Condition::Kind::EQUAL, make_src_atom(s0, idx), make_src_atom(s1, idx));
|
IR2_Condition(IR2_Condition::Kind::EQUAL, make_src_atom(s0, idx), make_src_atom(s1, idx));
|
||||||
|
condition.make_flipped();
|
||||||
}
|
}
|
||||||
return make_branch(condition, i1, likely, dest, idx);
|
return make_branch(condition, i1, likely, dest, idx);
|
||||||
}
|
}
|
||||||
|
@ -1065,7 +1065,7 @@ Form* cfg_to_ir(FormPool& pool, const Function& f, const CfgVtx* vtx) {
|
|||||||
} else if (dynamic_cast<const InfiniteLoopBlock*>(vtx)) {
|
} else if (dynamic_cast<const InfiniteLoopBlock*>(vtx)) {
|
||||||
auto wvtx = dynamic_cast<const InfiniteLoopBlock*>(vtx);
|
auto wvtx = dynamic_cast<const InfiniteLoopBlock*>(vtx);
|
||||||
auto condition = pool.alloc_single_element_form<ConditionElement>(
|
auto condition = pool.alloc_single_element_form<ConditionElement>(
|
||||||
nullptr, IR2_Condition::Kind::ALWAYS, std::nullopt, std::nullopt, RegSet());
|
nullptr, IR2_Condition::Kind::ALWAYS, std::nullopt, std::nullopt, RegSet(), false);
|
||||||
auto result = pool.alloc_single_element_form<WhileElement>(nullptr, condition,
|
auto result = pool.alloc_single_element_form<WhileElement>(nullptr, condition,
|
||||||
cfg_to_ir(pool, f, wvtx->block));
|
cfg_to_ir(pool, f, wvtx->block));
|
||||||
clean_up_infinite_while_loop(pool,
|
clean_up_infinite_while_loop(pool,
|
||||||
|
@ -436,6 +436,23 @@ void SSA::remap() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
std::unordered_map<Register, VarIdRecord, Register::hash> used_vars;
|
std::unordered_map<Register, VarIdRecord, Register::hash> used_vars;
|
||||||
|
// we do this in two passes. the first pass collects only the B0 variables and adds those first,
|
||||||
|
// so these remain index 0 (expected by later decompiler passes)
|
||||||
|
for (auto& block : blocks) {
|
||||||
|
assert(block.phis.empty());
|
||||||
|
for (auto& instr : block.ins) {
|
||||||
|
if (instr.dst.has_value() && map.var_id(*instr.dst) == 0) {
|
||||||
|
used_vars[instr.dst->reg()].insert(map.var_id(*instr.dst));
|
||||||
|
}
|
||||||
|
for (auto& src : instr.src) {
|
||||||
|
if (map.var_id(src) == 0) {
|
||||||
|
used_vars[src.reg()].insert(map.var_id(src));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// and the second pass grabs all of them
|
||||||
for (auto& block : blocks) {
|
for (auto& block : blocks) {
|
||||||
assert(block.phis.empty());
|
assert(block.phis.empty());
|
||||||
for (auto& instr : block.ins) {
|
for (auto& instr : block.ins) {
|
||||||
|
@ -112,4 +112,7 @@
|
|||||||
- Fixed bug where `(-> obj type)` caused a compiler error when `obj` had compile time type of `array` (the fancy boxed array)
|
- Fixed bug where `(-> obj type)` caused a compiler error when `obj` had compile time type of `array` (the fancy boxed array)
|
||||||
- Fixed use-after-free if the top-level form fails to compile and you continue trying to compile stuff.
|
- Fixed use-after-free if the top-level form fails to compile and you continue trying to compile stuff.
|
||||||
- `and` and `or` are more efficient and the type of the result is more specific: `LCA(symbol, cases...)`
|
- `and` and `or` are more efficient and the type of the result is more specific: `LCA(symbol, cases...)`
|
||||||
- `print-type` now fully compiles the argument and returns the result instead of `none`
|
- `print-type` now fully compiles the argument and returns the result instead of `none`
|
||||||
|
|
||||||
|
## V0.6
|
||||||
|
- There is no longer a separate compiler form for variable vs. constant shifts. Instead the compiler will pick the constant shift automatically when possible. The shifts are called `sar`, `shl` and `shr`, like the x86 instructions.
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
|
|
||||||
(defun log2 ((x int))
|
(defun log2 ((x int))
|
||||||
"Straight out of Bit Twiddling Hacks graphics.stanford.edu"
|
"Straight out of Bit Twiddling Hacks graphics.stanford.edu"
|
||||||
(- (sarv (the-as integer (the float x)) 23) 127)
|
(- (sar (the-as integer (the float x)) 23) 127)
|
||||||
)
|
)
|
||||||
|
|
||||||
(defun seek ((x float) (target float) (diff float))
|
(defun seek ((x float) (target float) (diff float))
|
||||||
@ -139,7 +139,7 @@
|
|||||||
(set! (-> *random-generator* seed) #x666EDD1E)
|
(set! (-> *random-generator* seed) #x666EDD1E)
|
||||||
|
|
||||||
(defmacro sext32-64 (x)
|
(defmacro sext32-64 (x)
|
||||||
`(sarv (shlv ,x 32) 32)
|
`(sar (shl ,x 32) 32)
|
||||||
)
|
)
|
||||||
|
|
||||||
(defun rand-uint31-gen ((gen random-generator))
|
(defun rand-uint31-gen ((gen random-generator))
|
||||||
@ -152,17 +152,17 @@
|
|||||||
;; mult3 v0, v1, a1
|
;; mult3 v0, v1, a1
|
||||||
(prod (imul64 16807 sd))
|
(prod (imul64 16807 sd))
|
||||||
;; mfhi v1
|
;; mfhi v1
|
||||||
(hi (shrv prod 32)) ;; sign extend this?
|
(hi (shr prod 32)) ;; sign extend this?
|
||||||
(lo (sarv (shlv prod 32) 32))
|
(lo (sar (shl prod 32) 32))
|
||||||
;; daddu v1, v1, v1
|
;; daddu v1, v1, v1
|
||||||
(v1 (+ hi hi))
|
(v1 (+ hi hi))
|
||||||
;; srl a1, v0, 31
|
;; srl a1, v0, 31
|
||||||
(a1 (logand #xffffffff (shrv lo 31)))
|
(a1 (logand #xffffffff (shr lo 31)))
|
||||||
;; or v1, v1, a1
|
;; or v1, v1, a1
|
||||||
;; daddu v0, v0 v1
|
;; daddu v0, v0 v1
|
||||||
(result (+ lo (logior v1 a1)))
|
(result (+ lo (logior v1 a1)))
|
||||||
)
|
)
|
||||||
(set! result (shrv (logand #xffffffff (shlv result 1)) 1))
|
(set! result (shr (logand #xffffffff (shl result 1)) 1))
|
||||||
(set! (-> gen seed) result)
|
(set! (-> gen seed) result)
|
||||||
result
|
result
|
||||||
)
|
)
|
||||||
|
@ -71,8 +71,8 @@
|
|||||||
;; these correspond to x86-64 variable shift instructions.
|
;; these correspond to x86-64 variable shift instructions.
|
||||||
;; the exact behavior of GOAL shifts (signed/unsigned) are unknown so for now shifts must
|
;; the exact behavior of GOAL shifts (signed/unsigned) are unknown so for now shifts must
|
||||||
;; be manually specified.
|
;; be manually specified.
|
||||||
(shlv value shift-amount)
|
(shl value shift-amount)
|
||||||
(sarv value (- shift-amount))
|
(sar value (- shift-amount))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -390,9 +390,6 @@ class Compiler {
|
|||||||
Val* compile_mul(const goos::Object& form, const goos::Object& rest, Env* env);
|
Val* compile_mul(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||||
Val* compile_imul64(const goos::Object& form, const goos::Object& rest, Env* env);
|
Val* compile_imul64(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||||
Val* compile_div(const goos::Object& form, const goos::Object& rest, Env* env);
|
Val* compile_div(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||||
Val* compile_shlv(const goos::Object& form, const goos::Object& rest, Env* env);
|
|
||||||
Val* compile_sarv(const goos::Object& form, const goos::Object& rest, Env* env);
|
|
||||||
Val* compile_shrv(const goos::Object& form, const goos::Object& rest, Env* env);
|
|
||||||
Val* compile_shl(const goos::Object& form, const goos::Object& rest, Env* env);
|
Val* compile_shl(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||||
Val* compile_sar(const goos::Object& form, const goos::Object& rest, Env* env);
|
Val* compile_sar(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||||
Val* compile_shr(const goos::Object& form, const goos::Object& rest, Env* env);
|
Val* compile_shr(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||||
|
@ -148,9 +148,6 @@ static const std::unordered_map<
|
|||||||
{"*", &Compiler::compile_mul},
|
{"*", &Compiler::compile_mul},
|
||||||
{"imul64", &Compiler::compile_imul64},
|
{"imul64", &Compiler::compile_imul64},
|
||||||
{"/", &Compiler::compile_div},
|
{"/", &Compiler::compile_div},
|
||||||
{"shlv", &Compiler::compile_shlv},
|
|
||||||
{"shrv", &Compiler::compile_shrv},
|
|
||||||
{"sarv", &Compiler::compile_sarv},
|
|
||||||
{"shl", &Compiler::compile_shl},
|
{"shl", &Compiler::compile_shl},
|
||||||
{"shr", &Compiler::compile_shr},
|
{"shr", &Compiler::compile_shr},
|
||||||
{"sar", &Compiler::compile_sar},
|
{"sar", &Compiler::compile_sar},
|
||||||
|
@ -396,30 +396,6 @@ Val* Compiler::compile_div(const goos::Object& form, const goos::Object& rest, E
|
|||||||
return get_none();
|
return get_none();
|
||||||
}
|
}
|
||||||
|
|
||||||
Val* Compiler::compile_shlv(const goos::Object& form, const goos::Object& rest, Env* env) {
|
|
||||||
auto args = get_va(form, rest);
|
|
||||||
va_check(form, args, {{}, {}}, {});
|
|
||||||
auto first = compile_error_guard(args.unnamed.at(0), env)->to_gpr(env);
|
|
||||||
auto second = compile_error_guard(args.unnamed.at(1), env)->to_gpr(env);
|
|
||||||
return compile_variable_shift(form, first, second, env, IntegerMathKind::SHLV_64);
|
|
||||||
}
|
|
||||||
|
|
||||||
Val* Compiler::compile_sarv(const goos::Object& form, const goos::Object& rest, Env* env) {
|
|
||||||
auto args = get_va(form, rest);
|
|
||||||
va_check(form, args, {{}, {}}, {});
|
|
||||||
auto first = compile_error_guard(args.unnamed.at(0), env)->to_gpr(env);
|
|
||||||
auto second = compile_error_guard(args.unnamed.at(1), env)->to_gpr(env);
|
|
||||||
return compile_variable_shift(form, first, second, env, IntegerMathKind::SARV_64);
|
|
||||||
}
|
|
||||||
|
|
||||||
Val* Compiler::compile_shrv(const goos::Object& form, const goos::Object& rest, Env* env) {
|
|
||||||
auto args = get_va(form, rest);
|
|
||||||
va_check(form, args, {{}, {}}, {});
|
|
||||||
auto first = compile_error_guard(args.unnamed.at(0), env)->to_gpr(env);
|
|
||||||
auto second = compile_error_guard(args.unnamed.at(1), env)->to_gpr(env);
|
|
||||||
return compile_variable_shift(form, first, second, env, IntegerMathKind::SHRV_64);
|
|
||||||
}
|
|
||||||
|
|
||||||
Val* Compiler::compile_variable_shift(const goos::Object& form,
|
Val* Compiler::compile_variable_shift(const goos::Object& form,
|
||||||
const RegVal* in,
|
const RegVal* in,
|
||||||
const RegVal* sa,
|
const RegVal* sa,
|
||||||
@ -449,35 +425,50 @@ Val* Compiler::compile_variable_shift(const goos::Object& form,
|
|||||||
|
|
||||||
Val* Compiler::compile_shl(const goos::Object& form, const goos::Object& rest, Env* env) {
|
Val* Compiler::compile_shl(const goos::Object& form, const goos::Object& rest, Env* env) {
|
||||||
auto args = get_va(form, rest);
|
auto args = get_va(form, rest);
|
||||||
va_check(form, args, {{}, {goos::ObjectType::INTEGER}}, {});
|
va_check(form, args, {{}, {}}, {});
|
||||||
auto first = compile_error_guard(args.unnamed.at(0), env)->to_gpr(env);
|
auto first = compile_error_guard(args.unnamed.at(0), env)->to_gpr(env);
|
||||||
auto sa = args.unnamed.at(1).as_int();
|
int64_t constant_sa = -1;
|
||||||
if (sa < 0 || sa > 64) {
|
if (try_getting_constant_integer(args.unnamed.at(1), &constant_sa, env)) {
|
||||||
throw_compiler_error(form, "Cannot shift by more than 64, or by a negative amount.");
|
if (constant_sa < 0 || constant_sa > 64) {
|
||||||
|
throw_compiler_error(form, "Cannot shift by more than 64, or by a negative amount.");
|
||||||
|
}
|
||||||
|
return compile_fixed_shift(form, first, constant_sa, env, IntegerMathKind::SHL_64);
|
||||||
|
} else {
|
||||||
|
auto second = compile_error_guard(args.unnamed.at(1), env)->to_gpr(env);
|
||||||
|
return compile_variable_shift(form, first, second, env, IntegerMathKind::SHLV_64);
|
||||||
}
|
}
|
||||||
return compile_fixed_shift(form, first, sa, env, IntegerMathKind::SHL_64);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Val* Compiler::compile_shr(const goos::Object& form, const goos::Object& rest, Env* env) {
|
Val* Compiler::compile_shr(const goos::Object& form, const goos::Object& rest, Env* env) {
|
||||||
auto args = get_va(form, rest);
|
auto args = get_va(form, rest);
|
||||||
va_check(form, args, {{}, {goos::ObjectType::INTEGER}}, {});
|
va_check(form, args, {{}, {}}, {});
|
||||||
auto first = compile_error_guard(args.unnamed.at(0), env)->to_gpr(env);
|
auto first = compile_error_guard(args.unnamed.at(0), env)->to_gpr(env);
|
||||||
auto sa = args.unnamed.at(1).as_int();
|
int64_t constant_sa = -1;
|
||||||
if (sa < 0 || sa > 64) {
|
if (try_getting_constant_integer(args.unnamed.at(1), &constant_sa, env)) {
|
||||||
throw_compiler_error(form, "Cannot shift by more than 64, or by a negative amount");
|
if (constant_sa < 0 || constant_sa > 64) {
|
||||||
|
throw_compiler_error(form, "Cannot shift by more than 64, or by a negative amount.");
|
||||||
|
}
|
||||||
|
return compile_fixed_shift(form, first, constant_sa, env, IntegerMathKind::SHR_64);
|
||||||
|
} else {
|
||||||
|
auto second = compile_error_guard(args.unnamed.at(1), env)->to_gpr(env);
|
||||||
|
return compile_variable_shift(form, first, second, env, IntegerMathKind::SHRV_64);
|
||||||
}
|
}
|
||||||
return compile_fixed_shift(form, first, sa, env, IntegerMathKind::SHR_64);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Val* Compiler::compile_sar(const goos::Object& form, const goos::Object& rest, Env* env) {
|
Val* Compiler::compile_sar(const goos::Object& form, const goos::Object& rest, Env* env) {
|
||||||
auto args = get_va(form, rest);
|
auto args = get_va(form, rest);
|
||||||
va_check(form, args, {{}, {goos::ObjectType::INTEGER}}, {});
|
va_check(form, args, {{}, {}}, {});
|
||||||
auto first = compile_error_guard(args.unnamed.at(0), env)->to_gpr(env);
|
auto first = compile_error_guard(args.unnamed.at(0), env)->to_gpr(env);
|
||||||
auto sa = args.unnamed.at(1).as_int();
|
int64_t constant_sa = -1;
|
||||||
if (sa < 0 || sa > 64) {
|
if (try_getting_constant_integer(args.unnamed.at(1), &constant_sa, env)) {
|
||||||
throw_compiler_error(form, "Cannot shift by more than 64, or by a negative amount");
|
if (constant_sa < 0 || constant_sa > 64) {
|
||||||
|
throw_compiler_error(form, "Cannot shift by more than 64, or by a negative amount.");
|
||||||
|
}
|
||||||
|
return compile_fixed_shift(form, first, constant_sa, env, IntegerMathKind::SAR_64);
|
||||||
|
} else {
|
||||||
|
auto second = compile_error_guard(args.unnamed.at(1), env)->to_gpr(env);
|
||||||
|
return compile_variable_shift(form, first, second, env, IntegerMathKind::SARV_64);
|
||||||
}
|
}
|
||||||
return compile_fixed_shift(form, first, sa, env, IntegerMathKind::SAR_64);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Val* Compiler::compile_fixed_shift(const goos::Object& form,
|
Val* Compiler::compile_fixed_shift(const goos::Object& form,
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "decompiler/analysis/reg_usage.h"
|
#include "decompiler/analysis/reg_usage.h"
|
||||||
#include "decompiler/analysis/cfg_builder.h"
|
#include "decompiler/analysis/cfg_builder.h"
|
||||||
#include "decompiler/analysis/expression_build.h"
|
#include "decompiler/analysis/expression_build.h"
|
||||||
|
#include "decompiler/analysis/final_output.h"
|
||||||
#include "common/goos/PrettyPrinter.h"
|
#include "common/goos/PrettyPrinter.h"
|
||||||
#include "decompiler/IR2/Form.h"
|
#include "decompiler/IR2/Form.h"
|
||||||
#include "third-party/json.hpp"
|
#include "third-party/json.hpp"
|
||||||
@ -180,6 +181,30 @@ void FormRegressionTest::test(const std::string& code,
|
|||||||
EXPECT_TRUE(expected_form == actual_form);
|
EXPECT_TRUE(expected_form == actual_form);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FormRegressionTest::test_final_function(
|
||||||
|
const std::string& code,
|
||||||
|
const std::string& type,
|
||||||
|
const std::string& expected,
|
||||||
|
bool allow_pairs,
|
||||||
|
const std::vector<std::pair<std::string, std::string>>& strings,
|
||||||
|
const std::unordered_map<int, std::vector<decompiler::TypeHint>>& hints) {
|
||||||
|
auto ts = dts->parse_type_spec(type);
|
||||||
|
auto test = make_function(code, ts, true, allow_pairs, "", strings, hints);
|
||||||
|
ASSERT_TRUE(test);
|
||||||
|
auto expected_form =
|
||||||
|
pretty_print::get_pretty_printer_reader().read_from_string(expected, false).as_pair()->car;
|
||||||
|
ASSERT_TRUE(test->func.ir2.top_form);
|
||||||
|
auto final = final_defun_out(test->func, test->func.ir2.env, *dts);
|
||||||
|
auto actual_form =
|
||||||
|
pretty_print::get_pretty_printer_reader().read_from_string(final, false).as_pair()->car;
|
||||||
|
if (expected_form != actual_form) {
|
||||||
|
printf("Got:\n%s\n\nExpected\n%s\n", pretty_print::to_string(actual_form).c_str(),
|
||||||
|
pretty_print::to_string(expected_form).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_TRUE(expected_form == actual_form);
|
||||||
|
}
|
||||||
|
|
||||||
std::unordered_map<int, std::vector<decompiler::TypeHint>> FormRegressionTest::parse_hint_json(
|
std::unordered_map<int, std::vector<decompiler::TypeHint>> FormRegressionTest::parse_hint_json(
|
||||||
const std::string& in) {
|
const std::string& in) {
|
||||||
std::unordered_map<int, std::vector<decompiler::TypeHint>> out;
|
std::unordered_map<int, std::vector<decompiler::TypeHint>> out;
|
||||||
|
@ -66,5 +66,13 @@ class FormRegressionTest : public ::testing::Test {
|
|||||||
test(code, type, expected, true, allow_pairs, method_name, strings, hints);
|
test(code, type, expected, true, allow_pairs, method_name, strings, hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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::unordered_map<int, std::vector<decompiler::TypeHint>>& hints = {});
|
||||||
|
|
||||||
std::unordered_map<int, std::vector<decompiler::TypeHint>> parse_hint_json(const std::string& in);
|
std::unordered_map<int, std::vector<decompiler::TypeHint>> parse_hint_json(const std::string& in);
|
||||||
};
|
};
|
@ -422,7 +422,7 @@ TEST_F(FormRegressionTest, ExprSizeOfType) {
|
|||||||
" daddiu sp, sp, 16";
|
" daddiu sp, sp, 16";
|
||||||
std::string type = "(function type uint)";
|
std::string type = "(function type uint)";
|
||||||
|
|
||||||
std::string expected = "(logand (l.d L346) (+ (sll (-> a0-1 allocated-length) 2) 43))";
|
std::string expected = "(logand (l.d L346) (+ (shl (-> a0-0 allocated-length) 2) 43))";
|
||||||
test_with_expr(func, type, expected, false, "");
|
test_with_expr(func, type, expected, false, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -469,6 +469,52 @@ TEST_F(FormRegressionTest, ExprBasicTypeP) {
|
|||||||
test_with_expr(func, type, expected);
|
test_with_expr(func, type, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(FormRegressionTest, FinalBasicTypeP) {
|
||||||
|
std::string func =
|
||||||
|
" sll r0, r0, 0\n"
|
||||||
|
"L285:\n"
|
||||||
|
" lwu v1, -4(a0)\n"
|
||||||
|
" lw a0, object(s7)\n"
|
||||||
|
|
||||||
|
"L286:\n"
|
||||||
|
" bne v1, a1, L287\n"
|
||||||
|
" or a2, s7, r0\n"
|
||||||
|
|
||||||
|
" daddiu v1, s7, #t\n"
|
||||||
|
" or v0, v1, r0\n"
|
||||||
|
" beq r0, r0, L288\n"
|
||||||
|
" sll r0, r0, 0\n"
|
||||||
|
|
||||||
|
" or v1, r0, r0\n"
|
||||||
|
"L287:\n"
|
||||||
|
" lwu v1, 4(v1)\n"
|
||||||
|
" bne v1, a0, L286\n"
|
||||||
|
" sll r0, r0, 0\n"
|
||||||
|
" or v0, s7, r0\n"
|
||||||
|
"L288:\n"
|
||||||
|
" jr ra\n"
|
||||||
|
" daddu sp, sp, r0";
|
||||||
|
std::string type = "(function basic type symbol)";
|
||||||
|
std::string expected =
|
||||||
|
"(defun test-function ((a0-0 basic) (a1-0 type))\n"
|
||||||
|
" (local-vars\n"
|
||||||
|
" (v1-0 type)\n"
|
||||||
|
" (a0-1 type)\n"
|
||||||
|
" (a2-0 symbol)\n"
|
||||||
|
" )\n"
|
||||||
|
" (begin\n"
|
||||||
|
" (set! v1-0 (-> a0-0 type))\n"
|
||||||
|
" (set! a0-1 object)\n"
|
||||||
|
" (until\n"
|
||||||
|
" (begin (set! v1-0 (-> v1-0 parent)) (= v1-0 a0-1))\n"
|
||||||
|
" (if (= v1-0 a1-0) (return (quote #t) (set! v1-0 0)))\n"
|
||||||
|
" )\n"
|
||||||
|
" (quote #f)\n"
|
||||||
|
" )\n"
|
||||||
|
" )";
|
||||||
|
test_final_function(func, type, expected);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(FormRegressionTest, ExprTypeTypep) {
|
TEST_F(FormRegressionTest, ExprTypeTypep) {
|
||||||
std::string func =
|
std::string func =
|
||||||
" sll r0, r0, 0\n"
|
" sll r0, r0, 0\n"
|
||||||
@ -616,7 +662,7 @@ TEST_F(FormRegressionTest, ExprRef) {
|
|||||||
"(begin\n"
|
"(begin\n"
|
||||||
" (set! v1-0 0)\n"
|
" (set! v1-0 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si v1-0 a1-0)\n"
|
" (< v1-0 a1-0)\n"
|
||||||
" (nop!)\n"
|
" (nop!)\n"
|
||||||
" (nop!)\n"
|
" (nop!)\n"
|
||||||
" (set! a0-0 (cdr a0-0))\n"
|
" (set! a0-0 (cdr a0-0))\n"
|
||||||
@ -684,7 +730,7 @@ TEST_F(FormRegressionTest, ExprPairMethod4) {
|
|||||||
" (set! v0-0 1)\n"
|
" (set! v0-0 1)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (and (!= v1-1 '()) "
|
" (and (!= v1-1 '()) "
|
||||||
" (<0.si (sll (the-as uint v1-1) 62))\n"
|
" (< (shl (the-as int v1-1) 62) 0)\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" (set! v0-0 (+ v0-0 1))\n"
|
" (set! v0-0 (+ v0-0 1))\n"
|
||||||
" (set! v1-1 (cdr v1-1))\n"
|
" (set! v1-1 (cdr v1-1))\n"
|
||||||
@ -1548,13 +1594,13 @@ TEST_F(FormRegressionTest, ExprSort) {
|
|||||||
" (set! s3-0 gp-0)\n"
|
" (set! s3-0 gp-0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (not\n"
|
" (not\n"
|
||||||
" (or (= (cdr s3-0) (quote ())) (>=0.si (sll (the-as uint (cdr s3-0)) 62)))\n"
|
" (or (= (cdr s3-0) (quote ())) (>= (shl (the-as int (cdr s3-0)) 62) 0))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" (set! s2-0 (car s3-0))\n"
|
" (set! s2-0 (car s3-0))\n"
|
||||||
" (set! s1-0 (car (cdr s3-0)))\n"
|
" (set! s1-0 (car (cdr s3-0)))\n"
|
||||||
" (set! v1-1 (s5-0 s2-0 s1-0))\n"
|
" (set! v1-1 (s5-0 s2-0 s1-0))\n"
|
||||||
" (when\n"
|
" (when\n"
|
||||||
" (and (or (not v1-1) (>0.si v1-1)) (!= v1-2 (quote #t)))\n"
|
" (and (or (not v1-1) (> (the-as int v1-1) 0)) (!= v1-2 (quote #t)))\n"
|
||||||
" (set! s4-0 (+ s4-0 1))\n"
|
" (set! s4-0 (+ s4-0 1))\n"
|
||||||
" (set! (car s3-0) s1-0)\n"
|
" (set! (car s3-0) s1-0)\n"
|
||||||
" (set! (car (cdr s3-0)) s2-0)\n"
|
" (set! (car (cdr s3-0)) s2-0)\n"
|
||||||
@ -1851,7 +1897,7 @@ TEST_F(FormRegressionTest, ExprMemCopy) {
|
|||||||
" (set! v0-0 a0-0)\n"
|
" (set! v0-0 a0-0)\n"
|
||||||
" (set! v1-0 0)\n"
|
" (set! v1-0 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si v1-0 a2-0)\n"
|
" (< v1-0 a2-0)\n"
|
||||||
" (set! (-> (the-as (pointer int8) a0-0)) (-> (the-as (pointer uint8) a1-0)))\n"
|
" (set! (-> (the-as (pointer int8) a0-0)) (-> (the-as (pointer uint8) a1-0)))\n"
|
||||||
" (set! a0-0 (+ a0-0 (the-as uint 1)))\n"
|
" (set! a0-0 (+ a0-0 (the-as uint 1)))\n"
|
||||||
" (set! a1-0 (+ a1-0 (the-as uint 1)))\n"
|
" (set! a1-0 (+ a1-0 (the-as uint 1)))\n"
|
||||||
@ -1894,7 +1940,7 @@ TEST_F(FormRegressionTest, ExprMemSet32) {
|
|||||||
" (set! v0-0 a0-0)\n"
|
" (set! v0-0 a0-0)\n"
|
||||||
" (set! v1-0 0)\n"
|
" (set! v1-0 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si v1-0 a1-0)\n"
|
" (< v1-0 a1-0)\n"
|
||||||
" (set! (-> (the-as (pointer int32) a0-0)) a2-0)\n"
|
" (set! (-> (the-as (pointer int32) a0-0)) a2-0)\n"
|
||||||
" (set! a0-0 (+ a0-0 (the-as uint 4)))\n"
|
" (set! a0-0 (+ a0-0 (the-as uint 4)))\n"
|
||||||
" (nop!)\n"
|
" (nop!)\n"
|
||||||
@ -1940,7 +1986,7 @@ TEST_F(FormRegressionTest, ExprMemOr) {
|
|||||||
" (set! v0-0 a0-0)\n"
|
" (set! v0-0 a0-0)\n"
|
||||||
" (set! v1-0 0)\n"
|
" (set! v1-0 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si v1-0 a2-0)\n"
|
" (< v1-0 a2-0)\n"
|
||||||
" (set!\n"
|
" (set!\n"
|
||||||
" (-> (the-as (pointer int8) a0-0))\n"
|
" (-> (the-as (pointer int8) a0-0))\n"
|
||||||
" (logior\n"
|
" (logior\n"
|
||||||
@ -2166,17 +2212,138 @@ TEST_F(FormRegressionTest, ExprPrintTreeBitmask) {
|
|||||||
" (set! s5-0 a1-0)\n"
|
" (set! s5-0 a1-0)\n"
|
||||||
" (set! s4-0 0)\n"
|
" (set! s4-0 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s4-0 s5-0)\n"
|
" (< s4-0 s5-0)\n"
|
||||||
" (if\n"
|
" (if\n"
|
||||||
" (zero? (logand gp-0 1))\n"
|
" (zero? (logand gp-0 1))\n"
|
||||||
" (format (quote #t) L323)\n"
|
" (format (quote #t) L323)\n"
|
||||||
" (format (quote #t) L322)\n"
|
" (format (quote #t) L322)\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" (set! gp-0 (srl (the-as uint gp-0) 1))\n"
|
" (set! gp-0 (shr (the-as uint gp-0) 1))\n"
|
||||||
" (set! s4-0 (+ s4-0 1))\n"
|
" (set! s4-0 (+ s4-0 1))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" (set! v1-3 (quote #f))\n"
|
" (set! v1-3 (quote #f))\n"
|
||||||
" (quote #f)\n"
|
" (quote #f)\n"
|
||||||
" )";
|
" )";
|
||||||
test_with_expr(func, type, expected, false, "", {{"L323", " "}, {"L322", "| "}});
|
test_with_expr(func, type, expected, false, "", {{"L323", " "}, {"L322", "| "}});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(FormRegressionTest, ExprPrintName) {
|
||||||
|
std::string func =
|
||||||
|
" sll r0, r0, 0\n"
|
||||||
|
"L136:\n"
|
||||||
|
" daddiu sp, sp, -16\n"
|
||||||
|
" sd ra, 0(sp)\n"
|
||||||
|
|
||||||
|
" bne a0, a1, L137\n"
|
||||||
|
" or v1, s7, r0\n"
|
||||||
|
|
||||||
|
" daddiu v0, s7, #t\n"
|
||||||
|
" beq r0, r0, L143\n"
|
||||||
|
" sll r0, r0, 0\n"
|
||||||
|
|
||||||
|
"L137:\n"
|
||||||
|
" lwu v1, -4(a0)\n"
|
||||||
|
" lw a2, string(s7)\n"
|
||||||
|
" dsubu v1, v1, a2\n"
|
||||||
|
" daddiu a2, s7, 8\n"
|
||||||
|
" movn a2, s7, v1\n"
|
||||||
|
" beql s7, a2, L138\n"
|
||||||
|
" or v1, a2, r0\n"
|
||||||
|
|
||||||
|
" lwu v1, -4(a1)\n"
|
||||||
|
" lw a2, string(s7)\n"
|
||||||
|
" dsubu a2, v1, a2\n"
|
||||||
|
" daddiu v1, s7, 8\n"
|
||||||
|
" movn v1, s7, a2\n"
|
||||||
|
|
||||||
|
"L138:\n"
|
||||||
|
" beq s7, v1, L139\n"
|
||||||
|
" or v1, s7, r0\n"
|
||||||
|
|
||||||
|
" lw t9, string=(s7)\n"
|
||||||
|
" jalr ra, t9\n"
|
||||||
|
" sll v0, ra, 0\n"
|
||||||
|
|
||||||
|
" beq r0, r0, L143\n"
|
||||||
|
" sll r0, r0, 0\n"
|
||||||
|
|
||||||
|
"L139:\n"
|
||||||
|
" lwu v1, -4(a0)\n"
|
||||||
|
" lw a2, string(s7)\n"
|
||||||
|
" dsubu v1, v1, a2\n"
|
||||||
|
" daddiu a2, s7, 8\n"
|
||||||
|
" movn a2, s7, v1\n"
|
||||||
|
" beql s7, a2, L140\n"
|
||||||
|
" or v1, a2, r0\n"
|
||||||
|
|
||||||
|
" lwu v1, -4(a1)\n"
|
||||||
|
" lw a2, symbol(s7)\n"
|
||||||
|
" dsubu a2, v1, a2\n"
|
||||||
|
" daddiu v1, s7, 8\n"
|
||||||
|
" movn v1, s7, a2\n"
|
||||||
|
|
||||||
|
"L140:\n"
|
||||||
|
" beq s7, v1, L141\n"
|
||||||
|
" or v1, s7, r0\n"
|
||||||
|
|
||||||
|
" lw t9, string=(s7)\n"
|
||||||
|
" ori v1, r0, 65336\n"
|
||||||
|
" daddu v1, v1, a1\n"
|
||||||
|
" lwu a1, 0(v1)\n"
|
||||||
|
" jalr ra, t9\n"
|
||||||
|
" sll v0, ra, 0\n"
|
||||||
|
"\n"
|
||||||
|
" beq r0, r0, L143\n"
|
||||||
|
" sll r0, r0, 0\n"
|
||||||
|
|
||||||
|
"L141:\n"
|
||||||
|
" lwu v1, -4(a1)\n"
|
||||||
|
" lw a2, string(s7)\n"
|
||||||
|
" dsubu v1, v1, a2\n"
|
||||||
|
" daddiu a2, s7, 8\n"
|
||||||
|
" movn a2, s7, v1\n"
|
||||||
|
" beql s7, a2, L142\n"
|
||||||
|
" or v1, a2, r0\n"
|
||||||
|
|
||||||
|
" lwu v1, -4(a0)\n"
|
||||||
|
" lw a2, symbol(s7)\n"
|
||||||
|
" dsubu a2, v1, a2\n"
|
||||||
|
" daddiu v1, s7, 8\n"
|
||||||
|
" movn v1, s7, a2\n"
|
||||||
|
|
||||||
|
"L142:\n"
|
||||||
|
" beq s7, v1, L143\n"
|
||||||
|
" or v0, s7, r0\n"
|
||||||
|
|
||||||
|
" lw t9, string=(s7)\n"
|
||||||
|
" or v1, a1, r0\n"
|
||||||
|
" ori a1, r0, 65336\n"
|
||||||
|
" daddu a0, a1, a0\n"
|
||||||
|
" lwu a1, 0(a0)\n"
|
||||||
|
" or a0, v1, r0\n"
|
||||||
|
" jalr ra, t9\n"
|
||||||
|
" sll v0, ra, 0\n"
|
||||||
|
|
||||||
|
"L143:\n"
|
||||||
|
" ld ra, 0(sp)\n"
|
||||||
|
" jr ra\n"
|
||||||
|
" daddiu sp, sp, 16";
|
||||||
|
std::string type = "(function basic basic symbol)";
|
||||||
|
|
||||||
|
std::string expected =
|
||||||
|
"(cond\n"
|
||||||
|
" ((= a0-0 a1-0) (quote #t))\n"
|
||||||
|
" ((and (= (-> a0-0 type) string) (= (-> a1-0 type) string))\n"
|
||||||
|
" (string= a0-0 a1-0)\n"
|
||||||
|
" )\n"
|
||||||
|
" ((and (= (-> a0-0 type) string) (= (-> a1-0 type) symbol))\n"
|
||||||
|
" (string= a0-0 (-> (+ 65336 (the-as int (the-as symbol a1-0))) 0))\n"
|
||||||
|
" )\n"
|
||||||
|
" ((and (= (-> a1-0 type) string) (= (-> a0-0 type) symbol))\n"
|
||||||
|
" (string= a1-0 (-> (+ 65336 (the-as int (the-as symbol a0-0))) 0))\n"
|
||||||
|
" )\n"
|
||||||
|
" )";
|
||||||
|
test_with_expr(func, type, expected, false, "", {},
|
||||||
|
parse_hint_json("[\t\t[24, [\"a1\", \"symbol\"]],\n"
|
||||||
|
"\t\t[39, [\"a0\", \"symbol\"]]]"));
|
||||||
}
|
}
|
@ -547,7 +547,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
|
|||||||
" ((= v1-1 (quote int32))\n"
|
" ((= v1-1 (quote int32))\n"
|
||||||
" (set! s5-0 0)\n"
|
" (set! s5-0 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-0 (-> gp-0 length))\n"
|
" (< s5-0 (-> gp-0 length))\n"
|
||||||
" (format\n"
|
" (format\n"
|
||||||
" (quote #t)\n"
|
" (quote #t)\n"
|
||||||
" (if (zero? s5-0) L341 L340)\n"
|
" (if (zero? s5-0) L341 L340)\n"
|
||||||
@ -561,7 +561,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
|
|||||||
" ((= v1-1 (quote uint32))\n"
|
" ((= v1-1 (quote uint32))\n"
|
||||||
" (set! s5-1 0)\n"
|
" (set! s5-1 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-1 (-> gp-0 length))\n"
|
" (< s5-1 (-> gp-0 length))\n"
|
||||||
" (format\n"
|
" (format\n"
|
||||||
" (quote #t)\n"
|
" (quote #t)\n"
|
||||||
" (if (zero? s5-1) L341 L340)\n"
|
" (if (zero? s5-1) L341 L340)\n"
|
||||||
@ -575,7 +575,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
|
|||||||
" ((= v1-1 (quote int64))\n"
|
" ((= v1-1 (quote int64))\n"
|
||||||
" (set! s5-2 0)\n"
|
" (set! s5-2 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-2 (-> gp-0 length))\n"
|
" (< s5-2 (-> gp-0 length))\n"
|
||||||
" (format\n"
|
" (format\n"
|
||||||
" (quote #t)\n"
|
" (quote #t)\n"
|
||||||
" (if (zero? s5-2) L341 L340)\n"
|
" (if (zero? s5-2) L341 L340)\n"
|
||||||
@ -589,7 +589,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
|
|||||||
" ((= v1-1 (quote uint64))\n"
|
" ((= v1-1 (quote uint64))\n"
|
||||||
" (set! s5-3 0)\n"
|
" (set! s5-3 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-3 (-> gp-0 length))\n"
|
" (< s5-3 (-> gp-0 length))\n"
|
||||||
" (format\n"
|
" (format\n"
|
||||||
" (quote #t)\n"
|
" (quote #t)\n"
|
||||||
" (if (zero? s5-3) L339 L338)\n"
|
" (if (zero? s5-3) L339 L338)\n"
|
||||||
@ -603,7 +603,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
|
|||||||
" ((= v1-1 (quote int8))\n"
|
" ((= v1-1 (quote int8))\n"
|
||||||
" (set! s5-4 0)\n"
|
" (set! s5-4 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-4 (-> gp-0 length))\n"
|
" (< s5-4 (-> gp-0 length))\n"
|
||||||
" (format\n"
|
" (format\n"
|
||||||
" (quote #t)\n"
|
" (quote #t)\n"
|
||||||
" (if (zero? s5-4) L341 L340)\n"
|
" (if (zero? s5-4) L341 L340)\n"
|
||||||
@ -617,7 +617,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
|
|||||||
" ((= v1-1 (quote uint8))\n"
|
" ((= v1-1 (quote uint8))\n"
|
||||||
" (set! s5-5 0)\n"
|
" (set! s5-5 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-5 (-> gp-0 length))\n"
|
" (< s5-5 (-> gp-0 length))\n"
|
||||||
" (format\n"
|
" (format\n"
|
||||||
" (quote #t)\n"
|
" (quote #t)\n"
|
||||||
" (if (zero? s5-5) L341 L340)\n"
|
" (if (zero? s5-5) L341 L340)\n"
|
||||||
@ -631,7 +631,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
|
|||||||
" ((= v1-1 (quote int16))\n"
|
" ((= v1-1 (quote int16))\n"
|
||||||
" (set! s5-6 0)\n"
|
" (set! s5-6 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-6 (-> gp-0 length))\n"
|
" (< s5-6 (-> gp-0 length))\n"
|
||||||
" (format\n"
|
" (format\n"
|
||||||
" (quote #t)\n"
|
" (quote #t)\n"
|
||||||
" (if (zero? s5-6) L341 L340)\n"
|
" (if (zero? s5-6) L341 L340)\n"
|
||||||
@ -645,7 +645,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
|
|||||||
" ((= v1-1 (quote uint16))\n"
|
" ((= v1-1 (quote uint16))\n"
|
||||||
" (set! s5-7 0)\n"
|
" (set! s5-7 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-7 (-> gp-0 length))\n"
|
" (< s5-7 (-> gp-0 length))\n"
|
||||||
" (format\n"
|
" (format\n"
|
||||||
" (quote #t)\n"
|
" (quote #t)\n"
|
||||||
" (if (zero? s5-7) L341 L340)\n"
|
" (if (zero? s5-7) L341 L340)\n"
|
||||||
@ -662,14 +662,14 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
|
|||||||
" (v1-40\n"
|
" (v1-40\n"
|
||||||
" (set! s5-8 0)\n"
|
" (set! s5-8 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-8 (-> gp-0 length))\n"
|
" (< s5-8 (-> gp-0 length))\n"
|
||||||
" (set! t9-10 format)\n"
|
" (set! t9-10 format)\n"
|
||||||
" (set! a0-21 (quote #t))\n"
|
" (set! a0-21 (quote #t))\n"
|
||||||
" (set! a1-11 (if (zero? s5-8) L339 L338))\n"
|
" (set! a1-11 (if (zero? s5-8) L339 L338))\n"
|
||||||
" (set!\n"
|
" (set!\n"
|
||||||
" v1-42\n"
|
" v1-42\n"
|
||||||
" (+\n"
|
" (+\n"
|
||||||
" (sll (the-as uint s5-8) 4)\n"
|
" (shl s5-8 4)\n"
|
||||||
" (the-as int (the-as (array uint128) gp-0))\n"
|
" (the-as int (the-as (array uint128) gp-0))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
@ -683,7 +683,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
|
|||||||
" (else\n"
|
" (else\n"
|
||||||
" (set! s5-9 0)\n"
|
" (set! s5-9 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-9 (-> gp-0 length))\n"
|
" (< s5-9 (-> gp-0 length))\n"
|
||||||
" (format\n"
|
" (format\n"
|
||||||
" (quote #t)\n"
|
" (quote #t)\n"
|
||||||
" (if (zero? s5-9) L341 L340)\n"
|
" (if (zero? s5-9) L341 L340)\n"
|
||||||
@ -704,7 +704,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
|
|||||||
" ((= (-> gp-0 content-type) float)\n"
|
" ((= (-> gp-0 content-type) float)\n"
|
||||||
" (set! s5-10 0)\n"
|
" (set! s5-10 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-10 (-> gp-0 length))\n"
|
" (< s5-10 (-> gp-0 length))\n"
|
||||||
" (if\n"
|
" (if\n"
|
||||||
" (zero? s5-10)\n"
|
" (zero? s5-10)\n"
|
||||||
" (format (quote #t) L343 (-> (the-as (array float) gp-0) s5-10))\n"
|
" (format (quote #t) L343 (-> (the-as (array float) gp-0) s5-10))\n"
|
||||||
@ -718,7 +718,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) {
|
|||||||
" (else\n"
|
" (else\n"
|
||||||
" (set! s5-11 0)\n"
|
" (set! s5-11 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-11 (-> gp-0 length))\n"
|
" (< s5-11 (-> gp-0 length))\n"
|
||||||
" (if\n"
|
" (if\n"
|
||||||
" (zero? s5-11)\n"
|
" (zero? s5-11)\n"
|
||||||
" (format (quote #t) L336 (-> (the-as (array basic) gp-0) s5-11))\n"
|
" (format (quote #t) L336 (-> (the-as (array basic) gp-0) s5-11))\n"
|
||||||
@ -1231,7 +1231,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
|
|||||||
" ((= v1-1 (quote int32))\n"
|
" ((= v1-1 (quote int32))\n"
|
||||||
" (set! s5-0 0)\n"
|
" (set! s5-0 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-0 (-> gp-0 length))\n"
|
" (< s5-0 (-> gp-0 length))\n"
|
||||||
" (format (quote #t) L328 s5-0 (-> (the-as (array int32) gp-0) s5-0))\n"
|
" (format (quote #t) L328 s5-0 (-> (the-as (array int32) gp-0) s5-0))\n"
|
||||||
" (set! s5-0 (+ s5-0 1))\n"
|
" (set! s5-0 (+ s5-0 1))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
@ -1241,7 +1241,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
|
|||||||
" ((= v1-1 (quote uint32))\n"
|
" ((= v1-1 (quote uint32))\n"
|
||||||
" (set! s5-1 0)\n"
|
" (set! s5-1 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-1 (-> gp-0 length))\n"
|
" (< s5-1 (-> gp-0 length))\n"
|
||||||
" (format (quote #t) L328 s5-1 (-> (the-as (array uint32) gp-0) s5-1))\n"
|
" (format (quote #t) L328 s5-1 (-> (the-as (array uint32) gp-0) s5-1))\n"
|
||||||
" (set! s5-1 (+ s5-1 1))\n"
|
" (set! s5-1 (+ s5-1 1))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
@ -1251,7 +1251,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
|
|||||||
" ((= v1-1 (quote int64))\n"
|
" ((= v1-1 (quote int64))\n"
|
||||||
" (set! s5-2 0)\n"
|
" (set! s5-2 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-2 (-> gp-0 length))\n"
|
" (< s5-2 (-> gp-0 length))\n"
|
||||||
" (format (quote #t) L328 s5-2 (-> (the-as (array int64) gp-0) s5-2))\n"
|
" (format (quote #t) L328 s5-2 (-> (the-as (array int64) gp-0) s5-2))\n"
|
||||||
" (set! s5-2 (+ s5-2 1))\n"
|
" (set! s5-2 (+ s5-2 1))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
@ -1261,7 +1261,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
|
|||||||
" ((= v1-1 (quote uint64))\n"
|
" ((= v1-1 (quote uint64))\n"
|
||||||
" (set! s5-3 0)\n"
|
" (set! s5-3 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-3 (-> gp-0 length))\n"
|
" (< s5-3 (-> gp-0 length))\n"
|
||||||
" (format (quote #t) L327 s5-3 (-> (the-as (array uint64) gp-0) s5-3))\n"
|
" (format (quote #t) L327 s5-3 (-> (the-as (array uint64) gp-0) s5-3))\n"
|
||||||
" (set! s5-3 (+ s5-3 1))\n"
|
" (set! s5-3 (+ s5-3 1))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
@ -1271,7 +1271,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
|
|||||||
" ((= v1-1 (quote int8))\n"
|
" ((= v1-1 (quote int8))\n"
|
||||||
" (set! s5-4 0)\n"
|
" (set! s5-4 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-4 (-> gp-0 length))\n"
|
" (< s5-4 (-> gp-0 length))\n"
|
||||||
" (format (quote #t) L328 s5-4 (-> (the-as (array int8) gp-0) s5-4))\n"
|
" (format (quote #t) L328 s5-4 (-> (the-as (array int8) gp-0) s5-4))\n"
|
||||||
" (set! s5-4 (+ s5-4 1))\n"
|
" (set! s5-4 (+ s5-4 1))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
@ -1281,7 +1281,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
|
|||||||
" ((= v1-1 (quote uint8))\n"
|
" ((= v1-1 (quote uint8))\n"
|
||||||
" (set! s5-5 0)\n"
|
" (set! s5-5 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-5 (-> gp-0 length))\n"
|
" (< s5-5 (-> gp-0 length))\n"
|
||||||
" (format (quote #t) L328 s5-5 (-> (the-as (array int8) gp-0) s5-5))\n"
|
" (format (quote #t) L328 s5-5 (-> (the-as (array int8) gp-0) s5-5))\n"
|
||||||
" (set! s5-5 (+ s5-5 1))\n"
|
" (set! s5-5 (+ s5-5 1))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
@ -1291,7 +1291,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
|
|||||||
" ((= v1-1 (quote int16))\n"
|
" ((= v1-1 (quote int16))\n"
|
||||||
" (set! s5-6 0)\n"
|
" (set! s5-6 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-6 (-> gp-0 length))\n"
|
" (< s5-6 (-> gp-0 length))\n"
|
||||||
" (format (quote #t) L328 s5-6 (-> (the-as (array int16) gp-0) s5-6))\n"
|
" (format (quote #t) L328 s5-6 (-> (the-as (array int16) gp-0) s5-6))\n"
|
||||||
" (set! s5-6 (+ s5-6 1))\n"
|
" (set! s5-6 (+ s5-6 1))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
@ -1301,7 +1301,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
|
|||||||
" ((= v1-1 (quote uint16))\n"
|
" ((= v1-1 (quote uint16))\n"
|
||||||
" (set! s5-7 0)\n"
|
" (set! s5-7 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-7 (-> gp-0 length))\n"
|
" (< s5-7 (-> gp-0 length))\n"
|
||||||
" (format (quote #t) L328 s5-7 (-> (the-as (array uint16) gp-0) s5-7))\n"
|
" (format (quote #t) L328 s5-7 (-> (the-as (array uint16) gp-0) s5-7))\n"
|
||||||
" (set! s5-7 (+ s5-7 1))\n"
|
" (set! s5-7 (+ s5-7 1))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
@ -1314,7 +1314,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
|
|||||||
" (v1-40\n"
|
" (v1-40\n"
|
||||||
" (set! s5-8 0)\n"
|
" (set! s5-8 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-8 (-> gp-0 length))\n"
|
" (< s5-8 (-> gp-0 length))\n"
|
||||||
" (set! t9-14 format)\n"
|
" (set! t9-14 format)\n"
|
||||||
" (set! a0-25 (quote #t))\n"
|
" (set! a0-25 (quote #t))\n"
|
||||||
" (set! a1-15 L327)\n"
|
" (set! a1-15 L327)\n"
|
||||||
@ -1322,7 +1322,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
|
|||||||
" (set!\n"
|
" (set!\n"
|
||||||
" v1-42\n"
|
" v1-42\n"
|
||||||
" (+\n"
|
" (+\n"
|
||||||
" (sll (the-as uint s5-8) 4)\n"
|
" (shl s5-8 4)\n"
|
||||||
" (the-as int (the-as (array uint128) gp-0))\n"
|
" (the-as int (the-as (array uint128) gp-0))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
@ -1336,7 +1336,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
|
|||||||
" (else\n"
|
" (else\n"
|
||||||
" (set! s5-9 0)\n"
|
" (set! s5-9 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-9 (-> gp-0 length))\n"
|
" (< s5-9 (-> gp-0 length))\n"
|
||||||
" (format (quote #t) L328 s5-9 (-> gp-0 s5-9))\n"
|
" (format (quote #t) L328 s5-9 (-> gp-0 s5-9))\n"
|
||||||
" (set! s5-9 (+ s5-9 1))\n"
|
" (set! s5-9 (+ s5-9 1))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
@ -1353,7 +1353,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
|
|||||||
" ((= (-> gp-0 content-type) float)\n"
|
" ((= (-> gp-0 content-type) float)\n"
|
||||||
" (set! s5-10 0)\n"
|
" (set! s5-10 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-10 (-> gp-0 length))\n"
|
" (< s5-10 (-> gp-0 length))\n"
|
||||||
" (format (quote #t) L326 s5-10 (-> (the-as (array float) gp-0) s5-10))\n"
|
" (format (quote #t) L326 s5-10 (-> (the-as (array float) gp-0) s5-10))\n"
|
||||||
" (set! s5-10 (+ s5-10 1))\n"
|
" (set! s5-10 (+ s5-10 1))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
@ -1363,7 +1363,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) {
|
|||||||
" (else\n"
|
" (else\n"
|
||||||
" (set! s5-11 0)\n"
|
" (set! s5-11 0)\n"
|
||||||
" (while\n"
|
" (while\n"
|
||||||
" (<.si s5-11 (-> gp-0 length))\n"
|
" (< s5-11 (-> gp-0 length))\n"
|
||||||
" (format (quote #t) L325 s5-11 (-> (the-as (array basic) gp-0) s5-11))\n"
|
" (format (quote #t) L325 s5-11 (-> (the-as (array basic) gp-0) s5-11))\n"
|
||||||
" (set! s5-11 (+ s5-11 1))\n"
|
" (set! s5-11 (+ s5-11 1))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
@ -1932,13 +1932,16 @@ TEST_F(FormRegressionTest, ExprValid) {
|
|||||||
" (set! s3-0 a1-0)\n"
|
" (set! s3-0 a1-0)\n"
|
||||||
" (set! s4-0 a2-0)\n"
|
" (set! s4-0 a2-0)\n"
|
||||||
" (set! s5-0 t0-0)\n"
|
" (set! s5-0 t0-0)\n"
|
||||||
" (and (>=.ui gp-0 __START-OF-TABLE__) (begin (<.ui gp-0 134217728) v1-1))\n"
|
" (and\n"
|
||||||
|
" (>= (the-as uint gp-0) (the-as uint __START-OF-TABLE__))\n"
|
||||||
|
" (< (the-as uint gp-0) (the-as uint 134217728))\n"
|
||||||
|
" )\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" (cond\n"
|
" (cond\n"
|
||||||
" ((not s3-0)\n"
|
" ((not s3-0)\n"
|
||||||
" (cond\n"
|
" (cond\n"
|
||||||
" ((nonzero? (logand gp-0 3))\n"
|
" ((nonzero? (logand (the-as int gp-0) 3))\n"
|
||||||
" (if s4-0 (set! v1-4 (format s5-0 L321 gp-0 s4-0)))\n"
|
" (if s4-0 (set! v1-4 (format s5-0 L321 gp-0 s4-0)))\n"
|
||||||
" (quote #f)\n"
|
" (quote #f)\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
@ -1946,18 +1949,22 @@ TEST_F(FormRegressionTest, ExprValid) {
|
|||||||
" (else (quote #t))\n"
|
" (else (quote #t))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" ((and a3-2 (not gp-0)) (quote #t))\n"
|
" ((and a3-0 (not gp-0)) (quote #t))\n"
|
||||||
" (else\n"
|
" (else\n"
|
||||||
" (cond\n"
|
" (cond\n"
|
||||||
" ((= s3-0 structure)\n"
|
" ((= s3-0 structure)\n"
|
||||||
" (cond\n"
|
" (cond\n"
|
||||||
" ((nonzero? (logand gp-0 15))\n"
|
" ((nonzero? (logand (the-as int gp-0) 15))\n"
|
||||||
" (if s4-0 (set! v1-8 (format s5-0 L319 gp-0 s4-0 s3-0)))\n"
|
" (if s4-0 (set! v1-8 (format s5-0 L319 gp-0 s4-0 s3-0)))\n"
|
||||||
" (quote #f)\n"
|
" (quote #f)\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" ((or\n"
|
" ((or\n"
|
||||||
" (not v1-1)\n"
|
" (not v1-1)\n"
|
||||||
" (begin (set! v1-10 32768) (.daddu v1-11 v1-10 s7-0) (<.ui gp-0 v1-11))\n"
|
" (begin\n"
|
||||||
|
" (set! v1-10 32768)\n"
|
||||||
|
" (.daddu v1-11 v1-10 s7-0)\n"
|
||||||
|
" (< (the-as uint gp-0) (the-as uint v1-11))\n"
|
||||||
|
" )\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" (if s4-0 (set! v1-13 (format s5-0 L318 gp-0 s4-0 s3-0)))\n"
|
" (if s4-0 (set! v1-13 (format s5-0 L318 gp-0 s4-0 s3-0)))\n"
|
||||||
" (quote #f)\n"
|
" (quote #f)\n"
|
||||||
@ -1967,7 +1974,7 @@ TEST_F(FormRegressionTest, ExprValid) {
|
|||||||
" )\n"
|
" )\n"
|
||||||
" ((= s3-0 pair)\n"
|
" ((= s3-0 pair)\n"
|
||||||
" (cond\n"
|
" (cond\n"
|
||||||
" ((!= (logand gp-0 7) 2)\n"
|
" ((!= (logand (the-as int gp-0) 7) 2)\n"
|
||||||
" (if s4-0 (set! v1-15 (format s5-0 L319 gp-0 s4-0 s3-0)))\n"
|
" (if s4-0 (set! v1-15 (format s5-0 L319 gp-0 s4-0 s3-0)))\n"
|
||||||
" (quote #f)\n"
|
" (quote #f)\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
@ -1980,14 +1987,14 @@ TEST_F(FormRegressionTest, ExprValid) {
|
|||||||
" )\n"
|
" )\n"
|
||||||
" ((= s3-0 binteger)\n"
|
" ((= s3-0 binteger)\n"
|
||||||
" (cond\n"
|
" (cond\n"
|
||||||
" ((zero? (logand gp-0 7)) (quote #t))\n"
|
" ((zero? (logand (the-as int gp-0) 7)) (quote #t))\n"
|
||||||
" (else\n"
|
" (else\n"
|
||||||
" (if s4-0 (set! v1-20 (format s5-0 L319 gp-0 s4-0 s3-0)))\n"
|
" (if s4-0 (set! v1-20 (format s5-0 L319 gp-0 s4-0 s3-0)))\n"
|
||||||
" (quote #f)\n"
|
" (quote #f)\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" ((!= (logand gp-0 7) 4)\n"
|
" ((!= (logand (the-as int gp-0) 7) 4)\n"
|
||||||
" (if s4-0 (set! v1-22 (format s5-0 L319 gp-0 s4-0 s3-0)))\n"
|
" (if s4-0 (set! v1-22 (format s5-0 L319 gp-0 s4-0 s3-0)))\n"
|
||||||
" (quote #f)\n"
|
" (quote #f)\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
@ -2020,14 +2027,18 @@ TEST_F(FormRegressionTest, ExprValid) {
|
|||||||
" (set! v1-43 32768)\n"
|
" (set! v1-43 32768)\n"
|
||||||
" (.daddu v1-44 v1-43 s7-0)\n"
|
" (.daddu v1-44 v1-43 s7-0)\n"
|
||||||
" (cond\n"
|
" (cond\n"
|
||||||
" ((>=.ui gp-0 v1-44)\n"
|
" ((>= (the-as uint gp-0) (the-as uint v1-44))\n"
|
||||||
" (if s4-0 (set! v1-46 (format s5-0 L315 gp-0 s4-0 s3-0)))\n"
|
" (if s4-0 (set! v1-46 (format s5-0 L315 gp-0 s4-0 s3-0)))\n"
|
||||||
" (quote #f)\n"
|
" (quote #f)\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" (else (quote #t))\n"
|
" (else (quote #t))\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
" ((begin (set! v1-47 32768) (.daddu v1-48 v1-47 s7-0) (<.ui gp-0 v1-48))\n"
|
" ((begin\n"
|
||||||
|
" (set! v1-47 32768)\n"
|
||||||
|
" (.daddu v1-48 v1-47 s7-0)\n"
|
||||||
|
" (< (the-as uint gp-0) (the-as uint v1-48))\n"
|
||||||
|
" )\n"
|
||||||
" (if s4-0 (set! v1-50 (format s5-0 L314 gp-0 s4-0 s3-0)))\n"
|
" (if s4-0 (set! v1-50 (format s5-0 L314 gp-0 s4-0 s3-0)))\n"
|
||||||
" (quote #f)\n"
|
" (quote #f)\n"
|
||||||
" )\n"
|
" )\n"
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
(defun ash ((value integer) (shift-amount integer))
|
(defun ash ((value integer) (shift-amount integer))
|
||||||
(declare (inline))
|
(declare (inline))
|
||||||
(if (> shift-amount 0)
|
(if (> shift-amount 0)
|
||||||
(shlv value shift-amount)
|
(shl value shift-amount)
|
||||||
(sarv value (- shift-amount))
|
(sar value (- shift-amount))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,2 +1,7 @@
|
|||||||
(+ (shlv 2 3) (shlv 1 0) (shlv 0 4) (shrv 2 3) (shrv 10 2) (shlv -2 1) (sarv -16 2))
|
|
||||||
|
(let ((one 1)
|
||||||
|
(two 2))
|
||||||
|
(+ (shl 2 3) (shl 1 0) (shl 0 4) (shr 2 3) (shr 10 two) (shl -2 one) (sar -16 two))
|
||||||
|
)
|
||||||
|
|
||||||
;; 16 1 0 0 2 -4 -4
|
;; 16 1 0 0 2 -4 -4
|
@ -543,7 +543,7 @@ TEST_P(VectorFloatParameterizedTestFixtureWithRunner, VF_ABS_DEST) {
|
|||||||
testCase.operation = [](float x, float y) {
|
testCase.operation = [](float x, float y) {
|
||||||
// Avoid compiler warnings for unused variable, making a varient that accepts a lambda with only
|
// Avoid compiler warnings for unused variable, making a varient that accepts a lambda with only
|
||||||
// 1 float is just unnecessary complexity
|
// 1 float is just unnecessary complexity
|
||||||
y = 0;
|
(void)y;
|
||||||
return fabs(x);
|
return fabs(x);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ int main(int argc, char** argv) {
|
|||||||
// write files:
|
// write files:
|
||||||
for (auto& entry : dgo.entries()) {
|
for (auto& entry : dgo.entries()) {
|
||||||
file_util::write_binary_file(file_util::combine_path(out_path, entry.unique_name),
|
file_util::write_binary_file(file_util::combine_path(out_path, entry.unique_name),
|
||||||
(void*)entry.data.data(), entry.data.size());
|
(const void*)entry.data.data(), entry.data.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user