diff options
Diffstat (limited to 'lib/CodeGen/RuntimeCheck.cc')
| -rw-r--r-- | lib/CodeGen/RuntimeCheck.cc | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/lib/CodeGen/RuntimeCheck.cc b/lib/CodeGen/RuntimeCheck.cc index c2ced87..e6d4bf8 100644 --- a/lib/CodeGen/RuntimeCheck.cc +++ b/lib/CodeGen/RuntimeCheck.cc @@ -1,4 +1,5 @@ #include "cps/RuntimeCheck.h" +#include "cps/TypeSystem.h" // kEnumOrdinalBase #include "llvm/IR/Function.h" #include "llvm/IR/Type.h" #include "llvm/IR/Constants.h" @@ -24,6 +25,8 @@ void RuntimeCheck::setupExternalFunctions() { 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); } void RuntimeCheck::emitErrorAndExit(Value *Condition, Value *Msg, int Line) { @@ -59,6 +62,27 @@ void RuntimeCheck::emitIndexCheck(Value *Index, Value *Lower, Value *Upper, int Value *TooLow = Builder.CreateICmpSLT(Index, Lower, "too_low"); Value *TooHigh = Builder.CreateICmpSGT(Index, Upper, "too_high"); Value *OutOfBounds = Builder.CreateOr(TooLow, TooHigh, "out_of_bounds"); - + emitErrorAndExit(OutOfBounds, OutOfBoundsMsg, Line); } + +void RuntimeCheck::emitEnumRangeCheck(Value *Ordinal, uint64_t ValueCount, + const std::string &TypeName, int Line) { + Value *Lo = ConstantInt::get(TheContext, APInt(64, static_cast<uint64_t>(kEnumOrdinalBase), true)); + Value *Hi = ConstantInt::get(TheContext, + APInt(64, static_cast<uint64_t>(kEnumOrdinalBase) + ValueCount, true)); + Value *TooLow = Builder.CreateICmpSLT(Ordinal, Lo, "enum_too_low"); + 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}); +} + +void RuntimeCheck::emitNullDerefCheck(Value *Ptr, int Line) { + Value *IsNull = Builder.CreateICmpEQ(Ptr, + ConstantPointerNull::get(PointerType::getUnqual(TheContext)), + "ptr_is_null"); + emitErrorAndExit(IsNull, NullDerefMsg, Line); +} |
