add some more cfg ir stuff

This commit is contained in:
water
2020-10-02 16:21:25 -04:00
parent 376c273845
commit 072283e442
11 changed files with 399 additions and 15 deletions
+1
View File
@@ -17,6 +17,7 @@ add_executable(decompiler
Disasm/InstructionMatching.cpp
Function/CfgVtx.cpp Function/CfgVtx.h
IR/BasicOpBuilder.cpp
IR/CfgBuilder.cpp
IR/IR.cpp)
target_link_libraries(decompiler
+2 -2
View File
@@ -572,8 +572,8 @@ bool Function::instr_starts_basic_op(int idx) {
return false;
}
IR* Function::get_basic_op_at_instr(int idx) {
return basic_ops.at(instruction_to_basic_op.at(idx)).get();
std::shared_ptr<IR> Function::get_basic_op_at_instr(int idx) {
return basic_ops.at(instruction_to_basic_op.at(idx));
}
int Function::get_basic_op_count() {
+3 -1
View File
@@ -68,10 +68,12 @@ class Function {
void add_basic_op(std::shared_ptr<IR> op, int start_instr, int end_instr);
bool has_basic_ops() { return !basic_ops.empty(); }
bool instr_starts_basic_op(int idx);
IR* get_basic_op_at_instr(int idx);
std::shared_ptr<IR> get_basic_op_at_instr(int idx);
int get_basic_op_count();
int get_failed_basic_op_count();
std::shared_ptr<IR> ir = nullptr;
int segment = -1;
int start_word = -1;
int end_word = -1; // not inclusive, but does include padding.
+1 -1
View File
@@ -1402,7 +1402,7 @@ void add_basic_ops_to_block(Function* func, const BasicBlock& block, LinkedObjec
if (!result) {
state.reset();
// temp hack for debug:
printf("Instruction -> BasicOp failed on %s\n", i.to_string(*file).c_str());
// printf("Instruction -> BasicOp failed on %s\n", i.to_string(*file).c_str());
func->add_basic_op(std::make_shared<IR_Failed>(), instr, instr + 1);
} else {
func->add_basic_op(result, instr, instr + length);
+180
View File
@@ -0,0 +1,180 @@
#include <unordered_set>
#include "CfgBuilder.h"
#include "decompiler/Function/CfgVtx.h"
#include "decompiler/Function/Function.h"
std::vector<std::shared_ptr<IR>> IR::get_all_ir(LinkedObjectFile& file) const {
std::vector<std::shared_ptr<IR>> result;
get_children(&result);
size_t last_checked = 0;
size_t last_last_checked = -1;
while (last_checked != last_last_checked) {
last_last_checked = last_checked;
auto end_of_check = result.size();
for (size_t i = last_checked; i < end_of_check; i++) {
auto it = result.at(i).get();
assert(it);
it->get_children(&result);
}
last_checked = end_of_check;
}
// Todo, remove this check which is just for debugging.
std::unordered_set<std::shared_ptr<IR>> unique_ir;
for (auto& x : result) {
unique_ir.insert(x);
}
assert(unique_ir.size() == result.size());
return result;
}
namespace {
std::shared_ptr<IR> cfg_to_ir(Function& f, LinkedObjectFile& file, CfgVtx* vtx);
/*!
* This adds a single CfgVtx* to a list of IR's by converting it with cfg to IR.
* The trick here is that it will recursively inline anything which would generate an IR begin.
* This avoids the case where Begin's are nested excessively.
*/
void insert_cfg_into_list(Function& f,
LinkedObjectFile& file,
std::vector<std::shared_ptr<IR>>* output,
CfgVtx* vtx) {
auto as_sequence = dynamic_cast<SequenceVtx*>(vtx);
auto as_block = dynamic_cast<BlockVtx*>(vtx);
if (as_sequence) {
for (auto& x : as_sequence->seq) {
insert_cfg_into_list(f, file, output, x);
}
} else if (as_block) {
auto& block = f.basic_blocks.at(as_block->block_id);
IR* last = nullptr;
for (int instr = block.start_word; instr < block.end_word; instr++) {
auto got = f.get_basic_op_at_instr(instr);
if (got.get() == last) {
continue;
}
last = got.get();
output->push_back(got);
}
} else {
output->push_back(cfg_to_ir(f, file, vtx));
}
}
std::shared_ptr<IR> cfg_to_ir(Function& f, LinkedObjectFile& file, CfgVtx* vtx) {
if (dynamic_cast<BlockVtx*>(vtx)) {
auto* bv = dynamic_cast<BlockVtx*>(vtx);
auto& block = f.basic_blocks.at(bv->block_id);
std::vector<std::shared_ptr<IR>> irs;
IR* last = nullptr;
for (int instr = block.start_word; instr < block.end_word; instr++) {
auto got = f.get_basic_op_at_instr(instr);
if (got.get() == last) {
continue;
}
last = got.get();
irs.push_back(got);
}
if (irs.size() == 1) {
return irs.front();
} else {
return std::make_shared<IR_Begin>(irs);
}
} else if (dynamic_cast<SequenceVtx*>(vtx)) {
auto* sv = dynamic_cast<SequenceVtx*>(vtx);
std::vector<std::shared_ptr<IR>> irs;
insert_cfg_into_list(f, file, &irs, sv);
return std::make_shared<IR_Begin>(irs);
} else if (dynamic_cast<WhileLoop*>(vtx)) {
auto wvtx = dynamic_cast<WhileLoop*>(vtx);
auto result = std::make_shared<IR_WhileLoop>(cfg_to_ir(f, file, wvtx->condition),
cfg_to_ir(f, file, wvtx->body));
return result;
}
else {
throw std::runtime_error("not yet implemented IR conversion.");
return nullptr;
}
}
void clean_up_while_loops(IR_Begin* sequence, LinkedObjectFile& file) {
std::vector<size_t> to_remove; // the list of branches to remove by index in this sequence
for (size_t i = 0; i < sequence->forms.size(); i++) {
auto* form_as_while = dynamic_cast<IR_WhileLoop*>(sequence->forms.at(i).get());
if (form_as_while) {
assert(i != 0);
auto prev_as_branch = dynamic_cast<IR_Branch*>(sequence->forms.at(i - 1).get());
assert(prev_as_branch);
printf("got while intro branch %s\n", prev_as_branch->print(file).c_str());
// this should be an always jump. We'll assume that the CFG builder successfully checked
// the brach destination, but we will check the condition.
assert(prev_as_branch->condition.kind == Condition::ALWAYS);
assert(prev_as_branch->branch_delay.kind == BranchDelay::NOP);
to_remove.push_back(i - 1);
// now we should try to find the condition branch:
IR_Branch* condition_branch = dynamic_cast<IR_Branch*>(form_as_while->condition.get());
std::shared_ptr<IR>* condition_branch_location = &form_as_while->condition;
if (!condition_branch) {
// not 100% sure this will always work
auto as_seq = dynamic_cast<IR_Begin*>(form_as_while->condition.get());
if (as_seq) {
condition_branch = dynamic_cast<IR_Branch*>(as_seq->forms.back().get());
condition_branch_location = &as_seq->forms.back();
}
}
assert(condition_branch);
assert(condition_branch->branch_delay.kind == BranchDelay::NOP);
printf("got while condition branch %s\n", condition_branch->print(file).c_str());
auto replacement = std::make_shared<IR_Compare>(condition_branch->condition);
*condition_branch_location = replacement;
}
}
// remove the implied forward always branches.
for (int i = int(to_remove.size()); i-- > 0;) {
auto idx = to_remove.at(i);
assert(dynamic_cast<IR_Branch*>(sequence->forms.at(idx).get()));
sequence->forms.erase(sequence->forms.begin() + idx);
}
}
} // namespace
std::shared_ptr<IR> build_cfg_ir(Function& function,
ControlFlowGraph& cfg,
LinkedObjectFile& file) {
// printf("build cfg ir\n");
if (!cfg.is_fully_resolved()) {
return nullptr;
}
try {
auto top_level = cfg.get_single_top_level();
// todo, we should apply transformations for fixing up branch instructions for each IR.
// and possibly annotate the IR control flow structure so that we can determine if its and/or
// or whatever. This may require rejecting a huge number of inline assembly functions, and
// possibly resolving the min/max/ash issue.
auto ir = cfg_to_ir(function, file, top_level);
auto all_children = ir->get_all_ir(file);
all_children.push_back(ir);
for (auto& child : all_children) {
// printf("child is %s\n", child->print(file).c_str());
auto as_begin = dynamic_cast<IR_Begin*>(child.get());
if (as_begin) {
clean_up_while_loops(as_begin, file);
}
}
return ir;
} catch (std::runtime_error& e) {
return nullptr;
}
}
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#include <memory>
class IR;
class Function;
class LinkedObjectFile;
class ControlFlowGraph;
std::shared_ptr<IR> build_cfg_ir(Function& function, ControlFlowGraph& cfg, LinkedObjectFile& file);
+142 -5
View File
@@ -5,15 +5,35 @@ std::string IR::print(const LinkedObjectFile& file) const {
return to_form(file)->toStringPretty();
}
std::shared_ptr<Form> IR_Failed::to_form(const LinkedObjectFile& file) const {
(void)file;
return buildList("INVALID-OPERATION");
}
void IR_Failed::get_children(std::vector<std::shared_ptr<IR>>* output) const {
(void)output;
}
std::shared_ptr<Form> IR_Register::to_form(const LinkedObjectFile& file) const {
(void)file;
return toForm(reg.to_charp());
}
void IR_Register::get_children(std::vector<std::shared_ptr<IR>>* output) const {
(void)output;
}
std::shared_ptr<Form> IR_Set::to_form(const LinkedObjectFile& file) const {
return buildList(toForm("set!"), dst->to_form(file), src->to_form(file));
}
void IR_Set::get_children(std::vector<std::shared_ptr<IR>>* output) const {
// note that we are not returning clobber here because it shouldn't contain anything that
// the IR simplification code should touch.
output->push_back(dst);
output->push_back(src);
}
std::shared_ptr<Form> IR_Store::to_form(const LinkedObjectFile& file) const {
std::string store_operator;
switch (kind) {
@@ -48,26 +68,33 @@ std::shared_ptr<Form> IR_Store::to_form(const LinkedObjectFile& file) const {
return buildList(toForm(store_operator), dst->to_form(file), src->to_form(file));
}
std::shared_ptr<Form> IR_Failed::to_form(const LinkedObjectFile& file) const {
(void)file;
return buildList("INVALID-OPERATION");
}
std::shared_ptr<Form> IR_Symbol::to_form(const LinkedObjectFile& file) const {
(void)file;
return toForm("'" + name);
}
void IR_Symbol::get_children(std::vector<std::shared_ptr<IR>>* output) const {
(void)output;
}
std::shared_ptr<Form> IR_SymbolValue::to_form(const LinkedObjectFile& file) const {
(void)file;
return toForm(name);
}
void IR_SymbolValue::get_children(std::vector<std::shared_ptr<IR>>* output) const {
(void)output;
}
std::shared_ptr<Form> IR_StaticAddress::to_form(const LinkedObjectFile& file) const {
// return buildList(toForm("&"), file.get_label_name(label_id));
return toForm(file.get_label_name(label_id));
}
void IR_StaticAddress::get_children(std::vector<std::shared_ptr<IR>>* output) const {
(void)output;
}
std::shared_ptr<Form> IR_Load::to_form(const LinkedObjectFile& file) const {
std::string load_operator;
switch (kind) {
@@ -116,6 +143,10 @@ std::shared_ptr<Form> IR_Load::to_form(const LinkedObjectFile& file) const {
return buildList(toForm(load_operator), location->to_form(file));
}
void IR_Load::get_children(std::vector<std::shared_ptr<IR>>* output) const {
output->push_back(location);
}
std::shared_ptr<Form> IR_FloatMath2::to_form(const LinkedObjectFile& file) const {
std::string math_operator;
switch (kind) {
@@ -144,6 +175,15 @@ std::shared_ptr<Form> IR_FloatMath2::to_form(const LinkedObjectFile& file) const
return buildList(toForm(math_operator), arg0->to_form(file), arg1->to_form(file));
}
void IR_FloatMath2::get_children(std::vector<std::shared_ptr<IR>>* output) const {
output->push_back(arg0);
output->push_back(arg1);
}
void IR_FloatMath1::get_children(std::vector<std::shared_ptr<IR>>* output) const {
output->push_back(arg);
}
std::shared_ptr<Form> IR_IntMath2::to_form(const LinkedObjectFile& file) const {
std::string math_operator;
switch (kind) {
@@ -198,6 +238,11 @@ std::shared_ptr<Form> IR_IntMath2::to_form(const LinkedObjectFile& file) const {
return buildList(toForm(math_operator), arg0->to_form(file), arg1->to_form(file));
}
void IR_IntMath2::get_children(std::vector<std::shared_ptr<IR>>* output) const {
output->push_back(arg0);
output->push_back(arg1);
}
std::shared_ptr<Form> IR_IntMath1::to_form(const LinkedObjectFile& file) const {
std::string math_operator;
switch (kind) {
@@ -210,6 +255,10 @@ std::shared_ptr<Form> IR_IntMath1::to_form(const LinkedObjectFile& file) const {
return buildList(toForm(math_operator), arg->to_form(file));
}
void IR_IntMath1::get_children(std::vector<std::shared_ptr<IR>>* output) const {
output->push_back(arg);
}
std::shared_ptr<Form> IR_FloatMath1::to_form(const LinkedObjectFile& file) const {
std::string math_operator;
switch (kind) {
@@ -239,11 +288,19 @@ std::shared_ptr<Form> IR_Call::to_form(const LinkedObjectFile& file) const {
return buildList("call!");
}
void IR_Call::get_children(std::vector<std::shared_ptr<IR>>* output) const {
(void)output;
}
std::shared_ptr<Form> IR_IntegerConstant::to_form(const LinkedObjectFile& file) const {
(void)file;
return toForm(std::to_string(value));
}
void IR_IntegerConstant::get_children(std::vector<std::shared_ptr<IR>>* output) const {
(void)output;
}
std::shared_ptr<Form> BranchDelay::to_form(const LinkedObjectFile& file) const {
(void)file;
switch (kind) {
@@ -262,6 +319,16 @@ std::shared_ptr<Form> BranchDelay::to_form(const LinkedObjectFile& file) const {
}
}
void BranchDelay::get_children(std::vector<std::shared_ptr<IR>>* output) const {
if (destination) {
output->push_back(destination);
}
if (source) {
output->push_back(source);
}
}
std::shared_ptr<Form> IR_Nop::to_form(const LinkedObjectFile& file) const {
(void)file;
return buildList("nop!");
@@ -296,6 +363,16 @@ int Condition::num_args() const {
}
}
void Condition::get_children(std::vector<std::shared_ptr<IR>>* output) const {
if (src0) {
output->push_back(src0);
}
if (src1) {
output->push_back(src1);
}
}
std::shared_ptr<Form> Condition::to_form(const LinkedObjectFile& file) const {
int nargs = num_args();
std::string condtion_operator;
@@ -381,11 +458,71 @@ std::shared_ptr<Form> IR_Branch::to_form(const LinkedObjectFile& file) const {
toForm(file.get_label_name(dest_label_idx)), branch_delay.to_form(file));
}
void IR_Branch::get_children(std::vector<std::shared_ptr<IR>>* output) const {
condition.get_children(output);
branch_delay.get_children(output);
}
std::shared_ptr<Form> IR_Compare::to_form(const LinkedObjectFile& file) const {
return condition.to_form(file);
}
void IR_Compare::get_children(std::vector<std::shared_ptr<IR>>* output) const {
condition.get_children(output);
}
std::shared_ptr<Form> IR_Suspend::to_form(const LinkedObjectFile& file) const {
(void)file;
return buildList("suspend!");
}
void IR_Nop::get_children(std::vector<std::shared_ptr<IR>>* output) const {
(void)output;
}
void IR_Suspend::get_children(std::vector<std::shared_ptr<IR>>* output) const {
(void)output;
}
std::shared_ptr<Form> IR_Begin::to_form(const LinkedObjectFile& file) const {
std::vector<std::shared_ptr<Form>> list;
list.push_back(toForm("begin"));
for (auto& x : forms) {
list.push_back(x->to_form(file));
}
return buildList(list);
}
void IR_Begin::get_children(std::vector<std::shared_ptr<IR>>* output) const {
for (auto& x : forms) {
output->push_back(x);
}
}
namespace {
void print_inlining_begin(std::vector<std::shared_ptr<Form>>* output,
IR* ir,
const LinkedObjectFile& file) {
auto as_begin = dynamic_cast<IR_Begin*>(ir);
if (as_begin) {
for (auto& x : as_begin->forms) {
output->push_back(x->to_form(file));
}
} else {
output->push_back(ir->to_form(file));
}
}
} // namespace
std::shared_ptr<Form> IR_WhileLoop::to_form(const LinkedObjectFile& file) const {
std::vector<std::shared_ptr<Form>> list;
list.push_back(toForm("while"));
list.push_back(condition->to_form(file));
print_inlining_begin(&list, body.get(), file);
return buildList(list);
}
void IR_WhileLoop::get_children(std::vector<std::shared_ptr<IR>>* output) const {
output->push_back(condition);
output->push_back(body);
}
+45 -6
View File
@@ -2,6 +2,7 @@
#define JAK_IR_H
#include <cassert>
#include <utility>
#include "decompiler/Disasm/Register.h"
#include "decompiler/util/LispPrint.h"
@@ -10,7 +11,9 @@ class LinkedObjectFile;
class IR {
public:
virtual std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const = 0;
std::vector<std::shared_ptr<IR>> get_all_ir(LinkedObjectFile& file) const;
std::string print(const LinkedObjectFile& file) const;
virtual void get_children(std::vector<std::shared_ptr<IR>>* output) const = 0;
bool is_basic_op = false;
};
@@ -19,12 +22,14 @@ class IR_Failed : public IR {
public:
IR_Failed() = default;
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_Register : public IR {
public:
IR_Register(Register _reg, int _instr_idx) : reg(_reg), instr_idx(_instr_idx) {}
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
Register reg;
int instr_idx = -1;
};
@@ -45,6 +50,7 @@ class IR_Set : public IR {
IR_Set(Kind _kind, std::shared_ptr<IR> _dst, std::shared_ptr<IR> _src)
: kind(_kind), dst(std::move(_dst)), src(std::move(_src)) {}
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
std::shared_ptr<IR> dst, src;
std::shared_ptr<IR> clobber = nullptr;
};
@@ -60,34 +66,38 @@ class IR_Store : public IR_Set {
class IR_Symbol : public IR {
public:
IR_Symbol(std::string _name) : name(std::move(_name)) {}
explicit IR_Symbol(std::string _name) : name(std::move(_name)) {}
std::string name;
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_SymbolValue : public IR {
public:
IR_SymbolValue(std::string _name) : name(std::move(_name)) {}
explicit IR_SymbolValue(std::string _name) : name(std::move(_name)) {}
std::string name;
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_StaticAddress : public IR {
public:
IR_StaticAddress(int _label_id) : label_id(_label_id) {}
explicit IR_StaticAddress(int _label_id) : label_id(_label_id) {}
int label_id = -1;
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_Load : public IR {
public:
enum Kind { UNSIGNED, SIGNED, FLOAT } kind;
IR_Load(Kind _kind, int _size, const std::shared_ptr<IR>& _location)
: kind(_kind), size(_size), location(_location) {}
IR_Load(Kind _kind, int _size, std::shared_ptr<IR> _location)
: kind(_kind), size(_size), location(std::move(_location)) {}
int size;
std::shared_ptr<IR> location;
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_FloatMath2 : public IR {
@@ -97,6 +107,7 @@ class IR_FloatMath2 : public IR {
: kind(_kind), arg0(std::move(_arg0)), arg1(std::move(_arg1)) {}
std::shared_ptr<IR> arg0, arg1;
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_FloatMath1 : public IR {
@@ -105,6 +116,7 @@ class IR_FloatMath1 : public IR {
IR_FloatMath1(Kind _kind, std::shared_ptr<IR> _arg) : kind(_kind), arg(std::move(_arg)) {}
std::shared_ptr<IR> arg;
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_IntMath2 : public IR {
@@ -130,6 +142,7 @@ class IR_IntMath2 : public IR {
: kind(_kind), arg0(std::move(_arg0)), arg1(std::move(_arg1)) {}
std::shared_ptr<IR> arg0, arg1;
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_IntMath1 : public IR {
@@ -138,12 +151,14 @@ class IR_IntMath1 : public IR {
IR_IntMath1(Kind _kind, std::shared_ptr<IR> _arg) : kind(_kind), arg(std::move(_arg)) {}
std::shared_ptr<IR> arg;
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_Call : public IR {
public:
IR_Call() = default;
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_IntegerConstant : public IR {
@@ -151,13 +166,15 @@ class IR_IntegerConstant : public IR {
int64_t value;
explicit IR_IntegerConstant(int64_t _value) : value(_value) {}
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
struct BranchDelay {
enum Kind { NOP, SET_REG_FALSE, SET_REG_TRUE, SET_REG_REG, UNKNOWN } kind;
std::shared_ptr<IR> destination = nullptr, source = nullptr;
BranchDelay(Kind _kind) : kind(_kind) {}
explicit BranchDelay(Kind _kind) : kind(_kind) {}
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const;
void get_children(std::vector<std::shared_ptr<IR>>* output) const;
};
struct Condition {
@@ -201,6 +218,7 @@ struct Condition {
int num_args() const;
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const;
std::shared_ptr<IR> src0, src1, clobber;
void get_children(std::vector<std::shared_ptr<IR>>* output) const;
};
class IR_Branch : public IR {
@@ -217,6 +235,7 @@ class IR_Branch : public IR {
bool likely;
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_Compare : public IR {
@@ -226,18 +245,38 @@ class IR_Compare : public IR {
Condition condition;
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_Nop : public IR {
public:
IR_Nop() = default;
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_Suspend : public IR {
public:
IR_Suspend() = default;
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_Begin : public IR {
public:
IR_Begin(const std::vector<std::shared_ptr<IR>>& _forms) : forms(std::move(_forms)) {}
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
std::vector<std::shared_ptr<IR>> forms;
};
class IR_WhileLoop : public IR {
public:
IR_WhileLoop(std::shared_ptr<IR> _condition, std::shared_ptr<IR> _body)
: condition(std::move(_condition)), body(std::move(_body)) {}
std::shared_ptr<Form> to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
std::shared_ptr<IR> condition, body;
};
#endif // JAK_IR_H
@@ -622,6 +622,11 @@ std::string LinkedObjectFile::print_disassembly() {
*/
}
if (func.ir) {
result += ";; ir\n";
result += func.ir->print(*this);
}
result += "\n\n\n";
}
+4
View File
@@ -19,6 +19,7 @@
#include "common/util/FileUtil.h"
#include "decompiler/Function/BasicBlocks.h"
#include "decompiler/IR/BasicOpBuilder.h"
#include "decompiler/IR/CfgBuilder.h"
/*!
* Get a unique name for this object file.
@@ -602,6 +603,7 @@ void ObjectFileDB::analyze_functions() {
timer.start();
int total_basic_blocks = 0;
for_each_function([&](Function& func, int segment_id, ObjectFileData& data) {
// printf("in %s\n", func.guessed_name.to_string().c_str());
auto blocks = find_blocks_in_function(data.linked_data, segment_id, func);
total_basic_blocks += blocks.size();
func.basic_blocks = blocks;
@@ -618,6 +620,8 @@ void ObjectFileDB::analyze_functions() {
total_basic_ops += func.get_basic_op_count();
total_failed_basic_ops += func.get_failed_basic_op_count();
func.ir = build_cfg_ir(func, *func.cfg, data.linked_data);
if (func.cfg->is_fully_resolved()) {
resolved_cfg_functions++;
}
@@ -36,6 +36,12 @@
"resend-exception", "kernel-set-interrupt-vector", "kernel-set-exception-vector", "return-from-exception",
"kernel-read", "kernel-read-function", "kernel-write", "kernel-write-function", "kernel-copy-to-kernel-ram",
"(method 11 cpu-thread)", "atan0", "sincos!", "sincos-rad!", "disasm-dma-list", "vblank-handler", "vif1-handler",
"vif1-handler-debug", "entity-actor-count", "decompress-frame-data-pair-to-accumulator",
"decompress-frame-data-to-accumulator", "normalize-frame-quaternions", "clear-frame-accumulator",
"generic-copy-vtx-dclr-dtex", "generic-no-light-dproc-only", "generic-no-light-proc", "mercneric-bittable-asm",
"generic-tie-decompress",
"collide-do-primitives", "draw-bones-check-longest-edge-asm",
"sp-launch-particles-var", "(method 15 collide-shape-prim-mesh)", "(method 15 collide-shape-prim-sphere)",
"(method 45 collide-shape)", "cam-layout-save-cam-trans", "kernel-copy-function", "dma-sync-hang", "generic-no-light-dproc",