Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Decompiler] Begin expression conversion, rearrange tests #209

Merged
merged 4 commits into from
Jan 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions decompiler/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
add_library(
decomp
SHARED

analysis/atomic_op_builder.cpp
analysis/cfg_builder.cpp
analysis/expression_build.cpp
analysis/reg_usage.cpp
analysis/variable_naming.cpp

data/game_count.cpp
data/game_text.cpp
data/StrFileReader.cpp
Expand All @@ -22,17 +29,13 @@ add_library(
IR/BasicOpBuilder.cpp
IR/IR.cpp

IR2/atomic_op_builder.cpp
IR2/AtomicOp.cpp
IR2/AtomicOpForm.cpp
IR2/AtomicOpTypeAnalysis.cpp
IR2/cfg_builder.cpp
IR2/Env.cpp
IR2/expression_build.cpp
IR2/Form.cpp
IR2/FormExpressionAnalysis.cpp
IR2/FormStack.cpp
IR2/reg_usage.cpp
IR2/variable_naming.cpp

ObjectFile/LinkedObjectFile.cpp
ObjectFile/LinkedObjectFileCreation.cpp
Expand Down
11 changes: 1 addition & 10 deletions decompiler/Function/BasicBlocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include "decompiler/util/DecompilerTypeSystem.h"
#include "decompiler/util/TP_Type.h"
// for RegSet:
#include "decompiler/IR2/reg_usage.h"
#include "decompiler/analysis/reg_usage.h"

namespace decompiler {
class LinkedObjectFile;
Expand All @@ -29,15 +29,6 @@ struct BasicBlock {
int succ_ft = -1;
int succ_branch = -1;

std::vector<RegSet> live, dead;
RegSet use, defs;
RegSet input, output;

bool op_has_reg_live_out(int basic_op_idx, Register reg) {
auto& lv = live.at(basic_op_idx - start_basic_op);
return lv.find(reg) != lv.end();
}

BasicBlock(int _start_word, int _end_word) : start_word(_start_word), end_word(_end_word) {}
};

Expand Down
2 changes: 1 addition & 1 deletion decompiler/Function/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <unordered_map>
#include <stdexcept>
#include <unordered_set>
#include "decompiler/IR2/atomic_op_builder.h"
#include "decompiler/analysis/atomic_op_builder.h"
#include "decompiler/Disasm/Instruction.h"
#include "decompiler/Disasm/Register.h"
#include "BasicBlocks.h"
Expand Down
4 changes: 2 additions & 2 deletions decompiler/Function/TypeAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ bool Function::run_type_analysis_ir2(const TypeSpec& my_type,
} catch (std::runtime_error& e) {
fmt::print("Type prop fail on {}: {}\n", guessed_name.to_string(), e.what());
warnings += ";; Type prop attempted and failed.\n";
ir2.env.set_types(block_init_types, op_types);
ir2.env.set_types(block_init_types, op_types, *ir2.atomic_ops);
return false;
}

Expand Down Expand Up @@ -137,7 +137,7 @@ bool Function::run_type_analysis_ir2(const TypeSpec& my_type,
my_type.last_arg().print());
}

ir2.env.set_types(block_init_types, op_types);
ir2.env.set_types(block_init_types, op_types, *ir2.atomic_ops);

return true;
}
Expand Down
4 changes: 2 additions & 2 deletions decompiler/IR2/AtomicOpForm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ConditionElement* IR2_Condition::get_as_form(FormPool& pool) const {
}

FormElement* SetVarOp::get_as_form(FormPool& pool) const {
auto source = pool.alloc_single_element_form<SimpleExpressionElement>(nullptr, m_src);
auto source = pool.alloc_single_element_form<SimpleExpressionElement>(nullptr, m_src, m_my_idx);
return pool.alloc_element<SetVarElement>(m_dst, source, is_sequence_point());
}

Expand All @@ -36,7 +36,7 @@ FormElement* StoreOp::get_as_form(FormPool& pool) const {
}

FormElement* LoadVarOp::get_as_form(FormPool& pool) const {
auto source = pool.alloc_single_element_form<SimpleExpressionElement>(nullptr, m_src);
auto source = pool.alloc_single_element_form<SimpleExpressionElement>(nullptr, m_src, m_my_idx);
auto load = pool.alloc_single_element_form<LoadSourceElement>(nullptr, source, m_size, m_kind);
return pool.alloc_element<SetVarElement>(m_dst, load, true);
}
Expand Down
22 changes: 21 additions & 1 deletion decompiler/IR2/Env.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <algorithm>
#include "Env.h"
#include "Form.h"
#include "decompiler/analysis/atomic_op_builder.h"

namespace decompiler {
std::string Env::get_variable_name(Register reg, int atomic_idx, VariableMode mode) const {
Expand All @@ -13,9 +14,28 @@ std::string Env::get_variable_name(Register reg, int atomic_idx, VariableMode mo
* Update the Env with the result of the type analysis pass.
*/
void Env::set_types(const std::vector<TypeState>& block_init_types,
const std::vector<TypeState>& op_end_types) {
const std::vector<TypeState>& op_end_types,
const FunctionAtomicOps& atomic_ops) {
m_block_init_types = block_init_types;
m_op_end_types = op_end_types;

// cache the init types (this ends up being faster)
m_op_init_types.resize(op_end_types.size(), nullptr);
for (int block_idx = 0; block_idx < int(m_block_init_types.size()); block_idx++) {
int first_op = atomic_ops.block_id_to_first_atomic_op.at(block_idx);
int end_op = atomic_ops.block_id_to_end_atomic_op.at(block_idx);
if (end_op > first_op) {
m_op_init_types.at(first_op) = &m_block_init_types.at(block_idx);
for (int op_idx = first_op; op_idx < (end_op - 1); op_idx++) {
m_op_init_types.at(op_idx + 1) = &m_op_end_types.at(op_idx);
}
}
}

for (auto x : m_op_init_types) {
assert(x);
}

m_has_types = true;
}

Expand Down
12 changes: 10 additions & 2 deletions decompiler/IR2/Env.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
#include "decompiler/util/TP_Type.h"
#include "decompiler/Disasm/Register.h"
#include "decompiler/IR2/IR2_common.h"
#include "decompiler/IR2/reg_usage.h"
#include "decompiler/analysis/reg_usage.h"

namespace decompiler {
class LinkedObjectFile;
class Form;
struct FunctionAtomicOps;

struct VariableNames {
struct VarInfo {
Expand Down Expand Up @@ -68,6 +69,11 @@ class Env {
return m_op_end_types.at(atomic_op_id);
}

const TypeState& get_types_before_op(int atomic_op_id) const {
assert(m_has_types);
return *m_op_init_types.at(atomic_op_id);
}

/*!
* Get the types in registers at the beginning of this basic block, before any operations
* have occurred.
Expand All @@ -78,7 +84,8 @@ class Env {
}

void set_types(const std::vector<TypeState>& block_init_types,
const std::vector<TypeState>& op_end_types);
const std::vector<TypeState>& op_end_types,
const FunctionAtomicOps& atomic_ops);

void set_local_vars(const VariableNames& names) {
m_var_names = names;
Expand All @@ -102,5 +109,6 @@ class Env {
bool m_has_types = false;
std::vector<TypeState> m_block_init_types;
std::vector<TypeState> m_op_end_types;
std::vector<TypeState*> m_op_init_types;
};
} // namespace decompiler
126 changes: 124 additions & 2 deletions decompiler/IR2/Form.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ std::string FormElement::to_string(const Env& env) const {
return to_form(env).print();
}

void FormElement::push_to_stack(const Env& env, FormStack&) {
void FormElement::push_to_stack(const Env& env, FormPool&, FormStack&) {
throw std::runtime_error("push_to_stack not implemented for " + to_string(env));
}

Expand Down Expand Up @@ -83,7 +83,8 @@ void Form::collect_vars(VariableSet& vars) const {
// SimpleExpressionElement
/////////////////////////////

SimpleExpressionElement::SimpleExpressionElement(SimpleExpression expr) : m_expr(std::move(expr)) {}
SimpleExpressionElement::SimpleExpressionElement(SimpleExpression expr, int my_idx)
: m_expr(std::move(expr)), m_my_idx(my_idx) {}

goos::Object SimpleExpressionElement::to_form(const Env& env) const {
return m_expr.to_form(env.file->labels, &env);
Expand Down Expand Up @@ -761,4 +762,125 @@ void ConditionalMoveFalseElement::collect_vars(VariableSet& vars) const {
vars.insert(dest);
source->collect_vars(vars);
}

/////////////////////////////
// GenericElement
/////////////////////////////

GenericOperator GenericOperator::make_fixed(FixedOperatorKind kind) {
GenericOperator op;
op.m_kind = Kind::FIXED_OPERATOR;
op.m_fixed_kind = kind;
return op;
}

void GenericOperator::collect_vars(VariableSet&) const {
switch (m_kind) {
case Kind::FIXED_OPERATOR:
return;
default:
assert(false);
}
}

goos::Object GenericOperator::to_form(const Env&) const {
switch (m_kind) {
case Kind::FIXED_OPERATOR:
return pretty_print::to_symbol(fixed_operator_to_string(m_fixed_kind));
default:
assert(false);
}
}

void GenericOperator::apply(const std::function<void(FormElement*)>&) {
switch (m_kind) {
case Kind::FIXED_OPERATOR:
break;
default:
assert(false);
}
}

void GenericOperator::apply_form(const std::function<void(Form*)>&) {
switch (m_kind) {
case Kind::FIXED_OPERATOR:
break;
default:
assert(false);
}
}

std::string fixed_operator_to_string(FixedOperatorKind kind) {
switch (kind) {
case FixedOperatorKind::GPR_TO_FPR:
return "gpr->fpr";
case FixedOperatorKind::DIVISION:
return "/";
case FixedOperatorKind::ADDITION:
return "+";
default:
assert(false);
}
}

GenericElement::GenericElement(GenericOperator op) : m_head(op) {}
GenericElement::GenericElement(GenericOperator op, Form* arg) : m_head(op), m_elts({arg}) {}
GenericElement::GenericElement(GenericOperator op, Form* arg0, Form* arg1)
: m_head(op), m_elts({arg0, arg1}) {}
GenericElement::GenericElement(GenericOperator op, std::vector<Form*> forms)
: m_head(op), m_elts(std::move(forms)) {}

goos::Object GenericElement::to_form(const Env& env) const {
std::vector<goos::Object> result;
result.push_back(m_head.to_form(env));
for (auto x : m_elts) {
result.push_back(x->to_form(env));
}
return pretty_print::build_list(result);
}

void GenericElement::apply(const std::function<void(FormElement*)>& f) {
f(this);
m_head.apply(f);
for (auto x : m_elts) {
x->apply(f);
}
}

void GenericElement::apply_form(const std::function<void(Form*)>& f) {
m_head.apply_form(f);
for (auto x : m_elts) {
x->apply_form(f);
}
}

void GenericElement::collect_vars(VariableSet& vars) const {
m_head.collect_vars(vars);
for (auto x : m_elts) {
x->collect_vars(vars);
}
}

/////////////////////////////
// CastElement
/////////////////////////////

CastElement::CastElement(TypeSpec type, Form* source) : m_type(std::move(type)), m_source(source) {}

goos::Object CastElement::to_form(const Env& env) const {
return pretty_print::build_list("the-as", m_type.print(), m_source->to_form(env));
}

void CastElement::apply(const std::function<void(FormElement*)>& f) {
f(this);
m_source->apply(f);
}

void CastElement::apply_form(const std::function<void(Form*)>& f) {
m_source->apply_form(f);
}

void CastElement::collect_vars(VariableSet& vars) const {
m_source->collect_vars(vars);
}
} // namespace decompiler
Loading