[intermediate representation] more implementation

This commit is contained in:
Philippe Tillet
2019-01-02 14:37:14 -05:00
parent 24bd2145df
commit 0378b9eb43
7 changed files with 171 additions and 29 deletions

View File

@@ -2,6 +2,7 @@
#define TDL_INCLUDE_IR_BASIC_BLOCK_H #define TDL_INCLUDE_IR_BASIC_BLOCK_H
#include <string> #include <string>
#include <list>
#include "value.h" #include "value.h"
namespace tdl{ namespace tdl{
@@ -14,16 +15,49 @@ class instruction;
/* Basic Block */ /* Basic Block */
class basic_block: public value{ class basic_block: public value{
public: public:
// Accessors // instruction iterator types
function* get_parent(); typedef std::list<instruction*> inst_list_t;
instruction* get_first_non_phi_or_dbg(); typedef inst_list_t::iterator iterator;
// Iterators typedef inst_list_t::const_iterator const_iterator;
instruction* begin(); typedef inst_list_t::reverse_iterator reverse_iterator;
instruction* end(); typedef inst_list_t::const_reverse_iterator const_reverse_iterator;
// CFG
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<basic_block*>& get_predecessors() const; const std::vector<basic_block*>& get_predecessors() const;
// add predecessor
void add_predecessor(basic_block* pred); void add_predecessor(basic_block* pred);
// Factory functions
// factory functions
static basic_block* create(context &ctx, const std::string &name, function *parent); static basic_block* create(context &ctx, const std::string &name, function *parent);
private: private:
@@ -31,6 +65,7 @@ private:
std::string name_; std::string name_;
function *parent_; function *parent_;
std::vector<basic_block*> preds_; std::vector<basic_block*> preds_;
inst_list_t inst_list_;
}; };
} }

View File

@@ -4,6 +4,7 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include "instructions.h" #include "instructions.h"
#include "basic_block.h"
namespace tdl{ namespace tdl{
namespace ir{ namespace ir{
@@ -18,14 +19,16 @@ class phi_node;
/* Builder */ /* Builder */
class builder{ class builder{
typedef basic_block::iterator iterator;
public: public:
// Constructor // Constructor
builder(context &ctx); builder(context &ctx);
// Setters // Setters
void set_insert_point(instruction* instr); void set_insert_point(iterator instr);
void set_insert_point(basic_block* block); void set_insert_point(basic_block* block);
basic_block* get_insert_block() { return block_; } basic_block* get_insert_block() { return block_; }
instruction* get_insert_point() { return insert_point_;} iterator get_insert_point() { return insert_point_;}
// Constants // Constants
value *get_int32(unsigned val); value *get_int32(unsigned val);
// Types // Types
@@ -33,7 +36,11 @@ public:
type *get_double_ty(); type *get_double_ty();
// Insert // Insert
template<typename InstTy> template<typename InstTy>
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 // Branch instructions
value* create_br(basic_block *dest); value* create_br(basic_block *dest);
value* create_cond_br(value *cond, basic_block* if_dest, basic_block* else_dest); value* create_cond_br(value *cond, basic_block* if_dest, basic_block* else_dest);
@@ -105,7 +112,7 @@ public:
private: private:
context &ctx_; context &ctx_;
basic_block *block_; basic_block *block_;
instruction *insert_point_; iterator insert_point_;
}; };
} }

View File

@@ -11,7 +11,8 @@ class context;
/* Constant */ /* Constant */
class constant: public value{ class constant: public value{
public:
static constant* get_all_ones_value(type *ty);
}; };
/* Undef value */ /* Undef value */
@@ -26,6 +27,18 @@ public:
static constant_data_array* get_string(context &ctx, const std::string &str); 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);
};
} }
} }

View File

@@ -15,9 +15,11 @@ class basic_block;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
class instruction: public user{ class instruction: public user{
public: protected:
// constructors // constructors
instruction(type *ty, unsigned num_used, instruction *next = nullptr); instruction(type *ty, unsigned num_ops, instruction *next = nullptr);
public:
// parent // parent
const basic_block *get_parent() const { return parent_;} const basic_block *get_parent() const { return parent_;}
@@ -80,22 +82,35 @@ public:
class cmp_inst: public instruction{ class cmp_inst: public instruction{
public: public:
typedef llvm::CmpInst::Predicate pred_t; typedef llvm::CmpInst::Predicate pred_t;
using pcmp = llvm::CmpInst;
private:
type* make_cmp_result_type(type *ty);
protected: protected:
cmp_inst(pred_t pred, value *lhs, value *rhs, type *ty, cmp_inst(pred_t pred, value *lhs, value *rhs, const std::string &name, instruction *next);
const std::string &name = "", instruction *next = nullptr);
static bool is_fp_predicate(pred_t pred);
static bool is_int_predicate(pred_t pred);
public:
private: private:
pred_t pred_; pred_t pred_;
}; };
class icmp_inst: public cmp_inst{ class icmp_inst: public cmp_inst{
using cmp_inst::cmp_inst;
public: public:
static icmp_inst* create(pred_t pred, value *lhs, value *rhs, static icmp_inst* create(pred_t pred, value *lhs, value *rhs,
const std::string &name = "", instruction *next = nullptr); const std::string &name = "", instruction *next = nullptr);
}; };
class fcmp_inst: public cmp_inst{ class fcmp_inst: public cmp_inst{
using cmp_inst::cmp_inst;
public: public:
static fcmp_inst* create(pred_t pred, value *lhs, value *rhs, static fcmp_inst* create(pred_t pred, value *lhs, value *rhs,
const std::string &name = "", instruction *next = nullptr); const std::string &name = "", instruction *next = nullptr);

View File

@@ -14,8 +14,8 @@ builder::builder(context &ctx):
// insertion helpers // insertion helpers
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
void builder::set_insert_point(instruction *instr){ void builder::set_insert_point(basic_block::iterator instr){
block_ = instr->get_parent(); block_ = (*instr)->get_parent();
insert_point_ = instr; insert_point_ = instr;
} }

View File

@@ -1,26 +1,98 @@
#include "ir/basic_block.h" #include "ir/basic_block.h"
#include "ir/instructions.h" #include "ir/instructions.h"
#include "ir/constant.h"
namespace tdl{ namespace tdl{
namespace ir{ namespace ir{
//===----------------------------------------------------------------------===//
// instruction classes
//===----------------------------------------------------------------------===//
instruction::instruction(type *ty, unsigned num_ops, instruction *next) instruction::instruction(type *ty, unsigned num_ops, instruction *next)
: user(ty, num_ops) { : user(ty, num_ops) {
if(next){ if(next){
basic_block *block = next->get_parent(); basic_block *block = next->get_parent();
assert(block && "Next instruction is not in a basic block!"); 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) { // phi_node classes
// BasicBlock *BB = InsertBefore->getParent(); //===----------------------------------------------------------------------===//
// assert(BB && "Instruction to insert before is not in a basic block!");
// BB->getInstList().insert(InsertBefore->getIterator(), this); // 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);
}
} }
} }

View File

@@ -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::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(); basic_block::iterator insert = block->get_first_non_phi();
if(instr) if(insert == block->end())
builder_.set_insert_point(instr); builder_.set_insert_point(insert);
ir::phi_node *res = builder_.create_phi(ty, num_values); ir::phi_node *res = builder_.create_phi(ty, num_values);
if(instr) if(insert == block->end())
builder_.set_insert_point(block); builder_.set_insert_point(block);
return res; return res;
} }