aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/RuntimeCheck.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/RuntimeCheck.cc')
-rw-r--r--lib/CodeGen/RuntimeCheck.cc59
1 files changed, 10 insertions, 49 deletions
diff --git a/lib/CodeGen/RuntimeCheck.cc b/lib/CodeGen/RuntimeCheck.cc
index 8075873..ee270e5 100644
--- a/lib/CodeGen/RuntimeCheck.cc
+++ b/lib/CodeGen/RuntimeCheck.cc
@@ -1,4 +1,5 @@
#include "cps/RuntimeCheck.h"
+#include "cps/ExceptionHandler.h"
#include "cps/TypeSystem.h" // kEnumOrdinalBase
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
@@ -7,52 +8,16 @@
using namespace llvm;
using namespace cps;
-RuntimeCheck::RuntimeCheck(Module &M, LLVMContext &C, IRBuilder<> &B)
- : TheModule(M), TheContext(C), Builder(B) {
- setupExternalFunctions();
-}
-
-void RuntimeCheck::setupExternalFunctions() {
- std::vector<Type*> PrintfArgs;
- PrintfArgs.push_back(PointerType::getUnqual(TheContext));
- FunctionType *PrintfType = FunctionType::get(Type::getInt32Ty(TheContext), PrintfArgs, true);
- PrintfFunc = TheModule.getOrInsertFunction("printf", PrintfType);
-
- std::vector<Type*> ExitArgs;
- ExitArgs.push_back(Type::getInt32Ty(TheContext));
- FunctionType *ExitType = FunctionType::get(Type::getVoidTy(TheContext), ExitArgs, false);
- ExitFunc = TheModule.getOrInsertFunction("exit", ExitType);
-
- DivZeroMsg = Builder.CreateGlobalStringPtr("[Fatal] line %d: Division by zero\n", "err_div_zero", 0, &TheModule);
- OutOfBoundsMsg = Builder.CreateGlobalStringPtr("[Fatal] line %d: Array index out of bounds\n", "err_bounds", 0, &TheModule);
- EnumRangeMsg = Builder.CreateGlobalStringPtr("[Fatal] line %d: Value out of range for enum %s\n", "err_enum_range", 0, &TheModule);
- NullDerefMsg = Builder.CreateGlobalStringPtr("[Fatal] line %d: Dereference of an unset pointer\n", "err_null_deref", 0, &TheModule);
- ArrayArgBoundsMsg = Builder.CreateGlobalStringPtr(
- "[Fatal] line %d: Array argument bounds [%lld:%lld] do not match the declared parameter bounds [%lld:%lld]\n",
- "err_arr_arg_bounds", 0, &TheModule);
-}
-
-void RuntimeCheck::emitErrorAndExit(Value *Condition, Value *Msg, int Line) {
- emitErrorAndExit(Condition, Msg, {ConstantInt::get(TheContext, APInt(32, Line))});
-}
+RuntimeCheck::RuntimeCheck(LLVMContext &C, IRBuilder<> &B, ExceptionHandler &EH)
+ : TheContext(C), Builder(B), Exceptions(EH) {}
-void RuntimeCheck::emitErrorAndExit(Value *Condition, Value *Msg, ArrayRef<Value *> FmtArgs) {
+void RuntimeCheck::emitCheck(Value *Condition) {
Function *TheFunction = Builder.GetInsertBlock()->getParent();
-
BasicBlock *FailBB = BasicBlock::Create(TheContext, "check_fail", TheFunction);
BasicBlock *ContBB = BasicBlock::Create(TheContext, "check_cont", TheFunction);
-
Builder.CreateCondBr(Condition, FailBB, ContBB);
-
Builder.SetInsertPoint(FailBB);
- std::vector<Value*> PrintArgs;
- PrintArgs.push_back(Msg);
- PrintArgs.insert(PrintArgs.end(), FmtArgs.begin(), FmtArgs.end());
- Builder.CreateCall(PrintfFunc, PrintArgs);
-
- Builder.CreateCall(ExitFunc, ConstantInt::get(TheContext, APInt(32, 1)));
- Builder.CreateUnreachable();
-
+ Exceptions.emitThrow();
Builder.SetInsertPoint(ContBB);
}
@@ -63,7 +28,7 @@ void RuntimeCheck::emitDivZeroCheck(Value *Divisor, int Line) {
} else {
IsZero = Builder.CreateICmpEQ(Divisor, ConstantInt::get(Divisor->getType(), 0), "is_zero");
}
- emitErrorAndExit(IsZero, DivZeroMsg, Line);
+ emitCheck(IsZero);
}
void RuntimeCheck::emitIndexCheck(Value *Index, Value *Lower, Value *Upper, int Line) {
@@ -71,7 +36,7 @@ void RuntimeCheck::emitIndexCheck(Value *Index, Value *Lower, Value *Upper, int
Value *TooHigh = Builder.CreateICmpSGT(Index, Upper, "too_high");
Value *OutOfBounds = Builder.CreateOr(TooLow, TooHigh, "out_of_bounds");
- emitErrorAndExit(OutOfBounds, OutOfBoundsMsg, Line);
+ emitCheck(OutOfBounds);
}
void RuntimeCheck::emitEnumRangeCheck(Value *Ordinal, uint64_t ValueCount,
@@ -83,16 +48,14 @@ void RuntimeCheck::emitEnumRangeCheck(Value *Ordinal, uint64_t ValueCount,
Value *TooHigh = Builder.CreateICmpSGE(Ordinal, Hi, "enum_too_high");
Value *OutOfRange = Builder.CreateOr(TooLow, TooHigh, "enum_out_of_range");
- Value *NameStr = Builder.CreateGlobalStringPtr(TypeName, "enum_name", 0, &TheModule);
- emitErrorAndExit(OutOfRange, EnumRangeMsg,
- {ConstantInt::get(TheContext, APInt(32, Line)), NameStr});
+ emitCheck(OutOfRange);
}
void RuntimeCheck::emitNullDerefCheck(Value *Ptr, int Line) {
Value *IsNull = Builder.CreateICmpEQ(Ptr,
ConstantPointerNull::get(PointerType::getUnqual(TheContext)),
"ptr_is_null");
- emitErrorAndExit(IsNull, NullDerefMsg, Line);
+ emitCheck(IsNull);
}
void RuntimeCheck::emitArrayArgBoundsCheck(Value *ActualLower, Value *ActualUpper,
@@ -104,7 +67,5 @@ void RuntimeCheck::emitArrayArgBoundsCheck(Value *ActualLower, Value *ActualUppe
Value *HiDiff = Builder.CreateICmpNE(ActualUpper, DeclHi, "arg_hi_ne");
Value *Mismatch = Builder.CreateOr(LoDiff, HiDiff, "arg_bounds_ne");
- emitErrorAndExit(Mismatch, ArrayArgBoundsMsg,
- {ConstantInt::get(TheContext, APInt(32, Line)),
- ActualLower, ActualUpper, DeclLo, DeclHi});
+ emitCheck(Mismatch);
}