|
|
#include "IRBuilder.h"
|
|
|
|
|
|
#include <iostream>
|
|
|
#include <assert.h>
|
|
|
#include <vector>
|
|
|
|
|
|
#define DEBUG
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
#define DBGLOG(text) std::cout << text << std::endl
|
|
|
#define DEBUG_OUTPUT ;
|
|
|
#endif
|
|
|
#ifndef DEBUG
|
|
|
#define DBGLOG(text)
|
|
|
#define DEBUG_OUTPUT std::cout << __LINE__ << std::endl
|
|
|
#endif
|
|
|
|
|
|
namespace SysYF
|
|
|
{
|
|
|
namespace IR
|
|
|
{
|
|
|
#define CONST_INT(num) ConstantInt::create(num, module)
|
|
|
#define CONST_FLOAT(num) ConstantFloat::create(num, module)
|
|
|
|
|
|
// You can define global variables here
|
|
|
// to store state
|
|
|
typedef struct
|
|
|
{
|
|
|
bool is_int;
|
|
|
int ival;
|
|
|
float fval;
|
|
|
} Oprand;
|
|
|
Oprand expr_cal_result; // 便于全局变量中表达式计算值中转
|
|
|
std::vector<Oprand> multi_arr_init;
|
|
|
class GlobalConst
|
|
|
{
|
|
|
public:
|
|
|
GlobalConst() {}
|
|
|
~GlobalConst() = default;
|
|
|
void add_int_const(std::string name, int val)
|
|
|
{
|
|
|
if (iconst_map.find(name) == iconst_map.end())
|
|
|
{ // 新加入的不是数组元素
|
|
|
std::vector<int> temp(1, val);
|
|
|
iconst_map.insert(std::make_pair(name, temp));
|
|
|
}
|
|
|
else // 新加入的是数组元素
|
|
|
iconst_map[name].push_back(val);
|
|
|
}
|
|
|
void add_float_const(std::string name, float val)
|
|
|
{
|
|
|
if (fconst_map.find(name) == fconst_map.end())
|
|
|
{ // 新加入的不是数组元素
|
|
|
std::vector<float> temp(1, val);
|
|
|
fconst_map.insert(std::make_pair(name, temp));
|
|
|
}
|
|
|
else // 新加入的是数组元素
|
|
|
fconst_map[name].push_back(val);
|
|
|
}
|
|
|
bool get_int_const(std::string name, int offset, int &val) // 若非数组则offset=0
|
|
|
{
|
|
|
if (iconst_map.find(name) != iconst_map.end())
|
|
|
{
|
|
|
val = iconst_map[name][offset];
|
|
|
return true;
|
|
|
}
|
|
|
else
|
|
|
return false;
|
|
|
}
|
|
|
bool get_float_const(std::string name, int offset, float &val)
|
|
|
{
|
|
|
if (fconst_map.find(name) != fconst_map.end())
|
|
|
{
|
|
|
val = fconst_map[name][offset];
|
|
|
return true;
|
|
|
}
|
|
|
else
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
std::map<std::string, std::vector<int>> iconst_map;
|
|
|
std::map<std::string, std::vector<float>> fconst_map;
|
|
|
};
|
|
|
GlobalConst _const_table = GlobalConst();
|
|
|
|
|
|
std::vector<SysYF::Ptr<Type>> FuncParas;
|
|
|
SysYF::Ptr<Type> Para;
|
|
|
std::string name_;
|
|
|
std::vector<std::string> names;
|
|
|
|
|
|
int Ifnum = 0;
|
|
|
int ReturnNum = 0;
|
|
|
Ptr<AllocaInst> retAlloca;
|
|
|
SysYF::Ptr<SysYF::IR::BasicBlock> retbb;
|
|
|
|
|
|
/* enum Condtype
|
|
|
{
|
|
|
equal,
|
|
|
greater,
|
|
|
less,
|
|
|
ge,
|
|
|
le,
|
|
|
notequal
|
|
|
|
|
|
}condtype_; */
|
|
|
/* SysYF::Ptr<SysYF::IR::CmpInst> _cmp; */
|
|
|
// store temporary value
|
|
|
Ptr<Value> tmp_val = nullptr; // 存储需要全局处理的expr node
|
|
|
Ptr<Value> lhs_addr = nullptr;
|
|
|
Ptr<Function> func_parent; // 便于在创建新的bb时获得对应的func_parent
|
|
|
int bb_label_num = 0; // 全局控制bb标签编号
|
|
|
bool func_first_bb; // 处理一个func域里有多个{},只创建一个scope
|
|
|
PtrVec<BasicBlock> break_point;
|
|
|
PtrVec<BasicBlock> continue_point; // 维护两个vector(栈)控制循环break和continue应跳转到的目标地址
|
|
|
// types
|
|
|
Ptr<Type> VOID_T;
|
|
|
Ptr<Type> INT1_T;
|
|
|
Ptr<Type> INT32_T;
|
|
|
Ptr<Type> FLOAT_T;
|
|
|
Ptr<Type> INT32PTR_T;
|
|
|
Ptr<Type> FLOATPTR_T;
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::Assembly &node)
|
|
|
{
|
|
|
VOID_T = Type::get_void_type(module);
|
|
|
INT1_T = Type::get_int1_type(module);
|
|
|
INT32_T = Type::get_int32_type(module);
|
|
|
FLOAT_T = Type::get_float_type(module);
|
|
|
INT32PTR_T = Type::get_int32_ptr_type(module);
|
|
|
FLOATPTR_T = Type::get_float_ptr_type(module);
|
|
|
for (const auto &def : node.global_defs)
|
|
|
{
|
|
|
def->accept(*this);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// You need to fill them
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::InitVal &node)
|
|
|
{
|
|
|
/* DBGLOG("Begin of Initval"); */
|
|
|
// 可能有一个或多个value需要初始化,elementList方便迭代accept
|
|
|
if (node.isExp)
|
|
|
{
|
|
|
node.expr->accept(*this);
|
|
|
multi_arr_init.push_back(expr_cal_result);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
for (auto item : node.elementList)
|
|
|
{
|
|
|
item->accept(*this);
|
|
|
}
|
|
|
}
|
|
|
/* DBGLOG("End of Initval"); */
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::FuncDef &node)
|
|
|
{
|
|
|
/* DBGLOG("Begin of FuncDef"); */
|
|
|
Ptr<Type> RetType;
|
|
|
switch (node.ret_type)
|
|
|
{
|
|
|
case SysYF::SyntaxTree::Type::VOID:
|
|
|
RetType = VOID_T;
|
|
|
break;
|
|
|
case SysYF::SyntaxTree::Type::INT:
|
|
|
RetType = INT32_T;
|
|
|
break;
|
|
|
case SysYF::SyntaxTree::Type::FLOAT:
|
|
|
RetType = FLOAT_T;
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
node.param_list->accept(*this);
|
|
|
auto FuncTY = FunctionType::create(RetType, FuncParas);
|
|
|
auto Func = Function::create(FuncTY, node.name, module);
|
|
|
func_parent = Func; // 标记当前func_parent(便于后续bb调用)
|
|
|
|
|
|
scope.push(node.name, Func);
|
|
|
scope.enter();
|
|
|
auto bb = BasicBlock::create(module, node.name + "_entry", Func);
|
|
|
builder->set_insert_point(bb);
|
|
|
func_first_bb = true; // 设置为第一次进入该func的bb{}
|
|
|
|
|
|
ReturnNum = 0;
|
|
|
|
|
|
if (RetType != VOID_T)
|
|
|
{
|
|
|
retAlloca = builder->create_alloca(RetType);
|
|
|
if (RetType == INT32_T)
|
|
|
builder->create_store(CONST_INT(0), retAlloca);
|
|
|
else if (RetType == FLOAT_T)
|
|
|
builder->create_store(CONST_FLOAT(0), retAlloca);
|
|
|
}
|
|
|
|
|
|
std::vector<SysYF::Ptr<Value>> args;
|
|
|
for (auto arg = Func->arg_begin(); arg != Func->arg_end(); arg++)
|
|
|
{
|
|
|
args.push_back(*arg);
|
|
|
}
|
|
|
for (size_t i = 0; i < names.size(); i++)
|
|
|
{
|
|
|
auto pAlloca = builder->create_alloca(FuncParas[i]);
|
|
|
builder->create_store(args[i], pAlloca);
|
|
|
scope.push(names[i], pAlloca);
|
|
|
}
|
|
|
|
|
|
retbb = BasicBlock::create(module, node.name + "_ret", Func);
|
|
|
|
|
|
node.body->accept(*this);
|
|
|
|
|
|
if (!builder->get_insert_block()->get_terminator())
|
|
|
builder->create_br(retbb);
|
|
|
|
|
|
builder->set_insert_point(retbb);
|
|
|
if (RetType == VOID_T)
|
|
|
{
|
|
|
builder->create_void_ret();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
auto retLoad = builder->create_load(retAlloca);
|
|
|
builder->create_ret(retLoad);
|
|
|
}
|
|
|
/* builder->create_br(retbb); */
|
|
|
/* scope.exit(); */
|
|
|
/* DBGLOG("End of FuncDef"); */
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::FuncFParamList &node)
|
|
|
{
|
|
|
FuncParas.clear();
|
|
|
names.clear();
|
|
|
for (auto &p : node.params)
|
|
|
{
|
|
|
p->accept(*this);
|
|
|
FuncParas.push_back(Para);
|
|
|
names.push_back(name_);
|
|
|
}
|
|
|
assert(FuncParas.size() == names.size());
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::FuncParam &node)
|
|
|
{
|
|
|
name_ = node.name;
|
|
|
if (node.array_index.size())
|
|
|
{
|
|
|
// 数组
|
|
|
if (node.param_type == SysYF::SyntaxTree::Type::INT)
|
|
|
Para = INT32PTR_T;
|
|
|
else if (node.param_type == SysYF::SyntaxTree::Type::FLOAT)
|
|
|
Para = FLOATPTR_T;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// 非数组
|
|
|
if (node.param_type == SysYF::SyntaxTree::Type::INT)
|
|
|
Para = INT32_T;
|
|
|
else if (node.param_type == SysYF::SyntaxTree::Type::FLOAT)
|
|
|
Para = FLOAT_T;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::VarDef &node)
|
|
|
{
|
|
|
/* DBGLOG("Begin of VarDef"); */
|
|
|
// 变量定义:判断是否是全局变量,判断是否是const,判断是否是数组类型
|
|
|
// 获取变量类型和变量名字,分配变量存储空间,若有需要初始化变量
|
|
|
Ptr<Type> vartype;
|
|
|
if (node.btype == SyntaxTree::Type::INT)
|
|
|
vartype = INT32_T;
|
|
|
else
|
|
|
vartype = FLOAT_T;
|
|
|
// if分级判断逻辑:全局or局部->数组or单变量->const of 非const(本次实验不涉及局部数组常量)->初始化or未初始化
|
|
|
if (scope.in_global()) // 全局变量
|
|
|
{
|
|
|
if (!node.array_length.empty()) // 数组类型
|
|
|
{
|
|
|
// 目前只考虑一维数组,多维数组需要处理vector类型的array_length得到各维度长度
|
|
|
std::vector<int> arr_len;
|
|
|
unsigned total_ = 1;
|
|
|
for (int i = 0; i < node.array_length.size(); i++)
|
|
|
{
|
|
|
node.array_length[i]->accept(*this);
|
|
|
arr_len.push_back(expr_cal_result.ival);
|
|
|
total_ *= expr_cal_result.ival;
|
|
|
}
|
|
|
Ptr<ArrayType> arr_type = ArrayType::create(vartype, total_);
|
|
|
if (node.is_inited)
|
|
|
{
|
|
|
PtrVec<Constant> init_val; // 待push_back,多维转线性排列
|
|
|
int last_dim = arr_len.back();
|
|
|
int line_idx = 0;
|
|
|
for (auto val : node.initializers->elementList) // 每一个val都是一个InitVal,可能是expr,也可能是elementlist
|
|
|
{
|
|
|
multi_arr_init.clear();
|
|
|
val->accept(*this);
|
|
|
for (int i = 0; i < multi_arr_init.size(); i++)
|
|
|
{
|
|
|
Oprand tmp = multi_arr_init[i];
|
|
|
if (vartype == INT32_T)
|
|
|
{
|
|
|
int temp = (tmp.is_int) ? tmp.ival : int(tmp.fval);
|
|
|
init_val.push_back(std::static_pointer_cast<Constant>(CONST_INT(temp)));
|
|
|
if (node.is_constant)
|
|
|
_const_table.add_int_const(node.name, temp);
|
|
|
}
|
|
|
else if (vartype == FLOAT_T)
|
|
|
{
|
|
|
float temp = (tmp.is_int) ? float(tmp.ival) : tmp.fval;
|
|
|
init_val.push_back(std::static_pointer_cast<Constant>(CONST_FLOAT(temp)));
|
|
|
if (node.is_constant)
|
|
|
_const_table.add_float_const(node.name, temp);
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
// 全局变量剩余部分初始化为0
|
|
|
for (int i = init_val.size(); i < arr_len; i++)
|
|
|
{
|
|
|
if (vartype == INT32_T)
|
|
|
{
|
|
|
init_val.push_back(std::static_pointer_cast<Constant>(CONST_INT(0)));
|
|
|
if (node.is_constant)
|
|
|
_const_table.add_int_const(node.name, 0);
|
|
|
}
|
|
|
else if (vartype == FLOAT_T)
|
|
|
{
|
|
|
init_val.push_back(std::static_pointer_cast<Constant>(CONST_FLOAT(0)));
|
|
|
if (node.is_constant)
|
|
|
_const_table.add_float_const(node.name, 0.0f);
|
|
|
}
|
|
|
}
|
|
|
auto initializer = ConstantArray::create(arr_type, init_val);
|
|
|
auto Global_array = GlobalVariable::create(node.name, module, arr_type, node.is_constant, std::static_pointer_cast<Constant>(initializer));
|
|
|
scope.push(node.name, Global_array);
|
|
|
}
|
|
|
else // 未显式初始化,全为0
|
|
|
{
|
|
|
if (node.is_constant)
|
|
|
{
|
|
|
for (int i = 0; i < arr_len; i++)
|
|
|
{
|
|
|
if (vartype == INT32_T)
|
|
|
_const_table.add_int_const(node.name, 0);
|
|
|
else
|
|
|
_const_table.add_float_const(node.name, 0.0f);
|
|
|
}
|
|
|
}
|
|
|
auto initializer = ConstantZero::create(arr_type, module);
|
|
|
auto Global_array = GlobalVariable::create(node.name, module, arr_type, node.is_constant, std::static_pointer_cast<Constant>(initializer));
|
|
|
scope.push(node.name, Global_array);
|
|
|
}
|
|
|
}
|
|
|
else // 单变量
|
|
|
{
|
|
|
if (node.is_inited)
|
|
|
{ // 只能是Ptr<Expr>类型
|
|
|
node.initializers->expr->accept(*this);
|
|
|
Ptr<Constant> init_val;
|
|
|
if (vartype == INT32_T)
|
|
|
{
|
|
|
int temp = (expr_cal_result.is_int) ? expr_cal_result.ival : int(expr_cal_result.fval);
|
|
|
init_val = std::static_pointer_cast<Constant>(CONST_INT(temp));
|
|
|
if (node.is_constant)
|
|
|
_const_table.add_int_const(node.name, temp);
|
|
|
}
|
|
|
else if (vartype == FLOAT_T)
|
|
|
{
|
|
|
float temp = (expr_cal_result.is_int) ? float(expr_cal_result.ival) : expr_cal_result.fval;
|
|
|
init_val = std::static_pointer_cast<Constant>(CONST_FLOAT(temp));
|
|
|
if (node.is_constant)
|
|
|
_const_table.add_float_const(node.name, temp);
|
|
|
}
|
|
|
auto Global_val = GlobalVariable::create(node.name, module, vartype, node.is_constant, init_val);
|
|
|
scope.push(node.name, Global_val);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (node.is_constant)
|
|
|
{
|
|
|
if (vartype == INT32_T)
|
|
|
_const_table.add_int_const(node.name, 0);
|
|
|
else
|
|
|
_const_table.add_float_const(node.name, 0.0f);
|
|
|
}
|
|
|
auto init_val = ConstantZero::create(vartype, module);
|
|
|
auto Global_val = GlobalVariable::create(node.name, module, vartype, node.is_constant, std::static_pointer_cast<Constant>(init_val));
|
|
|
scope.push(node.name, Global_val);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
else // 局部变量
|
|
|
{
|
|
|
if (!node.array_length.empty()) // 数组类型(不考虑const数组)
|
|
|
{
|
|
|
node.array_length[0]->accept(*this);
|
|
|
int arr_len = expr_cal_result.ival;
|
|
|
/* DBGLOG(arr_len); */
|
|
|
Ptr<ArrayType> arr_type = ArrayType::get(vartype, arr_len);
|
|
|
/* Ptr<PointerType> arr_type = PointerType::get(vartype); */
|
|
|
auto arr_val_alloca = builder->create_alloca(arr_type);
|
|
|
|
|
|
if (node.is_inited) // 若未显式初始化,则初始值未知
|
|
|
{
|
|
|
/* DBGLOG(node.initializers->elementList.size()); */
|
|
|
int arrIdx = 0; // gep类指令计算每个元素地址
|
|
|
for (auto val : node.initializers->elementList)
|
|
|
{
|
|
|
val->expr->accept(*this);
|
|
|
// 此时的类型转换IR指令为显式的
|
|
|
if (tmp_val->get_type() != vartype) // tmp_val为Ptr<Value>类型,便于生成类型转换IR
|
|
|
{
|
|
|
if (vartype == INT32_T)
|
|
|
tmp_val = builder->create_fptosi(tmp_val, INT32_T);
|
|
|
else
|
|
|
tmp_val = builder->create_sitofp(tmp_val, FLOAT_T);
|
|
|
}
|
|
|
// 根据初始化值store到对应的gep地址中
|
|
|
auto val_addr = builder->create_gep(arr_val_alloca, {CONST_INT(0), CONST_INT(arrIdx)});
|
|
|
builder->create_store(tmp_val, val_addr);
|
|
|
arrIdx++;
|
|
|
}
|
|
|
}
|
|
|
scope.push(node.name, arr_val_alloca);
|
|
|
}
|
|
|
else // 单变量, tmp_val便于发射类型转换ir,expr_cal_result便于维护常量表
|
|
|
{
|
|
|
auto var_alloca = builder->create_alloca(vartype);
|
|
|
if (node.is_inited)
|
|
|
{
|
|
|
node.initializers->expr->accept(*this);
|
|
|
if (tmp_val->get_type() != vartype)
|
|
|
{
|
|
|
if (vartype == INT32_T)
|
|
|
tmp_val = builder->create_fptosi(tmp_val, INT32_T);
|
|
|
else
|
|
|
tmp_val = builder->create_sitofp(tmp_val, FLOAT_T);
|
|
|
}
|
|
|
if (node.is_constant)
|
|
|
{
|
|
|
if (vartype == INT32_T)
|
|
|
{
|
|
|
int temp = (expr_cal_result.is_int) ? expr_cal_result.ival : int(expr_cal_result.fval);
|
|
|
_const_table.add_int_const(node.name, temp);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
float temp = (expr_cal_result.is_int) ? float(expr_cal_result.ival) : expr_cal_result.fval;
|
|
|
_const_table.add_float_const(node.name, temp);
|
|
|
}
|
|
|
}
|
|
|
builder->create_store(tmp_val, var_alloca);
|
|
|
}
|
|
|
scope.push(node.name, var_alloca);
|
|
|
}
|
|
|
}
|
|
|
/* DBGLOG("End of VarDef"); */
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::LVal &node)
|
|
|
{
|
|
|
/* DBGLOG("Begin of LVal"); */
|
|
|
/* DBGLOG(node.name); */
|
|
|
if (scope.in_global()) // 在全局变量初始化时,InitVal 中的初始值为 Exp时可以引用左值变量
|
|
|
{
|
|
|
/* DBGLOG("Begin of LVal if"); */
|
|
|
int tmp1;
|
|
|
float tmp2;
|
|
|
int offset = 0;
|
|
|
if (!node.array_index.empty())
|
|
|
{
|
|
|
// 暂时只考虑一维数组
|
|
|
node.array_index[0]->accept(*this);
|
|
|
offset = expr_cal_result.ival;
|
|
|
}
|
|
|
if (_const_table.get_int_const(node.name, offset, tmp1))
|
|
|
{
|
|
|
expr_cal_result.is_int = true;
|
|
|
expr_cal_result.ival = tmp1;
|
|
|
}
|
|
|
else if (_const_table.get_float_const(node.name, offset, tmp2))
|
|
|
{
|
|
|
expr_cal_result.is_int = false;
|
|
|
expr_cal_result.fval = tmp2;
|
|
|
}
|
|
|
}
|
|
|
else // 并非处于全局域,左值为被赋值对象(store)或赋值对象(load)(函数调用的情形在funcall里处理)
|
|
|
{
|
|
|
/* DBGLOG("Begin of LVal else"); */
|
|
|
auto lval_addr = scope.find(node.name, false);
|
|
|
bool IsArray = false;
|
|
|
if (!node.array_index.empty()) // 数组左值, 需要先发射gep指令,再发射load指令
|
|
|
{
|
|
|
/* DBGLOG("array"); */
|
|
|
node.array_index[0]->accept(*this);
|
|
|
assert(lval_addr != nullptr);
|
|
|
/* DBGLOG(node.name);
|
|
|
DBGLOG(lval_addr->get_type()->get_type_id()); */
|
|
|
// DEBUG_OUTPUT;
|
|
|
|
|
|
if (lval_addr->get_type()->get_pointer_element_type()->is_array_type()) // 左值非指针
|
|
|
{
|
|
|
/* DBGLOG("In LVal array"); */ // a[4]
|
|
|
auto lval = builder->create_gep(lval_addr, {CONST_INT(0), tmp_val});
|
|
|
lhs_addr = lval;
|
|
|
tmp_val = builder->create_load(lval);
|
|
|
IsArray = true;
|
|
|
}
|
|
|
else // 左值是指针
|
|
|
{ //(*a)[4]
|
|
|
|
|
|
auto ptr = builder->create_load(lval_addr);
|
|
|
auto lval = builder->create_gep(ptr, {tmp_val}); // 没有CONST_INT(0),基址是ptr
|
|
|
lhs_addr = lval;
|
|
|
tmp_val = builder->create_load(lval);
|
|
|
}
|
|
|
}
|
|
|
else if (lval_addr->get_type()->get_pointer_element_type()->is_pointer_type())
|
|
|
{ //*a
|
|
|
tmp_val = builder->create_load(lval_addr); // load得到的是指针值
|
|
|
lhs_addr = lval_addr;
|
|
|
}
|
|
|
else
|
|
|
{ // a
|
|
|
tmp_val = builder->create_load(lval_addr);
|
|
|
lhs_addr = lval_addr;
|
|
|
}
|
|
|
}
|
|
|
/* DBGLOG("End of LVal"); */
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::AssignStmt &node)
|
|
|
{
|
|
|
/* DBGLOG("Begin of Assign");
|
|
|
*/
|
|
|
/* DBGLOG(node.target->name); */
|
|
|
node.target->accept(*this);
|
|
|
auto lhs = tmp_val;
|
|
|
auto lhs_addr_ = lhs_addr;
|
|
|
node.value->accept(*this);
|
|
|
auto rhs = tmp_val;
|
|
|
auto lhstype = lhs->get_type(); // 获左值类型
|
|
|
|
|
|
/* DBGLOG(lhstype->get_type_id()); */
|
|
|
auto rhstype = rhs->get_type();
|
|
|
/* DBGLOG(rhstype->get_type_id()); */
|
|
|
// 检查是否需要显式类型转换和符号扩展ir指令
|
|
|
if (rhstype == INT1_T)
|
|
|
{
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
rhstype = INT32_T;
|
|
|
}
|
|
|
if (lhstype != rhstype)
|
|
|
{
|
|
|
if (lhstype == INT32_T)
|
|
|
rhs = builder->create_fptosi(rhs, INT32_T);
|
|
|
else
|
|
|
{
|
|
|
/* DBGLOG("create "); */
|
|
|
rhs = builder->create_sitofp(rhs, FLOAT_T);
|
|
|
}
|
|
|
}
|
|
|
builder->create_store(rhs, lhs_addr_);
|
|
|
/* DBGLOG("End of Assign"); */
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::Literal &node)
|
|
|
{
|
|
|
/* DBGLOG("Begin of Literal"); */
|
|
|
if (node.literal_type == SyntaxTree::Type::INT)
|
|
|
{
|
|
|
tmp_val = CONST_INT(node.int_const);
|
|
|
expr_cal_result.is_int = true;
|
|
|
expr_cal_result.ival = node.int_const;
|
|
|
}
|
|
|
else if (node.literal_type == SyntaxTree::Type::FLOAT)
|
|
|
{
|
|
|
tmp_val = CONST_FLOAT(node.float_const);
|
|
|
expr_cal_result.is_int = false;
|
|
|
expr_cal_result.fval = node.float_const;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// DBGLOG("error at literal");
|
|
|
}
|
|
|
|
|
|
/* DBGLOG("End of Literal"); */
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::ReturnStmt &node)
|
|
|
{
|
|
|
/* DBGLOG("Begin of Return"); */
|
|
|
auto RetType = builder->get_insert_block()->get_parent()->get_return_type();
|
|
|
/* auto funName = builder->get_insert_block()->get_parent()->get_name();
|
|
|
char num_[10];
|
|
|
sprintf(num_, "%d", ReturnNum++); */
|
|
|
/* retbb = BasicBlock::create(module, funName + "_ret_" + num_, func_parent);
|
|
|
*/
|
|
|
if (!RetType->is_void_type())
|
|
|
{
|
|
|
node.ret->accept(*this);
|
|
|
auto tmpType = tmp_val->get_type();
|
|
|
/* builder->create_br(retbb);
|
|
|
builder->set_insert_point(retbb); */
|
|
|
if (tmpType != RetType)
|
|
|
{
|
|
|
if (RetType == FLOAT_T)
|
|
|
{
|
|
|
if (tmpType == INT1_T)
|
|
|
// INT1 to INT32
|
|
|
tmp_val = builder->create_zext(tmp_val, INT32_T);
|
|
|
// INT32 to FLOAT
|
|
|
tmp_val = builder->create_sitofp(tmp_val, FLOAT_T);
|
|
|
}
|
|
|
else if (RetType == INT32_T)
|
|
|
{
|
|
|
// INT1 to INT32
|
|
|
if (tmpType == INT1_T)
|
|
|
tmp_val = builder->create_zext(tmp_val, INT32_T);
|
|
|
else if (tmpType == FLOAT_T)
|
|
|
// FLOAT to INT32
|
|
|
tmp_val = builder->create_fptosi(tmp_val, INT32_T);
|
|
|
}
|
|
|
}
|
|
|
builder->create_store(tmp_val, retAlloca);
|
|
|
}
|
|
|
builder->create_br(retbb);
|
|
|
/* DBGLOG("End of Return"); */
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::BlockStmt &node)
|
|
|
{
|
|
|
if (func_first_bb == true)
|
|
|
func_first_bb = false; // 后续不是firstbb
|
|
|
else
|
|
|
scope.enter();
|
|
|
for (auto stmt : node.body)
|
|
|
{
|
|
|
stmt->accept(*this);
|
|
|
}
|
|
|
scope.exit();
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::EmptyStmt &node) {}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::ExprStmt &node)
|
|
|
{
|
|
|
node.exp->accept(*this);
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::UnaryCondExpr &node)
|
|
|
{
|
|
|
// 返回icmp或/fcmp与0相比的结果到全局变量tmp_val,发射对应ir指令
|
|
|
node.rhs->accept(*this);
|
|
|
auto rhs = tmp_val;
|
|
|
auto rhstype = rhs->get_type();
|
|
|
if (node.op == SyntaxTree::UnaryCondOp::NOT) // 只有!非号需要处理,否则不形成UnaryCondExpr结点
|
|
|
{
|
|
|
if (rhstype->is_integer_type()) // 整型分1bit和32bit
|
|
|
{
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
{
|
|
|
auto zext = builder->create_zext(rhs, INT32_T);
|
|
|
tmp_val = builder->create_icmp_eq(CONST_INT(0), zext);
|
|
|
}
|
|
|
else
|
|
|
tmp_val = builder->create_icmp_eq(CONST_INT(0), rhs);
|
|
|
}
|
|
|
else if (rhstype->is_float_type())
|
|
|
tmp_val = builder->create_fcmp_eq(CONST_FLOAT(0), rhs);
|
|
|
else // rhs是指针类型
|
|
|
tmp_val = CONST_INT(true); // true 则为非零值
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::BinaryCondExpr &node)
|
|
|
{
|
|
|
Ptr<Value> lhs, rhs;
|
|
|
Ptr<Type> lhstype, rhstype;
|
|
|
if ((node.op != SyntaxTree::BinaryCondOp::LAND) && (node.op != SyntaxTree::BinaryCondOp::LOR))
|
|
|
{
|
|
|
node.lhs->accept(*this);
|
|
|
lhs = tmp_val;
|
|
|
lhstype = lhs->get_type();
|
|
|
node.rhs->accept(*this);
|
|
|
rhs = tmp_val;
|
|
|
rhstype = rhs->get_type();
|
|
|
}
|
|
|
|
|
|
switch (node.op)
|
|
|
{
|
|
|
case SyntaxTree::BinaryCondOp::LT:
|
|
|
if (lhstype->is_float_type() && rhstype->is_float_type())
|
|
|
{
|
|
|
tmp_val = builder->create_fcmp_lt(lhs, rhs);
|
|
|
}
|
|
|
else if (lhstype->is_integer_type() && rhstype->is_integer_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
lhs = builder->create_zext(lhs, INT32_T);
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
tmp_val = builder->create_icmp_lt(lhs, rhs);
|
|
|
}
|
|
|
else if (lhstype->is_float_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
rhs = builder->create_sitofp(rhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fcmp_lt(lhs, rhs);
|
|
|
}
|
|
|
else if (rhstype->is_float_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
lhs = builder->create_zext(lhs, INT32_T);
|
|
|
lhs = builder->create_sitofp(lhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fcmp_lt(lhs, rhs);
|
|
|
}
|
|
|
break;
|
|
|
case SyntaxTree::BinaryCondOp::LTE:
|
|
|
if (lhstype->is_float_type() && rhstype->is_float_type())
|
|
|
{
|
|
|
tmp_val = builder->create_fcmp_le(lhs, rhs);
|
|
|
}
|
|
|
else if (lhstype->is_integer_type() && rhstype->is_integer_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
lhs = builder->create_zext(lhs, INT32_T);
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
tmp_val = builder->create_icmp_le(lhs, rhs);
|
|
|
}
|
|
|
else if (lhstype->is_float_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
rhs = builder->create_sitofp(rhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fcmp_le(lhs, rhs);
|
|
|
}
|
|
|
else if (rhstype->is_float_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
lhs = builder->create_zext(lhs, INT32_T);
|
|
|
lhs = builder->create_sitofp(lhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fcmp_le(lhs, rhs);
|
|
|
}
|
|
|
break;
|
|
|
case SyntaxTree::BinaryCondOp::GT:
|
|
|
if (lhstype->is_float_type() && rhstype->is_float_type())
|
|
|
{
|
|
|
tmp_val = builder->create_fcmp_gt(lhs, rhs);
|
|
|
}
|
|
|
else if (lhstype->is_integer_type() && rhstype->is_integer_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
lhs = builder->create_zext(lhs, INT32_T);
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
tmp_val = builder->create_icmp_gt(lhs, rhs);
|
|
|
}
|
|
|
else if (lhstype->is_float_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
rhs = builder->create_sitofp(rhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fcmp_gt(lhs, rhs);
|
|
|
}
|
|
|
else if (rhstype->is_float_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
lhs = builder->create_zext(lhs, INT32_T);
|
|
|
lhs = builder->create_sitofp(lhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fcmp_gt(lhs, rhs);
|
|
|
}
|
|
|
break;
|
|
|
case SyntaxTree::BinaryCondOp::GTE:
|
|
|
if (lhstype->is_float_type() && rhstype->is_float_type())
|
|
|
{
|
|
|
tmp_val = builder->create_fcmp_ge(lhs, rhs);
|
|
|
}
|
|
|
else if (lhstype->is_integer_type() && rhstype->is_integer_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
lhs = builder->create_zext(lhs, INT32_T);
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
tmp_val = builder->create_icmp_ge(lhs, rhs);
|
|
|
}
|
|
|
else if (lhstype->is_float_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
rhs = builder->create_sitofp(rhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fcmp_ge(lhs, rhs);
|
|
|
}
|
|
|
else if (rhstype->is_float_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
lhs = builder->create_zext(lhs, INT32_T);
|
|
|
lhs = builder->create_sitofp(lhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fcmp_ge(lhs, rhs);
|
|
|
}
|
|
|
break;
|
|
|
case SyntaxTree::BinaryCondOp::EQ:
|
|
|
if (lhstype->is_float_type() && rhstype->is_float_type())
|
|
|
{
|
|
|
tmp_val = builder->create_fcmp_eq(lhs, rhs);
|
|
|
}
|
|
|
else if (lhstype->is_integer_type() && rhstype->is_integer_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
lhs = builder->create_zext(lhs, INT32_T);
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
tmp_val = builder->create_icmp_eq(lhs, rhs);
|
|
|
}
|
|
|
else if (lhstype->is_float_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
rhs = builder->create_sitofp(rhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fcmp_eq(lhs, rhs);
|
|
|
}
|
|
|
else if (rhstype->is_float_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
lhs = builder->create_zext(lhs, INT32_T);
|
|
|
lhs = builder->create_sitofp(lhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fcmp_eq(lhs, rhs);
|
|
|
}
|
|
|
break;
|
|
|
case SyntaxTree::BinaryCondOp::NEQ:
|
|
|
if (lhstype->is_float_type() && rhstype->is_float_type())
|
|
|
{
|
|
|
tmp_val = builder->create_fcmp_ne(lhs, rhs);
|
|
|
}
|
|
|
else if (lhstype->is_integer_type() && rhstype->is_integer_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
lhs = builder->create_zext(lhs, INT32_T);
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
tmp_val = builder->create_icmp_ne(lhs, rhs);
|
|
|
}
|
|
|
else if (lhstype->is_float_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
rhs = builder->create_sitofp(rhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fcmp_ne(lhs, rhs);
|
|
|
}
|
|
|
else if (rhstype->is_float_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
lhs = builder->create_zext(lhs, INT32_T);
|
|
|
lhs = builder->create_sitofp(lhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fcmp_ne(lhs, rhs);
|
|
|
}
|
|
|
break;
|
|
|
// 非常关键的控制流语句br(逻辑与/或)
|
|
|
case SyntaxTree::BinaryCondOp::LAND:
|
|
|
// lhs和rhs都应该是INT1_T
|
|
|
{
|
|
|
auto parent = func_parent;
|
|
|
char labelname[20];
|
|
|
sprintf(labelname, "true_bb_%d", bb_label_num++); // lhs&&rhs为true进入执行体
|
|
|
auto true_bb = BasicBlock::create(module, labelname, parent);
|
|
|
sprintf(labelname, "false_bb_%d", bb_label_num++); // lhs为false(应该就是after cond bb吧?也可能进入下一个cond bb)
|
|
|
auto false_bb = BasicBlock::create(module, labelname, parent);
|
|
|
sprintf(labelname, "next_bb_%d", bb_label_num++); // rhs判断域
|
|
|
auto next_bb = BasicBlock::create(module, labelname, parent);
|
|
|
sprintf(labelname, "after_bb_%d", bb_label_num++); //
|
|
|
auto after_bb = BasicBlock::create(module, labelname, parent);
|
|
|
|
|
|
auto result = builder->create_alloca(INT1_T);
|
|
|
node.lhs->accept(*this);
|
|
|
lhs = tmp_val;
|
|
|
lhstype = lhs->get_type();
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
{
|
|
|
builder->create_cond_br(lhs, next_bb, false_bb); // if true直接跳转到nextbb(rhs判断的bb),否则跳转到falsebb
|
|
|
}
|
|
|
else if (Type::is_eq_type(lhstype, INT32_T))
|
|
|
{
|
|
|
tmp_val = builder->create_icmp_ne(lhs, CONST_INT(0)); // 类型为INT32_T而不是INT1_T就不能直接create_cond_br,先判断真假
|
|
|
builder->create_cond_br(lhs, next_bb, false_bb);
|
|
|
}
|
|
|
else if (Type::is_eq_type(lhstype, FLOAT_T))
|
|
|
{
|
|
|
tmp_val = builder->create_fcmp_ne(lhs, CONST_FLOAT(0)); // 类型为INT32_T而不是INT1_T就不能直接create_cond_br,先判断真假
|
|
|
builder->create_cond_br(tmp_val, next_bb, false_bb);
|
|
|
}
|
|
|
else // 为无条件跳转
|
|
|
{
|
|
|
builder->create_br(next_bb);
|
|
|
}
|
|
|
builder->set_insert_point(next_bb); // rhs判断域
|
|
|
|
|
|
node.rhs->accept(*this);
|
|
|
rhs = tmp_val;
|
|
|
rhstype = rhs->get_type();
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
{
|
|
|
builder->create_cond_br(rhs, true_bb, false_bb); // if true直接跳转到truebb,否则跳转到falsebb
|
|
|
}
|
|
|
else if (Type::is_eq_type(rhstype, INT32_T))
|
|
|
{
|
|
|
tmp_val = builder->create_icmp_ne(rhs, CONST_INT(0)); // 类型为INT32_T而不是INT1_T就不能直接create_cond_br,先判断真假
|
|
|
builder->create_cond_br(rhs, true_bb, false_bb);
|
|
|
}
|
|
|
else if (Type::is_eq_type(rhstype, FLOAT_T))
|
|
|
{
|
|
|
tmp_val = builder->create_fcmp_ne(rhs, CONST_FLOAT(0)); // 类型为INT32_T而不是INT1_T就不能直接create_cond_br,先判断真假
|
|
|
builder->create_cond_br(tmp_val, true_bb, false_bb);
|
|
|
}
|
|
|
else // 为无条件跳转
|
|
|
{
|
|
|
builder->create_br(true_bb);
|
|
|
}
|
|
|
|
|
|
builder->set_insert_point(true_bb); // cond_bb判断域结束,进入true_bb执行体内部
|
|
|
builder->create_store(CONST_INT(true), result);
|
|
|
builder->create_br(after_bb);
|
|
|
builder->set_insert_point(false_bb);
|
|
|
builder->create_store(CONST_INT(false), result);
|
|
|
builder->create_br(after_bb);
|
|
|
// true_bb和false_bb IR结束后都要无条件br到after_bb
|
|
|
builder->set_insert_point(after_bb);
|
|
|
tmp_val = builder->create_load(result);
|
|
|
break;
|
|
|
}
|
|
|
case SyntaxTree::BinaryCondOp::LOR:
|
|
|
// lhs和rhs都应该是INT1_T, 与LAND稍有区别(使用短路计算)
|
|
|
auto parent = func_parent;
|
|
|
char labelname[20];
|
|
|
sprintf(labelname, "ture_bb_%d", bb_label_num++); // lhs&&rhs为true进入执行体
|
|
|
auto true_bb = BasicBlock::create(module, labelname, parent);
|
|
|
sprintf(labelname, "false_bb_%d", bb_label_num++); // lhs为false(应该就是after cond bb吧?也可能进入下一个cond bb)
|
|
|
auto false_bb = BasicBlock::create(module, labelname, parent);
|
|
|
sprintf(labelname, "next_bb_%d", bb_label_num++); // rhs判断域
|
|
|
auto next_bb = BasicBlock::create(module, labelname, parent);
|
|
|
sprintf(labelname, "after_bb_%d", bb_label_num++); //
|
|
|
auto after_bb = BasicBlock::create(module, labelname, parent);
|
|
|
|
|
|
auto result = builder->create_alloca(INT1_T);
|
|
|
node.lhs->accept(*this);
|
|
|
lhs = tmp_val;
|
|
|
lhstype = lhs->get_type();
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
{
|
|
|
builder->create_cond_br(lhs, true_bb, next_bb); // if true直接跳转到turebb执行体内,否则跳转到nextbb(rhs判断域)
|
|
|
}
|
|
|
else if (Type::is_eq_type(lhstype, INT32_T))
|
|
|
{
|
|
|
tmp_val = builder->create_icmp_ne(lhs, CONST_INT(0)); // 类型为INT32_T而不是INT1_T就不能直接create_cond_br,先判断真假
|
|
|
builder->create_cond_br(tmp_val, true_bb, next_bb);
|
|
|
}
|
|
|
else if (Type::is_eq_type(lhstype, FLOAT_T))
|
|
|
{
|
|
|
tmp_val = builder->create_fcmp_ne(lhs, CONST_FLOAT(0)); // 类型为INT32_T而不是INT1_T就不能直接create_cond_br,先判断真假
|
|
|
builder->create_cond_br(tmp_val, true_bb, next_bb);
|
|
|
}
|
|
|
else // 为无条件跳转
|
|
|
{
|
|
|
builder->create_br(true_bb);
|
|
|
}
|
|
|
builder->set_insert_point(next_bb); // rhs判断域
|
|
|
node.rhs->accept(*this);
|
|
|
rhs = tmp_val;
|
|
|
rhstype = rhs->get_type();
|
|
|
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
{
|
|
|
builder->create_cond_br(rhs, true_bb, false_bb); // if true直接跳转到truebb,否则跳转到falsebb
|
|
|
}
|
|
|
else if (Type::is_eq_type(rhstype, INT32_T))
|
|
|
{
|
|
|
tmp_val = builder->create_icmp_ne(rhs, CONST_INT(0)); // 类型为INT32_T而不是INT1_T就不能直接create_cond_br,先判断真假
|
|
|
builder->create_cond_br(tmp_val, true_bb, false_bb);
|
|
|
}
|
|
|
else if (Type::is_eq_type(rhstype, FLOAT_T))
|
|
|
{
|
|
|
tmp_val = builder->create_fcmp_ne(rhs, CONST_FLOAT(0)); // 类型为INT32_T而不是INT1_T就不能直接create_cond_br,先判断真假
|
|
|
builder->create_cond_br(tmp_val, true_bb, false_bb);
|
|
|
}
|
|
|
else // 为无条件跳转
|
|
|
{
|
|
|
builder->create_br(true_bb);
|
|
|
}
|
|
|
|
|
|
builder->set_insert_point(true_bb); // cond_bb判断域结束,进入true_bb执行体内部
|
|
|
builder->create_store(CONST_INT(true), result);
|
|
|
builder->create_br(after_bb);
|
|
|
builder->set_insert_point(false_bb);
|
|
|
builder->create_store(CONST_INT(false), result);
|
|
|
builder->create_br(after_bb);
|
|
|
// true_bb和false_bb IR结束后都要无条件br到after_bb
|
|
|
builder->set_insert_point(after_bb);
|
|
|
tmp_val = builder->create_load(result);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::BinaryExpr &node)
|
|
|
{
|
|
|
if (scope.in_global()) // 需要计算全局变量声明中某些表达式
|
|
|
{
|
|
|
int lhs_ival, rhs_ival;
|
|
|
float lhs_fval, rhs_fval;
|
|
|
bool lhs_is_int, rhs_is_int;
|
|
|
node.lhs->accept(*this);
|
|
|
if (expr_cal_result.is_int)
|
|
|
lhs_ival = expr_cal_result.ival;
|
|
|
else
|
|
|
lhs_fval = expr_cal_result.fval;
|
|
|
lhs_is_int = expr_cal_result.is_int;
|
|
|
node.rhs->accept(*this);
|
|
|
if (expr_cal_result.is_int)
|
|
|
rhs_ival = expr_cal_result.ival;
|
|
|
else
|
|
|
rhs_fval = expr_cal_result.fval;
|
|
|
rhs_is_int = expr_cal_result.is_int;
|
|
|
switch (node.op)
|
|
|
{
|
|
|
case SyntaxTree::BinOp::PLUS:
|
|
|
if (lhs_is_int && rhs_is_int)
|
|
|
{
|
|
|
expr_cal_result.is_int = true;
|
|
|
expr_cal_result.ival = lhs_ival + rhs_ival;
|
|
|
}
|
|
|
else if (!lhs_is_int && rhs_is_int)
|
|
|
{
|
|
|
expr_cal_result.is_int = false;
|
|
|
expr_cal_result.fval = lhs_fval + rhs_ival;
|
|
|
}
|
|
|
else if (lhs_is_int && !rhs_is_int)
|
|
|
{
|
|
|
expr_cal_result.is_int = false;
|
|
|
expr_cal_result.fval = lhs_ival + rhs_fval;
|
|
|
}
|
|
|
else if (!lhs_is_int && !rhs_is_int)
|
|
|
{
|
|
|
expr_cal_result.is_int = false;
|
|
|
expr_cal_result.fval = lhs_fval + rhs_fval;
|
|
|
}
|
|
|
break;
|
|
|
case SyntaxTree::BinOp::MINUS:
|
|
|
if (lhs_is_int && rhs_is_int)
|
|
|
{
|
|
|
expr_cal_result.is_int = true;
|
|
|
expr_cal_result.ival = lhs_ival - rhs_ival;
|
|
|
}
|
|
|
else if (!lhs_is_int && rhs_is_int)
|
|
|
{
|
|
|
expr_cal_result.is_int = false;
|
|
|
expr_cal_result.fval = lhs_fval - rhs_ival;
|
|
|
}
|
|
|
else if (lhs_is_int && !rhs_is_int)
|
|
|
{
|
|
|
expr_cal_result.is_int = false;
|
|
|
expr_cal_result.fval = lhs_ival - rhs_fval;
|
|
|
}
|
|
|
else if (!lhs_is_int && !rhs_is_int)
|
|
|
{
|
|
|
expr_cal_result.is_int = false;
|
|
|
expr_cal_result.fval = lhs_fval - rhs_fval;
|
|
|
}
|
|
|
break;
|
|
|
case SyntaxTree::BinOp::MULTIPLY:
|
|
|
if (lhs_is_int && rhs_is_int)
|
|
|
{
|
|
|
expr_cal_result.is_int = true;
|
|
|
expr_cal_result.ival = lhs_ival * rhs_ival;
|
|
|
}
|
|
|
else if (!lhs_is_int && rhs_is_int)
|
|
|
{
|
|
|
expr_cal_result.is_int = false;
|
|
|
expr_cal_result.fval = lhs_fval * rhs_ival;
|
|
|
}
|
|
|
else if (lhs_is_int && !rhs_is_int)
|
|
|
{
|
|
|
expr_cal_result.is_int = false;
|
|
|
expr_cal_result.fval = lhs_ival * rhs_fval;
|
|
|
}
|
|
|
else if (!lhs_is_int && !rhs_is_int)
|
|
|
{
|
|
|
expr_cal_result.is_int = false;
|
|
|
expr_cal_result.fval = lhs_fval * rhs_fval;
|
|
|
}
|
|
|
break;
|
|
|
case SyntaxTree::BinOp::DIVIDE:
|
|
|
if (lhs_is_int && rhs_is_int)
|
|
|
{
|
|
|
expr_cal_result.is_int = true;
|
|
|
expr_cal_result.ival = lhs_ival / rhs_ival;
|
|
|
}
|
|
|
else if (!lhs_is_int && rhs_is_int)
|
|
|
{
|
|
|
expr_cal_result.is_int = false;
|
|
|
expr_cal_result.fval = lhs_fval / rhs_ival;
|
|
|
}
|
|
|
else if (lhs_is_int && !rhs_is_int)
|
|
|
{
|
|
|
expr_cal_result.is_int = false;
|
|
|
expr_cal_result.fval = lhs_ival / rhs_fval;
|
|
|
}
|
|
|
else if (!lhs_is_int && !rhs_is_int)
|
|
|
{
|
|
|
expr_cal_result.is_int = false;
|
|
|
expr_cal_result.fval = lhs_fval / rhs_fval;
|
|
|
}
|
|
|
break;
|
|
|
case SyntaxTree::BinOp::MODULO:
|
|
|
expr_cal_result.is_int = true;
|
|
|
if (lhs_is_int && rhs_is_int)
|
|
|
expr_cal_result.ival = lhs_ival % rhs_ival;
|
|
|
else if (!lhs_is_int && rhs_is_int)
|
|
|
expr_cal_result.fval = int(lhs_fval) % rhs_ival;
|
|
|
else if (lhs_is_int && !rhs_is_int)
|
|
|
expr_cal_result.fval = lhs_ival % int(rhs_fval);
|
|
|
else if (!lhs_is_int && !rhs_is_int)
|
|
|
expr_cal_result.fval = int(lhs_fval) % int(rhs_fval);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
else // 生成相应计算ir指令, 根据最终指令形式分为float、int和指针计算三种
|
|
|
{
|
|
|
node.lhs->accept(*this);
|
|
|
auto lhs = tmp_val;
|
|
|
auto lhstype = lhs->get_type();
|
|
|
node.rhs->accept(*this);
|
|
|
auto rhs = tmp_val;
|
|
|
auto rhstype = rhs->get_type();
|
|
|
switch (node.op)
|
|
|
{
|
|
|
case SyntaxTree::BinOp::PLUS:
|
|
|
if (Type::is_eq_type(lhstype, FLOAT_T) || Type::is_eq_type(rhstype, FLOAT_T))
|
|
|
{ // 目标ir为float加法
|
|
|
if (lhstype->is_integer_type()) // 类型不匹配
|
|
|
{
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
{
|
|
|
auto zext = builder->create_zext(lhs, INT32_T);
|
|
|
auto itof = builder->create_sitofp(zext, FLOAT_T);
|
|
|
tmp_val = builder->create_fadd(itof, rhs);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
auto itof = builder->create_sitofp(lhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fadd(itof, rhs);
|
|
|
}
|
|
|
}
|
|
|
else if (rhstype->is_integer_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
{
|
|
|
auto zext = builder->create_zext(rhs, INT32_T);
|
|
|
auto itof = builder->create_sitofp(zext, FLOAT_T);
|
|
|
tmp_val = builder->create_fadd(lhs, itof);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
auto itof = builder->create_sitofp(rhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fadd(lhs, itof);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
tmp_val = builder->create_fadd(lhs, rhs);
|
|
|
}
|
|
|
else if (lhstype->is_integer_type() && rhstype->is_integer_type())
|
|
|
{ // 目标ir为32位加法
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
lhs = builder->create_zext(lhs, INT32_T);
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
tmp_val = builder->create_iadd(lhs, rhs);
|
|
|
}
|
|
|
else
|
|
|
{ // 目标ir为指针计算(地址计算gep)
|
|
|
PtrVec<Value> ptr_idx; // 为适配多维数组或结构体的多个idx寻址,设置为vector类型
|
|
|
if (lhstype->is_pointer_type())
|
|
|
{
|
|
|
ptr_idx.push_back(rhs);
|
|
|
tmp_val = builder->create_gep(lhs, ptr_idx);
|
|
|
}
|
|
|
else if (rhstype->is_pointer_type())
|
|
|
{
|
|
|
ptr_idx.push_back(lhs);
|
|
|
tmp_val = builder->create_gep(rhs, ptr_idx);
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case SyntaxTree::BinOp::MINUS:
|
|
|
if (Type::is_eq_type(lhstype, FLOAT_T) || Type::is_eq_type(rhstype, FLOAT_T))
|
|
|
{ // 目标ir为float减法
|
|
|
if (lhstype->is_integer_type()) // 类型不匹配
|
|
|
{
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
{
|
|
|
auto zext = builder->create_zext(lhs, INT32_T);
|
|
|
auto itof = builder->create_sitofp(zext, FLOAT_T);
|
|
|
tmp_val = builder->create_fsub(itof, rhs);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
auto itof = builder->create_sitofp(lhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fsub(itof, rhs);
|
|
|
}
|
|
|
}
|
|
|
else if (rhstype->is_integer_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
{
|
|
|
auto zext = builder->create_zext(rhs, INT32_T);
|
|
|
auto itof = builder->create_sitofp(zext, FLOAT_T);
|
|
|
tmp_val = builder->create_fsub(lhs, itof);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
auto itof = builder->create_sitofp(rhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fsub(lhs, itof);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
tmp_val = builder->create_fsub(lhs, rhs);
|
|
|
}
|
|
|
else if (lhstype->is_integer_type() && rhstype->is_integer_type())
|
|
|
{ // 目标ir为32位减法
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
lhs = builder->create_zext(lhs, INT32_T);
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
tmp_val = builder->create_isub(lhs, rhs);
|
|
|
}
|
|
|
else
|
|
|
{ // 目标ir为指针计算(地址计算gep), 只能lhs为指针类型
|
|
|
PtrVec<Value> ptr_idx; // 为适配多维数组或结构体的多个idx寻址,设置为vector类型
|
|
|
if (lhstype->is_pointer_type())
|
|
|
{
|
|
|
ptr_idx.push_back(rhs);
|
|
|
tmp_val = builder->create_gep(lhs, ptr_idx);
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
case SyntaxTree::BinOp::MULTIPLY:
|
|
|
if (Type::is_eq_type(lhstype, FLOAT_T) || Type::is_eq_type(rhstype, FLOAT_T))
|
|
|
{ // 目标ir为float乘法
|
|
|
if (lhstype->is_integer_type()) // 类型不匹配
|
|
|
{
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
{
|
|
|
auto zext = builder->create_zext(lhs, INT32_T);
|
|
|
auto itof = builder->create_sitofp(zext, FLOAT_T);
|
|
|
tmp_val = builder->create_fmul(itof, rhs);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
auto itof = builder->create_sitofp(lhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fmul(itof, rhs);
|
|
|
}
|
|
|
}
|
|
|
else if (rhstype->is_integer_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
{
|
|
|
auto zext = builder->create_zext(rhs, INT32_T);
|
|
|
auto itof = builder->create_sitofp(zext, FLOAT_T);
|
|
|
tmp_val = builder->create_fmul(lhs, itof);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
auto itof = builder->create_sitofp(rhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fmul(lhs, itof);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
tmp_val = builder->create_fmul(lhs, rhs);
|
|
|
}
|
|
|
else if (lhstype->is_integer_type() && rhstype->is_integer_type())
|
|
|
{ // 目标ir为32位乘法
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
lhs = builder->create_zext(lhs, INT32_T);
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
tmp_val = builder->create_imul(lhs, rhs);
|
|
|
}
|
|
|
break;
|
|
|
case SyntaxTree::BinOp::DIVIDE:
|
|
|
if (Type::is_eq_type(lhstype, FLOAT_T) || Type::is_eq_type(rhstype, FLOAT_T))
|
|
|
{ // 目标ir为float除法
|
|
|
if (lhstype->is_integer_type()) // 类型不匹配
|
|
|
{
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
{
|
|
|
auto zext = builder->create_zext(lhs, INT32_T);
|
|
|
auto itof = builder->create_sitofp(zext, FLOAT_T);
|
|
|
tmp_val = builder->create_fdiv(itof, rhs);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
auto itof = builder->create_sitofp(lhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fdiv(itof, rhs);
|
|
|
}
|
|
|
}
|
|
|
else if (rhstype->is_integer_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
{
|
|
|
auto zext = builder->create_zext(rhs, INT32_T);
|
|
|
auto itof = builder->create_sitofp(zext, FLOAT_T);
|
|
|
tmp_val = builder->create_fdiv(lhs, itof);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
auto itof = builder->create_sitofp(rhs, FLOAT_T);
|
|
|
tmp_val = builder->create_fdiv(lhs, itof);
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
tmp_val = builder->create_fdiv(lhs, rhs);
|
|
|
}
|
|
|
else if (lhstype->is_integer_type() && rhstype->is_integer_type())
|
|
|
{ // 目标ir为32位除法
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
lhs = builder->create_zext(lhs, INT32_T);
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
tmp_val = builder->create_isdiv(lhs, rhs);
|
|
|
}
|
|
|
break;
|
|
|
case SyntaxTree::BinOp::MODULO: // 取模运算只能是int类型(不能通过ir将float类型转换,这是不合法的)
|
|
|
if (lhstype->is_integer_type() && rhstype->is_integer_type())
|
|
|
{ // 目标ir为32位取模
|
|
|
if (Type::is_eq_type(lhstype, INT1_T))
|
|
|
lhs = builder->create_zext(lhs, INT32_T);
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
rhs = builder->create_zext(rhs, INT32_T);
|
|
|
tmp_val = builder->create_isrem(lhs, rhs);
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::UnaryExpr &node)
|
|
|
{
|
|
|
if (scope.in_global()) // 需要计算全局变量声明中某些表达式
|
|
|
{ // 只有minus需要修改值,否则值和类型都不用修改
|
|
|
node.rhs->accept(*this);
|
|
|
if (expr_cal_result.is_int)
|
|
|
{
|
|
|
if (node.op == SyntaxTree::UnaryOp::MINUS)
|
|
|
expr_cal_result.ival = -expr_cal_result.ival;
|
|
|
else if (node.op == SyntaxTree::UnaryOp::MINUS)
|
|
|
expr_cal_result.fval = -expr_cal_result.fval;
|
|
|
}
|
|
|
}
|
|
|
else // 需要更新tmp_val
|
|
|
{
|
|
|
node.rhs->accept(*this);
|
|
|
auto rhs = tmp_val;
|
|
|
auto rhstype = rhs->get_type();
|
|
|
switch (node.op)
|
|
|
{
|
|
|
case SyntaxTree::UnaryOp::PLUS:
|
|
|
break;
|
|
|
case SyntaxTree::UnaryOp::MINUS:
|
|
|
if (rhstype->is_integer_type())
|
|
|
{
|
|
|
if (Type::is_eq_type(rhstype, INT1_T))
|
|
|
{
|
|
|
auto zext = builder->create_zext(rhs, INT32_T);
|
|
|
tmp_val = builder->create_isub(CONST_INT(0), zext);
|
|
|
}
|
|
|
else
|
|
|
tmp_val = builder->create_isub(CONST_INT(0), rhs);
|
|
|
}
|
|
|
else if (rhstype->is_float_type())
|
|
|
tmp_val = builder->create_fsub(CONST_FLOAT(0), rhs);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::FuncCallStmt &node)
|
|
|
{
|
|
|
auto Func = dynamic_pointer_cast<Function>(scope.find(node.name, true));
|
|
|
auto RetType = Func->get_return_type();
|
|
|
PtrVec<Value> param;
|
|
|
param.clear();
|
|
|
auto FuncPara = Func->get_args();
|
|
|
int idx = 0;
|
|
|
|
|
|
// DBGLOG("begin the funccall");
|
|
|
for (auto funp : FuncPara)
|
|
|
{
|
|
|
node.params[idx]->accept(*this);
|
|
|
auto tmpType = tmp_val->get_type();
|
|
|
auto ParaType = funp->get_type();
|
|
|
|
|
|
if (ParaType == tmpType)
|
|
|
param.push_back(tmp_val);
|
|
|
else if (ParaType == INT32_T)
|
|
|
{
|
|
|
switch (tmpType->get_type_id())
|
|
|
{
|
|
|
// INT1 to INT32
|
|
|
case SysYF::IR::Type::TypeID::IntegerTyID:
|
|
|
tmp_val = builder->create_zext(tmp_val, INT32_T);
|
|
|
param.push_back(tmp_val);
|
|
|
break;
|
|
|
// FLOAT to INT32
|
|
|
case SysYF::IR::Type::TypeID::FloatTyID:
|
|
|
tmp_val = builder->create_fptosi(tmp_val, INT32_T);
|
|
|
param.push_back(tmp_val);
|
|
|
break;
|
|
|
// other
|
|
|
default:
|
|
|
// DBGLOG("Error type to INT32_T");
|
|
|
// DBGLOG(tmpType->get_type_id());
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
else if (ParaType == FLOAT_T)
|
|
|
{
|
|
|
switch (tmpType->get_type_id())
|
|
|
{
|
|
|
// INT1/32 to FLOAT
|
|
|
case SysYF::IR::Type::TypeID::IntegerTyID:
|
|
|
if (tmpType == INT1_T)
|
|
|
tmp_val = builder->create_zext(tmp_val, INT32_T);
|
|
|
tmp_val = builder->create_sitofp(tmp_val, FLOAT_T);
|
|
|
param.push_back(tmp_val);
|
|
|
break;
|
|
|
// other
|
|
|
default:
|
|
|
// DBGLOG("Error type to FLOAT_T");
|
|
|
// DBGLOG(tmpType->get_type_id());
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
else if (ParaType->is_pointer_type())
|
|
|
{
|
|
|
if (tmpType->is_array_type())
|
|
|
{
|
|
|
// DBGLOG(tmpType->get_type_id());
|
|
|
// DBGLOG("debug 1");
|
|
|
auto Element_pointer = builder->create_gep(lhs_addr, {CONST_INT(0), CONST_INT(0)});
|
|
|
// DBGLOG("debug 2");
|
|
|
param.push_back(Element_pointer);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// DBGLOG("ParaType == pointer");
|
|
|
// DBGLOG(tmpType->get_type_id());
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
// DBGLOG("Error ParaType");
|
|
|
// DBGLOG(ParaType->get_type_id());
|
|
|
// other
|
|
|
}
|
|
|
|
|
|
idx++;
|
|
|
}
|
|
|
|
|
|
if (RetType == VOID_T)
|
|
|
{
|
|
|
builder->create_call(Func, param);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
tmp_val = builder->create_call(Func, param);
|
|
|
}
|
|
|
// DBGLOG("end the funccall");
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::IfStmt &node)
|
|
|
{
|
|
|
/* DBGLOG("begin the IF"); */
|
|
|
SysYF::Ptr<SysYF::IR::BasicBlock> bbTrue, bbAfter, bbFalse, bbCond;
|
|
|
auto ParentFunc = builder->get_insert_block()->get_parent();
|
|
|
char num[10];
|
|
|
// itoa(Ifnum, num, 10);
|
|
|
/* DBGLOG("before the sprintf"); */
|
|
|
sprintf(num, "%d", Ifnum++);
|
|
|
/* DBGLOG("after the sprintf"); */
|
|
|
/* std::string s = "if_cond_";
|
|
|
bbCond = BasicBlock::create(module, s + num, ParentFunc); */
|
|
|
std::string s = "if_true_";
|
|
|
bbTrue = BasicBlock::create(module, s + num, ParentFunc);
|
|
|
if (node.else_statement)
|
|
|
{
|
|
|
s = "if_false_";
|
|
|
bbFalse = BasicBlock::create(module, s + num, ParentFunc);
|
|
|
}
|
|
|
s = "after_if_";
|
|
|
bbAfter = BasicBlock::create(module, s + num, ParentFunc);
|
|
|
|
|
|
/* DBGLOG("before visit cond"); */
|
|
|
/* builder->create_br(bbCond); */
|
|
|
/* builder->set_insert_point(bbCond); */
|
|
|
node.cond_exp->accept(*this);
|
|
|
/* DBGLOG("after visit cond"); */
|
|
|
|
|
|
SysYF::Ptr<Value> _cmp;
|
|
|
auto condType = tmp_val->get_type();
|
|
|
if (condType == INT1_T)
|
|
|
_cmp = tmp_val;
|
|
|
else if (condType == INT32_T)
|
|
|
_cmp = builder->create_icmp_ne(tmp_val, CONST_INT(0));
|
|
|
else if (condType == FLOAT_T)
|
|
|
_cmp = builder->create_fcmp_ne(tmp_val, CONST_FLOAT(0));
|
|
|
else
|
|
|
{
|
|
|
}
|
|
|
/* DBGLOG("after Init cmp"); */
|
|
|
if (!_cmp)
|
|
|
builder->create_br(bbTrue);
|
|
|
else if (node.else_statement)
|
|
|
builder->create_cond_br(_cmp, bbTrue, bbFalse);
|
|
|
else
|
|
|
builder->create_cond_br(_cmp, bbTrue, bbAfter);
|
|
|
|
|
|
builder->set_insert_point(bbTrue);
|
|
|
/* DBGLOG("before visit if_stmt"); */
|
|
|
|
|
|
node.if_statement->accept(*this);
|
|
|
/* DBGLOG("after visit if_stmt"); */
|
|
|
|
|
|
if (!builder->get_insert_block()->get_terminator())
|
|
|
builder->create_br(bbAfter);
|
|
|
|
|
|
if (node.else_statement)
|
|
|
{
|
|
|
builder->set_insert_point(bbFalse);
|
|
|
/* DBGLOG("before visit else"); */
|
|
|
node.else_statement->accept(*this);
|
|
|
if (!builder->get_insert_block()->get_terminator())
|
|
|
builder->create_br(bbAfter);
|
|
|
}
|
|
|
|
|
|
builder->set_insert_point(bbAfter);
|
|
|
/* DBGLOG("end the IF"); */
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::WhileStmt &node)
|
|
|
{
|
|
|
// 类比condexpr和ifstmt,需要创建bb label并控制跳转
|
|
|
char labelname[20];
|
|
|
auto parent = func_parent;
|
|
|
sprintf(labelname, "cond_bb_%d", bb_label_num++);
|
|
|
auto cond_bb = BasicBlock::create(module, labelname, parent);
|
|
|
sprintf(labelname, "true_bb_%d", bb_label_num++);
|
|
|
auto true_bb = BasicBlock::create(module, labelname, parent);
|
|
|
sprintf(labelname, "after_bb_%d", bb_label_num++);
|
|
|
auto after_bb = BasicBlock::create(module, labelname, parent);
|
|
|
|
|
|
break_point.push_back(after_bb); // break后直接跳转至afterbb(循环语句后紧接的bb)
|
|
|
continue_point.push_back(cond_bb); // continue后跳转至条件判断域condbb
|
|
|
|
|
|
builder->create_br(cond_bb); // 进入AST的whilrnode后先无条件进行一次条件判断
|
|
|
builder->set_insert_point(cond_bb);
|
|
|
node.cond_exp->accept(*this);
|
|
|
auto cond_judge = tmp_val;
|
|
|
auto cond_type = cond_judge->get_type();
|
|
|
// 只有当cond是INT1_T类型时才能直接生成cond_br, 否则要先判断cond是否为零值
|
|
|
if (Type::is_eq_type(cond_type, INT1_T))
|
|
|
{
|
|
|
builder->create_cond_br(cond_judge, true_bb, after_bb);
|
|
|
}
|
|
|
else if (Type::is_eq_type(cond_type, INT32_T))
|
|
|
{
|
|
|
cond_judge = builder->create_icmp_ne(cond_judge, CONST_INT(0));
|
|
|
builder->create_cond_br(cond_judge, true_bb, after_bb);
|
|
|
}
|
|
|
else if (Type::is_eq_type(cond_type, FLOAT_T))
|
|
|
{
|
|
|
cond_judge = builder->create_fcmp_ne(cond_judge, CONST_FLOAT(0));
|
|
|
builder->create_cond_br(cond_judge, true_bb, after_bb);
|
|
|
}
|
|
|
else // 说明能无条件跳转, while(1)
|
|
|
{
|
|
|
builder->create_br(true_bb);
|
|
|
}
|
|
|
|
|
|
builder->set_insert_point(true_bb); // 进入循环执行体内部生成IR
|
|
|
node.statement->accept(*this); // 访问循环体内部stmt, 自会生成IR
|
|
|
|
|
|
if (!(builder->get_insert_block()->get_terminator())) // ret与br都是Terminator Instructions也就是终止指令, 若没有则补充(while语句里没有)
|
|
|
builder->create_br(cond_bb);
|
|
|
|
|
|
builder->set_insert_point(after_bb);
|
|
|
// 离开前别忘了维护break和continue栈
|
|
|
break_point.pop_back();
|
|
|
continue_point.pop_back();
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::BreakStmt &node)
|
|
|
{ // 控制跳转目的地址
|
|
|
char labelname[20];
|
|
|
auto parent = func_parent;
|
|
|
sprintf(labelname, "break_dest_%d", bb_label_num++);
|
|
|
auto break_dest_bb = BasicBlock::create(module, labelname, parent);
|
|
|
builder->create_br(break_point.back()); // 还不需要pop, while语句中会pop
|
|
|
builder->set_insert_point(break_dest_bb);
|
|
|
}
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::ContinueStmt &node)
|
|
|
{ // 控制跳转目的地址
|
|
|
char labelname[20];
|
|
|
auto parent = func_parent;
|
|
|
sprintf(labelname, "cond_dest_%d", bb_label_num++);
|
|
|
auto cond_dest_bb = BasicBlock::create(module, labelname, parent);
|
|
|
builder->create_br(continue_point.back()); // 还不需要pop, while语句中会pop
|
|
|
builder->set_insert_point(cond_dest_bb);
|
|
|
}
|
|
|
|
|
|
}
|
|
|
} |