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