aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
author_ov4 <hausemasterstream@gmail.com>2026-02-02 08:45:01 +0000
committer_ov4 <hausemasterstream@gmail.com>2026-02-02 08:45:01 +0000
commit419420770c4545ea4010047ef2153004d4700eed (patch)
treebd19eed681dbb68ecb501b6cfc220c42a9803ef3 /lib/CodeGen
parentecc0fc463ba54dd0cbe33bc14415f432eaa959de (diff)
Added REAL and BOOLEAN types, DIV and MOD operators
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/ArithmeticHandler.cc67
-rw-r--r--lib/CodeGen/BooleanHandler.cc16
-rw-r--r--lib/CodeGen/CodeGen.cc110
-rw-r--r--lib/CodeGen/IntegerHandler.cc16
-rw-r--r--lib/CodeGen/RealHandler.cc16
5 files changed, 194 insertions, 31 deletions
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 <cstdio>
+
+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<FunctionGen>(*TheContext, *TheModule, *Builder, NamedValues);
+ IntHandler = std::make_unique<IntegerHandler>(*TheContext, *Builder, *TheModule, NamedValues);
+ RealHelper = std::make_unique<RealHandler>(*TheContext, *Builder, *TheModule, NamedValues);
+ BoolHandler = std::make_unique<BooleanHandler>(*TheContext, *Builder, *TheModule, NamedValues);
+ ArithHandler = std::make_unique<ArithmeticHandler>(*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<NumberExprAST*>(Expr)) {
- return ConstantInt::get(*TheContext, APInt(64, Num->getVal(), true));
+ if (auto *Num = dynamic_cast<IntegerExprAST*>(Expr)) {
+ return IntHandler->createLiteral(Num->getVal());
+ }
+
+ if (auto *Real = dynamic_cast<RealExprAST*>(Expr)) {
+ return RealHelper->createLiteral(Real->getVal());
+ }
+
+ if (auto *Bool = dynamic_cast<BooleanExprAST*>(Expr)) {
+ return BoolHandler->createLiteral(Bool->getVal());
}
if (auto *Var = dynamic_cast<VariableExprAST*>(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<AllocaInst>(A)->getAllocatedType();
+ return Builder->CreateLoad(AllocType, A, Var->getName().c_str());
}
-
if (auto *ArrAcc = dynamic_cast<ArrayAccessExprAST*>(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<CallExprAST*>(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<NumberExprAST*>(Stmt->getStep())) {
+ if (auto *Num = dynamic_cast<IntegerExprAST*>(Stmt->getStep())) {
if (Num->getVal() < 0) isNegativeStep = true;
}
}
@@ -353,10 +364,12 @@ void CodeGen::emitStmt(StmtAST *Stmt) {
}
if (auto *Decl = dynamic_cast<DeclareStmtAST*>(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<AssignStmtAST*>(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<AllocaInst>(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<InputStmtAST*>(Stmt)) {
Value *Alloca = NamedValues[In->getName()];
if (Alloca) {
+ AllocaInst *AI = cast<AllocaInst>(Alloca);
std::vector<Value*> 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<OutputStmtAST*>(Stmt)) {
@@ -385,8 +423,18 @@ void CodeGen::emitStmt(StmtAST *Stmt) {
Value *Val = emitExpr(Out->getExpr());
if (Val) {
std::vector<Value*> 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));
+}