refine mem2reg, frontend refactor
This commit is contained in:
parent
81bd968258
commit
3b5cd82206
@ -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)
|
||||
|
||||
@ -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
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -14,32 +14,24 @@ 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)) {
|
||||
|
||||
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) {
|
||||
@ -53,14 +45,9 @@ static void analyze_alloca(InstAllocaPtr_t ai, AllocaInfo &info) {
|
||||
std::cout << "]\n";
|
||||
std::cout.flush();
|
||||
}
|
||||
}
|
||||
|
||||
// static bool rewrite_single_store(InstAllocaPtr_t ai, AllocaInfo& alloca_info) {
|
||||
|
||||
// }
|
||||
|
||||
// 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 << ", ";
|
||||
print_alloca_livein(ai, livein_blocks);
|
||||
}
|
||||
std::cout << "]\n";
|
||||
std::cout.flush();
|
||||
}
|
||||
// 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);
|
||||
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;
|
||||
}
|
||||
|
||||
176
src/visitor.cpp
176
src/visitor.cpp
@ -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 {};
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -105,10 +105,8 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
|
||||
// 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
|
||||
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 {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user