diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGBuiltin.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 24 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 12 |
5 files changed, 36 insertions, 13 deletions
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index e8c05d3a46..6067408403 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -409,7 +409,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, if (getLangOpts().SanitizeUnreachable) EmitCheck(Builder.getFalse(), "builtin_unreachable", EmitCheckSourceLocation(E->getExprLoc()), - llvm::ArrayRef<llvm::Value *>()); + llvm::ArrayRef<llvm::Value *>(), CRK_Unrecoverable); else Builder.CreateUnreachable(); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index ad6e3beea3..ef17bdc1de 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -533,7 +533,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, llvm::ConstantInt::get(SizeTy, AlignVal), llvm::ConstantInt::get(Int8Ty, TCK) }; - EmitCheck(Cond, "type_mismatch", StaticData, Address); + EmitCheck(Cond, "type_mismatch", StaticData, Address, CRK_Recoverable); } // If possible, check that the vptr indicates that there is a subobject of @@ -586,7 +586,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, }; llvm::Value *DynamicData[] = { Address, Hash }; EmitCheck(Builder.CreateICmpEQ(CacheVal, Hash), - "dynamic_type_cache_miss", StaticData, DynamicData, true); + "dynamic_type_cache_miss", StaticData, DynamicData, + CRK_AlwaysRecoverable); } } @@ -2023,7 +2024,7 @@ llvm::Constant *CodeGenFunction::EmitCheckSourceLocation(SourceLocation Loc) { void CodeGenFunction::EmitCheck(llvm::Value *Checked, StringRef CheckName, llvm::ArrayRef<llvm::Constant *> StaticArgs, llvm::ArrayRef<llvm::Value *> DynamicArgs, - bool Recoverable) { + CheckRecoverableKind RecoverKind) { llvm::BasicBlock *Cont = createBasicBlock("cont"); llvm::BasicBlock *Handler = createBasicBlock("handler." + CheckName); @@ -2051,20 +2052,29 @@ void CodeGenFunction::EmitCheck(llvm::Value *Checked, StringRef CheckName, ArgTypes.push_back(IntPtrTy); } + bool Recover = (RecoverKind == CRK_AlwaysRecoverable) || + ((RecoverKind == CRK_Recoverable) && + CGM.getCodeGenOpts().SanitizeRecover); + llvm::FunctionType *FnType = llvm::FunctionType::get(CGM.VoidTy, ArgTypes, false); llvm::AttrBuilder B; - if (!Recoverable) { + if (!Recover) { B.addAttribute(llvm::Attributes::NoReturn) .addAttribute(llvm::Attributes::NoUnwind); } B.addAttribute(llvm::Attributes::UWTable); - llvm::Value *Fn = CGM.CreateRuntimeFunction(FnType, - ("__ubsan_handle_" + CheckName).str(), + + // Checks that have two variants use a suffix to differentiate them + bool NeedsAbortSuffix = (RecoverKind != CRK_Unrecoverable) && + !CGM.getCodeGenOpts().SanitizeRecover; + Twine FunctionName = "__ubsan_handle_" + CheckName + + Twine(NeedsAbortSuffix? "_abort" : ""); + llvm::Value *Fn = CGM.CreateRuntimeFunction(FnType, FunctionName.str(), llvm::Attributes::get(getLLVMContext(), B)); llvm::CallInst *HandlerCall = Builder.CreateCall(Fn, Args); - if (Recoverable) { + if (Recover) { Builder.CreateBr(Cont); } else { HandlerCall->setDoesNotReturn(); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 298be923cb..993e2a1dc7 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -645,7 +645,8 @@ void ScalarExprEmitter::EmitFloatConversionCheck(Value *OrigSrc, CGF.EmitCheckTypeDescriptor(OrigSrcType), CGF.EmitCheckTypeDescriptor(DstType) }; - CGF.EmitCheck(Check, "float_cast_overflow", StaticArgs, OrigSrc); + CGF.EmitCheck(Check, "float_cast_overflow", StaticArgs, OrigSrc, + CodeGenFunction::CRK_Recoverable); } /// EmitScalarConversion - Emit a conversion from the specified type to the @@ -850,7 +851,8 @@ void ScalarExprEmitter::EmitBinOpCheck(Value *Check, const BinOpInfo &Info) { DynamicData.push_back(Info.RHS); } - CGF.EmitCheck(Check, CheckName, StaticData, DynamicData); + CGF.EmitCheck(Check, CheckName, StaticData, DynamicData, + CodeGenFunction::CRK_Recoverable); } //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index f425e1d8ac..8f2e891fed 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -551,7 +551,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, if (getLangOpts().SanitizeReturn) EmitCheck(Builder.getFalse(), "missing_return", EmitCheckSourceLocation(FD->getLocation()), - llvm::ArrayRef<llvm::Value*>()); + llvm::ArrayRef<llvm::Value*>(), CRK_Unrecoverable); else if (CGM.getCodeGenOpts().OptimizationLevel == 0) Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::trap)); Builder.CreateUnreachable(); @@ -1141,7 +1141,8 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { EmitCheckTypeDescriptor(size->getType()) }; EmitCheck(Builder.CreateICmpSGT(Size, Zero), - "vla_bound_not_positive", StaticArgs, Size); + "vla_bound_not_positive", StaticArgs, Size, + CRK_Recoverable); } // Always zexting here would be wrong if it weren't diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index f2ab226ab5..ff3c737421 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -2575,13 +2575,23 @@ public: /// passing to a runtime sanitizer handler. llvm::Constant *EmitCheckSourceLocation(SourceLocation Loc); + /// \brief Specify under what conditions this check can be recovered + enum CheckRecoverableKind { + /// Always terminate program execution if this check fails + CRK_Unrecoverable, + /// Check supports recovering, allows user to specify which + CRK_Recoverable, + /// Runtime conditionally aborts, always need to support recovery. + CRK_AlwaysRecoverable + }; + /// \brief Create a basic block that will call a handler function in a /// sanitizer runtime with the provided arguments, and create a conditional /// branch to it. void EmitCheck(llvm::Value *Checked, StringRef CheckName, llvm::ArrayRef<llvm::Constant *> StaticArgs, llvm::ArrayRef<llvm::Value *> DynamicArgs, - bool Recoverable = false); + CheckRecoverableKind Recoverable); /// \brief Create a basic block that will call the trap intrinsic, and emit a /// conditional branch to it, for the -ftrapv checks. |