From 0378b9eb4379b51b3337207e79c651fa152a1008 Mon Sep 17 00:00:00 2001 From: Philippe Tillet Date: Wed, 2 Jan 2019 14:37:14 -0500 Subject: [PATCH] [intermediate representation] more implementation --- include/ir/basic_block.h | 51 ++++++++++++++++++++---- include/ir/builder.h | 15 +++++-- include/ir/constant.h | 15 ++++++- include/ir/instructions.h | 23 +++++++++-- lib/ir/builder.cpp | 4 +- lib/ir/instructions.cpp | 84 ++++++++++++++++++++++++++++++++++++--- lib/ir/module.cpp | 8 ++-- 7 files changed, 171 insertions(+), 29 deletions(-) diff --git a/include/ir/basic_block.h b/include/ir/basic_block.h index e98a7ddfd..240123796 100644 --- a/include/ir/basic_block.h +++ b/include/ir/basic_block.h @@ -2,6 +2,7 @@ #define TDL_INCLUDE_IR_BASIC_BLOCK_H #include +#include #include "value.h" namespace tdl{ @@ -14,16 +15,49 @@ class instruction; /* Basic Block */ class basic_block: public value{ public: - // Accessors - function* get_parent(); - instruction* get_first_non_phi_or_dbg(); - // Iterators - instruction* begin(); - instruction* end(); - // CFG + // instruction iterator types + typedef std::list inst_list_t; + typedef inst_list_t::iterator iterator; + typedef inst_list_t::const_iterator const_iterator; + typedef inst_list_t::reverse_iterator reverse_iterator; + typedef inst_list_t::const_reverse_iterator const_reverse_iterator; + + +public: + // parent + function* get_parent() { return parent_; } + + // get iterator to first instruction that is not a phi + iterator get_first_non_phi(); + + // get instruction list + inst_list_t &get_inst_list() { return inst_list_; } + + // instruction iterator functions + inline iterator begin() { return inst_list_.begin(); } + inline const_iterator begin() const { return inst_list_.begin(); } + inline iterator end () { return inst_list_.end(); } + inline const_iterator end () const { return inst_list_.end(); } + + inline reverse_iterator rbegin() { return inst_list_.rbegin(); } + inline const_reverse_iterator rbegin() const { return inst_list_.rbegin(); } + inline reverse_iterator rend () { return inst_list_.rend(); } + inline const_reverse_iterator rend () const { return inst_list_.rend(); } + + inline size_t size() const { return inst_list_.size(); } + inline bool empty() const { return inst_list_.empty(); } + inline const instruction &front() const { return *inst_list_.front(); } + inline instruction &front() { return *inst_list_.front(); } + inline const instruction &back() const { return *inst_list_.back(); } + inline instruction &back() { return *inst_list_.back(); } + + // get predecessors const std::vector& get_predecessors() const; + + // add predecessor void add_predecessor(basic_block* pred); - // Factory functions + + // factory functions static basic_block* create(context &ctx, const std::string &name, function *parent); private: @@ -31,6 +65,7 @@ private: std::string name_; function *parent_; std::vector preds_; + inst_list_t inst_list_; }; } diff --git a/include/ir/builder.h b/include/ir/builder.h index 2e208d62b..254d3bab6 100644 --- a/include/ir/builder.h +++ b/include/ir/builder.h @@ -4,6 +4,7 @@ #include #include #include "instructions.h" +#include "basic_block.h" namespace tdl{ namespace ir{ @@ -18,14 +19,16 @@ class phi_node; /* Builder */ class builder{ + typedef basic_block::iterator iterator; + public: // Constructor builder(context &ctx); // Setters - void set_insert_point(instruction* instr); + void set_insert_point(iterator instr); void set_insert_point(basic_block* block); basic_block* get_insert_block() { return block_; } - instruction* get_insert_point() { return insert_point_;} + iterator get_insert_point() { return insert_point_;} // Constants value *get_int32(unsigned val); // Types @@ -33,7 +36,11 @@ public: type *get_double_ty(); // Insert template - InstTy* insert(InstTy *instr, const std::string &name = ""); + InstTy* insert(InstTy *inst, const std::string &name = ""){ + if(block_) + block_->get_inst_list().insert(insert_point_, inst); + inst->set_name(name); + } // Branch instructions value* create_br(basic_block *dest); value* create_cond_br(value *cond, basic_block* if_dest, basic_block* else_dest); @@ -105,7 +112,7 @@ public: private: context &ctx_; basic_block *block_; - instruction *insert_point_; + iterator insert_point_; }; } diff --git a/include/ir/constant.h b/include/ir/constant.h index a7790e9d3..40f3b056c 100644 --- a/include/ir/constant.h +++ b/include/ir/constant.h @@ -11,7 +11,8 @@ class context; /* Constant */ class constant: public value{ - +public: + static constant* get_all_ones_value(type *ty); }; /* Undef value */ @@ -26,6 +27,18 @@ public: static constant_data_array* get_string(context &ctx, const std::string &str); }; +/* Constant int */ +class constant_int: public constant{ + +}; + +/* constant fp */ +class constant_fp: public constant{ +public: + static constant* get_zero_value_for_negation(type *ty); +}; + + } } diff --git a/include/ir/instructions.h b/include/ir/instructions.h index 05ee57070..95c26de1d 100644 --- a/include/ir/instructions.h +++ b/include/ir/instructions.h @@ -15,9 +15,11 @@ class basic_block; //===----------------------------------------------------------------------===// class instruction: public user{ -public: +protected: // constructors - instruction(type *ty, unsigned num_used, instruction *next = nullptr); + instruction(type *ty, unsigned num_ops, instruction *next = nullptr); + +public: // parent const basic_block *get_parent() const { return parent_;} @@ -80,22 +82,35 @@ public: class cmp_inst: public instruction{ public: typedef llvm::CmpInst::Predicate pred_t; + using pcmp = llvm::CmpInst; + +private: + type* make_cmp_result_type(type *ty); protected: - cmp_inst(pred_t pred, value *lhs, value *rhs, type *ty, - const std::string &name = "", instruction *next = nullptr); + cmp_inst(pred_t pred, value *lhs, value *rhs, const std::string &name, instruction *next); + + static bool is_fp_predicate(pred_t pred); + static bool is_int_predicate(pred_t pred); + +public: + private: pred_t pred_; }; class icmp_inst: public cmp_inst{ + using cmp_inst::cmp_inst; + public: static icmp_inst* create(pred_t pred, value *lhs, value *rhs, const std::string &name = "", instruction *next = nullptr); }; class fcmp_inst: public cmp_inst{ + using cmp_inst::cmp_inst; + public: static fcmp_inst* create(pred_t pred, value *lhs, value *rhs, const std::string &name = "", instruction *next = nullptr); diff --git a/lib/ir/builder.cpp b/lib/ir/builder.cpp index 209ab78c5..a5d14b913 100644 --- a/lib/ir/builder.cpp +++ b/lib/ir/builder.cpp @@ -14,8 +14,8 @@ builder::builder(context &ctx): // insertion helpers //===----------------------------------------------------------------------===// -void builder::set_insert_point(instruction *instr){ - block_ = instr->get_parent(); +void builder::set_insert_point(basic_block::iterator instr){ + block_ = (*instr)->get_parent(); insert_point_ = instr; } diff --git a/lib/ir/instructions.cpp b/lib/ir/instructions.cpp index 8a7061cc7..383085c10 100644 --- a/lib/ir/instructions.cpp +++ b/lib/ir/instructions.cpp @@ -1,26 +1,98 @@ #include "ir/basic_block.h" #include "ir/instructions.h" +#include "ir/constant.h" namespace tdl{ namespace ir{ +//===----------------------------------------------------------------------===// +// instruction classes +//===----------------------------------------------------------------------===// instruction::instruction(type *ty, unsigned num_ops, instruction *next) : user(ty, num_ops) { if(next){ basic_block *block = next->get_parent(); assert(block && "Next instruction is not in a basic block!"); + auto it = std::find(block->begin(), block->end(), next); + block->get_inst_list().insert(it, next); } } -// // If requested, insert this instruction into a basic block... -// if (InsertBefore) { -// BasicBlock *BB = InsertBefore->getParent(); -// assert(BB && "Instruction to insert before is not in a basic block!"); -// BB->getInstList().insert(InsertBefore->getIterator(), this); -// } +//===----------------------------------------------------------------------===// +// phi_node classes +//===----------------------------------------------------------------------===// + +// Add incoming +void phi_node::add_incoming(value *x, basic_block *bb){ + +} + +// Factory methods +phi_node* phi_node::create(type *ty, unsigned num_reserved){ + return new phi_node(ty, num_reserved); +} +//===----------------------------------------------------------------------===// +// binary_operator classes +//===----------------------------------------------------------------------===// + +binary_operator::binary_operator(op_t op, value *lhs, value *rhs, type *ty, const std::string &name, instruction *next) + : instruction(ty, 2, next), op_(op){ + set_operand(0, lhs); + set_operand(1, rhs); +} + +binary_operator *binary_operator::create(op_t op, value *lhs, value *rhs, const std::string &name, instruction *next){ + assert(lhs->get_type() == rhs->get_type() && + "Cannot create binary operator with two operands of differing type!"); + return new binary_operator(op, lhs, rhs, lhs->get_type(), name, next); +} + +binary_operator *binary_operator::create_fneg(value *arg, const std::string &name, instruction *next){ + assert(arg->get_type()->is_floating_point_ty()); + value *zero = constant_fp::get_zero_value_for_negation(arg->get_type()); + return binary_operator::create(llvm::Instruction::FSub, zero, arg, name, next); +} + +binary_operator *binary_operator::create_neg(value *arg, const std::string &name, instruction *next){ + assert(arg->get_type()->is_integer_ty()); + value *zero = constant_fp::get_zero_value_for_negation(arg->get_type()); + return binary_operator::create(llvm::Instruction::Sub, zero, arg, name, next); +} + +binary_operator *binary_operator::create_not(value *arg, const std::string &name, instruction *next){ + assert(arg->get_type()->is_integer_ty()); + constant *mask = constant::get_all_ones_value(arg->get_type()); + return binary_operator::create(llvm::Instruction::Xor, arg, mask, name, next); +} + +//===----------------------------------------------------------------------===// +// cmp_inst classes +//===----------------------------------------------------------------------===// + +bool cmp_inst::is_fp_predicate(pred_t pred) { + return pred >= pcmp::FIRST_FCMP_PREDICATE && pred <= pcmp::LAST_FCMP_PREDICATE; +} + +bool cmp_inst::is_int_predicate(pred_t pred) { + return pred >= pcmp::FIRST_ICMP_PREDICATE && pred <= pcmp::LAST_ICMP_PREDICATE; +} + +// icmp_inst + +icmp_inst* icmp_inst::create(pred_t pred, value *lhs, value *rhs, const std::string &name, instruction *next){ + assert(is_int_predicate(pred)); + return new icmp_inst(pred, lhs, rhs, name, next); +} + +// fcmp_inst + +fcmp_inst* fcmp_inst::create(pred_t pred, value *lhs, value *rhs, const std::string &name, instruction *next){ + assert(is_fp_predicate(pred)); + return new fcmp_inst(pred, lhs, rhs, name, next); +} } } diff --git a/lib/ir/module.cpp b/lib/ir/module.cpp index 3c6739213..c1979881b 100644 --- a/lib/ir/module.cpp +++ b/lib/ir/module.cpp @@ -27,11 +27,11 @@ void module::set_value(const std::string& name, ir::value *value){ } ir::phi_node* module::make_phi(ir::type *ty, unsigned num_values, ir::basic_block *block){ - ir::instruction* instr = block->get_first_non_phi_or_dbg(); - if(instr) - builder_.set_insert_point(instr); + basic_block::iterator insert = block->get_first_non_phi(); + if(insert == block->end()) + builder_.set_insert_point(insert); ir::phi_node *res = builder_.create_phi(ty, num_values); - if(instr) + if(insert == block->end()) builder_.set_insert_point(block); return res; }