add IR atomic interface and switch all basic ops to these

This commit is contained in:
water 2020-11-26 22:16:59 -05:00
parent d6ad0c0bb5
commit a9cfa19f92
5 changed files with 570 additions and 457 deletions

View file

@ -659,7 +659,7 @@ void Function::find_type_defs(LinkedObjectFile& file, DecompilerTypeSystem& dts)
}
}
void Function::add_basic_op(std::shared_ptr<IR> op, int start_instr, int end_instr) {
void Function::add_basic_op(std::shared_ptr<IR_Atomic> op, int start_instr, int end_instr) {
op->is_basic_op = true;
assert(end_instr > start_instr);
@ -679,7 +679,7 @@ bool Function::instr_starts_basic_op(int idx) {
return false;
}
std::shared_ptr<IR> Function::get_basic_op_at_instr(int idx) {
std::shared_ptr<IR_Atomic> Function::get_basic_op_at_instr(int idx) {
return basic_ops.at(instruction_to_basic_op.at(idx));
}

View file

@ -15,6 +15,7 @@
class DecompilerTypeSystem;
// Map of what type is in each register.
using TypeMap = std::unordered_map<Register, TypeSpec, Register::hash>;
class IR_Atomic;
class IR;
struct FunctionName {
@ -76,11 +77,11 @@ class Function {
void find_global_function_defs(LinkedObjectFile& file, DecompilerTypeSystem& dts);
void find_method_defs(LinkedObjectFile& file, DecompilerTypeSystem& dts);
void find_type_defs(LinkedObjectFile& file, DecompilerTypeSystem& dts);
void add_basic_op(std::shared_ptr<IR> op, int start_instr, int end_instr);
void add_basic_op(std::shared_ptr<IR_Atomic> op, int start_instr, int end_instr);
bool has_basic_ops() { return !basic_ops.empty(); }
bool has_typemaps() { return !basic_op_typemaps.empty(); }
bool instr_starts_basic_op(int idx);
std::shared_ptr<IR> get_basic_op_at_instr(int idx);
std::shared_ptr<IR_Atomic> get_basic_op_at_instr(int idx);
const TypeMap& get_typemap_by_instr_idx(int idx);
int get_basic_op_count();
int get_failed_basic_op_count();
@ -144,7 +145,7 @@ class Function {
} prologue;
bool uses_fp_register = false;
std::vector<std::shared_ptr<IR>> basic_ops;
std::vector<std::shared_ptr<IR_Atomic>> basic_ops;
private:
void check_epilogue(const LinkedObjectFile& file);

File diff suppressed because it is too large Load diff

View file

@ -99,6 +99,41 @@ goos::Object IR_Store::to_form(const LinkedObjectFile& file) const {
src->to_form(file));
}
goos::Object IR_Store_Atomic::to_form(const LinkedObjectFile& file) const {
std::string store_operator;
switch (kind) {
case FLOAT:
store_operator = "s.f";
break;
case INTEGER:
switch (size) {
case 1:
store_operator = "s.b";
break;
case 2:
store_operator = "s.h";
break;
case 4:
store_operator = "s.w";
break;
case 8:
store_operator = "s.d";
break;
case 16:
store_operator = "s.q";
break;
default:
assert(false);
}
break;
default:
assert(false);
}
return pretty_print::build_list(pretty_print::to_symbol(store_operator), dst->to_form(file),
src->to_form(file));
}
goos::Object IR_Symbol::to_form(const LinkedObjectFile& file) const {
(void)file;
return pretty_print::to_symbol("'" + name);

View file

@ -35,14 +35,23 @@ class IR {
bool is_basic_op = false;
};
class IR_Failed : public IR {
class IR_Atomic : public virtual IR {
public:
};
class IR_Failed : public virtual IR {
public:
IR_Failed() = default;
goos::Object to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_Register : public IR {
class IR_Failed_Atomic : public IR_Failed, public IR_Atomic {
public:
IR_Failed_Atomic() = default;
};
class IR_Register : public virtual IR {
public:
IR_Register(Register _reg, int _instr_idx) : reg(_reg), instr_idx(_instr_idx) {}
goos::Object to_form(const LinkedObjectFile& file) const override;
@ -55,7 +64,7 @@ class IR_Register : public IR {
int instr_idx = -1;
};
class IR_Set : public IR {
class IR_Set : public virtual IR {
public:
enum Kind {
REG_64,
@ -79,7 +88,14 @@ class IR_Set : public IR {
std::shared_ptr<IR> clobber = nullptr;
};
class IR_Store : public IR_Set {
// todo
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)) {}
};
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)
@ -88,7 +104,20 @@ class IR_Store : public IR_Set {
goos::Object to_form(const LinkedObjectFile& file) const override;
};
class IR_Symbol : public IR {
/*!
* Note, IR_Store_Atomic does not appear as a IR_Set_Atomic.
* This is to avoid the "diamond problem".
*/
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) {}
int size;
goos::Object to_form(const LinkedObjectFile& file) const override;
};
class IR_Symbol : public virtual IR {
public:
explicit IR_Symbol(std::string _name) : name(std::move(_name)) {}
std::string name;
@ -100,7 +129,7 @@ class IR_Symbol : public IR {
TypeSpec* out) const override;
};
class IR_SymbolValue : public IR {
class IR_SymbolValue : public virtual IR {
public:
explicit IR_SymbolValue(std::string _name) : name(std::move(_name)) {}
std::string name;
@ -112,7 +141,7 @@ class IR_SymbolValue : public IR {
TypeSpec* out) const override;
};
class IR_StaticAddress : public IR {
class IR_StaticAddress : public virtual IR {
public:
explicit IR_StaticAddress(int _label_id) : label_id(_label_id) {}
int label_id = -1;
@ -120,7 +149,7 @@ class IR_StaticAddress : public IR {
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_Load : public IR {
class IR_Load : public virtual IR {
public:
enum Kind { UNSIGNED, SIGNED, FLOAT } kind;
@ -136,7 +165,7 @@ class IR_Load : public IR {
TypeSpec* out) const override;
};
class IR_FloatMath2 : public IR {
class IR_FloatMath2 : public virtual IR {
public:
enum Kind { DIV, MUL, ADD, SUB, MIN, MAX } kind;
IR_FloatMath2(Kind _kind, std::shared_ptr<IR> _arg0, std::shared_ptr<IR> _arg1)
@ -150,7 +179,7 @@ class IR_FloatMath2 : public IR {
TypeSpec* out) const override;
};
class IR_FloatMath1 : public IR {
class IR_FloatMath1 : public virtual IR {
public:
enum Kind { FLOAT_TO_INT, INT_TO_FLOAT, ABS, NEG, SQRT } kind;
IR_FloatMath1(Kind _kind, std::shared_ptr<IR> _arg) : kind(_kind), arg(std::move(_arg)) {}
@ -159,7 +188,7 @@ class IR_FloatMath1 : public IR {
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_IntMath2 : public IR {
class IR_IntMath2 : public virtual IR {
public:
enum Kind {
ADD,
@ -191,7 +220,7 @@ class IR_IntMath2 : public IR {
TypeSpec* out) const override;
};
class IR_IntMath1 : public IR {
class IR_IntMath1 : public virtual IR {
public:
enum Kind { NOT, ABS, NEG } kind;
IR_IntMath1(Kind _kind, std::shared_ptr<IR> _arg) : kind(_kind), arg(std::move(_arg)) {}
@ -204,14 +233,20 @@ class IR_IntMath1 : public IR {
TypeSpec* out) const override;
};
class IR_Call : public IR {
class IR_Call : public virtual IR {
public:
IR_Call() = default;
goos::Object to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_IntegerConstant : public IR {
// todo
class IR_Call_Atomic : public virtual IR_Call, public IR_Atomic {
public:
IR_Call_Atomic() = default;
};
class IR_IntegerConstant : public virtual IR {
public:
int64_t value;
explicit IR_IntegerConstant(int64_t _value) : value(_value) {}
@ -293,7 +328,7 @@ struct Condition {
void invert();
};
class IR_Branch : public IR {
class IR_Branch : public virtual IR {
public:
IR_Branch(Condition _condition, int _dest_label_idx, BranchDelay _branch_delay, bool _likely)
: condition(std::move(_condition)),
@ -313,7 +348,17 @@ class IR_Branch : public IR {
LinkedObjectFile& file) const;
};
class IR_Compare : public IR {
// todo
class IR_Branch_Atomic : public virtual IR_Branch, public IR_Atomic {
public:
IR_Branch_Atomic(Condition _condition,
int _dest_label_idx,
BranchDelay _branch_delay,
bool _likely)
: IR_Branch(std::move(_condition), _dest_label_idx, std::move(_branch_delay), _likely) {}
};
class IR_Compare : public virtual IR {
public:
explicit IR_Compare(Condition _condition) : condition(std::move(_condition)) {}
@ -327,21 +372,26 @@ class IR_Compare : public IR {
TypeSpec* out) const override;
};
class IR_Nop : public IR {
class IR_Nop : public virtual IR {
public:
IR_Nop() = default;
goos::Object to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_Suspend : public IR {
class IR_Nop_Atomic : public IR_Nop, public IR_Atomic {
public:
IR_Nop_Atomic() = default;
};
class IR_Suspend : public virtual IR, public IR_Atomic {
public:
IR_Suspend() = default;
goos::Object to_form(const LinkedObjectFile& file) const override;
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_Begin : public IR {
class IR_Begin : public virtual IR {
public:
IR_Begin() = default;
explicit IR_Begin(const std::vector<std::shared_ptr<IR>>& _forms) : forms(std::move(_forms)) {}
@ -350,7 +400,7 @@ class IR_Begin : public IR {
std::vector<std::shared_ptr<IR>> forms;
};
class IR_WhileLoop : public IR {
class IR_WhileLoop : public virtual IR {
public:
IR_WhileLoop(std::shared_ptr<IR> _condition, std::shared_ptr<IR> _body)
: condition(std::move(_condition)), body(std::move(_body)) {}
@ -360,7 +410,7 @@ class IR_WhileLoop : public IR {
bool cleaned = false;
};
class IR_UntilLoop : public IR {
class IR_UntilLoop : public virtual IR {
public:
IR_UntilLoop(std::shared_ptr<IR> _condition, std::shared_ptr<IR> _body)
: condition(std::move(_condition)), body(std::move(_body)) {}
@ -369,7 +419,7 @@ class IR_UntilLoop : public IR {
std::shared_ptr<IR> condition, body;
};
class IR_CondWithElse : public IR {
class IR_CondWithElse : public virtual IR {
public:
struct Entry {
std::shared_ptr<IR> condition = nullptr;
@ -385,7 +435,7 @@ class IR_CondWithElse : public IR {
};
// this one doesn't have an else statement. Will return false if none of the cases are taken.
class IR_Cond : public IR {
class IR_Cond : public virtual IR {
public:
struct Entry {
std::shared_ptr<IR> condition = nullptr;
@ -400,7 +450,7 @@ class IR_Cond : public IR {
};
// this will work on pairs, bintegers, or basics
class IR_GetRuntimeType : public IR {
class IR_GetRuntimeType : public virtual IR {
public:
std::shared_ptr<IR> object, clobber;
IR_GetRuntimeType(std::shared_ptr<IR> _object, std::shared_ptr<IR> _clobber)
@ -409,7 +459,7 @@ class IR_GetRuntimeType : public IR {
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_ShortCircuit : public IR {
class IR_ShortCircuit : public virtual IR {
public:
struct Entry {
std::shared_ptr<IR> condition = nullptr;
@ -427,7 +477,7 @@ class IR_ShortCircuit : public IR {
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_Ash : public IR {
class IR_Ash : public virtual IR {
public:
std::shared_ptr<IR> shift_amount, value, clobber;
bool is_signed = true;
@ -443,7 +493,7 @@ class IR_Ash : public IR {
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_AsmOp : public IR {
class IR_AsmOp : public virtual IR {
public:
std::shared_ptr<IR> dst = nullptr;
std::shared_ptr<IR> src0 = nullptr;
@ -455,7 +505,12 @@ class IR_AsmOp : public IR {
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_CMoveF : public IR {
class IR_AsmOp_Atomic : public virtual IR_AsmOp, public IR_Atomic {
public:
IR_AsmOp_Atomic(std::string _name) : IR_AsmOp(std::move(_name)) {}
};
class IR_CMoveF : public virtual IR {
public:
std::shared_ptr<IR> src = nullptr;
bool on_zero = false;
@ -465,7 +520,7 @@ class IR_CMoveF : public IR {
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_AsmReg : public IR {
class IR_AsmReg : public virtual IR {
public:
enum Kind { VU_Q, VU_ACC } kind;
explicit IR_AsmReg(Kind _kind) : kind(_kind) {}
@ -473,7 +528,7 @@ class IR_AsmReg : public IR {
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_Return : public IR {
class IR_Return : public virtual IR {
public:
std::shared_ptr<IR> return_code;
std::shared_ptr<IR> dead_code;
@ -483,7 +538,7 @@ class IR_Return : public IR {
void get_children(std::vector<std::shared_ptr<IR>>* output) const override;
};
class IR_Break : public IR {
class IR_Break : public virtual IR {
public:
std::shared_ptr<IR> return_code;
std::shared_ptr<IR> dead_code;