[intermediate representation] more implementation
This commit is contained in:
@@ -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_;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -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_;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user