diff options
| author | Mike Stump <mrs@apple.com> | 2009-12-12 01:27:46 +0000 |
|---|---|---|
| committer | Mike Stump <mrs@apple.com> | 2009-12-12 01:27:46 +0000 |
| commit | 9c276ae0f24d4cee8f7954069d4b8eae45d0447d (patch) | |
| tree | 967ccefb7c10869562faaa2dd6f5b9feb43c8ce7 /lib/CodeGen/CGExpr.cpp | |
| parent | 498eb7ece2a5699e215acf071040de27d7882931 (diff) | |
Implement runtime checks for undefined behavior. WIP.
This implements a new flag -fcatch-undefined-behavior. The flag turns
on additional runtime checks for:
T a[I];
a[i] abort when i < 0 or i >= I.
Future stuff includes shifts by >= bitwidth amounts.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91198 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExpr.cpp')
| -rw-r--r-- | lib/CodeGen/CGExpr.cpp | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 70fa004de8..722ec868f5 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1012,6 +1012,36 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) { } } +static llvm::Constant *getAbortFn(CodeGenFunction &CGF) { + // void abort(); + + const llvm::FunctionType *FTy = + llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false); + + return CGF.CGM.CreateRuntimeFunction(FTy, "abort"); +} + +llvm::BasicBlock*CodeGenFunction::getAbortBB() { + if (AbortBB) + return AbortBB; + + llvm::BasicBlock *Cont = 0; + if (HaveInsertPoint()) { + Cont = createBasicBlock("cont"); + EmitBranch(Cont); + } + AbortBB = createBasicBlock("abort"); + EmitBlock(AbortBB); + llvm::CallInst *AbortCall = Builder.CreateCall(getAbortFn(*this)); + AbortCall->setDoesNotReturn(); + AbortCall->setDoesNotThrow(); + Builder.CreateUnreachable(); + + if (Cont) + EmitBlock(Cont); + return AbortBB; +} + LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { // The index must always be an integer, which is not an aggregate. Emit it. llvm::Value *Idx = EmitScalarExpr(E->getIdx()); @@ -1040,6 +1070,37 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) { llvm::IntegerType::get(VMContext, LLVMPointerWidth), IdxSigned, "idxprom"); + if (CatchUndefined) { + if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E->getBase())) { + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr())) { + if (ICE->getCastKind() == CastExpr::CK_ArrayToPointerDecay) { + if (const ConstantArrayType *CAT + = getContext().getAsConstantArrayType(DRE->getType())) { + llvm::APInt Size = CAT->getSize(); + llvm::BasicBlock *Cont = createBasicBlock("cont"); + if (IdxSigned) { + Builder.CreateCondBr(Builder.CreateICmpSGE(Idx, + llvm::ConstantInt::get(Idx->getType(), 0)), + Cont, getAbortBB()); + EmitBlock(Cont); + Cont = createBasicBlock("cont"); + Builder.CreateCondBr(Builder.CreateICmpSLT(Idx, + llvm::ConstantInt::get(Idx->getType(), Size)), + Cont, getAbortBB()); + EmitBlock(Cont); + } else { + llvm::BasicBlock *Cont = createBasicBlock("cont"); + Builder.CreateCondBr(Builder.CreateICmpULT(Idx, + llvm::ConstantInt::get(Idx->getType(), Size)), + Cont, getAbortBB()); + EmitBlock(Cont); + } + } + } + } + } + } + // We know that the pointer points to a type of the correct size, unless the // size is a VLA or Objective-C interface. llvm::Value *Address = 0; |
