Files
mysysy/src/SysYIRGenerator.cpp
2025-05-30 02:13:17 +08:00

1037 lines
34 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// SysYIRGenerator.cpp
// TODO类型转换及其检查
// TODOsysy库函数处理
// TODO数组处理
// TODO对while、continue、break的测试
#include "IR.h"
#include <any>
#include <memory>
using namespace std;
#include "SysYIRGenerator.h"
namespace sysy {
/*
* @brief: visit compUnit
* @details:
* compUnit: (decl | funcDef)+;
*/
std::any SysYIRGenerator::visitCompUnit(SysYParser::CompUnitContext *ctx) {
// create the IR module
auto pModule = new Module();
assert(pModule);
module.reset(pModule);
SymbolTable::ModuleScope scope(symbols_table);
// 待添加运行时库函数getint等
// generates globals and functions
auto type_i32 = Type::getIntType();
auto type_f32 = Type::getFloatType();
auto type_void = Type::getVoidType();
auto type_i32p = Type::getPointerType(type_i32);
auto type_f32p = Type::getPointerType(type_f32);
//runtime library
module->createFunction("getint", Type::getFunctionType(type_i32, {}));
module->createFunction("getch", Type::getFunctionType(type_i32, {}));
module->createFunction("getfloat", Type::getFunctionType(type_f32, {}));
symbols_table.insert("getint", module->getFunction("getint"));
symbols_table.insert("getch", module->getFunction("getch"));
symbols_table.insert("getfloat", module->getFunction("getfloat"));
module->createFunction("getarray", Type::getFunctionType(type_i32, {type_i32p}));
module->createFunction("getfarray", Type::getFunctionType(type_i32, {type_f32p}));
symbols_table.insert("getarray", module->getFunction("getarray"));
symbols_table.insert("getfarray", module->getFunction("getfarray"));
module->createFunction("putint", Type::getFunctionType(type_void, {type_i32}));
module->createFunction("putch", Type::getFunctionType(type_void, {type_i32}));
module->createFunction("putfloat", Type::getFunctionType(type_void, {type_f32}));
symbols_table.insert("putint", module->getFunction("putint"));
symbols_table.insert("putch", module->getFunction("putch"));
symbols_table.insert("putfloat", module->getFunction("putfloat"));
module->createFunction("putarray", Type::getFunctionType(type_void, {type_i32, type_i32p}));
module->createFunction("putfarray", Type::getFunctionType(type_void, {type_i32, type_f32p}));
symbols_table.insert("putarray", module->getFunction("putarray"));
symbols_table.insert("putfarray", module->getFunction("putfarray"));
module->createFunction("putf", Type::getFunctionType(type_void, {}));
symbols_table.insert("putf", module->getFunction("putf"));
module->createFunction("starttime", Type::getFunctionType(type_void, {type_i32}));
module->createFunction("stoptime", Type::getFunctionType(type_void, {type_i32}));
symbols_table.insert("starttime", module->getFunction("starttime"));
symbols_table.insert("stoptime", module->getFunction("stoptime"));
// visit all decls and funcDefs
for(auto decl:ctx->decl()){
decl->accept(this);
}
for(auto funcDef:ctx->funcDef()){
builder = IRBuilder();
printf("entry funcDef\n");
funcDef->accept(this);
}
// return the IR module ?
return pModule;
}
/*
* @brief: visit decl
* @details:
* decl: constDecl | varDecl;
* constDecl: CONST bType constDef (COMMA constDef)* SEMI;
* varDecl: bType varDef (COMMA varDef)* SEMI;
* constDecl and varDecl shares similar syntax structure
* we consider them together? not sure
*/
std::any SysYIRGenerator::visitDecl(SysYParser::DeclContext *ctx) {
if(ctx->constDecl())
return visitConstDecl(ctx->constDecl());
else if(ctx->varDecl())
return visitVarDecl(ctx->varDecl());
std::cerr << "error unkown decl" << ctx->getText() << std::endl;
return std::any();
}
/*
* @brief: visit constdecl
* @details:
* constDecl: CONST bType constDef (COMMA constDef)* SEMI;
* constDef: Ident (LBRACK constExp RBRACK)* (ASSIGN constInitVal)?;
*/
std::any SysYIRGenerator::visitConstDecl(SysYParser::ConstDeclContext *ctx) {
cout << "visitconstDecl" << endl;
current_type = any_cast<Type*>(ctx->bType()->accept(this));
for(auto constDef:ctx->constDef()){
constDef->accept(this);
}
return std::any();
}
/*
* @brief: visit btype
* @details:
* bType: INT | FLOAT;
*/
std::any SysYIRGenerator::visitBType(SysYParser::BTypeContext *ctx) {
if(ctx->INT())
return Type::getPointerType(Type::getIntType());
else if(ctx->FLOAT())
return Type::getPointerType(Type::getFloatType());
std::cerr << "error: unknown type" << ctx->getText() << std::endl;
return std::any();
}
/*
* @brief: visit constDef
* @details:
* constDef: Ident (LBRACK constExp RBRACK)* (ASSIGN constInitVal)?;
* constInitVal: constExp | LBRACE (constInitVal (COMMA constInitVal)*)? RBRACE;
*/
std::any SysYIRGenerator::visitConstDef(SysYParser::ConstDefContext *ctx){
auto name = ctx->Ident()->getText();
Type* type = current_type;
Value* init = ctx->constInitVal() ? any_cast<Value*>(ctx->constInitVal()->accept(this)) : (Value *)nullptr;
if (ctx->constExp().empty()){
//scalar
if(init){
if(symbols_table.isModuleScope()){
assert(init->isConstant() && "global must be initialized by constant");
Value* global = module->createGlobalValue(name, type, {}, init);
symbols_table.insert(name, global);
cout << "add module const " << name ;
if(init){
cout << " inited by " ;
init->print(cout);
}
cout << '\n';
}
else{
Value* alloca = builder.createAllocaInst(type, {}, name);
Value* store = builder.createStoreInst(init, alloca);
symbols_table.insert(name, alloca);
cout << "add local const " << name ;
if(init){
cout << " inited by " ;
init->print(cout);
}
cout << '\n';
}
}
else{
assert(false && "const without initialization");
}
}
else{
//array
std::cerr << "array constDef not implemented yet" << std::endl;
}
printf("visitConstDef %s\n",name.c_str());
return std::any();
}
/*
* @brief: visit constInitVal
* @details:
* constInitVal: constExp
* | LBRACE (constInitVal (COMMA constInitVal)*)? RBRACE;
*/
std::any SysYIRGenerator::visitConstInitVal(SysYParser::ConstInitValContext *ctx){
Value* initvalue;
if(ctx->constExp())
initvalue = any_cast<Value*>(ctx->constExp()->accept(this));
else{
//还未实现数组初始化等功能待验证
std::cerr << "array initvalue not implemented yet" << std::endl;
// auto numConstInitVals = ctx->constInitVal().size();
// vector<Value*> initvalues;
// for(int i = 0; i < numConstInitVals; i++)
// initvalues.push_back(any_cast<Value*>(ctx->constInitVal(i)->accept(this)));
// initvalue = ConstantValue::getArray(initvalues);
}
return initvalue;
}
/*
* @brief: visit function type
* @details:
* funcType: VOID | INT | FLOAT;
*/
std::any SysYIRGenerator::visitFuncType(SysYParser::FuncTypeContext* ctx){
if(ctx->INT())
return Type::getIntType();
else if(ctx->FLOAT())
return Type::getFloatType();
else if(ctx->VOID())
return Type::getVoidType();
std::cerr << "invalid function type: " << ctx->getText() << std::endl;
return std::any();
}
/*
* @brief: visit function define
* @details:
* funcDef: funcType Ident LPAREN funcFParams? RPAREN blockStmt;
* funcFParams: funcFParam (COMMA funcFParam)*;
* funcFParam: bType Ident (LBRACK RBRACK (LBRACK exp RBRACK)*)?;
* entry -> next -> others -> exit
* entry: allocas, br
* next: retval, params, br
* other: blockStmt init block
* exit: load retval, ret
*/
std::any SysYIRGenerator::visitFuncDef(SysYParser::FuncDefContext* ctx){
auto funcName = ctx->Ident()->getText();
auto returnType = any_cast<Type*>(ctx->funcType()->accept(this));
auto func = module->getFunction(funcName);
cout << "func: ";
returnType->print(cout);
cout << ' '<< funcName.c_str() << endl;
vector<Type*> paramTypes;
vector<string> paramNames;
if(ctx->funcFParams()){
for(auto funcParam:ctx->funcFParams()->funcFParam()){
Type* paramType = any_cast<Type*>(funcParam->bType()->accept(this));
paramTypes.push_back(paramType);
paramNames.push_back(funcParam->Ident()->getText());
}
}
auto funcType = FunctionType::get(returnType, paramTypes);
auto function = module->createFunction(funcName, funcType);
SymbolTable::FunctionScope scope(symbols_table);
BasicBlock* entryblock = function->getEntryBlock();
for(size_t i = 0; i < paramTypes.size(); i++)
entryblock->createArgument(paramTypes[i], paramNames[i]);
for(auto& arg: entryblock->getArguments())
symbols_table.insert(arg->getName(), (Value *)arg.get());
cout << "setposition entryblock" << endl;
builder.setPosition(entryblock, entryblock->end());
ctx->blockStmt()->accept(this);
return std::any();
}
/*
* @brief: visit varDecl
* @details:
* varDecl: bType varDef (COMMA varDef)* SEMI;
*/
std::any SysYIRGenerator::visitVarDecl(SysYParser::VarDeclContext *ctx){
cout << "visitVarDecl" << endl;
current_type = any_cast<Type *>(ctx->bType()->accept(this));
for(auto varDef:ctx->varDef()){
varDef->accept(this);
}
return std::any();
}
/*
* @brief: visit varDef
* @details:
* varDef: Ident (LBRACK constExp RBRACK)* (ASSIGN initVal)?;
*/
std::any SysYIRGenerator::visitVarDef(SysYParser::VarDefContext *ctx){
const std::string name = ctx->Ident()->getText();
Type* type = current_type;
Value* init = ctx->initVal() ? any_cast<Value*>(ctx->initVal()->accept(this)) : nullptr;
// const std::vector<Value *> dims = {};
cout << "vardef: ";
current_type->print(cout);
cout << ' ' << name << endl;
if(ctx->constExp().empty()){
//scalar
if(symbols_table.isModuleScope()){
if(init)
assert(init->isConstant() && "global must be initialized by constant");
Value* global = module->createGlobalValue(name, type, {}, init);
symbols_table.insert(name, global);
cout << "add module var " << name ;
// if(init){
// cout << " inited by " ;
// init->print(cout);
// }
cout << '\n';
}
else{
Value* alloca = builder.createAllocaInst(type, {}, name);
cout << "creatalloca" << endl;
alloca->print(cout);
Value* store = (StoreInst *)nullptr;
if(init != nullptr)
store = builder.createStoreInst(alloca, init, {}, name);
symbols_table.insert(name, alloca);
// alloca->setName(name);
cout << "add local var " ;
alloca->print(cout);
// if(init){
// cout << " inited by " ;
// init->print(cout);
// }
cout << '\n';
}
}
else{
//array
std::cerr << "array varDef not implemented yet" << std::endl;
}
return std::any();
}
/*
* @brief: visit initVal
* @details:
* initVal: exp | LBRACE (initVal (COMMA initVal)*)? RBRACE;
*/
std::any SysYIRGenerator::visitInitVal(SysYParser::InitValContext *ctx) {
Value* initvalue = nullptr;
if(ctx->exp())
initvalue = any_cast<Value*>(ctx->exp()->accept(this));
else{
//还未实现数组初始化等功能待验证
std::cerr << "array initvalue not implemented yet" << std::endl;
// auto numConstInitVals = ctx->constInitVal().size();
// vector<Value*> initvalues;
// for(int i = 0; i < numConstInitVals; i++)
// initvalues.push_back(any_cast<Value*>(ctx->constInitVal(i)->accept(this)));
// initvalue = ConstantValue::getArray(initvalues);
}
return initvalue;
}
// std::any SysYIRGenerator::visitFuncFParams(SysYParser::FuncFParamsContext* ctx){
// return visitChildren(ctx);
// }
// std::any SysYIRGenerator::visitFuncFParam(SysYParser::FuncFParamContext *ctx) {
// return visitChildren(ctx);
// }
/*
* @brief: visit blockStmt
* @details:
* blockStmt: LBRACE blockItem* RBRACE;
* blockItem: decl | stmt;
*/
std::any SysYIRGenerator::visitBlockStmt(SysYParser::BlockStmtContext* ctx){
SymbolTable::BlockScope scope(symbols_table);
for (auto item : ctx->blockItem()){
item->accept(this);
// if(builder.getBasicBlock()->isTerminal()){
// break;
// }
}
return std::any();
}
/*
* @brief: visit ifstmt
* @details:
* ifStmt: IF LPAREN cond RPAREN stmt (ELSE stmt)?;
*/
std::any SysYIRGenerator::visitIfStmt(SysYParser::IfStmtContext *ctx) {
auto condition = any_cast<Value *>(ctx->cond()->accept(this));
auto thenBlock = builder.getBasicBlock()->getParent()->addBasicBlock("then");
auto elseBlock = builder.getBasicBlock()->getParent()->addBasicBlock("else");
auto condbr = builder.createCondBrInst(condition,thenBlock,elseBlock,{},{});
builder.setPosition(thenBlock, thenBlock->end());
ctx->stmt(0)->accept(this);
if(ctx->ELSE()){
builder.setPosition(elseBlock, elseBlock->end());
ctx->stmt(1)->accept(this);
}
//无条件跳转到下一个基本块
// builder.createUncondBrInst(builder.getBasicBlock()->getParent()->addBasicBlock("next"),{});
return std::any();
}
/*
* @brief: visit whilestmt
* @details:
* whileStmt: WHILE LPAREN cond RPAREN stmt;
*/
std::any SysYIRGenerator::visitWhileStmt(SysYParser::WhileStmtContext* ctx) {
//需要解决一个函数多个循环的命名问题
auto header = builder.getBasicBlock()->getParent()->addBasicBlock("header");
auto body = builder.getBasicBlock()->getParent()->addBasicBlock("body");
auto exit = builder.getBasicBlock()->getParent()->addBasicBlock("exit");
SymbolTable::BlockScope scope(symbols_table);
{ // visit header block
builder.setPosition(header, header->end());
auto cond = any_cast<Value*>(ctx->cond()->accept(this));
auto condbr = builder.createCondBrInst(cond, body, exit, {}, {});
}
{ // visit body block
builder.setPosition(body, body->end());
ctx->stmt()->accept(this);
auto uncondbr = builder.createUncondBrInst(header, {});
}
// visit exit block
builder.setPosition(exit, exit->end());
//无条件跳转到下一个基本块以及一些参数传递
return std::any();
}
/*
* @brief: visit breakstmt
* @details:
* breakStmt: BREAK SEMICOLON;
*/
std::any SysYIRGenerator::visitBreakStmt(SysYParser::BreakStmtContext* ctx) {
//如何获取break所在body对应的header块
return std::any();
}
/*
* @brief Visit ReturnStmt
* returnStmt: RETURN exp? SEMICOLON;
*/
std::any SysYIRGenerator::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) {
cout << "visitReturnStmt" << endl;
// auto value = ctx->exp() ? any_cast_Value(visit(ctx->exp())) : nullptr;
Value* value = ctx->exp() ? any_cast<Value*>(ctx->exp()->accept(this)) : nullptr;
const auto func = builder.getBasicBlock()->getParent();
assert(func && "ret stmt block parent err!");
// 匹配 返回值类型 与 函数定义类型
if (func->getReturnType()->isVoid()) {
if (ctx->exp())
assert(false && "the returned value is not matching the function");
auto ret = builder.createReturnInst();
return std::any();
}
assert(ctx->exp() && "the returned value is not matching the function");
auto ret = builder.createReturnInst(value);
//需要增加无条件跳转吗
return std::any();
}
/*
* @brief: visit continuestmt
* @details:
* continueStmt: CONTINUE SEMICOLON;
*/
std::any SysYIRGenerator::visitContinueStmt(SysYParser::ContinueStmtContext* ctx) {
//如何获取continue所在body对应的header块
return std::any();
}
/*
* @brief visit assign stmt
* @details:
* assignStmt: lValue ASSIGN exp SEMICOLON
*/
std::any SysYIRGenerator::visitAssignStmt(SysYParser::AssignStmtContext* ctx) {
cout << "visitassignstme :\n";
auto lvalue = any_cast<Value *>(ctx->lValue()->accept(this));
cout << "getlval" << endl;//lvalue->print(cout);cout << ')';
auto rvalue = any_cast<Value *>(ctx->exp()->accept(this));
//可能要考虑类型转换例如int a = 1.0
cout << "getrval" << endl;//rvalue->print(cout);cout << ")\n";
builder.createStoreInst(rvalue, lvalue, {}, {});
return std::any();
}
/*
* @brief: visit lValue
* @details:
* lValue: Ident (LBRACK exp RBRACK)*;
*/
std::any SysYIRGenerator::visitLValue(SysYParser::LValueContext* ctx) {
cout << "visitLValue" << endl;
auto name = ctx->Ident()->getText();
Value* value = symbols_table.lookup(name);
assert(value && "lvalue not found");
if(ctx->exp().size() == 0){
//scalar
cout << "lvalue: " << name << endl;
return value;
}
else{
//array
std::cerr << "array lvalue not implemented yet" << std::endl;
}
std::cerr << "error lvalue" << ctx->getText() << std::endl;
return std::any();
}
std::any SysYIRGenerator::visitPrimExp(SysYParser::PrimExpContext *ctx){
cout << "visitPrimExp" << endl;
return visitChildren(ctx);
}
// std::any SysYIRGenerator::visitExp(SysYParser::ExpContext* ctx) {
// cout << "visitExp" << endl;
// return ctx->addExp()->accept(this);
// }
std::any SysYIRGenerator::visitNumber(SysYParser::NumberContext *ctx) {
cout << "visitNumber" << endl;
Value* res = nullptr;
if (auto iLiteral = ctx->ILITERAL()) {
/* 基数 (8, 10, 16) */
const auto text = iLiteral->getText();
int base = 10;
if (text.find("0x") == 0 || text.find("0X") == 0) {
base = 16;
} else if (text.find("0b") == 0 || text.find("0B") == 0) {
base = 2;
} else if (text.find("0") == 0) {
base = 8;
}
res = ConstantValue::get((int)std::stol(text, 0, base));
} else if (auto fLiteral = ctx->FLITERAL()) {
const auto text = fLiteral->getText();
res = ConstantValue::get((float)std::stof(text));
}
cout << "number: ";
res->print(cout);
cout << endl;
return res;
}
/*
* @brief: visit call
* @details:
* call: Ident LPAREN funcRParams? RPAREN;
*/
std::any SysYIRGenerator::visitCall(SysYParser::CallContext* ctx) {
cout << "visitCall" << endl;
auto funcName = ctx->Ident()->getText();
auto func = module->getFunction(funcName);
assert(func && "function not found");
//需要做类型检查和转换
std::vector<Value*> args;
if(ctx->funcRParams()){
for(auto exp:ctx->funcRParams()->exp()){
args.push_back(any_cast<Value*>(exp->accept(this)));
}
}
Value* call = builder.createCallInst(func, args);
return call;
}
/*
* @brief: visit unexp
* @details:
* unExp: unaryOp unaryExp
*/
std::any SysYIRGenerator::visitUnExp(SysYParser::UnExpContext *ctx) {
cout << "visitUnExp" << endl;
Value* res = nullptr;
auto op = ctx->unaryOp()->getText();
auto exp = any_cast<Value*>(ctx->unaryExp()->accept(this));
if(ctx->unaryOp()->ADD()){
res = exp;
}
else if(ctx->unaryOp()->SUB()){
res = builder.createNegInst(exp, exp->getName());
}
else if(ctx->unaryOp()->NOT()){
//not将非零值转换为0零值转换为1
res = builder.createNotInst(exp, exp->getName());
}
return res;
}
/*
* @brief: visit mulexp
* @details:
* mulExp: unaryExp ((MUL | DIV | MOD) unaryExp)*
*/
std::any SysYIRGenerator::visitMulExp(SysYParser::MulExpContext *ctx) {
cout << "visitMulExp" << endl;
Value* res = nullptr;
cout << "mulExplhsin\n";
Value* lhs = any_cast<Value *>(ctx->unaryExp(0)->accept(this));
cout << "mulExplhsout\n";
if(ctx->unaryExp().size() == 1){
cout << "unaryExp().size() = 1\n";
res = lhs;
}
else{
cout << "unaryExp().size() > 1\n";
for(size_t i = 1; i < ctx->unaryExp().size(); i++){
Value* rhs = any_cast<Value *>(ctx->unaryExp(i)->accept(this));
auto opNode = dynamic_cast<antlr4::tree::TerminalNode *>(ctx->children[2 * i - 1]);
if(opNode->getText() == "*"){
res = builder.createMulInst(lhs, rhs, lhs->getName() + "*" + rhs->getName());
}
else if(opNode->getText() == "/"){
res = builder.createDivInst(lhs, rhs, lhs->getName() + "/" + rhs->getName());
}
else if(opNode->getText() == "%"){
std::cerr << "mod not implemented yet" << std::endl;
// res = builder.createModInst(lhs, rhs, lhs->getName() + "%" + rhs->getName());
}
}
}
return res;
}
/*
* @brief: visit addexp
* @details:
* addExp: mulExp ((ADD | SUB) mulExp)*
*/
std::any SysYIRGenerator::visitAddExp(SysYParser::AddExpContext *ctx) {
cout << "visitAddExp" << endl;
Value* res = nullptr;
Value* lhs = any_cast<Value*>(ctx->mulExp(0)->accept(this));
if(ctx->mulExp().size() == 1){
cout << "ctx->mulExp().size() = 1\n";
res = lhs;
}
else{
for(size_t i = 1; i < ctx->mulExp().size(); i++){
cout << "i = " << i << "\n";
Value* rhs = any_cast<Value*>(ctx->mulExp(i)->accept(this));
auto opNode = dynamic_cast<antlr4::tree::TerminalNode *>(ctx->children[2 * i - 1]);
if(opNode->getText() == "+"){
res = builder.createAddInst(lhs, rhs, lhs->getName() + "+" + rhs->getName());
}
else if(opNode->getText() == "-"){
res = builder.createSubInst(lhs, rhs, lhs->getName() + "-" + rhs->getName());
}
}
lhs = res;
}
return res;
}
/*
* @brief: visit relexp
* @details:
* relExp: addExp ((LT | GT | LE | GE) addExp)*
*/
std::any SysYIRGenerator::visitRelExp(SysYParser::RelExpContext *ctx) {
cout << "visitRelExp" << endl;
Value* res = nullptr;
Value* lhs = any_cast<Value*>(ctx->addExp(0)->accept(this));
if(ctx->addExp().size() == 1){
res = lhs;
}
else{
for(size_t i = 1; i < ctx->addExp().size(); i++){
Value* rhs = any_cast<Value*>(ctx->addExp(i)->accept(this));
auto opNode = dynamic_cast<antlr4::tree::TerminalNode *>(ctx->children[2 * i - 1]);
if(lhs->getType() != rhs->getType()){
std::cerr << "type mismatch:type check not implemented" << std::endl;
}
Type* type = lhs->getType();
if(opNode->getText() == "<"){
if(type->isInt())
res = builder.createICmpLTInst(lhs, rhs, lhs->getName() + "<" + rhs->getName());
else if(type->isFloat())
res = builder.createFCmpLTInst(lhs, rhs, lhs->getName() + "<" + rhs->getName());
}
else if(opNode->getText() == ">"){
if(type->isInt())
res = builder.createICmpGTInst(lhs, rhs, lhs->getName() + ">" + rhs->getName());
else if(type->isFloat())
res = builder.createFCmpGTInst(lhs, rhs, lhs->getName() + ">" + rhs->getName());
}
else if(opNode->getText() == "<="){
if(type->isInt())
res = builder.createICmpLEInst(lhs, rhs, lhs->getName() + "<=" + rhs->getName());
else if(type->isFloat())
res = builder.createFCmpLEInst(lhs, rhs, lhs->getName() + "<=" + rhs->getName());
}
else if(opNode->getText() == ">="){
if(type->isInt())
res = builder.createICmpGEInst(lhs, rhs, lhs->getName() + ">=" + rhs->getName());
else if(type->isFloat())
res = builder.createFCmpGEInst(lhs, rhs, lhs->getName() + ">=" + rhs->getName());
}
}
}
return res;
}
/*
* @brief: visit eqexp
* @details:
* eqExp: relExp ((EQ | NEQ) relExp)*
*/
std::any SysYIRGenerator::visitEqExp(SysYParser::EqExpContext* ctx) {
cout << "visitEqExp" << endl;
Value* res = nullptr;
Value* lhs = any_cast<Value*>(ctx->relExp(0)->accept(this));
if(ctx->relExp().size() == 1){
res = lhs;
}
else{
for(size_t i = 1; i < ctx->relExp().size(); i++){
Value* rhs = any_cast<Value*>(ctx->relExp(i)->accept(this));
auto opNode = dynamic_cast<antlr4::tree::TerminalNode *>(ctx->children[2 * i - 1]);
if(lhs->getType() != rhs->getType()){
std::cerr << "type mismatch:type check not implemented" << std::endl;
}
Type* type = lhs->getType();
if(opNode->getText() == "=="){
if(type->isInt())
res = builder.createICmpEQInst(lhs, rhs, lhs->getName() + "==" + rhs->getName());
else if(type->isFloat())
res = builder.createFCmpEQInst(lhs, rhs, lhs->getName() + "==" + rhs->getName());
}
else if(opNode->getText() == "!="){
if(type->isInt())
res = builder.createICmpNEInst(lhs, rhs, lhs->getName() + "!=" + rhs->getName());
else if(type->isFloat())
res = builder.createFCmpNEInst(lhs, rhs, lhs->getName() + "!=" + rhs->getName());
}
}
}
return res;
}
/*
* @brief: visit lAndexp
* @details:
* lAndExp: eqExp (AND eqExp)*
*/
std::any SysYIRGenerator::visitLAndExp(SysYParser::LAndExpContext* ctx) {
cout << "visitLAndExp" << endl;
auto currentBlock = builder.getBasicBlock();
// auto trueBlock = currentBlock->getParent()->addBasicBlock("trueland" + std::to_string(++trueBlockNum));
auto falseBlock = currentBlock->getParent()->addBasicBlock("falseland" + std::to_string(++falseBlockNum));
Value* value = any_cast<Value*>(ctx->eqExp(0)->accept(this));
auto trueBlock = currentBlock;
for(size_t i = 1; i < ctx->eqExp().size(); i++){
trueBlock = trueBlock->getParent()->addBasicBlock("trueland" + std::to_string(++trueBlockNum));
builder.createCondBrInst(value, currentBlock, falseBlock, {}, {});
builder.setPosition(trueBlock, trueBlock->end());
value = any_cast<Value*>(ctx->eqExp(i)->accept(this));
}
//结构trueblk条件跳转到falseblk
// - trueBlock1->trueBlock2->trueBlock3->...->trueBlockn->nextblk
//entry-|
// -falseBlock->nextblk
//需要在最后一个trueblock的末尾加上无条件跳转到下一个基本块的指令
// builder.createCondBrInst(value, trueBlock, falseBlock, {}, {});
return std::any();
}
/*
* @brief: visit lOrexp
* @details:
* lOrExp: lAndExp (OR lAndExp)*
*/
std::any SysYIRGenerator::visitLOrExp(SysYParser::LOrExpContext* ctx) {
cout << "visitLOrExp" << endl;
auto currentBlock = builder.getBasicBlock();
auto trueBlock = currentBlock->getParent()->addBasicBlock("trueland" + std::to_string(++trueBlockNum));
Value* value = any_cast<Value*>(ctx->lAndExp(0)->accept(this));
auto falseBlock = currentBlock;
for(size_t i = 1; i < ctx->lAndExp().size(); i++){
falseBlock = currentBlock->getParent()->addBasicBlock("falseland" + std::to_string(++falseBlockNum));
builder.createCondBrInst(value, trueBlock, falseBlock, {}, {});
builder.setPosition(falseBlock, falseBlock->end());
value = any_cast<Value*>(ctx->lAndExp(i)->accept(this));
}
//结构trueblk条件跳转到falseblk
// - falseBlock1->falseBlock2->falseBlock3->...->falseBlockn->nextblk
//entry-|
// -trueBlock->nextblk
//需要在最后一个falseblock的末尾加上无条件跳转到下一个基本块的指令
// builder.createCondBrInst(value, trueBlock, falseBlock, {}, {});
return std::any();
}
/*
* @brief: visit constexp
* @details:
* constExp: addExp;
*/
std::any SysYIRGenerator::visitConstExp(SysYParser::ConstExpContext* ctx) {
cout << "visitConstExp" << endl;
ConstantValue* res = nullptr;
Value* value = any_cast<Value*>(ctx->addExp()->accept(this));
if(isa<ConstantValue>(value)){
res = dyncast<ConstantValue>(value);
}
else{
std::cerr << "error constexp" << ctx->getText() << std::endl;
}
return res;
}
/* begin
std::any SysYIRGenerator::visitConstGlobalDecl(SysYParser::ConstDeclContext *ctx, Type* type) {
std::vector<Value *> values;
for (auto constDef : ctx->constDef()) {
auto name = constDef->Ident()->getText();
// get its dimensions
vector<Value *> dims;
for (auto dim : constDef->constExp())
dims.push_back(any_cast<Value *>(dim->accept(this)));
if (dims.size() == 0) {
auto init = constDef->ASSIGN() ? any_cast<Value *>((constDef->constInitVal()->constExp()->accept(this)))
: nullptr;
if (init && isa<ConstantValue>(init)){
Type *btype = type->as<PointerType>()->getBaseType();
if (btype->isInt() && init->getType()->isFloat())
init = ConstantValue::get((int)dynamic_cast<ConstantValue *>(init)->getFloat());
else if (btype->isFloat() && init->getType()->isInt())
init = ConstantValue::get((float)dynamic_cast<ConstantValue *>(init)->getInt());
}
auto global_value = module->createGlobalValue(name, type, dims, init);
symbols_table.insert(name, global_value);
values.push_back(global_value);
}
else{
auto init = constDef->ASSIGN() ? any_cast<Value *>(dims[0])
: nullptr;
auto global_value = module->createGlobalValue(name, type, dims, init);
if (constDef->ASSIGN()) {
d = 0;
n = 0;
path.clear();
path = vector<int>(dims.size(), 0);
isalloca = false;
current_type = global_value->getType()->as<PointerType>()->getBaseType();
current_global = global_value;
numdims = global_value->getNumDims();
for (auto init : constDef->constInitVal()->constInitVal())
init->accept(this);
// visitConstInitValue(init);
}
symbols_table.insert(name, global_value);
values.push_back(global_value);
}
}
return values;
}
std::any SysYIRGenerator::visitVarGlobalDecl(SysYParser::VarDeclContext *ctx, Type* type){
std::vector<Value *> values;
for (auto varDef : ctx->varDef()) {
auto name = varDef->Ident()->getText();
// get its dimensions
vector<Value *> dims;
for (auto dim : varDef->constExp())
dims.push_back(any_cast<Value *>(dim->accept(this)));
if (dims.size() == 0) {
auto init = varDef->ASSIGN() ? any_cast<Value *>((varDef->initVal()->exp()->accept(this)))
: nullptr;
if (init && isa<ConstantValue>(init)){
Type *btype = type->as<PointerType>()->getBaseType();
if (btype->isInt() && init->getType()->isFloat())
init = ConstantValue::get((int)dynamic_cast<ConstantValue *>(init)->getFloat());
else if (btype->isFloat() && init->getType()->isInt())
init = ConstantValue::get((float)dynamic_cast<ConstantValue *>(init)->getInt());
}
auto global_value = module->createGlobalValue(name, type, dims, init);
symbols_table.insert(name, global_value);
values.push_back(global_value);
}
else{
auto init = varDef->ASSIGN() ? any_cast<Value *>(dims[0])
: nullptr;
auto global_value = module->createGlobalValue(name, type, dims, init);
if (varDef->ASSIGN()) {
d = 0;
n = 0;
path.clear();
path = vector<int>(dims.size(), 0);
isalloca = false;
current_type = global_value->getType()->as<PointerType>()->getBaseType();
current_global = global_value;
numdims = global_value->getNumDims();
for (auto init : varDef->initVal()->initVal())
init->accept(this);
// visitInitValue(init);
}
symbols_table.insert(name, global_value);
values.push_back(global_value);
}
}
return values;
}
std::any SysYIRGenerator::visitConstLocalDecl(SysYParser::ConstDeclContext *ctx, Type* type){
std::vector<Value *> values;
// handle variables
for (auto constDef : ctx->constDef()) {
auto name = constDef->Ident()->getText();
vector<Value *> dims;
for (auto dim : constDef->constExp())
dims.push_back(any_cast<Value *>(dim->accept(this)));
auto alloca = builder.createAllocaInst(type, dims, name);
symbols_table.insert(name, alloca);
if (constDef->ASSIGN()) {
if (alloca->getNumDims() == 0) {
auto value = any_cast<Value *>(constDef->constInitVal()->constExp()->accept(this));
if (isa<ConstantValue>(value)) {
if (ctx->bType()->INT() && dynamic_cast<ConstantValue *>(value)->isFloat())
value = ConstantValue::get((int)dynamic_cast<ConstantValue *>(value)->getFloat());
else if (ctx->bType()->FLOAT() && dynamic_cast<ConstantValue *>(value)->isInt())
value = ConstantValue::get((float)dynamic_cast<ConstantValue *>(value)->getInt());
}
else if (alloca->getType()->as<PointerType>()->getBaseType()->isInt() && value->getType()->isFloat())
value = builder.createFtoIInst(value);
else if (alloca->getType()->as<PointerType>()->getBaseType()->isFloat() && value->getType()->isInt())
value = builder.createIToFInst(value);
auto store = builder.createStoreInst(value, alloca);
}
else{
d = 0;
n = 0;
path.clear();
path = vector<int>(alloca->getNumDims(), 0);
isalloca = true;
current_alloca = alloca;
current_type = alloca->getType()->as<PointerType>()->getBaseType();
numdims = alloca->getNumDims();
for (auto init : constDef->constInitVal()->constInitVal())
init->accept(this);
}
}
values.push_back(alloca);
}
return values;
}
std::any SysYIRGenerator::visitVarLocalDecl(SysYParser::VarDeclContext *ctx, Type* type){
std::vector<Value *> values;
for (auto varDef : ctx->varDef()) {
auto name = varDef->Ident()->getText();
vector<Value *> dims;
for (auto dim : varDef->constExp())
dims.push_back(any_cast<Value *>(dim->accept(this)));
auto alloca = builder.createAllocaInst(type, dims, name);
symbols_table.insert(name, alloca);
if (varDef->ASSIGN()) {
if (alloca->getNumDims() == 0) {
auto value = any_cast<Value *>(varDef->initVal()->exp()->accept(this));
if (isa<ConstantValue>(value)) {
if (ctx->bType()->INT() && dynamic_cast<ConstantValue *>(value)->isFloat())
value = ConstantValue::get((int)dynamic_cast<ConstantValue *>(value)->getFloat());
else if (ctx->bType()->FLOAT() && dynamic_cast<ConstantValue *>(value)->isInt())
value = ConstantValue::get((float)dynamic_cast<ConstantValue *>(value)->getInt());
}
else if (alloca->getType()->as<PointerType>()->getBaseType()->isInt() && value->getType()->isFloat())
value = builder.createFtoIInst(value);
else if (alloca->getType()->as<PointerType>()->getBaseType()->isFloat() && value->getType()->isInt())
value = builder.createIToFInst(value);
auto store = builder.createStoreInst(value, alloca);
}
else{
d = 0;
n = 0;
path.clear();
path = vector<int>(alloca->getNumDims(), 0);
isalloca = true;
current_alloca = alloca;
current_type = alloca->getType()->as<PointerType>()->getBaseType();
numdims = alloca->getNumDims();
for (auto init : varDef->initVal()->initVal())
init->accept(this);
}
}
values.push_back(alloca);
}
return values;
}
end
*/
} // namespace sysy