summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
authorAlexey Samsonov <vonosmas@gmail.com>2014-11-11 22:03:54 +0000
committerAlexey Samsonov <vonosmas@gmail.com>2014-11-11 22:03:54 +0000
commite396bfc0646660661eef90edf258bfd16f225b62 (patch)
tree1103edd33f69355f587509bc93ef3655dd967dd2 /clang/lib/CodeGen
parent902edb9a2bd3bab6bdeabc59667c6b074b1c2e83 (diff)
downloadbcm5719-llvm-e396bfc0646660661eef90edf258bfd16f225b62.tar.gz
bcm5719-llvm-e396bfc0646660661eef90edf258bfd16f225b62.zip
Bundle conditions checked by UBSan with sanitizer kinds they implement.
Summary: This change makes CodeGenFunction::EmitCheck() take several conditions that needs to be checked (all of them need to be true), together with sanitizer kinds these checks are for. This would allow to split one call into UBSan runtime into several calls in case different sanitizer kinds would have different recoverability settings. Tests should be fixed accordingly, I'm working on it. Test Plan: regression test suite. Reviewers: rsmith Reviewed By: rsmith Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D6219 llvm-svn: 221716
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp7
-rw-r--r--clang/lib/CodeGen/CGCall.cpp8
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp67
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp54
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp13
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h7
6 files changed, 79 insertions, 77 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 3086de61abc..9f6f9f31060 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -475,9 +475,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__builtin_unreachable: {
if (SanOpts.has(SanitizerKind::Unreachable)) {
SanitizerScope SanScope(this);
- EmitCheck(Builder.getFalse(), "builtin_unreachable",
- EmitCheckSourceLocation(E->getExprLoc()), None,
- SanitizerKind::Unreachable);
+ EmitCheck(std::make_pair(static_cast<llvm::Value *>(Builder.getFalse()),
+ SanitizerKind::Unreachable),
+ "builtin_unreachable", EmitCheckSourceLocation(E->getExprLoc()),
+ None);
} else
Builder.CreateUnreachable();
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index ca5db851df3..06d02b52c8f 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2300,8 +2300,8 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
EmitCheckSourceLocation(EndLoc),
EmitCheckSourceLocation(RetNNAttr->getLocation()),
};
- EmitCheck(Cond, "nonnull_return", StaticData, None,
- SanitizerKind::ReturnsNonnullAttribute);
+ EmitCheck(std::make_pair(Cond, SanitizerKind::ReturnsNonnullAttribute),
+ "nonnull_return", StaticData, None);
}
}
Ret = Builder.CreateRet(RV);
@@ -2636,8 +2636,8 @@ static void emitNonNullArgCheck(CodeGenFunction &CGF, RValue RV,
CGF.EmitCheckSourceLocation(NNAttr->getLocation()),
llvm::ConstantInt::get(CGF.Int32Ty, ArgNo + 1),
};
- CGF.EmitCheck(Cond, "nonnull_arg", StaticData, None,
- SanitizerKind::NonnullAttribute);
+ CGF.EmitCheck(std::make_pair(Cond, SanitizerKind::NonnullAttribute),
+ "nonnull_arg", StaticData, None);
}
void CodeGenFunction::EmitCallArgs(CallArgList &Args,
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 877323bf926..0b8caa1e11a 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -476,10 +476,9 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
if (Address->getType()->getPointerAddressSpace())
return;
- SmallVector<SanitizerKind, 3> Kinds;
SanitizerScope SanScope(this);
- llvm::Value *Cond = nullptr;
+ SmallVector<std::pair<llvm::Value *, SanitizerKind>, 3> Checks;
llvm::BasicBlock *Done = nullptr;
bool AllowNullPointers = TCK == TCK_DowncastPointer || TCK == TCK_Upcast ||
@@ -487,7 +486,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
if ((SanOpts.has(SanitizerKind::Null) || AllowNullPointers) &&
!SkipNullCheck) {
// The glvalue must not be an empty glvalue.
- Cond = Builder.CreateICmpNE(
+ llvm::Value *IsNonNull = Builder.CreateICmpNE(
Address, llvm::Constant::getNullValue(Address->getType()));
if (AllowNullPointers) {
@@ -495,11 +494,10 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
// Skip the remaining checks in that case.
Done = createBasicBlock("null");
llvm::BasicBlock *Rest = createBasicBlock("not.null");
- Builder.CreateCondBr(Cond, Rest, Done);
+ Builder.CreateCondBr(IsNonNull, Rest, Done);
EmitBlock(Rest);
- Cond = nullptr;
} else {
- Kinds.push_back(SanitizerKind::Null);
+ Checks.push_back(std::make_pair(IsNonNull, SanitizerKind::Null));
}
}
@@ -517,8 +515,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
llvm::Value *LargeEnough =
Builder.CreateICmpUGE(Builder.CreateCall2(F, CastAddr, Min),
llvm::ConstantInt::get(IntPtrTy, Size));
- Cond = Cond ? Builder.CreateAnd(Cond, LargeEnough) : LargeEnough;
- Kinds.push_back(SanitizerKind::ObjectSize);
+ Checks.push_back(std::make_pair(LargeEnough, SanitizerKind::ObjectSize));
}
uint64_t AlignVal = 0;
@@ -535,19 +532,18 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
llvm::ConstantInt::get(IntPtrTy, AlignVal - 1));
llvm::Value *Aligned =
Builder.CreateICmpEQ(Align, llvm::ConstantInt::get(IntPtrTy, 0));
- Cond = Cond ? Builder.CreateAnd(Cond, Aligned) : Aligned;
- Kinds.push_back(SanitizerKind::Alignment);
+ Checks.push_back(std::make_pair(Aligned, SanitizerKind::Alignment));
}
}
- if (Cond) {
+ if (Checks.size() > 0) {
llvm::Constant *StaticData[] = {
EmitCheckSourceLocation(Loc),
EmitCheckTypeDescriptor(Ty),
llvm::ConstantInt::get(SizeTy, AlignVal),
llvm::ConstantInt::get(Int8Ty, TCK)
};
- EmitCheck(Cond, "type_mismatch", StaticData, Address, Kinds);
+ EmitCheck(Checks, "type_mismatch", StaticData, Address);
}
// If possible, check that the vptr indicates that there is a subobject of
@@ -605,6 +601,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
// hard work of checking whether the vptr is for an object of the right
// type. This will either fill in the cache and return, or produce a
// diagnostic.
+ llvm::Value *EqualHash = Builder.CreateICmpEQ(CacheVal, Hash);
llvm::Constant *StaticData[] = {
EmitCheckSourceLocation(Loc),
EmitCheckTypeDescriptor(Ty),
@@ -612,8 +609,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
llvm::ConstantInt::get(Int8Ty, TCK)
};
llvm::Value *DynamicData[] = { Address, Hash };
- EmitCheck(Builder.CreateICmpEQ(CacheVal, Hash), "dynamic_type_cache_miss",
- StaticData, DynamicData, SanitizerKind::Vptr);
+ EmitCheck(std::make_pair(EqualHash, SanitizerKind::Vptr),
+ "dynamic_type_cache_miss", StaticData, DynamicData);
}
}
@@ -701,8 +698,8 @@ void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base,
};
llvm::Value *Check = Accessed ? Builder.CreateICmpULT(IndexVal, BoundVal)
: Builder.CreateICmpULE(IndexVal, BoundVal);
- EmitCheck(Check, "out_of_bounds", StaticData, Index,
- SanitizerKind::ArrayBounds);
+ EmitCheck(std::make_pair(Check, SanitizerKind::ArrayBounds), "out_of_bounds",
+ StaticData, Index);
}
@@ -1181,8 +1178,9 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
EmitCheckSourceLocation(Loc),
EmitCheckTypeDescriptor(Ty)
};
- EmitCheck(Check, "load_invalid_value", StaticArgs, EmitCheckValue(Load),
- NeedsEnumCheck ? SanitizerKind::Enum : SanitizerKind::Bool);
+ SanitizerKind Kind = NeedsEnumCheck ? SanitizerKind::Enum : SanitizerKind::Bool;
+ EmitCheck(std::make_pair(Check, Kind), "load_invalid_value", StaticArgs,
+ EmitCheckValue(Load));
}
} else if (CGM.getCodeGenOpts().OptimizationLevel > 0)
if (llvm::MDNode *RangeInfo = getRangeForLoadFromType(Ty))
@@ -2221,32 +2219,33 @@ static CheckRecoverableKind getRecoverableKind(SanitizerKind Kind) {
}
}
-void CodeGenFunction::EmitCheck(llvm::Value *Checked, StringRef CheckName,
- ArrayRef<llvm::Constant *> StaticArgs,
- ArrayRef<llvm::Value *> DynamicArgs,
- ArrayRef<SanitizerKind> Kinds) {
+void CodeGenFunction::EmitCheck(
+ ArrayRef<std::pair<llvm::Value *, SanitizerKind>> Checked,
+ StringRef CheckName, ArrayRef<llvm::Constant *> StaticArgs,
+ ArrayRef<llvm::Value *> DynamicArgs) {
assert(IsSanitizerScope);
- assert(Kinds.size() > 0);
- CheckRecoverableKind RecoverKind = getRecoverableKind(Kinds[0]);
- for (int i = 1, n = Kinds.size(); i < n; ++i)
- assert(RecoverKind == getRecoverableKind(Kinds[i]) &&
+ assert(Checked.size() > 0);
+ llvm::Value *Cond = Checked[0].first;
+ CheckRecoverableKind RecoverKind = getRecoverableKind(Checked[0].second);
+ assert(SanOpts.has(Checked[0].second));
+ for (int i = 1, n = Checked.size(); i < n; ++i) {
+ Cond = Builder.CreateAnd(Cond, Checked[i].first);
+ assert(RecoverKind == getRecoverableKind(Checked[i].second) &&
"All recoverable kinds in a single check must be same!");
-#ifndef NDEBUG
- for (auto Kind : Kinds)
- assert(SanOpts.has(Kind));
-#endif
+ assert(SanOpts.has(Checked[i].second));
+ }
if (CGM.getCodeGenOpts().SanitizeUndefinedTrapOnError) {
assert (RecoverKind != CheckRecoverableKind::AlwaysRecoverable &&
"Runtime call required for AlwaysRecoverable kind!");
- return EmitTrapCheck(Checked);
+ return EmitTrapCheck(Cond);
}
llvm::BasicBlock *Cont = createBasicBlock("cont");
llvm::BasicBlock *Handler = createBasicBlock("handler." + CheckName);
- llvm::Instruction *Branch = Builder.CreateCondBr(Checked, Cont, Handler);
+ llvm::Instruction *Branch = Builder.CreateCondBr(Cond, Cont, Handler);
// Give hint that we very much don't expect to execute the handler
// Value chosen to match UR_NONTAKEN_WEIGHT, see BranchProbabilityInfo.cpp
@@ -3321,8 +3320,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
EmitCheckSourceLocation(E->getLocStart()),
EmitCheckTypeDescriptor(CalleeType)
};
- EmitCheck(CalleeRTTIMatch, "function_type_mismatch", StaticData, Callee,
- SanitizerKind::Function);
+ EmitCheck(std::make_pair(CalleeRTTIMatch, SanitizerKind::Function),
+ "function_type_mismatch", StaticData, Callee);
Builder.CreateBr(Cont);
EmitBlock(Cont);
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 10094228995..8807e828646 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -85,8 +85,8 @@ public:
return CGF.EmitCheckedLValue(E, TCK);
}
- void EmitBinOpCheck(Value *Check, const BinOpInfo &Info,
- ArrayRef<SanitizerKind> Kinds);
+ void EmitBinOpCheck(ArrayRef<std::pair<Value *, SanitizerKind>> Checks,
+ const BinOpInfo &Info);
Value *EmitLoadOfLValue(LValue LV, SourceLocation Loc) {
return CGF.EmitLoadOfLValue(LV, Loc).getScalarVal();
@@ -726,8 +726,8 @@ void ScalarExprEmitter::EmitFloatConversionCheck(Value *OrigSrc,
CGF.EmitCheckTypeDescriptor(OrigSrcType),
CGF.EmitCheckTypeDescriptor(DstType)
};
- CGF.EmitCheck(Check, "float_cast_overflow", StaticArgs, OrigSrc,
- SanitizerKind::FloatCastOverflow);
+ CGF.EmitCheck(std::make_pair(Check, SanitizerKind::FloatCastOverflow),
+ "float_cast_overflow", StaticArgs, OrigSrc);
}
/// EmitScalarConversion - Emit a conversion from the specified type to the
@@ -885,9 +885,10 @@ Value *ScalarExprEmitter::EmitNullValue(QualType Ty) {
/// \brief Emit a sanitization check for the given "binary" operation (which
/// might actually be a unary increment which has been lowered to a binary
-/// operation). The check passes if \p Check, which is an \c i1, is \c true.
-void ScalarExprEmitter::EmitBinOpCheck(Value *Check, const BinOpInfo &Info,
- ArrayRef<SanitizerKind> Kinds) {
+/// operation). The check passes if all values in \p Checks (which are \c i1),
+/// are \c true.
+void ScalarExprEmitter::EmitBinOpCheck(
+ ArrayRef<std::pair<Value *, SanitizerKind>> Checks, const BinOpInfo &Info) {
assert(CGF.IsSanitizerScope);
StringRef CheckName;
SmallVector<llvm::Constant *, 4> StaticData;
@@ -930,7 +931,7 @@ void ScalarExprEmitter::EmitBinOpCheck(Value *Check, const BinOpInfo &Info,
DynamicData.push_back(Info.RHS);
}
- CGF.EmitCheck(Check, CheckName, StaticData, DynamicData, Kinds);
+ CGF.EmitCheck(Checks, CheckName, StaticData, DynamicData);
}
//===----------------------------------------------------------------------===//
@@ -2179,12 +2180,11 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E,
void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
const BinOpInfo &Ops, llvm::Value *Zero, bool isDiv) {
- llvm::Value *Cond = nullptr;
- SmallVector<SanitizerKind, 2> Kinds;
+ SmallVector<std::pair<llvm::Value *, SanitizerKind>, 2> Checks;
if (CGF.SanOpts.has(SanitizerKind::IntegerDivideByZero)) {
- Cond = Builder.CreateICmpNE(Ops.RHS, Zero);
- Kinds.push_back(SanitizerKind::IntegerDivideByZero);
+ Checks.push_back(std::make_pair(Builder.CreateICmpNE(Ops.RHS, Zero),
+ SanitizerKind::IntegerDivideByZero));
}
if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) &&
@@ -2197,13 +2197,13 @@ void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
llvm::Value *LHSCmp = Builder.CreateICmpNE(Ops.LHS, IntMin);
llvm::Value *RHSCmp = Builder.CreateICmpNE(Ops.RHS, NegOne);
- llvm::Value *Overflow = Builder.CreateOr(LHSCmp, RHSCmp, "or");
- Cond = Cond ? Builder.CreateAnd(Cond, Overflow, "and") : Overflow;
- Kinds.push_back(SanitizerKind::SignedIntegerOverflow);
+ llvm::Value *NotOverflow = Builder.CreateOr(LHSCmp, RHSCmp, "or");
+ Checks.push_back(
+ std::make_pair(NotOverflow, SanitizerKind::SignedIntegerOverflow));
}
- if (Cond)
- EmitBinOpCheck(Cond, Ops, Kinds);
+ if (Checks.size() > 0)
+ EmitBinOpCheck(Checks, Ops);
}
Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
@@ -2217,8 +2217,9 @@ Value *ScalarExprEmitter::EmitDiv(const BinOpInfo &Ops) {
} else if (CGF.SanOpts.has(SanitizerKind::FloatDivideByZero) &&
Ops.Ty->isRealFloatingType()) {
llvm::Value *Zero = llvm::Constant::getNullValue(ConvertType(Ops.Ty));
- EmitBinOpCheck(Builder.CreateFCmpUNE(Ops.RHS, Zero), Ops,
- SanitizerKind::FloatDivideByZero);
+ llvm::Value *NonZero = Builder.CreateFCmpUNE(Ops.RHS, Zero);
+ EmitBinOpCheck(std::make_pair(NonZero, SanitizerKind::FloatDivideByZero),
+ Ops);
}
}
@@ -2303,9 +2304,10 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
// runtime. Otherwise, this is a -ftrapv check, so just emit a trap.
if (!isSigned || CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow)) {
CodeGenFunction::SanitizerScope SanScope(&CGF);
- EmitBinOpCheck(Builder.CreateNot(overflow), Ops,
- isSigned ? SanitizerKind::SignedIntegerOverflow
- : SanitizerKind::UnsignedIntegerOverflow);
+ llvm::Value *NotOverflow = Builder.CreateNot(overflow);
+ SanitizerKind Kind = isSigned ? SanitizerKind::SignedIntegerOverflow
+ : SanitizerKind::UnsignedIntegerOverflow;
+ EmitBinOpCheck(std::make_pair(NotOverflow, Kind), Ops);
} else
CGF.EmitTrapCheck(Builder.CreateNot(overflow));
return result;
@@ -2695,7 +2697,7 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
Valid = P;
}
- EmitBinOpCheck(Valid, Ops, SanitizerKind::Shift);
+ EmitBinOpCheck(std::make_pair(Valid, SanitizerKind::Shift), Ops);
}
// OpenCL 6.3j: shift values are effectively % word size of LHS.
if (CGF.getLangOpts().OpenCL)
@@ -2714,9 +2716,9 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) {
if (CGF.SanOpts.has(SanitizerKind::Shift) && !CGF.getLangOpts().OpenCL &&
isa<llvm::IntegerType>(Ops.LHS->getType())) {
CodeGenFunction::SanitizerScope SanScope(&CGF);
- EmitBinOpCheck(
- Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS)), Ops,
- SanitizerKind::Shift);
+ llvm::Value *Valid =
+ Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS));
+ EmitBinOpCheck(std::make_pair(Valid, SanitizerKind::Shift), Ops);
}
// OpenCL 6.3j: shift values are effectively % word size of LHS.
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index cbedf61c559..05c98fce0b8 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -899,9 +899,10 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
!FD->getReturnType()->isVoidType() && Builder.GetInsertBlock()) {
if (SanOpts.has(SanitizerKind::Return)) {
SanitizerScope SanScope(this);
- EmitCheck(Builder.getFalse(), "missing_return",
- EmitCheckSourceLocation(FD->getLocation()), None,
- SanitizerKind::Return);
+ llvm::Value *IsFalse = Builder.getFalse();
+ EmitCheck(std::make_pair(IsFalse, SanitizerKind::Return),
+ "missing_return", EmitCheckSourceLocation(FD->getLocation()),
+ None);
} else if (CGM.getCodeGenOpts().OptimizationLevel == 0)
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::trap));
Builder.CreateUnreachable();
@@ -1560,9 +1561,9 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
EmitCheckSourceLocation(size->getLocStart()),
EmitCheckTypeDescriptor(size->getType())
};
- EmitCheck(Builder.CreateICmpSGT(Size, Zero),
- "vla_bound_not_positive", StaticArgs, Size,
- SanitizerKind::VLABound);
+ EmitCheck(std::make_pair(Builder.CreateICmpSGT(Size, Zero),
+ SanitizerKind::VLABound),
+ "vla_bound_not_positive", StaticArgs, Size);
}
// Always zexting here would be wrong if it weren't
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 013fdc0ed22..4575e31dbd2 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2652,10 +2652,9 @@ public:
/// \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,
- ArrayRef<llvm::Constant *> StaticArgs,
- ArrayRef<llvm::Value *> DynamicArgs,
- ArrayRef<SanitizerKind> Kinds);
+ void EmitCheck(ArrayRef<std::pair<llvm::Value *, SanitizerKind>> Checked,
+ StringRef CheckName, ArrayRef<llvm::Constant *> StaticArgs,
+ ArrayRef<llvm::Value *> DynamicArgs);
/// \brief Create a basic block that will call the trap intrinsic, and emit a
/// conditional branch to it, for the -ftrapv checks.
OpenPOWER on IntegriCloud