From 419420770c4545ea4010047ef2153004d4700eed Mon Sep 17 00:00:00 2001 From: _ov4 Date: Mon, 2 Feb 2026 08:45:01 +0000 Subject: Added REAL and BOOLEAN types, DIV and MOD operators --- lib/CodeGen/ArithmeticHandler.cc | 67 ++++++++++++++++++++++++ lib/CodeGen/BooleanHandler.cc | 16 ++++++ lib/CodeGen/CodeGen.cc | 110 ++++++++++++++++++++++++++++----------- lib/CodeGen/IntegerHandler.cc | 16 ++++++ lib/CodeGen/RealHandler.cc | 16 ++++++ 5 files changed, 194 insertions(+), 31 deletions(-) create mode 100644 lib/CodeGen/ArithmeticHandler.cc create mode 100644 lib/CodeGen/BooleanHandler.cc create mode 100644 lib/CodeGen/IntegerHandler.cc create mode 100644 lib/CodeGen/RealHandler.cc (limited to 'lib/CodeGen') diff --git a/lib/CodeGen/ArithmeticHandler.cc b/lib/CodeGen/ArithmeticHandler.cc new file mode 100644 index 0000000..762f0a3 --- /dev/null +++ b/lib/CodeGen/ArithmeticHandler.cc @@ -0,0 +1,67 @@ +#include "cps/ArithmeticHandler.h" +#include + +using namespace llvm; +using namespace cps; + +Value *ArithmeticHandler::emitBinaryOp(int Op, Value *LHS, Value *RHS, int Line) { + bool LIsInt = LHS->getType()->isIntegerTy(64); + bool RIsInt = RHS->getType()->isIntegerTy(64); + bool LIsDouble = LHS->getType()->isDoubleTy(); + bool RIsDouble = RHS->getType()->isDoubleTy(); + + if (Op == '/') { + Value *LVal = LHS; + Value *RVal = RHS; + if (LIsInt) LVal = Builder.CreateSIToFP(LHS, Type::getDoubleTy(Context)); + if (RIsInt) RVal = Builder.CreateSIToFP(RHS, Type::getDoubleTy(Context)); + + // TODO: DIV divide by 0 runtime check + return Builder.CreateFDiv(LVal, RVal, "divtmp"); + } + + // DIV / MOD : Only Integer. + if (Op == tok_div || Op == tok_mod) { + if (!LIsInt || !RIsInt) { + fprintf(stderr, "Error: DIV and MOD operators require INTEGER operands.\n"); + return nullptr; + } + if (Op == tok_div) return Builder.CreateSDiv(LHS, RHS, "div_int_tmp"); + if (Op == tok_mod) return Builder.CreateSRem(LHS, RHS, "mod_tmp"); + } + + if (LIsDouble || RIsDouble) { + Value *LVal = LHS; + Value *RVal = RHS; + if (LIsInt) LVal = Builder.CreateSIToFP(LHS, Type::getDoubleTy(Context)); + if (RIsInt) RVal = Builder.CreateSIToFP(RHS, Type::getDoubleTy(Context)); + + switch (Op) { + case '+': return Builder.CreateFAdd(LVal, RVal, "addtmp"); + case '-': return Builder.CreateFSub(LVal, RVal, "subtmp"); + case '*': return Builder.CreateFMul(LVal, RVal, "multmp"); + + case tok_eq: return Builder.CreateFCmpOEQ(LVal, RVal, "eqtmp"); + case tok_ne: return Builder.CreateFCmpONE(LVal, RVal, "netmp"); + case '<': return Builder.CreateFCmpOLT(LVal, RVal, "slttmp"); + case '>': return Builder.CreateFCmpOGT(LVal, RVal, "sgttmp"); + case tok_le: return Builder.CreateFCmpOLE(LVal, RVal, "sletmp"); + case tok_ge: return Builder.CreateFCmpOGE(LVal, RVal, "sgetmp"); + } + } else { + switch (Op) { + case '+': return Builder.CreateAdd(LHS, RHS, "addtmp"); + case '-': return Builder.CreateSub(LHS, RHS, "subtmp"); + case '*': return Builder.CreateMul(LHS, RHS, "multmp"); + + case tok_eq: return Builder.CreateICmpEQ(LHS, RHS, "eqtmp"); + case tok_ne: return Builder.CreateICmpNE(LHS, RHS, "netmp"); + case '<': return Builder.CreateICmpSLT(LHS, RHS, "slttmp"); + case '>': return Builder.CreateICmpSGT(LHS, RHS, "sgttmp"); + case tok_le: return Builder.CreateICmpSLE(LHS, RHS, "sletmp"); + case tok_ge: return Builder.CreateICmpSGE(LHS, RHS, "sgetmp"); + } + } + + return nullptr; +} diff --git a/lib/CodeGen/BooleanHandler.cc b/lib/CodeGen/BooleanHandler.cc new file mode 100644 index 0000000..558ac95 --- /dev/null +++ b/lib/CodeGen/BooleanHandler.cc @@ -0,0 +1,16 @@ +#include "cps/BooleanHandler.h" + +using namespace llvm; +using namespace cps; + +void BooleanHandler::emitDeclare(const std::string &Name) { + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin()); + AllocaInst *Alloca = TmpB.CreateAlloca(Type::getInt1Ty(Context), nullptr, Name); + Builder.CreateStore(ConstantInt::get(Context, APInt(1, 0)), Alloca); + NamedValues[Name] = Alloca; +} + +Value *BooleanHandler::createLiteral(bool Val) { + return ConstantInt::get(Context, APInt(1, Val ? 1 : 0)); +} diff --git a/lib/CodeGen/CodeGen.cc b/lib/CodeGen/CodeGen.cc index bfbd8e0..da6b005 100644 --- a/lib/CodeGen/CodeGen.cc +++ b/lib/CodeGen/CodeGen.cc @@ -1,6 +1,7 @@ #include "cps/CodeGen.h" #include "cps/ArrayHandler.h" #include "llvm/IR/Verifier.h" +#include "llvm/IR/Instructions.h" #include "cps/Lexer.h" using namespace llvm; @@ -19,6 +20,11 @@ CodeGen::CodeGen() { FuncGen = std::make_unique(*TheContext, *TheModule, *Builder, NamedValues); + IntHandler = std::make_unique(*TheContext, *Builder, *TheModule, NamedValues); + RealHelper = std::make_unique(*TheContext, *Builder, *TheModule, NamedValues); + BoolHandler = std::make_unique(*TheContext, *Builder, *TheModule, NamedValues); + ArithHandler = std::make_unique(*TheContext, *Builder); + SetupExternalFunctions(); } @@ -32,7 +38,14 @@ void CodeGen::SetupExternalFunctions() { ScanfFunc = TheModule->getOrInsertFunction("scanf", ScanfType); PrintfFormatStr = Builder->CreateGlobalStringPtr("%lld\n", "fmt_nl", 0, TheModule.get()); + PrintfFloatFormatStr = Builder->CreateGlobalStringPtr("%f\n", "fmt_flt", 0, TheModule.get()); + PrintfStringFormatStr = Builder->CreateGlobalStringPtr("%s\n", "fmt_str", 0, TheModule.get()); + ScanfFormatStr = Builder->CreateGlobalStringPtr("%lld", "fmt_in", 0, TheModule.get()); + ScanfFloatFormatStr = Builder->CreateGlobalStringPtr("%lf", "fmt_in_flt", 0, TheModule.get()); + + TrueStr = Builder->CreateGlobalStringPtr("TRUE", "str_true", 0, TheModule.get()); + FalseStr = Builder->CreateGlobalStringPtr("FALSE", "str_false", 0, TheModule.get()); Arrays->setupExternalFunctions(); } @@ -65,8 +78,16 @@ void CodeGen::print() { Value *CodeGen::emitExpr(ExprAST *Expr) { if (!Expr) return nullptr; - if (auto *Num = dynamic_cast(Expr)) { - return ConstantInt::get(*TheContext, APInt(64, Num->getVal(), true)); + if (auto *Num = dynamic_cast(Expr)) { + return IntHandler->createLiteral(Num->getVal()); + } + + if (auto *Real = dynamic_cast(Expr)) { + return RealHelper->createLiteral(Real->getVal()); + } + + if (auto *Bool = dynamic_cast(Expr)) { + return BoolHandler->createLiteral(Bool->getVal()); } if (auto *Var = dynamic_cast(Expr)) { @@ -76,9 +97,9 @@ Value *CodeGen::emitExpr(ExprAST *Expr) { return nullptr; } - return Builder->CreateLoad(Type::getInt64Ty(*TheContext), A, Var->getName().c_str()); + Type *AllocType = cast(A)->getAllocatedType(); + return Builder->CreateLoad(AllocType, A, Var->getName().c_str()); } - if (auto *ArrAcc = dynamic_cast(Expr)) { return Arrays->emitArrayAccess(ArrAcc, *this); @@ -89,23 +110,7 @@ Value *CodeGen::emitExpr(ExprAST *Expr) { Value *R = emitExpr(Bin->getRHS()); if (!L || !R) return nullptr; - switch (Bin->getOp()) { - case '+': return Builder->CreateAdd(L, R, "addtmp"); - case '-': return Builder->CreateSub(L, R, "subtmp"); - case '*': return Builder->CreateMul(L, R, "multmp"); - case '/': - RuntimeChecker->emitDivZeroCheck(R, Bin->getLine()); - return Builder->CreateSDiv(L, R, "divtmp"); - case tok_eq: return Builder->CreateICmpEQ(L, R, "eqtmp"); - case tok_ne: return Builder->CreateICmpNE(L, R, "netmp"); - case '<': return Builder->CreateICmpSLT(L, R, "slttmp"); - case '>': return Builder->CreateICmpSGT(L, R, "sgttmp"); - case tok_le: return Builder->CreateICmpSLE(L, R, "sletmp"); - case tok_ge: return Builder->CreateICmpSGE(L, R, "sgetmp"); - default: - fprintf(stderr, "Error: Invalid binary operator\n"); - return nullptr; - } + return ArithHandler->emitBinaryOp(Bin->getOp(), L, R, Bin->getLine()); } if (auto *Call = dynamic_cast(Expr)) { @@ -150,6 +155,8 @@ void CodeGen::emitIfStmt(IfStmtAST *Stmt) { if (CondV->getType()->isIntegerTy(64)) CondV = Builder->CreateICmpNE(CondV, ConstantInt::get(*TheContext, APInt(64, 0)), "ifcond"); + if (CondV->getType()->isIntegerTy(1)) + CondV = Builder->CreateICmpNE(CondV, ConstantInt::get(*TheContext, APInt(1, 0)), "ifcond"); Function *TheFunction = Builder->GetInsertBlock()->getParent(); BasicBlock *ThenBB = BasicBlock::Create(*TheContext, "then", TheFunction); @@ -183,6 +190,8 @@ void CodeGen::emitWhileStmt(WhileStmtAST *Stmt) { if (!CondV) return; if (CondV->getType()->isIntegerTy(64)) CondV = Builder->CreateICmpNE(CondV, ConstantInt::get(*TheContext, APInt(64, 0)), "loopcond"); + if (CondV->getType()->isIntegerTy(1)) + CondV = Builder->CreateICmpNE(CondV, ConstantInt::get(*TheContext, APInt(1, 0)), "loopcond"); Builder->CreateCondBr(CondV, LoopBB, AfterBB); @@ -215,6 +224,8 @@ void CodeGen::emitRepeatStmt(RepeatStmtAST *Stmt) { if (CondV->getType()->isIntegerTy(64)) CondV = Builder->CreateICmpNE(CondV, ConstantInt::get(*TheContext, APInt(64, 0)), "untilcond"); + if (CondV->getType()->isIntegerTy(1)) + CondV = Builder->CreateICmpNE(CondV, ConstantInt::get(*TheContext, APInt(1, 0)), "untilcond"); Builder->CreateCondBr(CondV, AfterBB, LoopBB); @@ -249,7 +260,7 @@ void CodeGen::emitForStmt(ForStmtAST *Stmt) { bool isNegativeStep = false; if (Stmt->getStep()) { - if (auto *Num = dynamic_cast(Stmt->getStep())) { + if (auto *Num = dynamic_cast(Stmt->getStep())) { if (Num->getVal() < 0) isNegativeStep = true; } } @@ -353,10 +364,12 @@ void CodeGen::emitStmt(StmtAST *Stmt) { } if (auto *Decl = dynamic_cast(Stmt)) { - Function *TheFunction = Builder->GetInsertBlock()->getParent(); - AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Decl->getName()); - NamedValues[Decl->getName()] = Alloca; - Builder->CreateStore(ConstantInt::get(*TheContext, APInt(64, 0)), Alloca); + if (Decl->getType() == "INTEGER") IntHandler->emitDeclare(Decl->getName()); + else if (Decl->getType() == "REAL") RealHelper->emitDeclare(Decl->getName()); + else if (Decl->getType() == "BOOLEAN") BoolHandler->emitDeclare(Decl->getName()); + else { + fprintf(stderr, "Unknown type %s\n", Decl->getType().c_str()); + } } else if (auto *Assign = dynamic_cast(Stmt)) { Value *Val = emitExpr(Assign->getExpr()); @@ -366,16 +379,41 @@ void CodeGen::emitStmt(StmtAST *Stmt) { fprintf(stderr, "Error: Unknown variable name %s\n", Assign->getName().c_str()); return; } + + AllocaInst *AI = cast(Alloca); + + if (AI->getAllocatedType() == Type::getDoubleTy(*TheContext) && Val->getType()->isIntegerTy(64)) { + Val = Builder->CreateSIToFP(Val, Type::getDoubleTy(*TheContext)); + } Builder->CreateStore(Val, Alloca); } } else if (auto *In = dynamic_cast(Stmt)) { Value *Alloca = NamedValues[In->getName()]; if (Alloca) { + AllocaInst *AI = cast(Alloca); std::vector Args; - Args.push_back(ScanfFormatStr); - Args.push_back(Alloca); - Builder->CreateCall(ScanfFunc, Args); + + if (AI->getAllocatedType()->isDoubleTy()) { + Args.push_back(ScanfFloatFormatStr); + Args.push_back(Alloca); + Builder->CreateCall(ScanfFunc, Args); + } else if (AI->getAllocatedType()->isIntegerTy(1)) { + AllocaInst *TempInt = CreateEntryBlockAlloca(Builder->GetInsertBlock()->getParent(), "tmp_bool_input"); + + Args.push_back(ScanfFormatStr); + Args.push_back(TempInt); + Builder->CreateCall(ScanfFunc, Args); + + Value *Val = Builder->CreateLoad(Type::getInt64Ty(*TheContext), TempInt); + Value *BoolVal = Builder->CreateICmpNE(Val, ConstantInt::get(*TheContext, APInt(64, 0)), "bool_cast"); + + Builder->CreateStore(BoolVal, Alloca); + } else { + Args.push_back(ScanfFormatStr); + Args.push_back(Alloca); + Builder->CreateCall(ScanfFunc, Args); + } } } else if (auto *Out = dynamic_cast(Stmt)) { @@ -385,8 +423,18 @@ void CodeGen::emitStmt(StmtAST *Stmt) { Value *Val = emitExpr(Out->getExpr()); if (Val) { std::vector Args; - Args.push_back(PrintfFormatStr); - Args.push_back(Val); + if (Val->getType()->isDoubleTy()) { + Args.push_back(PrintfFloatFormatStr); + Args.push_back(Val); + } else if (Val->getType()->isIntegerTy(1)) { + Args.push_back(PrintfStringFormatStr); + Value *StrPtr = Builder->CreateSelect(Val, TrueStr, FalseStr); + Args.push_back(StrPtr); + } else { + Args.push_back(PrintfFormatStr); + Args.push_back(Val); + } + Builder->CreateCall(PrintfFunc, Args); } } diff --git a/lib/CodeGen/IntegerHandler.cc b/lib/CodeGen/IntegerHandler.cc new file mode 100644 index 0000000..8161593 --- /dev/null +++ b/lib/CodeGen/IntegerHandler.cc @@ -0,0 +1,16 @@ +#include "cps/IntegerHandler.h" + +using namespace llvm; +using namespace cps; + +void IntegerHandler::emitDeclare(const std::string &Name) { + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin()); + AllocaInst *Alloca = TmpB.CreateAlloca(Type::getInt64Ty(Context), nullptr, Name); + Builder.CreateStore(ConstantInt::get(Context, APInt(64, 0)), Alloca); + NamedValues[Name] = Alloca; +} + +Value *IntegerHandler::createLiteral(int64_t Val) { + return ConstantInt::get(Context, APInt(64, Val, true)); +} diff --git a/lib/CodeGen/RealHandler.cc b/lib/CodeGen/RealHandler.cc new file mode 100644 index 0000000..a73dee2 --- /dev/null +++ b/lib/CodeGen/RealHandler.cc @@ -0,0 +1,16 @@ +#include "cps/RealHandler.h" + +using namespace llvm; +using namespace cps; + +void RealHandler::emitDeclare(const std::string &Name) { + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin()); + AllocaInst *Alloca = TmpB.CreateAlloca(Type::getDoubleTy(Context), nullptr, Name); + Builder.CreateStore(ConstantFP::get(Context, APFloat(0.0)), Alloca); + NamedValues[Name] = Alloca; +} + +Value *RealHandler::createLiteral(double Val) { + return ConstantFP::get(Context, APFloat(Val)); +} -- cgit v1.3.1-4-g156e