[Decompiler] WIP Conversion to SSA and variable naming (#195)

* begin ssa algorithm

* ssa based splitting appears to work

* add merge pass

* finish basic implementation

* better output

* bug fix
This commit is contained in:
water111
2021-01-16 10:54:09 -05:00
committed by GitHub
parent 8f86f0f00e
commit 1071ff6003
18 changed files with 932 additions and 62 deletions
+23 -12
View File
@@ -11,7 +11,7 @@ namespace decompiler {
// VARIABLE
/////////////////////////////
Variable::Variable(Mode mode, Register reg, int atomic_idx, bool allow_all)
Variable::Variable(VariableMode mode, Register reg, int atomic_idx, bool allow_all)
: m_mode(mode), m_reg(reg), m_atomic_idx(atomic_idx) {
// make sure we're using a valid GPR.
if (reg.get_kind() == Reg::GPR && !allow_all) {
@@ -28,12 +28,12 @@ std::string Variable::to_string(const Env* env, Print mode) const {
return m_reg.to_string();
case Print::FULL:
return fmt::format("{}-{:03d}-{}", m_reg.to_charp(), m_atomic_idx,
m_mode == Mode::READ ? 'r' : 'w');
m_mode == VariableMode::READ ? 'r' : 'w');
case Print::AS_VARIABLE:
return env->get_variable_name(m_reg, m_atomic_idx);
return env->get_variable_name(m_reg, m_atomic_idx, m_mode);
case Print::AUTOMATIC:
if (env->has_local_vars()) {
return env->get_variable_name(m_reg, m_atomic_idx);
return env->get_variable_name(m_reg, m_atomic_idx, m_mode);
} else {
return m_reg.to_string();
}
@@ -58,6 +58,11 @@ AtomicOp::AtomicOp(int my_idx) : m_my_idx(my_idx) {}
std::string AtomicOp::to_string(const std::vector<DecompilerLabel>& labels, const Env* env) const {
return pretty_print::to_string(to_form(labels, env));
}
std::string AtomicOp::to_string(const Env& env) const {
return to_string(env.file->labels, &env);
}
bool AtomicOp::operator!=(const AtomicOp& other) const {
return !((*this) == other);
}
@@ -411,7 +416,10 @@ AsmOp::AsmOp(Instruction instr, int my_idx) : AtomicOp(my_idx), m_instr(std::mov
if (m_instr.n_dst == 1) {
auto& dst = m_instr.get_dst(0);
if (dst.is_reg()) {
m_dst = Variable(Variable::Mode::WRITE, dst.get_reg(), my_idx, true);
auto reg = dst.get_reg();
if (reg.get_kind() == Reg::FPR || reg.get_kind() == Reg::GPR) {
m_dst = Variable(VariableMode::WRITE, reg, my_idx, true);
}
}
}
@@ -419,7 +427,10 @@ AsmOp::AsmOp(Instruction instr, int my_idx) : AtomicOp(my_idx), m_instr(std::mov
for (int i = 0; i < m_instr.n_src; i++) {
auto& src = m_instr.get_src(i);
if (src.is_reg()) {
m_src[i] = Variable(Variable::Mode::READ, src.get_reg(), my_idx, true);
auto reg = src.get_reg();
if (reg.get_kind() == Reg::FPR || reg.get_kind() == Reg::GPR) {
m_src[i] = Variable(VariableMode::READ, reg, my_idx, true);
}
}
}
}
@@ -964,14 +975,14 @@ IR2_BranchDelay::IR2_BranchDelay(Kind kind) : m_kind(kind) {
IR2_BranchDelay::IR2_BranchDelay(Kind kind, Variable var0) : m_kind(kind) {
assert(m_kind == Kind::SET_REG_FALSE || m_kind == Kind::SET_REG_TRUE ||
m_kind == Kind::SET_BINTEGER || m_kind == Kind::SET_PAIR);
assert(var0.mode() == Variable::Mode::WRITE);
assert(var0.mode() == VariableMode::WRITE);
m_var[0] = var0;
}
IR2_BranchDelay::IR2_BranchDelay(Kind kind, Variable var0, Variable var1) : m_kind(kind) {
assert(m_kind == Kind::NEGATE || m_kind == Kind::SET_REG_REG);
assert(var0.mode() == Variable::Mode::WRITE);
assert(var1.mode() == Variable::Mode::READ);
assert(var0.mode() == VariableMode::WRITE);
assert(var1.mode() == VariableMode::READ);
m_var[0] = var0;
m_var[1] = var1;
}
@@ -979,9 +990,9 @@ IR2_BranchDelay::IR2_BranchDelay(Kind kind, Variable var0, Variable var1) : m_ki
IR2_BranchDelay::IR2_BranchDelay(Kind kind, Variable var0, Variable var1, Variable var2)
: m_kind(kind) {
assert(m_kind == Kind::DSLLV);
assert(var0.mode() == Variable::Mode::WRITE);
assert(var1.mode() == Variable::Mode::READ);
assert(var2.mode() == Variable::Mode::READ);
assert(var0.mode() == VariableMode::WRITE);
assert(var1.mode() == VariableMode::READ);
assert(var2.mode() == VariableMode::READ);
m_var[0] = var0;
m_var[1] = var1;
m_var[2] = var2;