[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
#include <string>
#include <list>
#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<instruction*> 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<basic_block*>& 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<basic_block*> preds_;
inst_list_t inst_list_;
};
}

View File

@@ -4,6 +4,7 @@
#include <vector>
#include <string>
#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<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
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_;
};
}

View File

@@ -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);
};
}
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);
}
}
}

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::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;
}