add reginfo to basic ops

This commit is contained in:
water
2020-11-27 14:46:55 -05:00
parent a9cfa19f92
commit 4fb8381105
6 changed files with 1101 additions and 394 deletions
+10
View File
@@ -699,4 +699,14 @@ int Function::get_failed_basic_op_count() {
}
}
return count;
}
int Function::get_reginfo_basic_op_count() {
int count = 0;
for (auto& x : basic_ops) {
if (x->reg_info_set) {
count++;
}
}
return count;
}
+1
View File
@@ -85,6 +85,7 @@ class Function {
const TypeMap& get_typemap_by_instr_idx(int idx);
int get_basic_op_count();
int get_failed_basic_op_count();
int get_reginfo_basic_op_count();
void run_type_analysis(const TypeSpec& my_type,
DecompilerTypeSystem& dts,
LinkedObjectFile& file);
File diff suppressed because it is too large Load Diff
+196
View File
@@ -64,6 +64,131 @@ void IR_Set::get_children(std::vector<std::shared_ptr<IR>>* output) const {
output->push_back(src);
}
template <>
void IR_Set_Atomic::update_reginfo_self<IR_IntMath2>(int n_dest, int n_src, int n_clobber) {
auto dst_as_reg = dynamic_cast<IR_Register*>(dst.get());
if (dst_as_reg) {
write_regs.push_back(dst_as_reg->reg);
}
auto src_as = dynamic_cast<IR_IntMath2*>(src.get());
assert(src_as);
for (auto& x : {src_as->arg0, src_as->arg1}) {
auto reg = dynamic_cast<IR_Register*>(x.get());
if (reg) {
read_regs.push_back(reg->reg);
}
}
assert(int(write_regs.size()) == n_dest);
assert(int(read_regs.size()) == n_src);
assert(int(clobber_regs.size()) == n_clobber);
reg_info_set = true;
}
template <>
void IR_Set_Atomic::update_reginfo_self<IR_IntMath1>(int n_dest, int n_src, int n_clobber) {
auto dst_as_reg = dynamic_cast<IR_Register*>(dst.get());
if (dst_as_reg) {
write_regs.push_back(dst_as_reg->reg);
}
auto src_as = dynamic_cast<IR_IntMath1*>(src.get());
assert(src_as);
auto reg = dynamic_cast<IR_Register*>(src_as->arg.get());
if (reg) {
read_regs.push_back(reg->reg);
}
assert(int(write_regs.size()) == n_dest);
assert(int(read_regs.size()) == n_src);
assert(int(clobber_regs.size()) == n_clobber);
reg_info_set = true;
}
template <>
void IR_Set_Atomic::update_reginfo_self<IR_Load>(int n_dest, int n_src, int n_clobber) {
auto dst_as_reg = dynamic_cast<IR_Register*>(dst.get());
if (dst_as_reg) {
write_regs.push_back(dst_as_reg->reg);
}
auto src_as = dynamic_cast<IR_Load*>(src.get());
assert(src_as);
// try to get the source as a register
auto reg = dynamic_cast<IR_Register*>(src_as->location.get());
if (reg) {
read_regs.push_back(reg->reg);
}
// or as math with a register
auto math = dynamic_cast<IR_IntMath2*>(src_as->location.get());
if (math) {
for (auto& x : {math->arg0, math->arg1}) {
auto math_reg = dynamic_cast<IR_Register*>(x.get());
if (math_reg) {
read_regs.push_back(math_reg->reg);
}
}
}
assert(int(write_regs.size()) == n_dest);
assert(int(read_regs.size()) == n_src);
assert(int(clobber_regs.size()) == n_clobber);
reg_info_set = true;
}
template <>
void IR_Set_Atomic::update_reginfo_self<IR_Compare>(int n_dest, int n_src, int n_clobber) {
auto dst_as_reg = dynamic_cast<IR_Register*>(dst.get());
if (dst_as_reg) {
write_regs.push_back(dst_as_reg->reg);
}
auto src_as_cmp = dynamic_cast<IR_Compare*>(src.get());
assert(src_as_cmp);
for (auto& x : {src_as_cmp->condition.src0, src_as_cmp->condition.src1}) {
auto as_reg = dynamic_cast<IR_Register*>(x.get());
if (as_reg) {
read_regs.push_back(as_reg->reg);
}
}
auto as_reg = dynamic_cast<IR_Register*>(src_as_cmp->condition.clobber.get());
if (as_reg) {
clobber_regs.push_back(as_reg->reg);
}
assert(int(write_regs.size()) == n_dest);
assert(int(read_regs.size()) == n_src);
assert(int(clobber_regs.size()) == n_clobber);
reg_info_set = true;
}
/*!
* Set the register info, assuming this is a register to register set.
*/
void IR_Set_Atomic::update_reginfo_regreg() {
auto dst_as_reg = dynamic_cast<IR_Register*>(dst.get());
if (dst_as_reg) {
write_regs.push_back(dst_as_reg->reg);
}
auto src_as = dynamic_cast<IR_Register*>(src.get());
if (src_as) {
read_regs.push_back(src_as->reg);
}
assert(int(write_regs.size()) == 1);
assert(int(read_regs.size()) == 1);
assert(int(clobber_regs.size()) == 0);
reg_info_set = true;
}
goos::Object IR_Store::to_form(const LinkedObjectFile& file) const {
std::string store_operator;
switch (kind) {
@@ -134,6 +259,34 @@ goos::Object IR_Store_Atomic::to_form(const LinkedObjectFile& file) const {
src->to_form(file));
}
void IR_Store_Atomic::update_reginfo_self(int n_dest, int n_src, int n_clobber) {
auto src_reg = dynamic_cast<IR_Register*>(src.get());
if (src_reg) {
read_regs.push_back(src_reg->reg);
}
auto dst_reg = dynamic_cast<IR_Register*>(dst.get());
if (dst_reg) {
read_regs.push_back(dst_reg->reg);
}
// or as math with a register
auto math = dynamic_cast<IR_IntMath2*>(dst.get());
if (math) {
for (auto& x : {math->arg0, math->arg1}) {
auto math_reg = dynamic_cast<IR_Register*>(x.get());
if (math_reg) {
read_regs.push_back(math_reg->reg);
}
}
}
assert(int(write_regs.size()) == n_dest);
assert(int(read_regs.size()) == n_src);
assert(int(clobber_regs.size()) == n_clobber);
reg_info_set = true;
}
goos::Object IR_Symbol::to_form(const LinkedObjectFile& file) const {
(void)file;
return pretty_print::to_symbol("'" + name);
@@ -680,6 +833,33 @@ void IR_Branch::get_children(std::vector<std::shared_ptr<IR>>* output) const {
branch_delay.get_children(output);
}
void IR_Branch_Atomic::update_reginfo_self(int n_dest, int n_src, int n_clobber) {
// first, grab from condition
for (auto& x : {condition.src0, condition.src1}) {
auto as_reg = dynamic_cast<IR_Register*>(x.get());
if (as_reg) {
read_regs.push_back(as_reg->reg);
}
}
auto as_reg = dynamic_cast<IR_Register*>(condition.clobber.get());
if (as_reg) {
clobber_regs.push_back(as_reg->reg);
}
assert(int(write_regs.size()) == n_dest);
assert(int(read_regs.size()) == n_src);
assert(int(clobber_regs.size()) == n_clobber);
// copy from branch delay
read_regs.insert(read_regs.end(), branch_delay.read_regs.begin(), branch_delay.read_regs.end());
write_regs.insert(write_regs.end(), branch_delay.write_regs.begin(),
branch_delay.write_regs.end());
clobber_regs.insert(clobber_regs.end(), branch_delay.clobber_regs.begin(),
branch_delay.clobber_regs.end());
reg_info_set = true;
}
goos::Object IR_Compare::to_form(const LinkedObjectFile& file) const {
return condition.to_form(file);
}
@@ -900,6 +1080,22 @@ void IR_AsmOp::get_children(std::vector<std::shared_ptr<IR>>* output) const {
}
}
void IR_AsmOp_Atomic::set_reg_info() {
auto dst_as_reg = dynamic_cast<IR_Register*>(dst.get());
if (dst_as_reg) {
write_regs.push_back(dst_as_reg->reg);
}
for (auto& x : {src0, src1, src2}) {
auto src_as_reg = dynamic_cast<IR_Register*>(x.get());
if (src_as_reg) {
read_regs.push_back(src_as_reg->reg);
}
}
reg_info_set = true;
}
goos::Object IR_CMoveF::to_form(const LinkedObjectFile& file) const {
return pretty_print::build_list(
pretty_print::to_symbol(on_zero ? "cmove-false-on-zero" : "cmove-false-on-nonzero"),
+21 -2
View File
@@ -37,6 +37,8 @@ class IR {
class IR_Atomic : public virtual IR {
public:
std::vector<Register> read_regs, write_regs, clobber_regs;
bool reg_info_set = false;
};
class IR_Failed : public virtual IR {
@@ -93,13 +95,22 @@ class IR_Set_Atomic : public IR_Set, public IR_Atomic {
public:
IR_Set_Atomic(IR_Set::Kind _kind, std::shared_ptr<IR> _dst, std::shared_ptr<IR> _src)
: IR_Set(_kind, std::move(_dst), std::move(_src)) {}
template <typename T>
void update_reginfo_self(int n_dest, int n_src, int n_clobber);
void update_reginfo_regreg();
};
class IR_IntMath2;
template <>
void IR_Set_Atomic::update_reginfo_self<IR_IntMath2>(int n_dest, int n_src, int n_clobber);
class IR_Store : public virtual IR_Set {
public:
enum Kind { INTEGER, FLOAT } kind;
IR_Store(Kind _kind, std::shared_ptr<IR> _dst, std::shared_ptr<IR> _src, int _size)
: IR_Set(IR_Set::LOAD, std::move(_dst), std::move(_src)), kind(_kind), size(_size) {}
: IR_Set(IR_Set::STORE, std::move(_dst), std::move(_src)), kind(_kind), size(_size) {}
int size;
goos::Object to_form(const LinkedObjectFile& file) const override;
};
@@ -112,9 +123,10 @@ class IR_Store_Atomic : public IR_Set_Atomic {
public:
enum Kind { INTEGER, FLOAT } kind;
IR_Store_Atomic(Kind _kind, std::shared_ptr<IR> _dst, std::shared_ptr<IR> _src, int _size)
: IR_Set_Atomic(IR_Set::LOAD, std::move(_dst), std::move(_src)), kind(_kind), size(_size) {}
: IR_Set_Atomic(IR_Set::STORE, std::move(_dst), std::move(_src)), kind(_kind), size(_size) {}
int size;
goos::Object to_form(const LinkedObjectFile& file) const override;
void update_reginfo_self(int n_dest, int n_src, int n_clobber);
};
class IR_Symbol : public virtual IR {
@@ -274,6 +286,10 @@ struct BranchDelay {
explicit BranchDelay(Kind _kind) : kind(_kind) {}
goos::Object to_form(const LinkedObjectFile& file) const;
void get_children(std::vector<std::shared_ptr<IR>>* output) const;
std::vector<Register> read_regs;
std::vector<Register> write_regs;
std::vector<Register> clobber_regs;
};
struct Condition {
@@ -356,6 +372,8 @@ class IR_Branch_Atomic : public virtual IR_Branch, public IR_Atomic {
BranchDelay _branch_delay,
bool _likely)
: IR_Branch(std::move(_condition), _dest_label_idx, std::move(_branch_delay), _likely) {}
// note - counts only for the condition.
void update_reginfo_self(int n_dst, int n_src, int n_clobber);
};
class IR_Compare : public virtual IR {
@@ -508,6 +526,7 @@ class IR_AsmOp : public virtual IR {
class IR_AsmOp_Atomic : public virtual IR_AsmOp, public IR_Atomic {
public:
IR_AsmOp_Atomic(std::string _name) : IR_AsmOp(std::move(_name)) {}
void set_reg_info();
};
class IR_CMoveF : public virtual IR {
+4
View File
@@ -811,6 +811,7 @@ void ObjectFileDB::analyze_functions() {
int total_named_functions = 0;
int total_basic_ops = 0;
int total_failed_basic_ops = 0;
int total_reginfo_ops = 0;
int asm_funcs = 0;
int non_asm_funcs = 0;
@@ -848,6 +849,7 @@ void ObjectFileDB::analyze_functions() {
}
total_basic_ops += func.get_basic_op_count();
total_failed_basic_ops += func.get_failed_basic_op_count();
total_reginfo_ops += func.get_reginfo_basic_op_count();
if (func.is_inspect_method) {
auto result = inspect_inspect_method(func, func.method_of_type, dts, data.linked_data);
@@ -925,6 +927,8 @@ void ObjectFileDB::analyze_functions() {
int successful_basic_ops = total_basic_ops - total_failed_basic_ops;
spdlog::info(" {}/{} basic ops converted successfully ({:.3f}%)", successful_basic_ops,
total_basic_ops, 100.f * float(successful_basic_ops) / float(total_basic_ops));
spdlog::info(" {}/{} basic ops with reginfo ({:.3f}%)", total_reginfo_ops, total_basic_ops,
100.f * float(total_reginfo_ops) / float(total_basic_ops));
spdlog::info(" {}/{} cfgs converted to ir ({:.3f}%)", successful_cfg_irs, non_asm_funcs,
100.f * float(successful_cfg_irs) / float(non_asm_funcs));
spdlog::info(" {}/{} functions passed type analysis ({:.2f}%)\n", successful_type_analysis,