#ifndef _SYSYF_INSTRUCTION_H_ #define _SYSYF_INSTRUCTION_H_ #include "User.h" #include "Type.h" #include "Constant.h" #include "BasicBlock.h" namespace SysYF { namespace IR { class BasicBlock; class Function; class Instruction; class Instruction : public User { public: enum OpID { // Terminator Instructions ret, br, // Standard binary operators add, sub, mul, sdiv, srem, // Float binaru opeartors fadd, fsub, fmul, fdiv, // Memory operators alloca, load, store, // Other operators cmp, fcmp, phi, call, getelementptr, // Zero extend zext, // type cast bewteen float and singed integer fptosi, sitofp, }; inline const Ptr get_parent() const { return parent_; } inline Ptr get_parent() { return parent_; } void set_parent(Ptr parent) { this->parent_ = parent; } // Return the function this instruction belongs to. Ptr get_function(); Ptr get_module(); OpID get_instr_type() { return op_id_; } std::string get_instr_op_name() { switch (op_id_) { case ret: return "ret"; break; case br: return "br"; break; case add: return "add"; break; case sub: return "sub"; break; case mul: return "mul"; break; case sdiv: return "sdiv"; break; case srem: return "srem"; break; case fadd: return "fadd"; break; case fsub: return "fsub"; break; case fmul: return "fmul"; break; case fdiv: return "fdiv"; break; case alloca: return "alloca"; break; case load: return "load"; break; case store: return "store"; break; case cmp: return "cmp"; break; case fcmp: return "fcmp"; break; case phi: return "phi"; break; case call: return "call"; break; case getelementptr: return "getelementptr"; break; case zext: return "zext"; break; case fptosi: return "fptosi"; break; case sitofp: return "sitofp"; break; default: return ""; break; } } bool is_void() { return ((op_id_ == ret) || (op_id_ == br) || (op_id_ == store) || (op_id_ == call && this->get_type()->is_void_type())); } bool is_phi() { return op_id_ == phi; } bool is_store() { return op_id_ == store; } bool is_alloca() { return op_id_ == alloca; } bool is_ret() { return op_id_ == ret; } bool is_load() { return op_id_ == load; } bool is_br() { return op_id_ == br; } bool is_add() { return op_id_ == add; } bool is_sub() { return op_id_ == sub; } bool is_mul() { return op_id_ == mul; } bool is_div() { return op_id_ == sdiv; } bool is_rem() { return op_id_ == srem; } bool is_fadd() { return op_id_ == fadd; } bool is_fsub() { return op_id_ == fsub; } bool is_fmul() { return op_id_ == fmul; } bool is_fdiv() { return op_id_ == fdiv; } bool is_cmp() { return op_id_ == cmp; } bool is_fcmp() { return op_id_ == fcmp; } bool is_call() { return op_id_ == call; } bool is_gep() { return op_id_ == getelementptr; } bool is_zext() { return op_id_ == zext; } bool is_fptosi() { return op_id_ == fptosi; } bool is_sitofp() { return op_id_ == sitofp; } bool isBinary() { return (is_add() || is_sub() || is_mul() || is_div() || is_rem() || is_fadd() || is_fsub() || is_fmul() || is_fdiv()) && (get_num_operand() == 2); } bool isTerminator() { return is_br() || is_ret(); } void set_id(int id){id_ = id;} int get_id() const{return id_;} private: OpID op_id_; int id_; unsigned num_ops_; Ptr parent_; // must be called after Instruction() in any derived class void insert_to_bb(); protected: // create instruction, but not insert to bb (insert to bb in method create in the derived class) // ty here is result type explicit Instruction(Ptr ty, OpID id, unsigned num_ops, Ptr parent = nullptr); void init(Ptr ty, OpID id, unsigned num_ops, Ptr parent = nullptr); }; class BinaryInst : public Instruction { private: explicit BinaryInst(Ptr ty, OpID id, Ptr v1, Ptr v2, Ptr bb); public: static Ptr create_add(Ptr v1, Ptr v2, Ptr bb, Ptr m); static Ptr create_sub(Ptr v1, Ptr v2, Ptr bb, Ptr m); static Ptr create_mul(Ptr v1, Ptr v2, Ptr bb, Ptr m); static Ptr create_sdiv(Ptr v1, Ptr v2, Ptr bb, Ptr m); static Ptr create_srem(Ptr v1, Ptr v2, Ptr bb, Ptr m); static Ptr create_fadd(Ptr v1, Ptr v2, Ptr bb, Ptr m); static Ptr create_fsub(Ptr v1, Ptr v2, Ptr bb, Ptr m); static Ptr create_fmul(Ptr v1, Ptr v2, Ptr bb, Ptr m); static Ptr create_fdiv(Ptr v1, Ptr v2, Ptr bb, Ptr m); virtual std::string print() override; private: void init(Ptr ty, OpID id, Ptr v1, Ptr v2, Ptr bb); void assertValid() {} }; class CmpInst : public Instruction { public: enum CmpOp { EQ, // == NE, // != GT, // > GE, // >= LT, // < LE // <= }; private: explicit CmpInst(Ptr ty, CmpOp op, Ptr lhs, Ptr rhs, Ptr bb); public: static Ptr create_cmp(CmpOp op, Ptr lhs, Ptr rhs, Ptr bb, Ptr m); CmpOp get_cmp_op() { return cmp_op_; } virtual std::string print() override; private: CmpOp cmp_op_; void init(Ptr ty, CmpOp op, Ptr lhs, Ptr rhs, Ptr bb); void assertValid() {} }; class FCmpInst : public Instruction { public: enum CmpOp { EQ, // == NE, // != GT, // > GE, // >= LT, // < LE // <= }; private: explicit FCmpInst(Ptr ty, CmpOp op, Ptr lhs, Ptr rhs, Ptr bb); void init(Ptr ty, CmpOp op, Ptr lhs, Ptr rhs, Ptr bb); public: static Ptr create_fcmp(CmpOp op, Ptr lhs, Ptr rhs, Ptr bb, Ptr m); CmpOp get_cmp_op() { return cmp_op_; } virtual std::string print() override; private: CmpOp cmp_op_; void assertValid() {} }; class CallInst : public Instruction { private: explicit CallInst(Ptr func, PtrVec args, Ptr bb); void init(Ptr func, PtrVec args, Ptr bb); explicit CallInst(Ptr ret_ty, PtrVec args, Ptr bb); void init(Ptr ret_ty, PtrVec args, Ptr bb); public: static Ptr create(Ptr func, PtrVec args, Ptr bb); Ptr get_function_type() const; virtual std::string print() override; }; class BranchInst : public Instruction { private: explicit BranchInst(Ptr cond, Ptr if_true, Ptr if_false, Ptr bb); void init(Ptr cond, Ptr if_true, Ptr if_false, Ptr bb); explicit BranchInst(Ptr cond, Ptr bb); void init(Ptr cond, Ptr bb); explicit BranchInst(Ptr if_true, Ptr bb); void init(Ptr if_true, Ptr bb); explicit BranchInst(Ptr bb); void init(Ptr bb); public: static Ptr create_cond_br(Ptr cond, Ptr if_true, Ptr if_false, Ptr bb); static Ptr create_br(Ptr if_true, Ptr bb); bool is_cond_br() const; virtual std::string print() override; }; class ReturnInst : public Instruction { private: explicit ReturnInst(Ptr val, Ptr bb); void init(Ptr val, Ptr bb); explicit ReturnInst(Ptr bb); void init(Ptr bb); public: static Ptr create_ret(Ptr val, Ptr bb); static Ptr create_void_ret(Ptr bb); bool is_void_ret() const; virtual std::string print() override; }; class GetElementPtrInst : public Instruction { private: explicit GetElementPtrInst(Ptr ptr, PtrVec idxs, Ptr bb); void init(Ptr ptr, PtrVec idxs, Ptr bb); public: static Ptr get_element_type(Ptr ptr, PtrVec idxs); static Ptr create_gep(Ptr ptr, PtrVec idxs, Ptr bb); Ptr get_element_type() const; virtual std::string print() override; private: Ptr element_ty_; }; class StoreInst : public Instruction { private: explicit StoreInst(Ptr val, Ptr ptr, Ptr bb); void init(Ptr val, Ptr ptr, Ptr bb); public: static Ptr create_store(Ptr val, Ptr ptr, Ptr bb); Ptr get_rval() { return this->get_operand(0); } Ptr get_lval() { return this->get_operand(1); } virtual std::string print() override; }; class LoadInst : public Instruction { private: explicit LoadInst(Ptr ty, Ptr ptr, Ptr bb); void init(Ptr ty, Ptr ptr, Ptr bb); public: static Ptr create_load(Ptr ty, Ptr ptr, Ptr bb); Ptr get_lval() { return this->get_operand(0); } Ptr get_load_type() const; virtual std::string print() override; }; class AllocaInst : public Instruction { private: explicit AllocaInst(Ptr ty, Ptr bb); void init(Ptr ty, Ptr bb); public: static Ptr create_alloca(Ptr ty, Ptr bb); Ptr get_alloca_type() const; virtual std::string print() override; private: Ptr alloca_ty_; }; class ZextInst : public Instruction { private: explicit ZextInst(OpID op, Ptr val, Ptr ty, Ptr bb); void init(OpID op, Ptr val, Ptr ty, Ptr bb); public: static Ptr create_zext(Ptr val, Ptr ty, Ptr bb); Ptr get_dest_type() const; virtual std::string print() override; private: Ptr dest_ty_; }; class FpToSiInst : public Instruction { private: explicit FpToSiInst(OpID op, Ptr val, Ptr ty, Ptr bb); void init(OpID op, Ptr val, Ptr ty, Ptr bb); public: static Ptr create_fptosi(Ptr val, Ptr ty, Ptr bb); Ptr get_dest_type() const; virtual std::string print() override; private: Ptr dest_ty_; }; class SiToFpInst : public Instruction { private: explicit SiToFpInst(OpID op, Ptr val, Ptr ty, Ptr bb); void init(OpID op, Ptr val, Ptr ty, Ptr bb); public: static Ptr create_sitofp(Ptr val, Ptr ty, Ptr bb); Ptr get_dest_type() const; virtual std::string print() override; private: Ptr dest_ty_; }; class PhiInst : public Instruction { private: explicit PhiInst(OpID op, PtrVec vals, PtrVec val_bbs, Ptr ty, Ptr bb); void init(OpID op, PtrVec vals, PtrVec val_bbs, Ptr ty, Ptr bb); public: static Ptr create_phi(Ptr ty, Ptr bb); Ptr get_lval() { return l_val_; } void set_lval(Ptr l_val) { l_val_ = l_val; } void add_phi_pair_operand(Ptr val, Ptr pre_bb) { this->add_operand(val); this->add_operand(pre_bb); } virtual std::string print() override; private: Ptr l_val_; }; } } #endif // _SYSYF_INSTRUCTION_H_