refine mem2reg, frontend refactor

This commit is contained in:
ridethepig 2023-06-15 09:21:56 +08:00
parent 81bd968258
commit 3b5cd82206
12 changed files with 367 additions and 528 deletions

View File

@ -36,6 +36,7 @@ inline sptr(DST) strict_shared_cast(SRC src) {
#define STD_FIND(container, val) std::find(container.begin(), container.end(), val)
#define STD_FOUND(container, val) (STD_FIND(container, val) != container.end())
#define INSET(cont, val) (cont.find(val) != cont.end())
#define BEGINEND(cont) cont.begin(), cont.end()
#define INF (0x3f3f3f3f)
#define BTWN(v, l, r) (l <= v && v <= r)

View File

@ -52,7 +52,7 @@ public:
int ir_seqno = -1;
InstTag tag;
BasicBlockPtr_t parent_bb;
decltype(BasicBlock::inst_list.begin()) inst_itr;
std::list<InstructionPtr_t>::iterator inst_itr;
Instruction(InstTag inst_tag, TypePtr_t type, BasicBlockPtr_t parent_bb)
: User("", type), tag(inst_tag), parent_bb(parent_bb) {}
std::string tag_string() {
@ -98,6 +98,14 @@ public:
std::string str = type->to_IR_string() + " %" + std::to_string(ir_seqno);
return str;
}
static sptr(InstAlloca) New(const std::string &name, TypePtr_t type, sptr(BasicBlock) parent_bb) {
auto inst = std::make_shared<InstAlloca>(type, parent_bb);
inst->name = name;
auto func_head_bb = parent_bb->parent->bb_list.front();
// put all alloca in the head of each basic block
inst->inst_itr = func_head_bb->inst_list.insert(func_head_bb->inst_list.begin(), inst);
return inst;
}
};
class InstStore : public Instruction {
@ -108,6 +116,11 @@ public:
Add_Operand(value);
Add_Operand(pointer);
}
static sptr(InstStore) New(sptr(Value) value, sptr(Value) pointer, sptr(BasicBlock) parent_bb) {
auto inst = std::make_shared<InstStore>(value, pointer, parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
};
class InstLoad : public Instruction {
@ -120,6 +133,11 @@ public:
std::string str = type->to_IR_string() + " %" + std::to_string(ir_seqno);
return str;
}
static sptr(InstLoad) New(std::shared_ptr<Value> value, TypePtr_t type, std::shared_ptr<BasicBlock> parent_bb) {
auto inst = std::make_shared<InstLoad>(value, type, parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
};
class InstBinary : public Instruction {
@ -139,6 +157,34 @@ public:
std::string str = type->to_IR_string() + " %" + std::to_string(ir_seqno);
return str;
}
static sptr(InstBinary) New(
InstTag inst_tag,
std::shared_ptr<Value> op1,
std::shared_ptr<Value> op2,
std::shared_ptr<BasicBlock> parent_bb
) {
std::shared_ptr<InstBinary> inst;
if (InstTag::Lt <= inst_tag && inst_tag <= InstTag::Ne) {
inst = std::make_shared<InstBinary>(inst_tag, TypeHelper::TYPE_I1, op1, op2, parent_bb);
}
else if (InstTag::Add <= inst_tag && inst_tag <= InstTag::Div) {
inst = std::make_shared<InstBinary>(inst_tag, TypeHelper::TYPE_I32, op1, op2, parent_bb);
}
else {
panic("Invalid Binary Operation");
}
assert(Type::isType<IntegerType>(op1->type));
assert(Type::isType<IntegerType>(op2->type));
if (!(Type::asType<IntegerType>(op1->type)->int_type == Type::asType<IntegerType>(op2->type)->int_type)) {
if (!(shared_cast<ConstantInt>(op1) && shared_cast<ConstantInt>(op1)->value == 0)
&& !(shared_cast<ConstantInt>(op2) && shared_cast<ConstantInt>(op2)->value == 0)) {
LOG(ERROR) << op1->to_string() << ",\t" << op2->to_string();
assert(0);
}
}
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
};
//<result> = zext <ty> <value> to <ty2>
@ -153,6 +199,11 @@ public:
std::string str = type->to_IR_string() + " %" + std::to_string(ir_seqno);
return str;
}
static sptr(InstZext) New(std::shared_ptr<Value> op, std::shared_ptr<BasicBlock> parent_bb) {
auto inst = std::make_shared<InstZext>(op, parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
};
class InstBranch : public Instruction {
@ -164,11 +215,22 @@ public:
this->Add_Operand(true_block);
this->Add_Operand(false_block);
}
static sptr(InstBranch)
New(ValuePtr_t cond, BasicBlockPtr_t true_block, BasicBlockPtr_t false_block, BasicBlockPtr_t parent_bb) {
auto inst = std::make_shared<InstBranch>(cond, true_block, false_block, parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
// unconditional branch
InstBranch(BasicBlockPtr_t target_block, BasicBlockPtr_t parent_bb)
: Instruction(InstTag::Br, TypeHelper::TYPE_VOID, parent_bb) {
this->Add_Operand(target_block);
}
static sptr(InstBranch) New(BasicBlockPtr_t target_block, BasicBlockPtr_t parent_bb) {
auto inst = std::make_shared<InstBranch>(target_block, parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
};
class InstReturn : public Instruction {
@ -178,6 +240,16 @@ public:
this->Add_Operand(ret_val);
}
InstReturn(BasicBlockPtr_t parent_bb) : Instruction(InstTag::Ret, TypeHelper::TYPE_VOID, parent_bb) {}
static sptr(InstReturn) New(ValuePtr_t ret_val, BasicBlockPtr_t parent_bb) {
auto inst = std::make_shared<InstReturn>(ret_val, parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
static sptr(InstReturn) New(BasicBlockPtr_t parent_bb) {
auto inst = std::make_shared<InstReturn>(parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
};
// call's type is the function's return type
@ -197,6 +269,15 @@ public:
std::string str = type->to_IR_string() + " %" + std::to_string(ir_seqno);
return str;
}
static std::shared_ptr<InstCall> New(
FunctionPtr_t func,
const std::vector<ValuePtr_t> &args,
BasicBlockPtr_t parent_bb
) {
auto inst = std::make_shared<InstCall>(func, args, parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
};
// getelementptr <ty>, ptr <ptrval>{, [inrange] <ty> <idx>}*
@ -212,10 +293,10 @@ public:
TypePtr_t element_type;
InstGEP(ValuePtr_t pointer, const std::vector<ValuePtr_t> &indices, BasicBlockPtr_t parent_bb)
: Instruction(InstTag::GEP, std::make_shared<PointerType>(extract_type(pointer, indices)), parent_bb) {
if (Value::is<InstGEP>(pointer)) {
if (shared_cast<InstGEP>(pointer)) {
aim_to = std::dynamic_pointer_cast<InstGEP>(pointer)->aim_to;
}
else if (Value::is<InstAlloca>(pointer) || Value::is<GlobalVar>(pointer)) {
else if (shared_cast<InstAlloca>(pointer) || shared_cast<GlobalVar>(pointer)) {
aim_to = pointer;
}
else {
@ -234,6 +315,15 @@ public:
std::string str = type->to_IR_string() + " %" + std::to_string(ir_seqno);
return str;
}
static std::shared_ptr<InstGEP> New(
ValuePtr_t pointer,
const std::vector<ValuePtr_t> &indices,
BasicBlockPtr_t parent_bb
) {
auto inst = std::make_shared<InstGEP>(pointer, indices, parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
// get the inner
static TypePtr_t extract_type(ValuePtr_t pointer, const std::vector<ValuePtr_t> &indices) {
@ -261,7 +351,7 @@ public:
void set_incoming_val(unsigned index, ValuePtr_t val) {
auto old_op = operand_list[index];
operand_list[index] = val;
if (val) val->use_list.push_back({val, this, index});
if (val) val->use_list.push_back({/*val.get(),*/ this, index});
if (old_op) {
if (std::find(operand_list.begin(), operand_list.end(), old_op) == operand_list.end()) {
old_op->u_remove_use(this);
@ -272,6 +362,17 @@ public:
std::string str = type->to_IR_string() + " %" + std::to_string(ir_seqno);
return str;
}
static InstPhiPtr_t New(
TypePtr_t type,
const decltype(Function::bb_list) &incoming_vals,
BasicBlockPtr_t parent_bb,
const std::string &name
) {
auto inst = std::make_shared<InstPhi>(type, incoming_vals, parent_bb);
inst->name = name;
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.begin(), inst);
return inst;
}
};
} // namespace CompSysY

View File

@ -24,7 +24,7 @@ DEF_PTR_T(ConstantInt);
// typedef std::tuple<ValuePtr_t, UserPtr_t, int> UseEdge_t;
struct Use {
ValuePtr_t value;
// Value* value;
User *user;
unsigned op_index;
};
@ -40,24 +40,6 @@ public:
Value(const std::string &name, TypePtr_t type) : name(name), type(type) {}
virtual ~Value() = default;
template <typename TT>
static bool is(std::shared_ptr<Value> ptr) {
if (ptr.get()) {
// auto &r = *ptr.get();
// return typeid(r) == typeid(TT);
return dynamic_cast<TT *>(ptr.get()) != nullptr;
}
LOG(WARNING) << "Comparing with nullptr";
assert(0);
return false;
}
// it is caller's duty to check before use `asType`
template <typename TT>
static std::shared_ptr<TT> as(std::shared_ptr<Value> ptr) {
return std::dynamic_pointer_cast<TT>(ptr);
}
virtual std::string to_string() {
return name + ": " + type->to_string();
}
@ -90,7 +72,8 @@ public:
User(const std::string &name, TypePtr_t type) : Value(name, type) {}
void Add_Operand(ValuePtr_t op) {
op->use_list.push_back({op, this, (unsigned)operand_list.size()});
// value, use, op_index
op->use_list.push_back({/*op.get(),*/ this, (unsigned)operand_list.size()});
operand_list.push_back(op);
}
// make anything that use this value use the new value
@ -104,7 +87,7 @@ public:
auto index = use.op_index;
user->operand_list[index] = value;
assert(value);
value->use_list.push_back({value, user, index});
value->use_list.push_back({/*value.get(),*/ user, index});
}
// all original uses are gone
use_list.clear();
@ -174,6 +157,14 @@ public:
BasicBlock(const std::string &name, std::shared_ptr<Function> parent) : Value(name, TypeHelper::TYPE_LABEL) {
this->parent = parent;
}
static sptr(BasicBlock)
New(const std::string &name, std::shared_ptr<Function> parent, const BasicBlockListNode_t &cur_bb_itr) {
static int count = 0;
auto basic_block = std::make_shared<BasicBlock>("blk" + std::to_string(count++), parent);
basic_block->itr = parent->bb_list.insert(std::next(cur_bb_itr), basic_block);
return basic_block;
}
};
class Constant : public Value {
@ -185,7 +176,7 @@ class ConstantInt : public Constant {
public:
int value;
ConstantInt(const std::string &name, int value) : Constant(name, TypeHelper::TYPE_I32), value(value) {}
static std::shared_ptr<ConstantInt> make_shared(int value) {
static std::shared_ptr<ConstantInt> New(int value) {
return std::make_shared<ConstantInt>("", value);
}
virtual std::string to_string() override {

View File

@ -20,76 +20,6 @@
namespace CompSysY {
#pragma region FactoryFunctionDeclaration
std::shared_ptr<ConstantInt> build_ConstantInt(const std::string &name, int value);
std::shared_ptr<BasicBlock> build_BasicBlock(
const std::string &name,
std::shared_ptr<Function> parent,
const BasicBlockListNode_t &cur_bb_itr
);
std::shared_ptr<InstLoad> build_InstLoad(
std::shared_ptr<Value> value,
TypePtr_t type,
std::shared_ptr<BasicBlock> parent_bb
);
std::shared_ptr<InstStore> build_InstStore(
std::shared_ptr<Value> value,
std::shared_ptr<Value> pointer,
std::shared_ptr<BasicBlock> parent_bb
);
std::shared_ptr<InstAlloca> build_InstAlloca(
const std::string &str,
TypePtr_t type,
std::shared_ptr<BasicBlock> parent_bb
);
std::shared_ptr<InstBinary> build_InstBinary(
InstTag inst_tag,
std::shared_ptr<Value> op1,
std::shared_ptr<Value> op2,
std::shared_ptr<BasicBlock> parent_bb
);
std::shared_ptr<InstZext> build_InstZext(std::shared_ptr<Value> op, std::shared_ptr<BasicBlock> parent_bb);
std::shared_ptr<InstBranch> build_InstBranch(
ValuePtr_t cond,
BasicBlockPtr_t true_block,
BasicBlockPtr_t false_block,
BasicBlockPtr_t parent_bb
);
std::shared_ptr<InstBranch> build_InstBranch(BasicBlockPtr_t target_block, BasicBlockPtr_t parent_bb);
std::shared_ptr<InstReturn> build_InstReturn(ValuePtr_t ret_val, BasicBlockPtr_t parent_bb);
std::shared_ptr<InstReturn> build_InstReturn(BasicBlockPtr_t parent_bb);
std::shared_ptr<InstCall> build_InstCall(
FunctionPtr_t func,
const std::vector<ValuePtr_t> &args,
BasicBlockPtr_t parent_bb
);
std::shared_ptr<InstGEP> build_InstGEP(
ValuePtr_t pointer,
const std::vector<ValuePtr_t> &indices,
BasicBlockPtr_t parent_bb
);
InstPhiPtr_t build_InstPhi(
TypePtr_t type,
const decltype(Function::bb_list) &incoming_vals,
BasicBlockPtr_t parent_bb,
const std::string &name
);
#pragma endregion
class Visitor : public SysyBaseVisitor {
private:
struct VisitorState {

View File

@ -79,16 +79,6 @@ static MOperand value2moperand(
return vr;
}
else if (auto glob = shared_cast<GlobalVar>(ir_value)) {
// auto itr = val2mop.find(ir_value);
// if (itr != val2mop.end()) {
// return itr->second;
// }
// auto inst_symld = MInstSymbol::New(mc_bb->parent_func->bb_list.front(), true);
// auto vr = MOperand::VirtReg(mc_bb->parent_func->virt_reg_cnt++);
// val2mop.insert({ir_value, vr});
// inst_symld->symbol = glob;
// inst_symld->dst = vr;
// return vr;
auto op_glob = MOperand::Glob(glob);
if (force_reg) {
auto inst_la = MInstMove::New(mc_bb, InsertPos::Tail);

View File

@ -147,7 +147,7 @@ std::vector<MOperand> MInstCall::get_use() const {
#pragma endregion
void MInst::PostNew(sptr(MInst) inst, MInstTag tag, sptr(MBasicBlock) parent_bb, InsertPos ins_ty) {
inst->inst_tag = tag;
inst->inst_tag = tag;
inst->parent_bb = parent_bb;
switch (ins_ty) {
case InsertPos::Head: inst->itr = parent_bb->inst_list.insert(parent_bb->inst_list.begin(), inst); break;

View File

@ -41,13 +41,13 @@ static void connect(BasicBlockPtr_t pred, BasicBlockPtr_t succ) {
static void _build_cfg(const FunctionPtr_t func) {
for (auto itr = std::next(func->bb_list.begin()); itr != func->bb_list.end();) {
auto bb = *itr;
if (bb->inst_list.size() == 1 && Value::is<InstBranch>(bb->inst_list.front())) {
auto br = Value::as<InstBranch>(bb->inst_list.front());
if (bb->inst_list.size() == 1 && shared_cast<InstBranch>(bb->inst_list.front())) {
auto br = shared_cast<InstBranch>(bb->inst_list.front());
if (br->operand_list.size() == 1) {
VLOG(6) << "remove dummy jump block:" << bb->name;
for (auto &use : bb->use_list) {
use.user->operand_list[use.op_index] = br->operand_list[0];
br->operand_list[0]->use_list.push_back({br->operand_list[0], use.user, use.op_index});
br->operand_list[0]->use_list.push_back({/*br->operand_list[0],*/ use.user, use.op_index});
}
itr = func->bb_list.erase(itr);
continue;
@ -57,14 +57,14 @@ static void _build_cfg(const FunctionPtr_t func) {
}
for (auto basicblock : func->bb_list) {
auto _inst_br = basicblock->inst_list.back();
if (!Value::is<InstBranch>(_inst_br)) continue;
auto inst_br = Value::as<InstBranch>(_inst_br);
if (!shared_cast<InstBranch>(_inst_br)) continue;
auto inst_br = shared_cast<InstBranch>(_inst_br);
if (inst_br->operand_list.size() == 1) {
connect(basicblock, Value::as<BasicBlock>(inst_br->operand_list[0]));
connect(basicblock, shared_cast<BasicBlock>(inst_br->operand_list[0]));
}
else if (inst_br->operand_list.size() == 3) {
connect(basicblock, Value::as<BasicBlock>(inst_br->operand_list[1]));
connect(basicblock, Value::as<BasicBlock>(inst_br->operand_list[2]));
connect(basicblock, shared_cast<BasicBlock>(inst_br->operand_list[1]));
connect(basicblock, shared_cast<BasicBlock>(inst_br->operand_list[2]));
}
else {
panic("br should have either 1 or 3 operands");

View File

@ -14,53 +14,40 @@ namespace CompSysY {
struct AllocaInfo {
std::vector<BasicBlockPtr_t> def_blocks = {};
std::vector<BasicBlockPtr_t> use_blocks = {};
bool only_in_1_block = true;
BasicBlockPtr_t only_block = nullptr;
InstStore *only_store = nullptr;
};
static void analyze_alloca(InstAllocaPtr_t ai, AllocaInfo &info) {
static void analyze_alloca_defuse(InstAllocaPtr_t ai, AllocaInfo &info) {
for (auto use : ai->use_list) {
auto user = dynamic_cast<Instruction *>(use.user);
if (dynamic_cast<InstStore *>(user)) {
const auto si = dynamic_cast<InstStore *>(user);
info.def_blocks.push_back(si->parent_bb);
info.only_store = si;
}
else {
assert(dynamic_cast<InstLoad *>(user));
const auto li = dynamic_cast<InstLoad *>(user);
info.use_blocks.push_back(li->parent_bb);
}
if (info.only_in_1_block) {
if (!info.only_block)
info.only_block = user->parent_bb;
else if (info.only_block != user->parent_bb)
info.only_in_1_block = false;
}
}
if (VLOG_IS_ON(6)) {
std::cout << "Alloca " << ai->name;
std::cout << " Def: [";
for (auto blk : info.def_blocks) {
std::cout << blk->name << ", ";
}
std::cout << "]\n";
std::cout << " Use: [";
for (auto blk : info.use_blocks) {
std::cout << blk->name << ", ";
}
std::cout << "]\n";
std::cout.flush();
}
}
// static bool rewrite_single_store(InstAllocaPtr_t ai, AllocaInfo& alloca_info) {
// }
static void print_alloca_defuse(InstAllocaPtr_t ai, const AllocaInfo &info) {
std::cout << "Alloca " << ai->name;
std::cout << " Def: [";
for (auto blk : info.def_blocks) {
std::cout << blk->name << ", ";
}
std::cout << "]\n";
std::cout << " Use: [";
for (auto blk : info.use_blocks) {
std::cout << blk->name << ", ";
}
std::cout << "]\n";
std::cout.flush();
}
// live in analysis
static void live_in_blocks(
static void analyze_alloca_livein(
InstAllocaPtr_t ai,
AllocaInfo &alloca_info,
const std::unordered_set<BasicBlockPtr_t> &def_blocks,
@ -74,15 +61,15 @@ static void live_in_blocks(
if (def_blocks.count(bb) == 0) continue;
for (auto itr : bb->inst_list) {
// a store to this alloca(variable) before a load, it is dead in this block
if (Value::is<InstStore>(itr) && Value::as<InstStore>(itr)->operand_list[1] == ai) {
if (shared_cast<InstStore>(itr) && shared_cast<InstStore>(itr)->operand_list[1] == ai) {
worklist[i] = worklist.back();
worklist.pop_back();
--i;
break;
}
else if (Value::is<InstLoad>(itr)) {
else if (shared_cast<InstLoad>(itr)) {
// a load before store, it live in this block
if (Value::as<InstLoad>(itr)->operand_list[0] == ai) break;
if (shared_cast<InstLoad>(itr)->operand_list[0] == ai) break;
}
}
}
@ -101,6 +88,15 @@ static void live_in_blocks(
}
}
static void print_alloca_livein(InstAllocaPtr_t ai, const std::unordered_set<BasicBlockPtr_t> &livein_blocks) {
std::cout << "Live-in blocks of " << ai->name << ": [";
for (auto livein : livein_blocks) {
std::cout << livein->name << ", ";
}
std::cout << "]\n";
std::cout.flush();
}
struct RenameInfo {
BasicBlockPtr_t bb;
BasicBlockPtr_t pred;
@ -155,8 +151,8 @@ static void print_dom_tree(BasicBlockPtr_t rt) {
// https://roife.github.io/2022/02/07/mem2reg/
// https://github.com/Enna1/LLVM-Study-Notes/blob/master/source/ssa/SSA-Construction.rst
static void _mem_2_reg(FunctionPtr_t func) {
VLOG(4) << "Run mem2reg for " << func->name;
VLOG(4) << " Gen Dominance Tree & Frontier";
LOG(TRACE) << "Run mem2reg for " << func->name;
VLOG(6) << "[mem2reg] Gen Dominance Tree & Frontier";
gen_dominance(func);
gen_dominance_frontier(func);
if (VLOG_IS_ON(6)) print_dom_tree(func->bb_list.front());
@ -170,18 +166,22 @@ static void _mem_2_reg(FunctionPtr_t func) {
for (auto bb : func->bb_list) {
for (auto inst : bb->inst_list) {
if (Value::is<InstAlloca>(inst)) {
if (shared_cast<InstAlloca>(inst)) {
// assert(inst->parent_bb == bb);
// 貌似没问题parent_bb是插入alloca的时候的那个block而alloca实际上是被插入在entry_block的
assert(bb == func->bb_list.front() && "Alloca should be at front of a func");
auto ai = Value::as<InstAlloca>(inst);
// assert(is_alloca_promotable(ai) && "Invalid alloca");
auto ai = shared_cast<InstAlloca>(inst);
// 暂时只考虑int类型的alloca, 数组和指针都先不管
if (!Type::isType<IntegerType>(get_pointed_type(ai->type))) continue;
alloca_list.push_back(ai);
}
}
}
VLOG(4) << " alloca pruning & phi insertion";
int id = 0;
for (auto bb : func->bb_list) {
bb_to_id[bb] = id++;
}
VLOG(6) << "[mem2reg] Alloca pruning & phi insertion";
for (unsigned i = 0; i != alloca_list.size(); ++i) {
auto ai = alloca_list[i];
// remove empty use
@ -192,36 +192,23 @@ static void _mem_2_reg(FunctionPtr_t func) {
--i;
continue;
}
// analyze alloca's def&use
AllocaInfo alloca_info;
analyze_alloca(ai, alloca_info);
if (alloca_info.def_blocks.size() == 1) {
LOG(WARNING) << "To rewrite single store";
}
if (alloca_info.only_in_1_block) {
LOG(WARNING) << "To promote single block alloca";
}
// numbering bb
if (bb_to_id.empty()) {
int id = 0;
for (auto bb : func->bb_list) {
bb_to_id[bb] = id++;
}
analyze_alloca_defuse(ai, alloca_info);
if (VLOG_IS_ON(6)) {
print_alloca_defuse(ai, alloca_info);
}
alloca_to_id[alloca_list[i]] = i;
std::unordered_set<BasicBlockPtr_t> def_blocks(alloca_info.def_blocks.begin(), alloca_info.def_blocks.end());
// compute alloca's livein blocks
std::unordered_set<BasicBlockPtr_t> def_blocks(BEGINEND(alloca_info.def_blocks));
std::unordered_set<BasicBlockPtr_t> livein_blocks;
live_in_blocks(ai, alloca_info, def_blocks, livein_blocks);
analyze_alloca_livein(ai, alloca_info, def_blocks, livein_blocks);
if (VLOG_IS_ON(6)) {
std::cout << "Live-in blocks of " << ai->name << ": [";
for (auto livein : livein_blocks) {
std::cout << livein->name << ", ";
}
std::cout << "]\n";
std::cout.flush();
print_alloca_livein(ai, livein_blocks);
}
// llvm use IDF to calculate phi blocks.
// But that is too complicated
// SSA book Algo 3.1
// llvm use IDF to calculate phi blocks. But that is too complicated
// SSA book Algo 3.1, with non-livein blocks skipped
// 算法本质上是对于该alloca的每个def块,在对应的支配边界上放置phi(如果放过就不放了),同时如果alloca没有在DF中用到,也会跳过
std::vector<bool> visited(func->bb_list.size(), false);
for (auto bb : def_blocks) {
worklist.push(bb);
@ -230,15 +217,13 @@ static void _mem_2_reg(FunctionPtr_t func) {
auto bb = worklist.front();
worklist.pop();
for (auto frontier : bb->DF_set) {
// LOG(DEBUG) << "visiting " << bb->name <<" : " << frontier->name;
auto frontier_index = bb_to_id.at(frontier);
if (!visited[frontier_index]) {
visited[frontier_index] = true;
// livein-block opt is workable in IDF, but not here
// if (livein_blocks.count(frontier)) {
auto inst_phi = build_InstPhi(TypeHelper::TYPE_I32, frontier->pred_list, frontier, ai->name);
phi_to_allocaid.insert({inst_phi, i});
// }
if (livein_blocks.count(frontier)) {
auto inst_phi = InstPhi::New(TypeHelper::TYPE_I32, frontier->pred_list, frontier, ai->name);
phi_to_allocaid.insert({inst_phi, i});
}
if (!def_blocks.count(frontier)) {
worklist.push(frontier);
}
@ -247,10 +232,10 @@ static void _mem_2_reg(FunctionPtr_t func) {
}
}
if (alloca_list.empty()) return;
// renaming
VLOG(4) << " variable renaming";
VLOG(6) << "[mem2reg] Variable renaming";
std::vector<ValuePtr_t> _init_values;
for (int i = 0; i < alloca_list.size(); ++i) _init_values.push_back(ConstantInt::make_shared(0));
for (int i = 0; i < alloca_list.size(); ++i) _init_values.push_back(ConstantInt::New(0));
std::vector<RenameInfo> rename_list = {{func->bb_list.front(), nullptr, _init_values}};
std::vector<bool> visited(bb_to_id.size(), 0);
while (!rename_list.empty()) {
@ -259,8 +244,8 @@ static void _mem_2_reg(FunctionPtr_t func) {
// replace block with more specific alloca
for (auto inst : rename_info.bb->inst_list) {
// phi only appear at block head
if (!Value::is<InstPhi>(inst)) break;
auto phi = Value::as<InstPhi>(inst);
if (!shared_cast<InstPhi>(inst)) break;
auto phi = shared_cast<InstPhi>(inst);
auto alloca_index = phi_to_allocaid.at(phi);
int pred_index = -1;
for (auto pred : rename_info.bb->pred_list) {
@ -276,15 +261,15 @@ static void _mem_2_reg(FunctionPtr_t func) {
for (auto itr = rename_info.bb->inst_list.begin(); itr != rename_info.bb->inst_list.end();) {
auto inst = *itr++;
// we skip non-integer alloca, they are not in our alloca_list
if (Value::is<InstAlloca>(inst) && alloca_to_id.count(Value::as<InstAlloca>(inst))) {
if (shared_cast<InstAlloca>(inst) && alloca_to_id.count(shared_cast<InstAlloca>(inst))) {
rename_info.bb->inst_list.remove(inst);
}
else if (Value::is<InstLoad>(inst)) {
auto li = Value::as<InstLoad>(inst);
if (!(Value::is<InstAlloca>(li->operand_list[0]))) {
else if (shared_cast<InstLoad>(inst)) {
auto li = shared_cast<InstLoad>(inst);
if (!(shared_cast<InstAlloca>(li->operand_list[0]))) {
continue;
}
auto ai = Value::as<InstAlloca>(li->operand_list[0]);
auto ai = shared_cast<InstAlloca>(li->operand_list[0]);
if (!Type::isType<IntegerType>(get_pointed_type(ai->type))) {
continue;
}
@ -293,12 +278,12 @@ static void _mem_2_reg(FunctionPtr_t func) {
li->u_replace_users(rename_info.value_list[alloca_index]);
inst->u_remove_from_usees();
}
else if (Value::is<InstStore>(inst)) {
auto si = Value::as<InstStore>(inst);
if (!(Value::is<InstAlloca>(si->operand_list[1]))) {
else if (shared_cast<InstStore>(inst)) {
auto si = shared_cast<InstStore>(inst);
if (!(shared_cast<InstAlloca>(si->operand_list[1]))) {
continue;
}
auto ai = Value::as<InstAlloca>(si->operand_list[1]);
auto ai = shared_cast<InstAlloca>(si->operand_list[1]);
if (!Type::isType<IntegerType>(get_pointed_type(ai->type))) {
continue;
}
@ -309,8 +294,8 @@ static void _mem_2_reg(FunctionPtr_t func) {
si->u_replace_users(nullptr);
rename_info.bb->inst_list.remove(inst);
}
else if (Value::is<InstPhi>(inst)) {
auto phi = Value::as<InstPhi>(inst);
else if (shared_cast<InstPhi>(inst)) {
auto phi = shared_cast<InstPhi>(inst);
int alloca_index = phi_to_allocaid.at(phi);
rename_info.value_list[alloca_index] = phi;
}

View File

@ -490,7 +490,7 @@ if !spilledNodes.empty() then
void PassRegAlloc::apply_coalesced(MFunction *func) {
for (auto bb : func->bb_list) {
for (auto itr = bb->inst_list.begin(); itr != bb->inst_list.end(); ) {
for (auto itr = bb->inst_list.begin(); itr != bb->inst_list.end();) {
auto inst = *itr;
auto defs = inst->get_def_ptr();
auto uses = inst->get_use_ptr();
@ -508,7 +508,7 @@ void PassRegAlloc::apply_coalesced(MFunction *func) {
continue;
}
}
++ itr;
++itr;
}
}
}

View File

@ -195,11 +195,11 @@ std::any Visitor::visitVarDef(SysyParser::VarDefContext *ctx) {
}
// local variable
else {
auto alloca_ = build_InstAlloca(var_name, TypeHelper::TYPE_I32, _state.current_bb);
auto alloca_ = InstAlloca::New(var_name, TypeHelper::TYPE_I32, _state.current_bb);
_scope_tab.push_name(var_name, alloca_);
if (ctx->initVal()) {
auto init_val = any_to_Value(visitInitVal(ctx->initVal()));
build_InstStore(init_val, alloca_, _state.current_bb);
InstStore::New(init_val, alloca_, _state.current_bb);
}
}
}
@ -214,7 +214,7 @@ std::any Visitor::visitVarDef(SysyParser::VarDefContext *ctx) {
auto array_type = ArrayType::build_from_list(dim_list);
// local array
if (_scope_tab.get_level()) {
auto alloca_ = build_InstAlloca(var_name, array_type, _state.current_bb);
auto alloca_ = InstAlloca::New(var_name, array_type, _state.current_bb);
_scope_tab.push_name(var_name, alloca_);
if (ctx->initVal()) {
_state.arr_dim_index = 0;
@ -223,21 +223,21 @@ std::any Visitor::visitVarDef(SysyParser::VarDefContext *ctx) {
_state.arr_dim_list = nullptr;
sysy_assert(_state.arr_dim_index == 0);
// Build GEP
auto base_ptr = build_InstGEP(alloca_, {CONST0, CONST0}, _state.current_bb);
auto base_ptr = InstGEP::New(alloca_, {CONST0, CONST0}, _state.current_bb);
for (int i = 1; i < dim_list.size(); ++i) {
base_ptr = build_InstGEP(base_ptr, {CONST0, CONST0}, _state.current_bb);
base_ptr = InstGEP::New(base_ptr, {CONST0, CONST0}, _state.current_bb);
}
auto inst_call = build_InstCall(
auto inst_call = InstCall::New(
_func_tab.get_name("memset").value(),
{base_ptr, CONST0, ConstantInt::make_shared(array_value.size() * 4)},
{base_ptr, CONST0, ConstantInt::New(array_value.size() * 4)},
_state.current_bb
);
// TODO: BAAU-2021 calls memset in `libc` (not sysylib) to optimize this process
if (array_value[0]) build_InstStore(array_value[0], base_ptr, _state.current_bb);
if (array_value[0]) InstStore::New(array_value[0], base_ptr, _state.current_bb);
for (int i = 1; i < array_value.size(); ++i) {
if (!array_value[i]) continue;
auto ptr = build_InstGEP(base_ptr, {ConstantInt::make_shared(i)}, _state.current_bb);
build_InstStore(array_value[i], ptr, _state.current_bb);
auto ptr = InstGEP::New(base_ptr, {ConstantInt::New(i)}, _state.current_bb);
InstStore::New(array_value[i], ptr, _state.current_bb);
}
}
// If there is no init expr, let it be
@ -287,7 +287,7 @@ std::any Visitor::visitInitVal(SysyParser::InitValContext *ctx) {
for (auto init_val : ctx->initVal()) {
if (init_val->exp()) {
auto exp_value = any_to_Value(visitInitVal(init_val));
if (_state.isGlobalIint) assert(Value::is<ConstantInt>(exp_value));
if (_state.isGlobalIint) assert(shared_cast<ConstantInt>(exp_value));
cur_arr.push_back(exp_value);
}
else {
@ -385,16 +385,16 @@ std::any Visitor::visitAddExp(SysyParser::AddExpContext *ctx) {
auto add_exp = any_to_Value(visitAddExp(ctx->addExp()));
auto mul_exp = any_to_Value(visitMulExp(ctx->mulExp()));
if (std::dynamic_pointer_cast<IntegerType>(add_exp->type)->isI1()) {
add_exp = build_InstZext(add_exp, _state.current_bb);
add_exp = InstZext::New(add_exp, _state.current_bb);
}
if (std::dynamic_pointer_cast<IntegerType>(mul_exp->type)->isI1()) {
mul_exp = build_InstZext(mul_exp, _state.current_bb);
mul_exp = InstZext::New(mul_exp, _state.current_bb);
}
if (ctx->ADD()) {
mul_exp = build_InstBinary(InstTag::Add, add_exp, mul_exp, _state.current_bb);
mul_exp = InstBinary::New(InstTag::Add, add_exp, mul_exp, _state.current_bb);
}
else if (ctx->SUB()) {
mul_exp = build_InstBinary(InstTag::Sub, add_exp, mul_exp, _state.current_bb);
mul_exp = InstBinary::New(InstTag::Sub, add_exp, mul_exp, _state.current_bb);
}
else
panic("Unreachable");
@ -430,19 +430,19 @@ std::any Visitor::visitMulExp(SysyParser::MulExpContext *ctx) {
auto mul_exp = any_to_Value(visitMulExp(ctx->mulExp()));
auto unary_exp = any_to_Value(visitUnaryExp(ctx->unaryExp()));
if (std::dynamic_pointer_cast<IntegerType>(unary_exp->type)->isI1()) {
unary_exp = build_InstZext(unary_exp, _state.current_bb);
unary_exp = InstZext::New(unary_exp, _state.current_bb);
}
if (std::dynamic_pointer_cast<IntegerType>(mul_exp->type)->isI1()) {
mul_exp = build_InstZext(mul_exp, _state.current_bb);
mul_exp = InstZext::New(mul_exp, _state.current_bb);
}
if (ctx->MUL()) {
unary_exp = build_InstBinary(InstTag::Mul, mul_exp, unary_exp, _state.current_bb);
unary_exp = InstBinary::New(InstTag::Mul, mul_exp, unary_exp, _state.current_bb);
}
else if (ctx->DIV()) {
unary_exp = build_InstBinary(InstTag::Div, mul_exp, unary_exp, _state.current_bb);
unary_exp = InstBinary::New(InstTag::Div, mul_exp, unary_exp, _state.current_bb);
}
else if (ctx->MOD()) {
unary_exp = build_InstBinary(InstTag::Mod, mul_exp, unary_exp, _state.current_bb);
unary_exp = InstBinary::New(InstTag::Mod, mul_exp, unary_exp, _state.current_bb);
}
else
panic("Unreachable");
@ -460,16 +460,16 @@ std::any Visitor::visitRelExp(SysyParser::RelExpContext *ctx) {
auto add_exp = any_to_Value(visitAddExp(ctx->addExp()));
sysy_assert(IntegerType::isIntegerTypeI32(rel_exp->type));
if (ctx->LE()) {
add_exp = build_InstBinary(InstTag::Le, rel_exp, add_exp, _state.current_bb);
add_exp = InstBinary::New(InstTag::Le, rel_exp, add_exp, _state.current_bb);
}
else if (ctx->LT()) {
add_exp = build_InstBinary(InstTag::Lt, rel_exp, add_exp, _state.current_bb);
add_exp = InstBinary::New(InstTag::Lt, rel_exp, add_exp, _state.current_bb);
}
else if (ctx->GE()) {
add_exp = build_InstBinary(InstTag::Ge, rel_exp, add_exp, _state.current_bb);
add_exp = InstBinary::New(InstTag::Ge, rel_exp, add_exp, _state.current_bb);
}
else if (ctx->GT()) {
add_exp = build_InstBinary(InstTag::Gt, rel_exp, add_exp, _state.current_bb);
add_exp = InstBinary::New(InstTag::Gt, rel_exp, add_exp, _state.current_bb);
}
else {
LOG(ERROR) << ctx->relExp()->getStart()->getLine() << ":" << ctx->relExp()->getText();
@ -492,16 +492,16 @@ std::any Visitor::visitEqExp(SysyParser::EqExpContext *ctx) {
need_zext = true;
}
if (need_zext && IntegerType::isIntegerTypeI1(eq_exp->type)) {
eq_exp = build_InstZext(eq_exp, _state.current_bb);
eq_exp = InstZext::New(eq_exp, _state.current_bb);
}
if (need_zext && IntegerType::isIntegerTypeI1(rel_exp->type)) {
rel_exp = build_InstZext(rel_exp, _state.current_bb);
rel_exp = InstZext::New(rel_exp, _state.current_bb);
}
if (ctx->EQ()) {
rel_exp = build_InstBinary(InstTag::Eq, eq_exp, rel_exp, _state.current_bb);
rel_exp = InstBinary::New(InstTag::Eq, eq_exp, rel_exp, _state.current_bb);
}
else if (ctx->NE()) {
rel_exp = build_InstBinary(InstTag::Ne, eq_exp, rel_exp, _state.current_bb);
rel_exp = InstBinary::New(InstTag::Ne, eq_exp, rel_exp, _state.current_bb);
}
else
panic("Unreachable");
@ -521,15 +521,15 @@ std::any Visitor::visitEqExp(SysyParser::EqExpContext *ctx) {
std::any Visitor::visitLAndExp(SysyParser::LAndExpContext *ctx) {
auto eq_exp_list = ctx->eqExp();
for (int i = 0; i < eq_exp_list.size(); ++i) {
auto next_block = build_BasicBlock("", _state.current_func, _state.current_bb->itr);
auto next_block = BasicBlock::New("", _state.current_func, _state.current_bb->itr);
auto eq_exp = any_to_Value(visitEqExp(eq_exp_list[i]));
auto condition = eq_exp;
if (!IntegerType::isIntegerTypeI1(eq_exp->type))
condition = build_InstBinary(InstTag::Ne, eq_exp, CONST0, _state.current_bb);
build_InstBranch(condition, next_block, ctx->false_block, _state.current_bb);
condition = InstBinary::New(InstTag::Ne, eq_exp, CONST0, _state.current_bb);
InstBranch::New(condition, next_block, ctx->false_block, _state.current_bb);
_state.current_bb = next_block;
}
build_InstBranch(ctx->true_block, _state.current_bb);
InstBranch::New(ctx->true_block, _state.current_bb);
return {};
}
@ -540,7 +540,7 @@ std::any Visitor::visitLOrExp(SysyParser::LOrExpContext *ctx) {
auto and_exp_list = ctx->lAndExp();
auto n_and_exp = and_exp_list.size();
for (int i = 0; i < n_and_exp - 1; ++i) {
auto next_block = build_BasicBlock("", _state.current_func, _state.current_bb->itr);
auto next_block = BasicBlock::New("", _state.current_func, _state.current_bb->itr);
ctx->lAndExp(i)->true_block = ctx->true_block;
ctx->lAndExp(i)->false_block = next_block;
visitLAndExp(and_exp_list[i]);
@ -588,18 +588,18 @@ std::any Visitor::visitUnaryExp(SysyParser::UnaryExpContext *ctx) {
auto unary_exp = any_to_Value(_result);
sysy_assert(unary_exp->type->type_tag == Type::TypeTag::IntegerType);
if (std::dynamic_pointer_cast<IntegerType>(unary_exp->type)->isI1()) {
unary_exp = build_InstZext(unary_exp, _state.current_bb);
unary_exp = InstZext::New(unary_exp, _state.current_bb);
}
if (ctx->unaryOp()->NOT()) {
// should eval to i1
sysy_assert(_state.isCondExp);
return build_InstBinary(InstTag::Eq, unary_exp, CONST0, _state.current_bb);
return InstBinary::New(InstTag::Eq, unary_exp, CONST0, _state.current_bb);
}
else if (ctx->unaryOp()->ADD()) {
return unary_exp;
}
else if (ctx->unaryOp()->SUB()) {
return build_InstBinary(InstTag::Sub, CONST0, unary_exp, _state.current_bb);
return InstBinary::New(InstTag::Sub, CONST0, unary_exp, _state.current_bb);
}
}
else if (ctx->IDENT()) {
@ -625,7 +625,7 @@ std::any Visitor::visitUnaryExp(SysyParser::UnaryExpContext *ctx) {
args.push_back(exp);
}
}
return build_InstCall(func, args, _state.current_bb);
return InstCall::New(func, args, _state.current_bb);
}
else if (ctx->primaryExp()) {
return visitPrimaryExp(ctx->primaryExp());
@ -675,7 +675,7 @@ std::any Visitor::visitPrimaryExp(SysyParser::PrimaryExpContext *ctx) {
// LOG(WARNING) << "lval type is pointer: " << lval->type->type_tag;
// should be InstAlloca
auto ptr_type = std::dynamic_pointer_cast<PointerType>(lval->type);
return build_InstLoad(lval, ptr_type->pointed_type, _state.current_bb);
return InstLoad::New(lval, ptr_type->pointed_type, _state.current_bb);
}
}
}
@ -704,7 +704,7 @@ std::any Visitor::visitIntConst(SysyParser::IntConstContext *ctx) {
else if (ctx->OCTAL_CONST()) {
const_int = std::stol(ctx->OCTAL_CONST()->getText(), nullptr, 8);
}
return build_ConstantInt("", const_int);
return ConstantInt::New(const_int);
}
// lVal: IDENT ('[' exp ']')*;
@ -737,7 +737,7 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
auto gep = lval;
for (auto exp_ctx : ctx->exp()) {
auto exp = any_to_Value(visitExp(exp_ctx));
gep = build_InstGEP(gep, {exp}, _state.current_bb);
gep = InstGEP::New(gep, {exp}, _state.current_bb);
}
return gep;
}
@ -748,22 +748,22 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
// @retval: InstLoad
LOG(WARNING) << "Unexpected pointer";
auto pointed_type = std::dynamic_pointer_cast<PointerType>(lval->type)->pointed_type;
auto inst_load = build_InstLoad(lval, pointed_type, _state.current_bb);
auto inst_load = InstLoad::New(lval, pointed_type, _state.current_bb);
return inst_load;
}
else {
// fparam array, whose first dim is represented by a pointer
#if 0
auto pointed_type = Type::asType<PointerType>(lval->type)->pointed_type;
auto inst_load = build_InstLoad(lval, pointed_type, _state.current_bb);
auto inst_load = InstLoad::New(lval, pointed_type, _state.current_bb);
auto exp_list = ctx->exp();
if (exp_list.size() == 1) {
auto exp_val = any_to_Value(visitExp(exp_list[0]));
auto ptr = build_InstGEP(inst_load, {exp_val}, _state.current_bb);
auto ptr = InstGEP::New(inst_load, {exp_val}, _state.current_bb);
pointed_type = Type::asType<PointerType>(ptr->type)->pointed_type;
return ptr;
}
auto ptr = build_InstGEP(inst_load, {CONST0}, _state.current_bb);
auto ptr = InstGEP::New(inst_load, {CONST0}, _state.current_bb);
pointed_type = Type::asType<PointerType>(ptr->type)->pointed_type;
ValuePtr_t offset = ConstantInt::make_shared(0);
assert(Type::isType<ArrayType>(pointed_type));
@ -774,42 +774,42 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
auto array_type = std::dynamic_pointer_cast<ArrayType>(pointed_type);
auto exp_val = any_to_Value(visitExp(exp_list[i]));
auto dim_size = ConstantInt::make_shared(array_type->element_count);
auto inst_add = build_InstBinary(InstTag::Add, offset, exp_val, _state.current_bb);
auto inst_mul = build_InstBinary(InstTag::Mul, inst_add, dim_size, _state.current_bb);
auto inst_add = InstBinary::New(InstTag::Add, offset, exp_val, _state.current_bb);
auto inst_mul = InstBinary::New(InstTag::Mul, inst_add, dim_size, _state.current_bb);
offset = inst_mul;
pointed_type = array_type->element_type;
ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb);
ptr = InstGEP::New(ptr, {CONST0, CONST0}, _state.current_bb);
}
// visit the last dimension, mul is not needed
auto exp_val = any_to_Value(visitExp(exp_list.back()));
auto inst_add = build_InstBinary(InstTag::Add, offset, exp_val, _state.current_bb);
auto inst_add = InstBinary::New(InstTag::Add, offset, exp_val, _state.current_bb);
offset = inst_add; // finally, we get the offset
pointed_type = std::dynamic_pointer_cast<PointerType>(ptr->type)->pointed_type;
if (shared_cast<IntegerType>(pointed_type)) {
// return the address of the array element
auto arr_elem_ptr = build_InstGEP(ptr, {offset}, _state.current_bb);
auto arr_elem_ptr = InstGEP::New(ptr, {offset}, _state.current_bb);
return arr_elem_ptr;
}
else {
LOG(WARNING) << "Should be int";
auto arr_ptr = build_InstGEP(ptr, {CONST0, offset}, _state.current_bb);
auto arr_ptr = InstGEP::New(ptr, {CONST0, offset}, _state.current_bb);
return arr_ptr;
}
#else
// for array type in fparam, say a[][5][4], the type looks like:
// alloca->pointer->array[5x4]->array[4]
auto exp_list = ctx->exp();
auto inst_load = build_InstLoad(lval, lval_pointed_type, _state.current_bb);
auto inst_load = InstLoad::New(lval, lval_pointed_type, _state.current_bb);
ValuePtr_t ptr = inst_load;
auto exp_val = any_to_Value(visitExp(exp_list.front()));
ptr = build_InstGEP(ptr, {exp_val}, _state.current_bb);
ptr = InstGEP::New(ptr, {exp_val}, _state.current_bb);
for (int i = 1; i < exp_list.size(); ++i) {
auto exp_val = any_to_Value(visitExp(exp_list[i]));
ptr = build_InstGEP(ptr, {CONST0, exp_val}, _state.current_bb);
ptr = InstGEP::New(ptr, {CONST0, exp_val}, _state.current_bb);
}
if (Type::isType<ArrayType>(get_pointed_type(ptr->type))) {
ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb);
ptr = InstGEP::New(ptr, {CONST0, CONST0}, _state.current_bb);
}
return ptr;
#endif
@ -819,7 +819,7 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
// get &array[0]
#if 0
auto exp_list = ctx->exp();
auto ptr = build_InstGEP(lval, {CONST0, CONST0}, _state.current_bb);
auto ptr = InstGEP::New(lval, {CONST0, CONST0}, _state.current_bb);
auto pointed_type = std::dynamic_pointer_cast<PointerType>(ptr->type)->pointed_type;
ValuePtr_t offset = ConstantInt::make_shared(0);
// calculate offset by hand: offset = (offset + exp[i]) * dim_size[i]
@ -828,27 +828,27 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
auto array_type = std::dynamic_pointer_cast<ArrayType>(pointed_type);
auto exp_val = any_to_Value(visitExp(exp_list[i]));
auto dim_size = ConstantInt::make_shared(array_type->element_count);
auto inst_add = build_InstBinary(InstTag::Add, offset, exp_val, _state.current_bb);
auto inst_mul = build_InstBinary(InstTag::Mul, inst_add, dim_size, _state.current_bb);
auto inst_add = InstBinary::New(InstTag::Add, offset, exp_val, _state.current_bb);
auto inst_mul = InstBinary::New(InstTag::Mul, inst_add, dim_size, _state.current_bb);
offset = inst_mul;
pointed_type = array_type->element_type;
ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb);
ptr = InstGEP::New(ptr, {CONST0, CONST0}, _state.current_bb);
}
auto exp_val = any_to_Value(visitExp(exp_list.back()));
auto inst_add = build_InstBinary(InstTag::Add, offset, exp_val, _state.current_bb);
auto inst_add = InstBinary::New(InstTag::Add, offset, exp_val, _state.current_bb);
offset = inst_add; // finally, we get the offset
pointed_type = std::dynamic_pointer_cast<PointerType>(ptr->type)->pointed_type;
if (shared_cast<IntegerType>(pointed_type)) {
// return the address of the array element
auto arr_elem_ptr = build_InstGEP(ptr, {offset}, _state.current_bb);
auto arr_elem_ptr = InstGEP::New(ptr, {offset}, _state.current_bb);
return arr_elem_ptr;
}
else {
// return the address of an sub array
auto array_type = std::dynamic_pointer_cast<ArrayType>(pointed_type);
auto dim_size = ConstantInt::make_shared(array_type->element_count);
offset = build_InstBinary(InstTag::Mul, offset, dim_size, _state.current_bb);
auto arr_elem_ptr = build_InstGEP(ptr, {CONST0, offset}, _state.current_bb);
offset = InstBinary::New(InstTag::Mul, offset, dim_size, _state.current_bb);
auto arr_elem_ptr = InstGEP::New(ptr, {CONST0, offset}, _state.current_bb);
return arr_elem_ptr;
}
#else
@ -856,10 +856,10 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
ValuePtr_t ptr = lval;
for (int i = 0; i < exp_list.size(); ++i) {
auto exp_val = any_to_Value(visitExp(exp_list[i]));
ptr = build_InstGEP(ptr, {CONST0, exp_val}, _state.current_bb);
ptr = InstGEP::New(ptr, {CONST0, exp_val}, _state.current_bb);
}
if (Type::isType<ArrayType>(get_pointed_type(ptr->type))) {
ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb);
ptr = InstGEP::New(ptr, {CONST0, CONST0}, _state.current_bb);
}
return ptr;
#endif
@ -881,7 +881,7 @@ std::any Visitor::visitFuncDef(SysyParser::FuncDefContext *ctx) {
auto func_obj = std::make_shared<Function>(func_name, func_ret_type);
module.function_list.push_back(func_obj);
_func_tab.push_name(func_name, func_obj);
auto basic_block = build_BasicBlock(func_name + "_ENTRY", func_obj, func_obj->bb_list.begin());
auto basic_block = BasicBlock::New(func_name + "_ENTRY", func_obj, func_obj->bb_list.begin());
_scope_tab.enter_scope(true);
_state.current_func = func_obj;
_state.current_bb = basic_block;
@ -898,12 +898,12 @@ std::any Visitor::visitFuncDef(SysyParser::FuncDefContext *ctx) {
if (func_obj->bb_list.back()->inst_list.size() == 0 && func_obj->bb_list.back()->name == "after_ret") {
func_obj->bb_list.pop_back();
}
if (func_obj->bb_list.back()->inst_list.size() == 0 || !Value::is<InstReturn>(func_obj->bb_list.back()->inst_list.back())) {
if (func_obj->bb_list.back()->inst_list.size() == 0 || !shared_cast<InstReturn>(func_obj->bb_list.back()->inst_list.back())) {
if (func_ret_type->type_tag == Type::TypeTag::VoidType) {
build_InstReturn(_state.current_bb);
InstReturn::New(_state.current_bb);
}
else {
build_InstReturn(CONST0, _state.current_bb);
InstReturn::New(CONST0, _state.current_bb);
}
}
return {};
@ -916,8 +916,8 @@ std::any Visitor::visitFuncFParams(SysyParser::FuncFParamsContext *ctx) {
auto fparam_type = any_to_Type(visitFuncFParam(fparam_ctx));
auto fparam_name = fparam_ctx->IDENT()->getText();
auto fparam = std::make_shared<FParam>(fparam_name, fparam_type);
auto alloca_ = build_InstAlloca(fparam_name, fparam_type, _state.current_bb);
build_InstStore(fparam, alloca_, _state.current_bb);
auto alloca_ = InstAlloca::New(fparam_name, fparam_type, _state.current_bb);
InstStore::New(fparam, alloca_, _state.current_bb);
_scope_tab.push_name(fparam_name, alloca_);
_state.current_func->fparam_list.push_back(fparam);
}
@ -973,7 +973,7 @@ stmt: lVal '=' exp ';' # assignStmt
std::any Visitor::visitAssignStmt(SysyParser::AssignStmtContext *ctx) {
auto lval = any_to_Value(visitLVal(ctx->lVal()));
auto rhs = any_to_Value(visitExp(ctx->exp()));
auto store = build_InstStore(rhs, lval, _state.current_bb);
auto store = InstStore::New(rhs, lval, _state.current_bb);
return {};
}
@ -981,11 +981,11 @@ std::any Visitor::visitAssignStmt(SysyParser::AssignStmtContext *ctx) {
std::any Visitor::visitIfStmt(SysyParser::IfStmtContext *ctx) {
VLOG(5) << "Visiting IfStmt "
<< "; lineno=" << ctx->getStart()->getLine();
auto true_block = build_BasicBlock("_then", _state.current_func, _state.current_bb->itr);
auto next_block = build_BasicBlock("_next", _state.current_func, true_block->itr);
auto true_block = BasicBlock::New("_then", _state.current_func, _state.current_bb->itr);
auto next_block = BasicBlock::New("_next", _state.current_func, true_block->itr);
auto false_block = next_block;
if (ctx->ELSE()) {
false_block = build_BasicBlock("_else", _state.current_func, true_block->itr);
false_block = BasicBlock::New("_else", _state.current_func, true_block->itr);
}
ctx->cond()->lOrExp()->true_block = true_block;
ctx->cond()->lOrExp()->false_block = false_block;
@ -993,11 +993,11 @@ std::any Visitor::visitIfStmt(SysyParser::IfStmtContext *ctx) {
_state.current_bb = true_block;
visit(ctx->stmt(0));
build_InstBranch(next_block, _state.current_bb); // use current_bb, god knows what happened
InstBranch::New(next_block, _state.current_bb); // use current_bb, god knows what happened
if (ctx->ELSE()) {
_state.current_bb = false_block;
visit(ctx->stmt(1));
build_InstBranch(next_block, _state.current_bb);
InstBranch::New(next_block, _state.current_bb);
}
_state.current_bb = next_block;
return {};
@ -1008,10 +1008,10 @@ std::any Visitor::visitWhileStmt(SysyParser::WhileStmtContext *ctx) {
VLOG(5) << "Visiting WhileStmt "
<< "; lineno=" << ctx->getStart()->getLine();
auto while_id = std::to_string(_state.loop_stmt_count);
auto cond_block = build_BasicBlock("_loop_cond_" + while_id, _state.current_func, _state.current_bb->itr);
auto body_block = build_BasicBlock("_loop_body_" + while_id, _state.current_func, cond_block->itr);
auto next_block = build_BasicBlock("_loop_exit_" + while_id, _state.current_func, body_block->itr);
build_InstBranch(cond_block, _state.current_bb);
auto cond_block = BasicBlock::New("_loop_cond_" + while_id, _state.current_func, _state.current_bb->itr);
auto body_block = BasicBlock::New("_loop_body_" + while_id, _state.current_func, cond_block->itr);
auto next_block = BasicBlock::New("_loop_exit_" + while_id, _state.current_func, body_block->itr);
InstBranch::New(cond_block, _state.current_bb);
_state.loop_stack.push_back({cond_block, body_block, next_block, _state.loop_stmt_count++});
// condition
ctx->cond()->lOrExp()->true_block = body_block;
@ -1021,7 +1021,7 @@ std::any Visitor::visitWhileStmt(SysyParser::WhileStmtContext *ctx) {
// body
_state.current_bb = body_block;
visit(ctx->stmt());
build_InstBranch(cond_block, _state.current_bb);
InstBranch::New(cond_block, _state.current_bb);
// exit
_state.loop_stack.pop_back();
_state.current_bb = next_block;
@ -1030,27 +1030,27 @@ std::any Visitor::visitWhileStmt(SysyParser::WhileStmtContext *ctx) {
std::any Visitor::visitBreakStmt(SysyParser::BreakStmtContext *ctx) {
sysy_assert(!_state.loop_stack.empty());
build_InstBranch(_state.loop_stack.back().next, _state.current_bb);
_state.current_bb = build_BasicBlock("_after_break", _state.current_func, _state.current_bb->itr);
InstBranch::New(_state.loop_stack.back().next, _state.current_bb);
_state.current_bb = BasicBlock::New("_after_break", _state.current_func, _state.current_bb->itr);
return {};
}
std::any Visitor::visitContinueStmt(SysyParser::ContinueStmtContext *ctx) {
sysy_assert(!_state.loop_stack.empty());
build_InstBranch(_state.loop_stack.back().cond, _state.current_bb);
_state.current_bb = build_BasicBlock("_after_continue", _state.current_func, _state.current_bb->itr);
InstBranch::New(_state.loop_stack.back().cond, _state.current_bb);
_state.current_bb = BasicBlock::New("_after_continue", _state.current_func, _state.current_bb->itr);
return {};
}
std::any Visitor::visitReturnStmt(SysyParser::ReturnStmtContext *ctx) {
if (ctx->exp()) {
auto exp = any_to_Value(visitExp(ctx->exp()));
build_InstReturn(exp, _state.current_bb);
InstReturn::New(exp, _state.current_bb);
}
else {
build_InstReturn(_state.current_bb);
InstReturn::New(_state.current_bb);
}
auto new_bb = build_BasicBlock("after_ret", _state.current_func, _state.current_bb->itr);
auto new_bb = BasicBlock::New("after_ret", _state.current_func, _state.current_bb->itr);
_state.current_bb = new_bb;
return {};
}

View File

@ -1,155 +0,0 @@
#include "common.h"
#include "llir.h"
#include "visitor.h"
#include <cassert>
#include <memory>
namespace CompSysY {
std::shared_ptr<ConstantInt> build_ConstantInt(const std::string &name, int value) {
auto lala = std::make_shared<ConstantInt>(name, value);
return lala;
}
std::shared_ptr<BasicBlock> build_BasicBlock(
const std::string &name,
std::shared_ptr<Function> parent,
const BasicBlockListNode_t &cur_bb_itr
) {
static int count = 0;
auto basic_block = std::make_shared<BasicBlock>("blk" + std::to_string(count++), parent);
basic_block->itr = parent->bb_list.insert(std::next(cur_bb_itr), basic_block);
return basic_block;
}
std::shared_ptr<InstLoad> build_InstLoad(
std::shared_ptr<Value> value,
TypePtr_t type,
std::shared_ptr<BasicBlock> parent_bb
) {
auto inst = std::make_shared<InstLoad>(value, type, parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
std::shared_ptr<InstStore> build_InstStore(
std::shared_ptr<Value> value,
std::shared_ptr<Value> pointer,
std::shared_ptr<BasicBlock> parent_bb
) {
auto inst = std::make_shared<InstStore>(value, pointer, parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
// a little bit different, we put all alloca in the head of each basic block
std::shared_ptr<InstAlloca> build_InstAlloca(
const std::string &name,
TypePtr_t type,
std::shared_ptr<BasicBlock> parent_bb
) {
auto inst = std::make_shared<InstAlloca>(type, parent_bb);
inst->name = name;
auto func_head_bb = parent_bb->parent->bb_list.front();
inst->inst_itr = func_head_bb->inst_list.insert(func_head_bb->inst_list.begin(), inst);
// parent_bb->inst_list.push_back(inst_alloca);
return inst;
}
std::shared_ptr<InstBinary> build_InstBinary(
InstTag inst_tag,
std::shared_ptr<Value> op1,
std::shared_ptr<Value> op2,
std::shared_ptr<BasicBlock> parent_bb
) {
std::shared_ptr<InstBinary> inst;
if (InstTag::Lt <= inst_tag && inst_tag <= InstTag::Ne) {
inst = std::make_shared<InstBinary>(inst_tag, TypeHelper::TYPE_I1, op1, op2, parent_bb);
}
else if (InstTag::Add <= inst_tag && inst_tag <= InstTag::Div) {
inst = std::make_shared<InstBinary>(inst_tag, TypeHelper::TYPE_I32, op1, op2, parent_bb);
}
else {
panic("Invalid Binary Operation");
}
assert(Type::isType<IntegerType>(op1->type));
assert(Type::isType<IntegerType>(op2->type));
if (!(Type::asType<IntegerType>(op1->type)->int_type == Type::asType<IntegerType>(op2->type)->int_type)) {
if (!(Value::is<ConstantInt>(op1) && Value::as<ConstantInt>(op1)->value == 0)
&& !(Value::is<ConstantInt>(op2) && Value::as<ConstantInt>(op2)->value == 0)) {
LOG(ERROR) << op1->to_string() << ",\t" << op2->to_string();
assert(0);
}
}
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
std::shared_ptr<InstZext> build_InstZext(std::shared_ptr<Value> op, std::shared_ptr<BasicBlock> parent_bb) {
auto inst = std::make_shared<InstZext>(op, parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
std::shared_ptr<InstBranch> build_InstBranch(
ValuePtr_t cond,
BasicBlockPtr_t true_block,
BasicBlockPtr_t false_block,
BasicBlockPtr_t parent_bb
) {
auto inst = std::make_shared<InstBranch>(cond, true_block, false_block, parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
std::shared_ptr<InstBranch> build_InstBranch(BasicBlockPtr_t target_block, BasicBlockPtr_t parent_bb) {
auto inst = std::make_shared<InstBranch>(target_block, parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
std::shared_ptr<InstReturn> build_InstReturn(ValuePtr_t ret_val, BasicBlockPtr_t parent_bb) {
auto inst = std::make_shared<InstReturn>(ret_val, parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
std::shared_ptr<InstReturn> build_InstReturn(BasicBlockPtr_t parent_bb) {
auto inst = std::make_shared<InstReturn>(parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
std::shared_ptr<InstCall> build_InstCall(
FunctionPtr_t func,
const std::vector<ValuePtr_t> &args,
BasicBlockPtr_t parent_bb
) {
auto inst = std::make_shared<InstCall>(func, args, parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
std::shared_ptr<InstGEP> build_InstGEP(
ValuePtr_t pointer,
const std::vector<ValuePtr_t> &indices,
BasicBlockPtr_t parent_bb
) {
auto inst = std::make_shared<InstGEP>(pointer, indices, parent_bb);
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.end(), inst);
return inst;
}
InstPhiPtr_t build_InstPhi(
TypePtr_t type,
const decltype(Function::bb_list) &incoming_vals,
BasicBlockPtr_t parent_bb,
const std::string &name
) {
auto inst = std::make_shared<InstPhi>(type, incoming_vals, parent_bb);
inst->name = name;
inst->inst_itr = parent_bb->inst_list.insert(parent_bb->inst_list.begin(), inst);
return inst;
}
} // namespace CompSysY

View File

@ -104,11 +104,9 @@ static void _build_arr_init_list(
static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &block_list, int reg_count) {
// first pass, allocate sequence number
for (auto block_itr = block_list.begin(); block_itr != block_list.end(); ++block_itr) {
auto block = *block_itr;
sysy_assert(block->ir_seqno == -1); // multi-alloc is error
auto block = *block_itr;
block->ir_seqno = reg_count++;
for (auto inst : block->inst_list) {
sysy_assert(inst->ir_seqno == -1); // multi-alloc is error
switch (inst->tag) {
// These are not to get a seqno
case InstTag::Br:
@ -160,22 +158,22 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
VLOG(7) << "Build inst" << _inst->ir_seqno << ": " << _inst->to_string();
switch (_inst->tag) {
case InstTag::Br: {
auto inst = Value::as<InstBranch>(_inst);
auto inst = shared_cast<InstBranch>(_inst);
assert(inst->ir_seqno == -1);
ostr << "br ";
if (inst->operand_list.size() == 1) {
assert(Value::is<BasicBlock>(inst->operand_list[0]));
auto bb_dest = Value::as<BasicBlock>(inst->operand_list[0]);
assert(shared_cast<BasicBlock>(inst->operand_list[0]));
auto bb_dest = shared_cast<BasicBlock>(inst->operand_list[0]);
VLOG(7) << "br to " << bb_dest->name;
assert(bb_dest->ir_seqno >= 0);
ostr << "label %" << bb_dest->ir_seqno;
}
else {
assert(Value::is<Instruction>(inst->operand_list[0]));
assert(shared_cast<Instruction>(inst->operand_list[0]));
assert(Type::isType<IntegerType>(inst->operand_list[0]->type));
auto cond = Value::as<Instruction>(inst->operand_list[0]);
auto bb_true = Value::as<BasicBlock>(inst->operand_list[1]);
auto bb_false = Value::as<BasicBlock>(inst->operand_list[2]);
auto cond = shared_cast<Instruction>(inst->operand_list[0]);
auto bb_true = shared_cast<BasicBlock>(inst->operand_list[1]);
auto bb_false = shared_cast<BasicBlock>(inst->operand_list[2]);
if (!Type::asType<IntegerType>(cond->type)->isI1()) {
LOG(ERROR) << "Expect cond evals to i1: " << cond->to_string();
panic("Grammar check");
@ -188,7 +186,7 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
break;
}
case InstTag::Ret: {
auto inst = Value::as<InstReturn>(_inst);
auto inst = shared_cast<InstReturn>(_inst);
assert(inst->ir_seqno == -1);
ostr << "ret ";
if (inst->operand_list.size() == 0) {
@ -196,17 +194,17 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
ostr << "void";
}
else {
if (Value::is<Instruction>(inst->operand_list[0])) {
auto op0 = Value::as<Instruction>(inst->operand_list[0]);
if (shared_cast<Instruction>(inst->operand_list[0])) {
auto op0 = shared_cast<Instruction>(inst->operand_list[0]);
assert(op0->ir_seqno >= 0);
ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno;
}
else if (Value::is<ConstantInt>(inst->operand_list[0])) {
auto op0 = Value::as<ConstantInt>(inst->operand_list[0]);
else if (shared_cast<ConstantInt>(inst->operand_list[0])) {
auto op0 = shared_cast<ConstantInt>(inst->operand_list[0]);
ostr << op0->to_IR_string();
}
else if (Value::is<FParam>(inst->operand_list[0])) {
auto op0 = Value::as<FParam>(inst->operand_list[0]);
else if (shared_cast<FParam>(inst->operand_list[0])) {
auto op0 = shared_cast<FParam>(inst->operand_list[0]);
ostr << op0->to_IR_string();
}
else {
@ -217,38 +215,38 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
break;
}
case InstTag::Store: {
auto inst = Value::as<InstStore>(_inst);
auto inst = shared_cast<InstStore>(_inst);
assert(inst->ir_seqno == -1);
ostr << "store ";
if (Value::is<Instruction>(inst->operand_list[0])) {
auto op0 = Value::as<Instruction>(inst->operand_list[0]);
if (shared_cast<Instruction>(inst->operand_list[0])) {
auto op0 = shared_cast<Instruction>(inst->operand_list[0]);
assert(op0->ir_seqno >= 0);
ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno << ", ";
}
else if (Value::is<ConstantInt>(inst->operand_list[0])) {
auto op0 = Value::as<ConstantInt>(inst->operand_list[0]);
else if (shared_cast<ConstantInt>(inst->operand_list[0])) {
auto op0 = shared_cast<ConstantInt>(inst->operand_list[0]);
ostr << op0->to_IR_string() << ", ";
}
else if (Value::is<FParam>(inst->operand_list[0])) {
auto op0 = Value::as<FParam>(inst->operand_list[0]);
else if (shared_cast<FParam>(inst->operand_list[0])) {
auto op0 = shared_cast<FParam>(inst->operand_list[0]);
ostr << op0->to_IR_string() << ", ";
}
else {
LOG(ERROR) << "Unexpected type of op0: " << inst->operand_list[0]->to_string();
assert(0);
}
if (Value::is<GlobalVar>(inst->operand_list[1])) {
auto op1 = Value::as<GlobalVar>(inst->operand_list[1]);
if (shared_cast<GlobalVar>(inst->operand_list[1])) {
auto op1 = shared_cast<GlobalVar>(inst->operand_list[1]);
ostr << op1->type->to_IR_string() << " @" << op1->name;
}
else if (Value::is<Instruction>(inst->operand_list[1])) {
auto op1 = Value::as<Instruction>(inst->operand_list[1]);
else if (shared_cast<Instruction>(inst->operand_list[1])) {
auto op1 = shared_cast<Instruction>(inst->operand_list[1]);
assert(op1->ir_seqno >= 0);
ostr << op1->type->to_IR_string() << " %" << op1->ir_seqno;
}
else if (Value::is<FParam>(inst->operand_list[0])) {
auto op0 = Value::as<FParam>(inst->operand_list[0]);
else if (shared_cast<FParam>(inst->operand_list[0])) {
auto op0 = shared_cast<FParam>(inst->operand_list[0]);
ostr << op0->to_IR_string();
}
else {
@ -260,9 +258,9 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
}
// Call's seqno is dependent on its return type
case InstTag::Call: {
auto inst = Value::as<InstCall>(_inst);
auto inst = shared_cast<InstCall>(_inst);
LOG(DEBUG) << inst->operand_list[0]->to_string();
auto func = Value::as<Function>(inst->operand_list[0]);
auto func = shared_cast<Function>(inst->operand_list[0]);
auto func_type = Type::asType<FunctionType>(func->type);
if (Type::isType<VoidType>(func_type->return_type)) {
assert(inst->ir_seqno == -1);
@ -275,17 +273,17 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
ostr << func->name << "(";
if (inst->operand_list.size() > 1) {
for (int i = 1; i < inst->operand_list.size(); ++i) {
if (Value::is<Instruction>(inst->operand_list[i])) {
auto op0 = Value::as<Instruction>(inst->operand_list[i]);
if (shared_cast<Instruction>(inst->operand_list[i])) {
auto op0 = shared_cast<Instruction>(inst->operand_list[i]);
assert(op0->ir_seqno >= 0);
ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno;
}
else if (Value::is<ConstantInt>(inst->operand_list[i])) {
auto op0 = Value::as<ConstantInt>(inst->operand_list[i]);
else if (shared_cast<ConstantInt>(inst->operand_list[i])) {
auto op0 = shared_cast<ConstantInt>(inst->operand_list[i]);
ostr << op0->to_IR_string();
}
else if (Value::is<FParam>(inst->operand_list[i])) {
auto op0 = Value::as<FParam>(inst->operand_list[i]);
else if (shared_cast<FParam>(inst->operand_list[i])) {
auto op0 = shared_cast<FParam>(inst->operand_list[i]);
ostr << op0->to_IR_string();
}
else {
@ -312,36 +310,36 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
case InstTag::Ne:
{
auto inst = Value::as<InstBinary>(_inst);
auto inst = shared_cast<InstBinary>(_inst);
ostr << "%" << inst->ir_seqno << " = " << inst->tag_string() << " ";
if (Value::is<Instruction>(inst->operand_list[0])) {
auto op0 = Value::as<Instruction>(inst->operand_list[0]);
if (shared_cast<Instruction>(inst->operand_list[0])) {
auto op0 = shared_cast<Instruction>(inst->operand_list[0]);
assert(op0->ir_seqno >= 0);
ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno << ", ";
}
else if (Value::is<ConstantInt>(inst->operand_list[0])) {
auto op0 = Value::as<ConstantInt>(inst->operand_list[0]);
else if (shared_cast<ConstantInt>(inst->operand_list[0])) {
auto op0 = shared_cast<ConstantInt>(inst->operand_list[0]);
ostr << op0->to_IR_string() << ", ";
}
else if (Value::is<FParam>(inst->operand_list[0])) {
auto op0 = Value::as<FParam>(inst->operand_list[0]);
else if (shared_cast<FParam>(inst->operand_list[0])) {
auto op0 = shared_cast<FParam>(inst->operand_list[0]);
ostr << op0->to_IR_string() << ", ";
}
else {
LOG(ERROR) << "Unexpected type of op0: " << inst->operand_list[0]->to_string();
assert(0);
}
if (Value::is<Instruction>(inst->operand_list[1])) {
auto op1 = Value::as<Instruction>(inst->operand_list[1]);
if (shared_cast<Instruction>(inst->operand_list[1])) {
auto op1 = shared_cast<Instruction>(inst->operand_list[1]);
assert(op1->ir_seqno >= 0);
ostr << "%" << op1->ir_seqno;
}
else if (Value::is<ConstantInt>(inst->operand_list[1])) {
auto op1 = Value::as<ConstantInt>(inst->operand_list[1]);
else if (shared_cast<ConstantInt>(inst->operand_list[1])) {
auto op1 = shared_cast<ConstantInt>(inst->operand_list[1]);
ostr << op1->value;
}
else if (Value::is<FParam>(inst->operand_list[1])) {
auto op1 = Value::as<FParam>(inst->operand_list[1]);
else if (shared_cast<FParam>(inst->operand_list[1])) {
auto op1 = shared_cast<FParam>(inst->operand_list[1]);
ostr << "%" << op1->ir_seqno;
}
else {
@ -351,21 +349,20 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
break;
}
case InstTag::Load: {
auto inst = Value::as<InstLoad>(_inst);
assert(inst->ir_seqno != -1);
auto inst = shared_cast<InstLoad>(_inst);
assert(Type::isType<PointerType>(inst->operand_list[0]->type));
ostr << "%" << inst->ir_seqno << " = load " << inst->type->to_IR_string() << ", ";
if (Value::is<GlobalVar>(inst->operand_list[0])) {
auto op = Value::as<GlobalVar>(inst->operand_list[0]);
if (shared_cast<GlobalVar>(inst->operand_list[0])) {
auto op = shared_cast<GlobalVar>(inst->operand_list[0]);
ostr << op->type->to_IR_string() << " @" << op->name;
}
else if (Value::is<Instruction>(inst->operand_list[0])) {
auto op = Value::as<Instruction>(inst->operand_list[0]);
else if (shared_cast<Instruction>(inst->operand_list[0])) {
auto op = shared_cast<Instruction>(inst->operand_list[0]);
assert(op->ir_seqno >= 0);
ostr << op->type->to_IR_string() << " %" << op->ir_seqno;
}
else if (Value::is<FParam>(inst->operand_list[0])) {
auto op0 = Value::as<FParam>(inst->operand_list[0]);
else if (shared_cast<FParam>(inst->operand_list[0])) {
auto op0 = shared_cast<FParam>(inst->operand_list[0]);
ostr << op0->to_IR_string();
}
else {
@ -375,21 +372,21 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
break;
}
case InstTag::GEP: {
auto inst = Value::as<InstGEP>(_inst);
auto inst = shared_cast<InstGEP>(_inst);
assert(inst->ir_seqno >= 0);
auto pointer_type = Type::asType<PointerType>(inst->operand_list[0]->type);
ostr << "%" << inst->ir_seqno << " = getelementptr " << pointer_type->pointed_type->to_IR_string() << ", ";
if (Value::is<GlobalVar>(inst->operand_list[0])) {
auto op0 = Value::as<GlobalVar>(inst->operand_list[0]);
if (shared_cast<GlobalVar>(inst->operand_list[0])) {
auto op0 = shared_cast<GlobalVar>(inst->operand_list[0]);
ostr << op0->to_IR_string();
}
else if (Value::is<Instruction>(inst->operand_list[0])) {
auto op0 = Value::as<Instruction>(inst->operand_list[0]);
else if (shared_cast<Instruction>(inst->operand_list[0])) {
auto op0 = shared_cast<Instruction>(inst->operand_list[0]);
ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno;
}
else if (Value::is<FParam>(inst->operand_list[0])) {
auto op0 = Value::as<FParam>(inst->operand_list[0]);
else if (shared_cast<FParam>(inst->operand_list[0])) {
auto op0 = shared_cast<FParam>(inst->operand_list[0]);
ostr << op0->to_IR_string();
}
else {
@ -402,28 +399,27 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
break;
}
case InstTag::Alloca: {
auto inst = Value::as<InstAlloca>(_inst);
assert(inst->ir_seqno != -1);
auto inst = shared_cast<InstAlloca>(_inst);
auto pointer_type = Type::asType<PointerType>(inst->type);
ostr << "%" << inst->ir_seqno << " = alloca " << pointer_type->pointed_type->to_IR_string() << ", align 4";
ostr << " ;" << inst->name;
break;
}
case InstTag::Zext: {
auto inst = Value::as<InstZext>(_inst);
auto inst = shared_cast<InstZext>(_inst);
assert(inst->ir_seqno >= 0);
ostr << "%" << inst->ir_seqno << " = zext ";
if (Value::is<Instruction>(inst->operand_list[0])) {
auto op0 = Value::as<Instruction>(inst->operand_list[0]);
if (shared_cast<Instruction>(inst->operand_list[0])) {
auto op0 = shared_cast<Instruction>(inst->operand_list[0]);
assert(op0->ir_seqno >= 0);
ostr << op0->type->to_IR_string() << " %" << op0->ir_seqno << " to ";
}
else if (Value::is<ConstantInt>(inst->operand_list[0])) {
auto op0 = Value::as<ConstantInt>(inst->operand_list[0]);
else if (shared_cast<ConstantInt>(inst->operand_list[0])) {
auto op0 = shared_cast<ConstantInt>(inst->operand_list[0]);
ostr << op0->to_IR_string() << "to ";
}
else if (Value::is<FParam>(inst->operand_list[0])) {
auto op0 = Value::as<FParam>(inst->operand_list[0]);
else if (shared_cast<FParam>(inst->operand_list[0])) {
auto op0 = shared_cast<FParam>(inst->operand_list[0]);
ostr << op0->to_IR_string() << "to ";
}
else {
@ -434,26 +430,26 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
break;
}
case InstTag::Phi: {
auto inst = Value::as<InstPhi>(_inst);
auto inst = shared_cast<InstPhi>(_inst);
assert(inst->ir_seqno >= 0);
ostr << "%" << inst->ir_seqno << " = phi " << inst->type->to_IR_string() << " ";
for (int i = 0; i < inst->operand_list.size(); ++i) {
auto op = inst->operand_list[i];
ostr << "[";
if (Value::is<GlobalVar>(op)) {
auto op0 = Value::as<GlobalVar>(op);
if (shared_cast<GlobalVar>(op)) {
auto op0 = shared_cast<GlobalVar>(op);
ostr << "@" << op0->name;
}
else if (Value::is<Instruction>(op)) {
auto op0 = Value::as<Instruction>(op);
else if (shared_cast<Instruction>(op)) {
auto op0 = shared_cast<Instruction>(op);
ostr << "%" << op0->ir_seqno;
}
else if (Value::is<FParam>(op)) {
auto op0 = Value::as<FParam>(op);
else if (shared_cast<FParam>(op)) {
auto op0 = shared_cast<FParam>(op);
ostr << "%" << op0->ir_seqno;
}
else if (Value::is<ConstantInt>(op)) {
auto op0 = Value::as<ConstantInt>(op);
else if (shared_cast<ConstantInt>(op)) {
auto op0 = shared_cast<ConstantInt>(op);
ostr << op0->value;
}
else {