mirror of
https://github.com/open-goal/jak-project
synced 2026-08-21 14:54:53 -04:00
add reginfo to basic ops
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
+869
-392
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user