diff options
| -rw-r--r-- | AGENTS/SUBSYSTEMS.md | 9 | ||||
| -rw-r--r-- | include/cps/ArithmeticHandler.h | 8 | ||||
| -rw-r--r-- | lib/CodeGen/ArithmeticHandler.cc | 4 | ||||
| -rw-r--r-- | lib/CodeGen/CodeGen.cc | 3 | ||||
| -rw-r--r-- | lib/CodeGen/RuntimeCheck.cc | 7 |
5 files changed, 22 insertions, 9 deletions
diff --git a/AGENTS/SUBSYSTEMS.md b/AGENTS/SUBSYSTEMS.md index 0075222..d4d1189 100644 --- a/AGENTS/SUBSYSTEMS.md +++ b/AGENTS/SUBSYSTEMS.md @@ -51,10 +51,11 @@ FileHandler, is deliberately ignorant of user kinds). The enum range check after producer (constants, same-name copies, zero-init, memset-0 arrays) is valid by construction, which is why 0-based ordinals are load-bearing. -**Runtime checks** (`RuntimeCheck`): only array bounds checking and the file checks are -actually wired up. `emitDivZeroCheck` exists but has **zero call sites** — division by -zero (for `/`, DIV and MOD) is currently unchecked; the TODO sits in -`ArithmeticHandler.cc`. The public `emitErrorAndExit(Cond, Msg, ArrayRef<Value*>)` +**Runtime checks** (`RuntimeCheck`): array bounds, file misuse, enum ranges, null +dereferences and array-parameter bounds contracts are checked at their emit sites. +`ArithmeticHandler` calls `emitDivZeroCheck` before `/`, DIV and MOD; the check accepts +i64 and double divisors, including both floating-point signed zeros, and exits with +a `[Fatal]` diagnostic and status 1. The public `emitErrorAndExit(Cond, Msg, ArrayRef<Value*>)` overload exists for failure sites whose printf arguments (line, filename) are runtime values — FileHandler's helpers use it; the private compile-time-line form delegates to it. diff --git a/include/cps/ArithmeticHandler.h b/include/cps/ArithmeticHandler.h index ca6266d..af7394b 100644 --- a/include/cps/ArithmeticHandler.h +++ b/include/cps/ArithmeticHandler.h @@ -5,14 +5,18 @@ namespace cps { +class RuntimeCheck; + class ArithmeticHandler { llvm::LLVMContext &Context; llvm::IRBuilder<> &Builder; bool &HadError; + RuntimeCheck &RuntimeChecker; public: - ArithmeticHandler(llvm::LLVMContext &Ctx, llvm::IRBuilder<> &B, bool &HadErrorFlag) - : Context(Ctx), Builder(B), HadError(HadErrorFlag) {} + ArithmeticHandler(llvm::LLVMContext &Ctx, llvm::IRBuilder<> &B, bool &HadErrorFlag, + RuntimeCheck &RC) + : Context(Ctx), Builder(B), HadError(HadErrorFlag), RuntimeChecker(RC) {} llvm::Value *emitBinaryOp(int Op, llvm::Value *LHS, llvm::Value *RHS, int Line); }; diff --git a/lib/CodeGen/ArithmeticHandler.cc b/lib/CodeGen/ArithmeticHandler.cc index fa71e0c..b7f0665 100644 --- a/lib/CodeGen/ArithmeticHandler.cc +++ b/lib/CodeGen/ArithmeticHandler.cc @@ -1,5 +1,6 @@ #include "cps/ArithmeticHandler.h" #include "cps/Lexer.h" +#include "cps/RuntimeCheck.h" #include <cstdio> using namespace llvm; @@ -32,7 +33,7 @@ Value *ArithmeticHandler::emitBinaryOp(int Op, Value *LHS, Value *RHS, int Line) return nullptr; } - // TODO: DIV divide by 0 runtime check + RuntimeChecker.emitDivZeroCheck(RVal, Line); return Builder.CreateFDiv(LVal, RVal, "divtmp"); } @@ -42,6 +43,7 @@ Value *ArithmeticHandler::emitBinaryOp(int Op, Value *LHS, Value *RHS, int Line) HadError = true; return nullptr; } + RuntimeChecker.emitDivZeroCheck(RHS, Line); if (Op == tok_div) return Builder.CreateSDiv(LHS, RHS, "div_int_tmp"); if (Op == tok_mod) return Builder.CreateSRem(LHS, RHS, "mod_tmp"); } diff --git a/lib/CodeGen/CodeGen.cc b/lib/CodeGen/CodeGen.cc index a6669a6..d5942e9 100644 --- a/lib/CodeGen/CodeGen.cc +++ b/lib/CodeGen/CodeGen.cc @@ -85,7 +85,8 @@ CodeGen::CodeGen() { Symbols, HadError); - ArithHandler = std::make_unique<ArithmeticHandler>(*TheContext, *Builder, HadError); + ArithHandler = std::make_unique<ArithmeticHandler>(*TheContext, *Builder, HadError, + *RuntimeChecker); StrHandler = std::make_unique<StringHandler>(*TheContext, *Builder, *TheModule); StrConvHandler = std::make_unique<StringConversionHandler>(*TheContext, *Builder, *TheModule); Files = std::make_unique<FileHandler>(*TheContext, *Builder, *TheModule, *RuntimeChecker); diff --git a/lib/CodeGen/RuntimeCheck.cc b/lib/CodeGen/RuntimeCheck.cc index 40304fd..8075873 100644 --- a/lib/CodeGen/RuntimeCheck.cc +++ b/lib/CodeGen/RuntimeCheck.cc @@ -57,7 +57,12 @@ void RuntimeCheck::emitErrorAndExit(Value *Condition, Value *Msg, ArrayRef<Value } void RuntimeCheck::emitDivZeroCheck(Value *Divisor, int Line) { - Value *IsZero = Builder.CreateICmpEQ(Divisor, ConstantInt::get(TheContext, APInt(64, 0)), "is_zero"); + Value *IsZero; + if (Divisor->getType()->isDoubleTy()) { + IsZero = Builder.CreateFCmpOEQ(Divisor, ConstantFP::get(Divisor->getType(), 0.0), "is_zero"); + } else { + IsZero = Builder.CreateICmpEQ(Divisor, ConstantInt::get(Divisor->getType(), 0), "is_zero"); + } emitErrorAndExit(IsZero, DivZeroMsg, Line); } |
