From 93175ba5edb0eacc182f573c4fd4556f089da305 Mon Sep 17 00:00:00 2001 From: _ov4 Date: Fri, 30 Jan 2026 13:28:45 +0000 Subject: Added BYREF and BYVAL --- lib/CodeGen/ArrayHandler.cc | 8 +-- lib/CodeGen/CodeGen.cc | 66 +++++++++++++++++--- lib/CodeGen/FunctionGen.cc | 36 +++++++---- lib/Lexer/Lexer.cc | 3 + lib/Parser/ParserFunction.cc | 139 ++++++++++++++++++++++++++++++++++++++++++ lib/Parser/Parser_Function.cc | 129 --------------------------------------- 6 files changed, 227 insertions(+), 154 deletions(-) create mode 100644 lib/Parser/ParserFunction.cc delete mode 100644 lib/Parser/Parser_Function.cc (limited to 'lib') diff --git a/lib/CodeGen/ArrayHandler.cc b/lib/CodeGen/ArrayHandler.cc index 18b9253..5842f77 100644 --- a/lib/CodeGen/ArrayHandler.cc +++ b/lib/CodeGen/ArrayHandler.cc @@ -8,7 +8,7 @@ using namespace llvm; using namespace cps; -ArrayHandler::ArrayHandler(LLVMContext &C, IRBuilder<> &B, Module &M, std::map &NV, RuntimeCheck &RC) +ArrayHandler::ArrayHandler(LLVMContext &C, IRBuilder<> &B, Module &M, std::map &NV, RuntimeCheck &RC) : TheContext(&C), Builder(&B), TheModule(&M), NamedValues(&NV), RuntimeChecker(RC) { setupExternalFunctions(); } @@ -125,7 +125,7 @@ Value* ArrayHandler::emitArrayAccess(ArrayAccessExprAST *Expr, CodeGen &CG) { Value *Offset = computeFlatIndex(Name, Indices); - AllocaInst *Alloca = (*NamedValues)[Name]; + Value *Alloca = (*NamedValues)[Name]; Value *RawPtr = Builder->CreateLoad(PointerType::getUnqual(*TheContext), Alloca); Value *IntPtr = Builder->CreateBitCast(RawPtr, PointerType::getUnqual(*TheContext)); Value *ElemPtr = Builder->CreateGEP(Type::getInt64Ty(*TheContext), IntPtr, Offset); @@ -154,7 +154,7 @@ void ArrayHandler::emitArrayAssign(ArrayAssignStmtAST *Stmt, CodeGen &CG) { Value *Val = CG.emitExpr(Stmt->getExpr()); Value *Offset = computeFlatIndex(Name, Indices); - AllocaInst *Alloca = (*NamedValues)[Name]; + Value *Alloca = (*NamedValues)[Name]; Value *RawPtr = Builder->CreateLoad(PointerType::getUnqual(*TheContext), Alloca); Value *IntPtr = Builder->CreateBitCast(RawPtr, PointerType::getUnqual(*TheContext)); Value *ElemPtr = Builder->CreateGEP(Type::getInt64Ty(*TheContext), IntPtr, Offset); @@ -197,7 +197,7 @@ void ArrayHandler::emitPrintLoop(const std::string &Name, int CurrentDim, std::v if (CurrentDim == Meta.Rank) { Value *Offset = computeFlatIndex(Name, CurrentIndices); - AllocaInst *Alloca = (*NamedValues)[Name]; + Value *Alloca = (*NamedValues)[Name]; Value *RawPtr = Builder->CreateLoad(PointerType::getUnqual(*TheContext), Alloca); Value *IntPtr = Builder->CreateBitCast(RawPtr, PointerType::getUnqual(*TheContext)); Value *ElemPtr = Builder->CreateGEP(Type::getInt64Ty(*TheContext), IntPtr, Offset); diff --git a/lib/CodeGen/CodeGen.cc b/lib/CodeGen/CodeGen.cc index 6358699..bfbd8e0 100644 --- a/lib/CodeGen/CodeGen.cc +++ b/lib/CodeGen/CodeGen.cc @@ -70,7 +70,7 @@ Value *CodeGen::emitExpr(ExprAST *Expr) { } if (auto *Var = dynamic_cast(Expr)) { - AllocaInst *A = NamedValues[Var->getName()]; + Value *A = NamedValues[Var->getName()]; if (!A) { fprintf(stderr, "Error: Unknown variable name %s\n", Var->getName().c_str()); return nullptr; @@ -109,9 +109,34 @@ Value *CodeGen::emitExpr(ExprAST *Expr) { } if (auto *Call = dynamic_cast(Expr)) { + Function *CalleeF = TheModule->getFunction(Call->getCallee()); std::vector Args; - for (const auto &Arg : Call->getArgs()) { - Args.push_back(emitExpr(Arg.get())); + + for (unsigned i = 0; i < Call->getArgs().size(); ++i) { + ExprAST *ArgExpr = Call->getArgs()[i].get(); + bool isByRef = false; + + if (CalleeF && i < CalleeF->arg_size()) { + if (CalleeF->getArg(i)->getType()->isPointerTy()) { + isByRef = true; + } + } + + if (isByRef) { + if (auto *Var = dynamic_cast(ArgExpr)) { + Value *Ptr = NamedValues[Var->getName()]; + if (!Ptr) { + fprintf(stderr, "Error: Unknown variable %s in BYREF call\n", Var->getName().c_str()); + return nullptr; + } + Args.push_back(Ptr); + } else { + fprintf(stderr, "Error: BYREF argument must be a variable.\n"); + return nullptr; + } + } else { + Args.push_back(emitExpr(ArgExpr)); + } } return FuncGen->emitCallExpr(Call, Args); } @@ -203,7 +228,7 @@ void CodeGen::emitForStmt(ForStmtAST *Stmt) { Value *StartVal = emitExpr(Stmt->getStart()); if (!StartVal) return; - AllocaInst *Alloca = NamedValues[VarName]; + Value *Alloca = NamedValues[VarName]; if (!Alloca) { fprintf(stderr, "Error: Unknown variable in FOR loop %s\n", VarName.c_str()); return; @@ -285,9 +310,34 @@ void CodeGen::emitStmt(StmtAST *Stmt) { } else if (auto *Call = dynamic_cast(Stmt)) { + Function *CalleeF = TheModule->getFunction(Call->getCallee()); std::vector Args; - for (const auto &ArgExpr : Call->getArgs()) { - Args.push_back(emitExpr(ArgExpr.get())); + + for (unsigned i = 0; i < Call->getArgs().size(); ++i) { + ExprAST *ArgExpr = Call->getArgs()[i].get(); + bool isByRef = false; + + if (CalleeF && i < CalleeF->arg_size()) { + if (CalleeF->getArg(i)->getType()->isPointerTy()) { + isByRef = true; + } + } + + if (isByRef) { + if (auto *Var = dynamic_cast(ArgExpr)) { + Value *Ptr = NamedValues[Var->getName()]; + if (!Ptr) { + fprintf(stderr, "Error: Unknown variable %s in BYREF call\n", Var->getName().c_str()); + return; + } + Args.push_back(Ptr); + } else { + fprintf(stderr, "Error: BYREF argument must be a variable.\n"); + return; + } + } else { + Args.push_back(emitExpr(ArgExpr)); + } } FuncGen->emitCallStmt(Call, Args); return; @@ -311,7 +361,7 @@ void CodeGen::emitStmt(StmtAST *Stmt) { else if (auto *Assign = dynamic_cast(Stmt)) { Value *Val = emitExpr(Assign->getExpr()); if (Val) { - AllocaInst *Alloca = NamedValues[Assign->getName()]; + Value *Alloca = NamedValues[Assign->getName()]; if (!Alloca) { fprintf(stderr, "Error: Unknown variable name %s\n", Assign->getName().c_str()); return; @@ -320,7 +370,7 @@ void CodeGen::emitStmt(StmtAST *Stmt) { } } else if (auto *In = dynamic_cast(Stmt)) { - AllocaInst *Alloca = NamedValues[In->getName()]; + Value *Alloca = NamedValues[In->getName()]; if (Alloca) { std::vector Args; Args.push_back(ScanfFormatStr); diff --git a/lib/CodeGen/FunctionGen.cc b/lib/CodeGen/FunctionGen.cc index b2adc08..a929943 100644 --- a/lib/CodeGen/FunctionGen.cc +++ b/lib/CodeGen/FunctionGen.cc @@ -13,27 +13,37 @@ Type *FunctionGen::getLLVMType(const std::string &TypeName) { return Type::getInt64Ty(Context); } -void FunctionGen::createArgumentAllocas(Function *F, const std::vector> &Args) { +void FunctionGen::createArgumentAllocas(Function *F, const std::vector> &Args) { Function::arg_iterator AI = F->arg_begin(); for (unsigned Idx = 0, E = Args.size(); Idx != E; ++Idx, ++AI) { - std::string ArgName = Args[Idx].first; - std::string ArgTypeStr = Args[Idx].second; - - Type *ArgType = getLLVMType(ArgTypeStr); - IRBuilder<> TmpB(&F->getEntryBlock(), F->getEntryBlock().begin()); - AllocaInst *Alloca = TmpB.CreateAlloca(ArgType, nullptr, ArgName); + std::string ArgName = std::get<0>(Args[Idx]); + std::string ArgTypeStr = std::get<1>(Args[Idx]); + bool IsRef = std::get<2>(Args[Idx]); Value *ArgVal = &(*AI); - Builder.CreateStore(ArgVal, Alloca); - - NamedValues[ArgName] = Alloca; + ArgVal->setName(ArgName); + + if (IsRef) { + NamedValues[ArgName] = ArgVal; + } else { + Type *ArgType = getLLVMType(ArgTypeStr); + IRBuilder<> TmpB(&F->getEntryBlock(), F->getEntryBlock().begin()); + AllocaInst *Alloca = TmpB.CreateAlloca(ArgType, nullptr, ArgName); + + Builder.CreateStore(ArgVal, Alloca); + NamedValues[ArgName] = Alloca; + } } } Function *FunctionGen::emitPrototype(PrototypeAST *Proto) { std::vector ArgTypes; for (const auto &Arg : Proto->getArgs()) { - ArgTypes.push_back(getLLVMType(Arg.second)); + Type *T = getLLVMType(std::get<1>(Arg)); + if (std::get<2>(Arg)) { + T = T->getPointerTo(); + } + ArgTypes.push_back(T); } Type *RetType = getLLVMType(Proto->getReturnType()); @@ -43,7 +53,7 @@ Function *FunctionGen::emitPrototype(PrototypeAST *Proto) { unsigned Idx = 0; for (auto &Arg : F->args()) { if (Idx < Proto->getArgs().size()) - Arg.setName(Proto->getArgs()[Idx++].first); + Arg.setName(std::get<0>(Proto->getArgs()[Idx++])); } return F; } @@ -65,7 +75,7 @@ Function *FunctionGen::emitFunctionDef(FunctionDefAST *FuncAST, BasicBlock *BB = BasicBlock::Create(Context, "entry", TheFunction); Builder.SetInsertPoint(BB); - std::map OldNamedValues = NamedValues; + std::map OldNamedValues = NamedValues; NamedValues.clear(); createArgumentAllocas(TheFunction, Proto->getArgs()); diff --git a/lib/Lexer/Lexer.cc b/lib/Lexer/Lexer.cc index 6854cc9..da2e47f 100644 --- a/lib/Lexer/Lexer.cc +++ b/lib/Lexer/Lexer.cc @@ -54,6 +54,9 @@ int Lexer::gettok() { if (IdentifierStr == "RETURN") return tok_return; if (IdentifierStr == "RETURNS") return tok_returns; if (IdentifierStr == "CALL") return tok_call; + + if (IdentifierStr == "BYREF") return tok_byref; + if (IdentifierStr == "BYVAL") return tok_byval; return tok_identifier; } diff --git a/lib/Parser/ParserFunction.cc b/lib/Parser/ParserFunction.cc new file mode 100644 index 0000000..d689aa6 --- /dev/null +++ b/lib/Parser/ParserFunction.cc @@ -0,0 +1,139 @@ +#include "cps/Parser.h" +#include "cps/FunctionAST.h" +#include + +using namespace cps; + +std::vector> Parser::ParsePrototypeArgs() { + std::vector> Args; + if (CurTok != '(') return Args; + getNextToken(); + + while (CurTok != ')') { + if (CurTok == -1000 || CurTok == -1001) getNextToken(); + + bool IsRef = false; + if (CurTok == tok_byref) { + IsRef = true; + getNextToken(); + } else if (CurTok == tok_byval) { + IsRef = false; + getNextToken(); + } + + if (CurTok != tok_identifier) { + fprintf(stderr, "Error: Expected argument name\n"); + return Args; + } + std::string Name = Lex.IdentifierStr; + getNextToken(); + + if (CurTok != tok_colon) { + fprintf(stderr, "Error: Expected ':' after argument name\n"); + return Args; + } + getNextToken(); + + std::string Type = "INTEGER"; + if (CurTok == tok_integer_kw) { + getNextToken(); + } else if (CurTok == tok_identifier) { + Type = Lex.IdentifierStr; + getNextToken(); + } else { + fprintf(stderr, "Error: Expected type (e.g. INTEGER) for argument '%s'\n", Name.c_str()); + return Args; + } + + Args.emplace_back(Name, Type, IsRef); + + if (CurTok == ')') break; + if (CurTok != ',') { + fprintf(stderr, "Error: Expected ',' or ')'\n"); + return Args; + } + getNextToken(); + } + getNextToken(); + return Args; +} + + +std::unique_ptr Parser::ParseFunction() { + getNextToken(); + std::string Name = Lex.IdentifierStr; + getNextToken(); + + auto Args = ParsePrototypeArgs(); + + std::string RetType = "INTEGER"; + if (CurTok == tok_returns) { + getNextToken(); + getNextToken(); + } + + auto Proto = std::make_unique(Name, std::move(Args), RetType); + + std::vector> Body; + while (CurTok != tok_endfunction && CurTok != tok_eof) { + auto Stmt = ParseStatement(); + if (Stmt) Body.push_back(std::move(Stmt)); + else if (CurTok != tok_eof && CurTok != tok_endfunction) getNextToken(); + } + getNextToken(); + + return std::make_unique(std::move(Proto), std::move(Body)); +} + +std::unique_ptr Parser::ParseProcedure() { + getNextToken(); + std::string Name = Lex.IdentifierStr; + getNextToken(); + + auto Args = ParsePrototypeArgs(); + auto Proto = std::make_unique(Name, std::move(Args), "VOID"); + + std::vector> Body; + while (CurTok != tok_endprocedure && CurTok != tok_eof) { + auto Stmt = ParseStatement(); + if (Stmt) Body.push_back(std::move(Stmt)); + else if (CurTok != tok_eof && CurTok != tok_endprocedure) getNextToken(); + } + getNextToken(); + + return std::make_unique(std::move(Proto), std::move(Body)); +} + +std::unique_ptr Parser::ParseCallStmt() { + getNextToken(); + std::string Callee = Lex.IdentifierStr; + getNextToken(); + + std::vector> Args; + if (CurTok == '(') { + getNextToken(); + while (CurTok != ')') { + auto Arg = ParseExpression(); + if (Arg) Args.push_back(std::move(Arg)); + + if (CurTok == ')') break; + if (CurTok != ',') { + fprintf(stderr, "Error: Expected ',' or ')' in call\n"); + return nullptr; + } + getNextToken(); + } + getNextToken(); + } + + return std::make_unique(Callee, std::move(Args)); +} + +std::unique_ptr Parser::ParseReturnStmt() { + getNextToken(); + std::unique_ptr Expr = nullptr; + if (CurTok != tok_endif && CurTok != tok_else && CurTok != tok_endfunction && CurTok != tok_endprocedure) { + Expr = ParseExpression(); + } + return std::make_unique(std::move(Expr)); +} diff --git a/lib/Parser/Parser_Function.cc b/lib/Parser/Parser_Function.cc deleted file mode 100644 index bdb4ee7..0000000 --- a/lib/Parser/Parser_Function.cc +++ /dev/null @@ -1,129 +0,0 @@ -#include "cps/Parser.h" -#include "cps/FunctionAST.h" - -using namespace cps; - -std::vector> Parser::ParsePrototypeArgs() { - std::vector> Args; - if (CurTok != '(') return Args; - getNextToken(); - - while (CurTok != ')') { - if (CurTok == -1000 || CurTok == -1001) getNextToken(); - - if (CurTok != tok_identifier) { - fprintf(stderr, "Error: Expected argument name\n"); - return Args; - } - std::string Name = Lex.IdentifierStr; - getNextToken(); - - if (CurTok != tok_colon) { - fprintf(stderr, "Error: Expected ':' after argument name\n"); - return Args; - } - getNextToken(); - - std::string Type = "INTEGER"; - if (CurTok == tok_integer_kw) { - getNextToken(); - } else if (CurTok == tok_identifier) { - Type = Lex.IdentifierStr; - getNextToken(); - } else { - fprintf(stderr, "Error: Expected type (e.g. INTEGER) for argument '%s'\n", Name.c_str()); - return Args; - } - - Args.push_back({Name, Type}); - - if (CurTok == ')') break; - if (CurTok != ',') { - fprintf(stderr, "Error: Expected ',' or ')'\n"); - return Args; - } - getNextToken(); - } - getNextToken(); - return Args; -} - - -std::unique_ptr Parser::ParseFunction() { - getNextToken(); - std::string Name = Lex.IdentifierStr; - getNextToken(); - - auto Args = ParsePrototypeArgs(); - - std::string RetType = "INTEGER"; - if (CurTok == tok_returns) { - getNextToken(); - getNextToken(); - } - - auto Proto = std::make_unique(Name, std::move(Args), RetType); - - std::vector> Body; - while (CurTok != tok_endfunction && CurTok != tok_eof) { - auto Stmt = ParseStatement(); - if (Stmt) Body.push_back(std::move(Stmt)); - else if (CurTok != tok_eof && CurTok != tok_endfunction) getNextToken(); - } - getNextToken(); - - return std::make_unique(std::move(Proto), std::move(Body)); -} - -std::unique_ptr Parser::ParseProcedure() { - getNextToken(); - std::string Name = Lex.IdentifierStr; - getNextToken(); - - auto Args = ParsePrototypeArgs(); - auto Proto = std::make_unique(Name, std::move(Args), "VOID"); - - std::vector> Body; - while (CurTok != tok_endprocedure && CurTok != tok_eof) { - auto Stmt = ParseStatement(); - if (Stmt) Body.push_back(std::move(Stmt)); - else if (CurTok != tok_eof && CurTok != tok_endprocedure) getNextToken(); - } - getNextToken(); - - return std::make_unique(std::move(Proto), std::move(Body)); -} - -std::unique_ptr Parser::ParseCallStmt() { - getNextToken(); - std::string Callee = Lex.IdentifierStr; - getNextToken(); - - std::vector> Args; - if (CurTok == '(') { - getNextToken(); - while (CurTok != ')') { - auto Arg = ParseExpression(); - if (Arg) Args.push_back(std::move(Arg)); - - if (CurTok == ')') break; - if (CurTok != ',') { - fprintf(stderr, "Error: Expected ',' or ')' in call\n"); - return nullptr; - } - getNextToken(); - } - getNextToken(); - } - - return std::make_unique(Callee, std::move(Args)); -} - -std::unique_ptr Parser::ParseReturnStmt() { - getNextToken(); - std::unique_ptr Expr = nullptr; - if (CurTok != tok_endif && CurTok != tok_else && CurTok != tok_endfunction && CurTok != tok_endprocedure) { - Expr = ParseExpression(); - } - return std::make_unique(std::move(Expr)); -} -- cgit v1.3.1-4-g156e