|
|
|
@ -10,10 +10,14 @@ namespace IR
|
|
|
|
|
// You can define global variables here
|
|
|
|
|
|
|
|
|
|
// to store state
|
|
|
|
|
std::vector<SysYF::Ptr<Type>> funcParam;
|
|
|
|
|
int exprRes = 0;
|
|
|
|
|
|
|
|
|
|
// store temporary value
|
|
|
|
|
Ptr<Value> tmp_val = nullptr;
|
|
|
|
|
std::vector<SysYF::Ptr<Type>> funcFParam;
|
|
|
|
|
int exprRes = 0;
|
|
|
|
|
std::string curFuncName = "";
|
|
|
|
|
Ptr<SysYF::IR::Instruction> tmpInst;
|
|
|
|
|
bool isFloat = false;
|
|
|
|
|
|
|
|
|
|
// types
|
|
|
|
|
Ptr<Type> VOID_T;
|
|
|
|
@ -61,13 +65,13 @@ void IRBuilder::visit(SyntaxTree::InitVal &node) {
|
|
|
|
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::FuncDef &node) {
|
|
|
|
|
node.param_list->accept(*this);
|
|
|
|
|
auto funcType = FunctionType::create(GetType(node.ret_type), funcParam);
|
|
|
|
|
auto funcType = FunctionType::create(GetType(node.ret_type), funcFParam);
|
|
|
|
|
auto createFunc = Function::create(funcType, node.name, module);
|
|
|
|
|
node.body->accept(*this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::FuncFParamList &node) {
|
|
|
|
|
funcParam.clear();
|
|
|
|
|
funcFParam.clear();
|
|
|
|
|
for (const auto ¶ : node.params) {
|
|
|
|
|
para->accept(*this);
|
|
|
|
|
}
|
|
|
|
@ -77,30 +81,30 @@ void IRBuilder::visit(SyntaxTree::FuncParam &node) {
|
|
|
|
|
case SyntaxTree::Type::INT:
|
|
|
|
|
if (!node.array_index.empty()) {
|
|
|
|
|
// TODO: high dim array
|
|
|
|
|
funcParam.push_back(INT32PTR_T);
|
|
|
|
|
funcFParam.push_back(INT32PTR_T);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
funcParam.push_back(INT32_T);
|
|
|
|
|
funcFParam.push_back(INT32_T);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::Type::FLOAT:
|
|
|
|
|
if (!node.array_index.empty()) {
|
|
|
|
|
// TODO: high dim array
|
|
|
|
|
funcParam.push_back(FLOATPTR_T);
|
|
|
|
|
funcFParam.push_back(FLOATPTR_T);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
funcParam.push_back(FLOAT_T);
|
|
|
|
|
funcFParam.push_back(FLOAT_T);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::Type::VOID:
|
|
|
|
|
funcParam.push_back(VOID_T);
|
|
|
|
|
funcFParam.push_back(VOID_T);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::Type::STRING:
|
|
|
|
|
funcParam.push_back(INT32PTR_T);
|
|
|
|
|
funcFParam.push_back(INT32PTR_T);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::Type::BOOL:
|
|
|
|
|
funcParam.push_back(INT1_T);
|
|
|
|
|
funcFParam.push_back(INT1_T);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
funcParam.push_back(INT32_T);
|
|
|
|
|
funcFParam.push_back(INT32_T);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -110,47 +114,207 @@ void IRBuilder::visit(SyntaxTree::VarDef &node) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::LVal &node) {
|
|
|
|
|
|
|
|
|
|
auto ident = scope.find(node.name, false);
|
|
|
|
|
if (!node.array_index.empty()) {
|
|
|
|
|
//TODO: high dim array
|
|
|
|
|
node.array_index[0]->accept(*this);
|
|
|
|
|
auto index = tmpInst;
|
|
|
|
|
tmpInst = builder->create_gep(ident, {CONST_INT(0), index});
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
tmpInst = dynamic_pointer_cast<Instruction>(ident);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::AssignStmt &node) {
|
|
|
|
|
|
|
|
|
|
node.target->accept(*this);
|
|
|
|
|
auto target = tmpInst;
|
|
|
|
|
node.value->accept(*this);
|
|
|
|
|
auto value = tmpInst;
|
|
|
|
|
builder->create_store(value, target);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::Literal &node) {
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
switch(node.literal_type) {
|
|
|
|
|
case SyntaxTree::Type::INT:
|
|
|
|
|
tmp_val = CONST_INT(node.int_val);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::Type::FLOAT:
|
|
|
|
|
tmp_val = CONST_FLOAT(node.float_val);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::Type::BOOL:
|
|
|
|
|
tmp_val = CONST_INT(node.bool_val);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::Type::STRING:
|
|
|
|
|
tmp_val = CONST_INT(node.str_val);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
tmp_val = CONST_INT(0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::ReturnStmt &node) {
|
|
|
|
|
|
|
|
|
|
node.ret->accept(*this);
|
|
|
|
|
builder->create_ret(tmpInst);
|
|
|
|
|
return ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::BlockStmt &node) {
|
|
|
|
|
|
|
|
|
|
for (const auto &stmt : node.body) {
|
|
|
|
|
stmt->accept(*this);
|
|
|
|
|
}
|
|
|
|
|
return ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::EmptyStmt &node) {
|
|
|
|
|
|
|
|
|
|
return ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::ExprStmt &node) {
|
|
|
|
|
|
|
|
|
|
node.exp->accept(*this);
|
|
|
|
|
return ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::UnaryCondExpr &node) {
|
|
|
|
|
|
|
|
|
|
node.rhs->accept(*this);
|
|
|
|
|
switch (node.op) {
|
|
|
|
|
case SyntaxTree::UnaryCondOp::NOT:
|
|
|
|
|
if(isFloat){
|
|
|
|
|
tmpInst = builder->create_fcmp_eq(tmpInst, CONST_FLOAT(0.0));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
tmpInst = builder->create_icmp_eq(tmpInst, CONST_INT(0));
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::BinaryCondExpr &node) {
|
|
|
|
|
|
|
|
|
|
node.lhs->accept(*this);
|
|
|
|
|
auto lhs = tmpInst;
|
|
|
|
|
node.rhs->accept(*this);
|
|
|
|
|
auto rhs = tmpInst;
|
|
|
|
|
switch (node.op) {
|
|
|
|
|
case SyntaxTree::BinaryCondOp::LT:
|
|
|
|
|
if (isFloat) {
|
|
|
|
|
tmpInst = builder->create_fcmp_lt(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
tmpInst = builder->create_icmp_gt(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::BinaryCondOp::LTE:
|
|
|
|
|
if (isFloat) {
|
|
|
|
|
tmpInst = builder->create_fcmp_le(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
tmpInst = builder->create_icmp_le(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::BinaryCondOp::GT:
|
|
|
|
|
if (isFloat) {
|
|
|
|
|
tmpInst = builder->create_fcmp_gt(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
tmpInst = builder->create_icmp_gt(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::BinaryCondOp::GTE:
|
|
|
|
|
if (isFloat) {
|
|
|
|
|
tmpInst = builder->create_fcmp_ge(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
tmpInst = builder->create_icmp_ge(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::BinaryCondOp::EQ:
|
|
|
|
|
if (isFloat) {
|
|
|
|
|
tmpInst = builder->create_fcmp_eq(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
tmpInst = builder->create_icmp_eq(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::BinaryCondOp::NEQ:
|
|
|
|
|
if (isFloat) {
|
|
|
|
|
tmpInst = builder->create_fcmp_ne(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
tmpInst = builder->create_icmp_ne(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::BinaryCondOp::LAND:
|
|
|
|
|
//TODO: and
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::BinaryCondOp::LOR:
|
|
|
|
|
//TODO: or
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::BinaryExpr &node) {
|
|
|
|
|
node.lhs->accept(*this);
|
|
|
|
|
auto lhs = tmpInst;
|
|
|
|
|
node.rhs->accept(*this);
|
|
|
|
|
auto rhs = tmpInst;
|
|
|
|
|
switch (node.op) {
|
|
|
|
|
case SyntaxTree::BinOp::PLUS:
|
|
|
|
|
if(isFloat){
|
|
|
|
|
tmpInst = builder->create_fadd(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
tmpInst = builder->create_iadd(lhs, rhs);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::BinOp::MINUS:
|
|
|
|
|
if(isFloat){
|
|
|
|
|
tmpInst = builder->create_fsub(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
tmpInst = builder->create_isub(lhs, rhs);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::BinOp::MULTIPLY:
|
|
|
|
|
if(isFloat){
|
|
|
|
|
tmpInst = builder->create_fmul(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
tmpInst = builder->create_imul(lhs, rhs);
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::BinOp::DIVIDE:
|
|
|
|
|
if(isFloat){
|
|
|
|
|
tmpInst = builder->create_fdiv(lhs, rhs);
|
|
|
|
|
} else {
|
|
|
|
|
tmpInst = builder->create_isdiv(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::BinOp::MODULO:
|
|
|
|
|
if(isFloat){
|
|
|
|
|
// not support
|
|
|
|
|
} else {
|
|
|
|
|
tmpInst = builder->create_isrem(lhs, rhs);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::UnaryExpr &node) {
|
|
|
|
|
|
|
|
|
|
node.rhs->accept(*this);
|
|
|
|
|
switch (node.op) {
|
|
|
|
|
case SyntaxTree::UnaryOp::PLUS:
|
|
|
|
|
break;
|
|
|
|
|
case SyntaxTree::UnaryOp::MINUS:
|
|
|
|
|
if(isFloat){
|
|
|
|
|
tmpInst = builder->create_fsub(CONST_FLOAT(0.0), tmpInst);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
tmpInst = builder->create_isub(CONST_INT(0), tmpInst);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::FuncCallStmt &node) {
|
|
|
|
@ -158,11 +322,37 @@ void IRBuilder::visit(SyntaxTree::FuncCallStmt &node) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::IfStmt &node) {
|
|
|
|
|
|
|
|
|
|
auto curFunc = dynamic_pointer_cast<Function>(scope.find(curFuncName, true));
|
|
|
|
|
node.cond_exp->accept(*this);
|
|
|
|
|
auto cond = tmp_val;
|
|
|
|
|
auto trueBB = BasicBlock::create(module, "trueBB_if", curFunc);
|
|
|
|
|
auto falseBB = BasicBlock::create(module, "falseBB_if", curFunc);
|
|
|
|
|
builder->create_cond_br(cond, trueBB, falseBB);
|
|
|
|
|
builder->set_insert_point(trueBB);
|
|
|
|
|
node.if_statement->accept(*this);
|
|
|
|
|
builder->set_insert_point(falseBB);
|
|
|
|
|
node.else_statement->accept(*this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::WhileStmt &node) {
|
|
|
|
|
auto curFunc = dynamic_pointer_cast<Function>(scope.find(curFuncName, true));
|
|
|
|
|
auto condBB = BasicBlock::create(module, "condBB_while", curFunc);
|
|
|
|
|
auto bodyBB = BasicBlock::create(module, "bodyBB_while", curFunc);
|
|
|
|
|
auto afterBB = BasicBlock::create(module, "afterBB_while", curFunc);
|
|
|
|
|
|
|
|
|
|
builder->create_br(condBB);
|
|
|
|
|
|
|
|
|
|
builder->set_insert_point(condBB);
|
|
|
|
|
node.cond_exp->accept(*this);
|
|
|
|
|
auto cond = tmp_val;
|
|
|
|
|
|
|
|
|
|
builder->create_cond_br(cond, bodyBB, afterBB);
|
|
|
|
|
|
|
|
|
|
builder->set_insert_point(bodyBB);
|
|
|
|
|
node.statement->accept(*this);
|
|
|
|
|
builder->create_br(condBB);
|
|
|
|
|
|
|
|
|
|
builder->set_insert_point(afterBB);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void IRBuilder::visit(SyntaxTree::BreakStmt &node) {
|
|
|
|
|