[Decompiler] Expression Building (#211)

* up to ash

* add more expressions

* fix some return variable usage nonsense

* bfloat print working

* basic-type working

* type working, fix decompiler on all files

* clang format
This commit is contained in:
water111
2021-01-24 16:39:15 -05:00
committed by GitHub
parent 27f0a7ca44
commit 2f722e6379
28 changed files with 1440 additions and 247 deletions
+37 -10
View File
@@ -12,18 +12,33 @@ bool in_set(RegSet& set, const Register& obj) {
return set.find(obj) != set.end();
}
void phase1(const FunctionAtomicOps& ops, int block_id, RegUsageInfo* out) {
void phase1(const FunctionAtomicOps& ops,
int block_id,
RegUsageInfo* out,
bool insert_v0_read_instruction_at_end) {
int end_op = ops.block_id_to_end_atomic_op.at(block_id);
int start_op = ops.block_id_to_first_atomic_op.at(block_id);
for (int i = end_op; i-- > start_op;) {
const auto& instr = ops.ops.at(i);
int loop_end = end_op;
if (insert_v0_read_instruction_at_end) {
loop_end++;
}
for (int i = loop_end; i-- > start_op;) {
std::vector<Register> read;
std::vector<Register> write;
if (i == end_op) {
read = {Register(Reg::GPR, Reg::V0)};
} else {
const auto& instr = ops.ops.at(i);
read = instr->read_regs();
write = instr->write_regs();
}
auto& lv = out->op.at(i).live;
auto& dd = out->op.at(i).dead;
auto& block = out->block.at(block_id);
// make all read live out
auto read = instr->read_regs();
lv.clear();
for (auto& x : read) {
lv.insert(x);
@@ -31,7 +46,6 @@ void phase1(const FunctionAtomicOps& ops, int block_id, RegUsageInfo* out) {
// kill things which are overwritten
dd.clear();
auto write = instr->write_regs();
for (auto& x : write) {
if (!in_set(lv, x)) {
dd.insert(x);
@@ -100,7 +114,8 @@ bool phase2(const std::vector<BasicBlock>& blocks, int block_id, RegUsageInfo* i
void phase3(const FunctionAtomicOps& ops,
const std::vector<BasicBlock>& blocks,
int block_id,
RegUsageInfo* info) {
RegUsageInfo* info,
bool insert_v0_read_instruction_at_end) {
RegSet live_local;
const auto& block_obj = blocks.at(block_id);
for (auto s : {block_obj.succ_branch, block_obj.succ_ft}) {
@@ -115,7 +130,12 @@ void phase3(const FunctionAtomicOps& ops,
int end_op = ops.block_id_to_end_atomic_op.at(block_id);
int start_op = ops.block_id_to_first_atomic_op.at(block_id);
for (int i = end_op; i-- > start_op;) {
int loop_end = end_op;
if (insert_v0_read_instruction_at_end) {
loop_end++;
}
for (int i = loop_end; i-- > start_op;) {
auto& lv = info->op.at(i).live;
auto& dd = info->op.at(i).dead;
@@ -130,15 +150,20 @@ void phase3(const FunctionAtomicOps& ops,
}
}
bool should_insert_v0_read(const std::vector<BasicBlock>& blocks, const Function& function, int i) {
return i == int(blocks.size()) - 1 && function.type.arg_count() > 0 &&
function.type.last_arg() != TypeSpec("none");
}
} // namespace
RegUsageInfo analyze_ir2_register_usage(const Function& function) {
const auto& blocks = function.basic_blocks;
const auto& ops = function.ir2.atomic_ops;
RegUsageInfo result(blocks.size(), ops->ops.size());
RegUsageInfo result(blocks.size(), ops->ops.size() + 1);
for (int i = 0; i < int(blocks.size()); i++) {
phase1(*ops, i, &result);
phase1(*ops, i, &result, should_insert_v0_read(blocks, function, i));
}
bool changed = false;
@@ -152,7 +177,7 @@ RegUsageInfo analyze_ir2_register_usage(const Function& function) {
} while (changed);
for (int i = 0; i < int(blocks.size()); i++) {
phase3(*ops, blocks, i, &result);
phase3(*ops, blocks, i, &result, should_insert_v0_read(blocks, function, i));
}
// we want to know if an op "consumes" a register.
@@ -187,6 +212,8 @@ RegUsageInfo analyze_ir2_register_usage(const Function& function) {
}
}
result.op.pop_back();
assert(result.op.size() == ops->ops.size());
return result;
}
} // namespace decompiler