[decompiler] bug fixes related to infinite loop CFGs, argument registers (#622)

* temp

* clean up

* more clean
This commit is contained in:
water111
2021-06-23 22:09:02 -04:00
committed by GitHub
parent 997d5b57db
commit 44f8ff6d25
10 changed files with 115 additions and 48 deletions
+36 -2
View File
@@ -279,6 +279,16 @@ bool is_possible_coloring_move(Register dst, Register src) {
return false;
}
namespace {
int arg_count(const Function& f) {
if (f.type.arg_count() > 0) {
return f.type.arg_count() - 1;
} else {
return 0;
}
}
} // namespace
/*!
* Create a "really crude" SSA, as described in
* "Aycock and Horspool Simple Generation of Static Single-Assignment Form"
@@ -310,6 +320,8 @@ SSA make_rc_ssa(const Function& function, const RegUsageInfo& rui, const Functio
// local map: current register names at the current op.
std::unordered_map<Register, VarSSA, Register::hash> current_regs;
// if we're block zero, write function arguments:
// initialize phis. this is only done on:
// - variables live out at the first op
// - variables read by the first op
@@ -336,6 +348,19 @@ SSA make_rc_ssa(const Function& function, const RegUsageInfo& rui, const Functio
}
}
if (block_id == 0) {
SSA::Ins ins(-1);
for (int i = 0; i < arg_count(function); i++) {
auto dest_reg = Register::get_arg_reg(i);
auto it = current_regs.find(dest_reg);
if (it == current_regs.end()) {
current_regs.insert(std::make_pair(dest_reg, ssa.get_phi_dest(block_id, dest_reg)));
}
ins.src.push_back(current_regs.at(dest_reg));
}
ssa.blocks.at(block_id).ins.push_back(ins);
}
// loop over ops, creating and reading from variables as needed.
for (int op_id = start_op; op_id < end_op; op_id++) {
const auto& op = ops.ops.at(op_id);
@@ -546,7 +571,7 @@ void SSA::merge_all_phis() {
* Remaps all SSA variable ids to final variable IDs.
* This forces you to have all positive, consecutive IDs, with 0 being the entry value.
*/
void SSA::remap() {
void SSA::remap(int) {
// this keeps the order of variable assignments in the instruction order, not var_id order.
struct VarIdRecord {
std::unordered_set<int> set;
@@ -676,6 +701,9 @@ void SSA::make_vars(const Function& function, const DecompilerTypeSystem& dts) {
const TypeState* init_types = &function.ir2.env.get_types_at_block_entry(block_id);
for (auto& instr : block.ins) {
auto op_id = instr.op_id;
if (op_id < 0) {
continue;
}
const TypeState* end_types = &function.ir2.env.get_types_after_op(op_id);
@@ -762,6 +790,9 @@ VariableNames SSA::get_vars() const {
const auto& block = blocks.at(block_id);
for (auto& instr : block.ins) {
auto op_id = instr.op_id;
if (op_id < 0) {
continue;
}
if (instr.dst.has_value()) {
auto& ids = result.write_opid_to_varid[instr.dst->reg()];
if (int(ids.size()) <= op_id) {
@@ -776,6 +807,9 @@ VariableNames SSA::get_vars() const {
const auto& block = blocks.at(block_id);
for (auto& instr : block.ins) {
auto op_id = instr.op_id;
if (op_id < 0) {
continue;
}
for (auto& src : instr.src) {
auto& ids = result.read_opid_to_varid[src.reg()];
if (int(ids.size()) <= op_id) {
@@ -944,7 +978,7 @@ std::optional<VariableNames> run_variable_renaming(const Function& function,
// merge same vars (decided this made things worse)
// do rename
ssa.remap();
ssa.remap(arg_count(function));
if (debug_prints) {
fmt::print("{}", ssa.print());
}