summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp568
1 files changed, 380 insertions, 188 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
index 1fe4c18..63cc5b5 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
@@ -26,7 +26,8 @@
#include "llvm/Intrinsics.h"
#include "llvm/LLVMContext.h"
#include "llvm/MDBuilder.h"
-#include "llvm/Target/TargetData.h"
+#include "llvm/DataLayout.h"
+#include "llvm/ADT/Hashing.h"
using namespace clang;
using namespace CodeGen;
@@ -156,50 +157,6 @@ void CodeGenFunction::EmitAnyExprToMem(const Expr *E,
}
}
-namespace {
-/// \brief An adjustment to be made to the temporary created when emitting a
-/// reference binding, which accesses a particular subobject of that temporary.
- struct SubobjectAdjustment {
- enum {
- DerivedToBaseAdjustment,
- FieldAdjustment,
- MemberPointerAdjustment
- } Kind;
-
- union {
- struct {
- const CastExpr *BasePath;
- const CXXRecordDecl *DerivedClass;
- } DerivedToBase;
-
- FieldDecl *Field;
-
- struct {
- const MemberPointerType *MPT;
- llvm::Value *Ptr;
- } Ptr;
- };
-
- SubobjectAdjustment(const CastExpr *BasePath,
- const CXXRecordDecl *DerivedClass)
- : Kind(DerivedToBaseAdjustment) {
- DerivedToBase.BasePath = BasePath;
- DerivedToBase.DerivedClass = DerivedClass;
- }
-
- SubobjectAdjustment(FieldDecl *Field)
- : Kind(FieldAdjustment) {
- this->Field = Field;
- }
-
- SubobjectAdjustment(const MemberPointerType *MPT, llvm::Value *Ptr)
- : Kind(MemberPointerAdjustment) {
- this->Ptr.MPT = MPT;
- this->Ptr.Ptr = Ptr;
- }
- };
-}
-
static llvm::Value *
CreateReferenceTemporary(CodeGenFunction &CGF, QualType Type,
const NamedDecl *InitializedDecl) {
@@ -232,32 +189,18 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
const CXXDestructorDecl *&ReferenceTemporaryDtor,
QualType &ObjCARCReferenceLifetimeType,
const NamedDecl *InitializedDecl) {
- // Look through single-element init lists that claim to be lvalues. They're
- // just syntactic wrappers in this case.
- if (const InitListExpr *ILE = dyn_cast<InitListExpr>(E)) {
- if (ILE->getNumInits() == 1 && ILE->isGLValue())
- E = ILE->getInit(0);
- }
-
- // Look through expressions for materialized temporaries (for now).
- if (const MaterializeTemporaryExpr *M
- = dyn_cast<MaterializeTemporaryExpr>(E)) {
- // Objective-C++ ARC:
- // If we are binding a reference to a temporary that has ownership, we
- // need to perform retain/release operations on the temporary.
- if (CGF.getContext().getLangOpts().ObjCAutoRefCount &&
- E->getType()->isObjCLifetimeType() &&
- (E->getType().getObjCLifetime() == Qualifiers::OCL_Strong ||
- E->getType().getObjCLifetime() == Qualifiers::OCL_Weak ||
- E->getType().getObjCLifetime() == Qualifiers::OCL_Autoreleasing))
- ObjCARCReferenceLifetimeType = E->getType();
-
- E = M->GetTemporaryExpr();
- }
+ const MaterializeTemporaryExpr *M = NULL;
+ E = E->findMaterializedTemporary(M);
+ // Objective-C++ ARC:
+ // If we are binding a reference to a temporary that has ownership, we
+ // need to perform retain/release operations on the temporary.
+ if (M && CGF.getLangOpts().ObjCAutoRefCount &&
+ M->getType()->isObjCLifetimeType() &&
+ (M->getType().getObjCLifetime() == Qualifiers::OCL_Strong ||
+ M->getType().getObjCLifetime() == Qualifiers::OCL_Weak ||
+ M->getType().getObjCLifetime() == Qualifiers::OCL_Autoreleasing))
+ ObjCARCReferenceLifetimeType = M->getType();
- if (const CXXDefaultArgExpr *DAE = dyn_cast<CXXDefaultArgExpr>(E))
- E = DAE->getExpr();
-
if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(E)) {
CGF.enterFullExpression(EWC);
CodeGenFunction::RunCleanupsScope Scope(CGF);
@@ -335,54 +278,13 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
return ReferenceTemporary;
}
-
- SmallVector<SubobjectAdjustment, 2> Adjustments;
- while (true) {
- E = E->IgnoreParens();
-
- if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
- if ((CE->getCastKind() == CK_DerivedToBase ||
- CE->getCastKind() == CK_UncheckedDerivedToBase) &&
- E->getType()->isRecordType()) {
- E = CE->getSubExpr();
- CXXRecordDecl *Derived
- = cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl());
- Adjustments.push_back(SubobjectAdjustment(CE, Derived));
- continue;
- }
-
- if (CE->getCastKind() == CK_NoOp) {
- E = CE->getSubExpr();
- continue;
- }
- } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
- if (!ME->isArrow() && ME->getBase()->isRValue()) {
- assert(ME->getBase()->getType()->isRecordType());
- if (FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
- E = ME->getBase();
- Adjustments.push_back(SubobjectAdjustment(Field));
- continue;
- }
- }
- } else if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
- if (BO->isPtrMemOp()) {
- assert(BO->getLHS()->isRValue());
- E = BO->getLHS();
- const MemberPointerType *MPT =
- BO->getRHS()->getType()->getAs<MemberPointerType>();
- llvm::Value *Ptr = CGF.EmitScalarExpr(BO->getRHS());
- Adjustments.push_back(SubobjectAdjustment(MPT, Ptr));
- }
- }
- if (const OpaqueValueExpr *opaque = dyn_cast<OpaqueValueExpr>(E))
- if (opaque->getType()->isRecordType())
- return CGF.EmitOpaqueValueLValue(opaque).getAddress();
+ SmallVector<SubobjectAdjustment, 2> Adjustments;
+ E = E->skipRValueSubobjectAdjustments(Adjustments);
+ if (const OpaqueValueExpr *opaque = dyn_cast<OpaqueValueExpr>(E))
+ if (opaque->getType()->isRecordType())
+ return CGF.EmitOpaqueValueLValue(opaque).getAddress();
- // Nothing changed.
- break;
- }
-
// Create a reference temporary if necessary.
AggValueSlot AggSlot = AggValueSlot::ignored();
if (CGF.hasAggregateLLVMType(E->getType()) &&
@@ -446,8 +348,9 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
}
case SubobjectAdjustment::MemberPointerAdjustment: {
+ llvm::Value *Ptr = CGF.EmitScalarExpr(Adjustment.Ptr.RHS);
Object = CGF.CGM.getCXXABI().EmitMemberDataPointerAddress(
- CGF, Object, Adjustment.Ptr.Ptr, Adjustment.Ptr.MPT);
+ CGF, Object, Ptr, Adjustment.Ptr.MPT);
break;
}
}
@@ -486,6 +389,15 @@ CodeGenFunction::EmitReferenceBindingToExpr(const Expr *E,
ReferenceTemporaryDtor,
ObjCARCReferenceLifetimeType,
InitializedDecl);
+ if (SanitizePerformTypeCheck && !E->getType()->isFunctionType()) {
+ // C++11 [dcl.ref]p5 (as amended by core issue 453):
+ // If a glvalue to which a reference is directly bound designates neither
+ // an existing object or function of an appropriate type nor a region of
+ // storage of suitable size and alignment to contain an object of the
+ // reference's type, the behavior is undefined.
+ QualType Ty = E->getType();
+ EmitTypeCheck(TCK_ReferenceBinding, E->getExprLoc(), Value, Ty);
+ }
if (!ReferenceTemporaryDtor && ObjCARCReferenceLifetimeType.isNull())
return RValue::get(Value);
@@ -549,22 +461,133 @@ unsigned CodeGenFunction::getAccessedFieldNo(unsigned Idx,
->getZExtValue();
}
-void CodeGenFunction::EmitCheck(llvm::Value *Address, unsigned Size) {
- if (!CatchUndefined)
+/// Emit the hash_16_bytes function from include/llvm/ADT/Hashing.h.
+static llvm::Value *emitHash16Bytes(CGBuilderTy &Builder, llvm::Value *Low,
+ llvm::Value *High) {
+ llvm::Value *KMul = Builder.getInt64(0x9ddfea08eb382d69ULL);
+ llvm::Value *K47 = Builder.getInt64(47);
+ llvm::Value *A0 = Builder.CreateMul(Builder.CreateXor(Low, High), KMul);
+ llvm::Value *A1 = Builder.CreateXor(Builder.CreateLShr(A0, K47), A0);
+ llvm::Value *B0 = Builder.CreateMul(Builder.CreateXor(High, A1), KMul);
+ llvm::Value *B1 = Builder.CreateXor(Builder.CreateLShr(B0, K47), B0);
+ return Builder.CreateMul(B1, KMul);
+}
+
+void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
+ llvm::Value *Address,
+ QualType Ty, CharUnits Alignment) {
+ if (!SanitizePerformTypeCheck)
return;
- // This needs to be to the standard address space.
- Address = Builder.CreateBitCast(Address, Int8PtrTy);
+ // Don't check pointers outside the default address space. The null check
+ // isn't correct, the object-size check isn't supported by LLVM, and we can't
+ // communicate the addresses to the runtime handler for the vptr check.
+ if (Address->getType()->getPointerAddressSpace())
+ return;
- llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::objectsize, IntPtrTy);
+ llvm::Value *Cond = 0;
- llvm::Value *Min = Builder.getFalse();
- llvm::Value *C = Builder.CreateCall2(F, Address, Min);
- llvm::BasicBlock *Cont = createBasicBlock();
- Builder.CreateCondBr(Builder.CreateICmpUGE(C,
- llvm::ConstantInt::get(IntPtrTy, Size)),
- Cont, getTrapBB());
- EmitBlock(Cont);
+ if (getLangOpts().SanitizeNull) {
+ // The glvalue must not be an empty glvalue.
+ Cond = Builder.CreateICmpNE(
+ Address, llvm::Constant::getNullValue(Address->getType()));
+ }
+
+ if (getLangOpts().SanitizeObjectSize && !Ty->isIncompleteType()) {
+ uint64_t Size = getContext().getTypeSizeInChars(Ty).getQuantity();
+
+ // The glvalue must refer to a large enough storage region.
+ // FIXME: If Address Sanitizer is enabled, insert dynamic instrumentation
+ // to check this.
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::objectsize, IntPtrTy);
+ llvm::Value *Min = Builder.getFalse();
+ llvm::Value *CastAddr = Builder.CreateBitCast(Address, Int8PtrTy);
+ llvm::Value *LargeEnough =
+ Builder.CreateICmpUGE(Builder.CreateCall2(F, CastAddr, Min),
+ llvm::ConstantInt::get(IntPtrTy, Size));
+ Cond = Cond ? Builder.CreateAnd(Cond, LargeEnough) : LargeEnough;
+ }
+
+ uint64_t AlignVal = 0;
+
+ if (getLangOpts().SanitizeAlignment) {
+ AlignVal = Alignment.getQuantity();
+ if (!Ty->isIncompleteType() && !AlignVal)
+ AlignVal = getContext().getTypeAlignInChars(Ty).getQuantity();
+
+ // The glvalue must be suitably aligned.
+ if (AlignVal) {
+ llvm::Value *Align =
+ Builder.CreateAnd(Builder.CreatePtrToInt(Address, IntPtrTy),
+ llvm::ConstantInt::get(IntPtrTy, AlignVal - 1));
+ llvm::Value *Aligned =
+ Builder.CreateICmpEQ(Align, llvm::ConstantInt::get(IntPtrTy, 0));
+ Cond = Cond ? Builder.CreateAnd(Cond, Aligned) : Aligned;
+ }
+ }
+
+ if (Cond) {
+ llvm::Constant *StaticData[] = {
+ EmitCheckSourceLocation(Loc),
+ EmitCheckTypeDescriptor(Ty),
+ llvm::ConstantInt::get(SizeTy, AlignVal),
+ llvm::ConstantInt::get(Int8Ty, TCK)
+ };
+ EmitCheck(Cond, "type_mismatch", StaticData, Address);
+ }
+
+ // If possible, check that the vptr indicates that there is a subobject of
+ // type Ty at offset zero within this object.
+ CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();
+ if (getLangOpts().SanitizeVptr && TCK != TCK_ConstructorCall &&
+ RD && RD->hasDefinition() && RD->isDynamicClass()) {
+ // Compute a hash of the mangled name of the type.
+ //
+ // FIXME: This is not guaranteed to be deterministic! Move to a
+ // fingerprinting mechanism once LLVM provides one. For the time
+ // being the implementation happens to be deterministic.
+ llvm::SmallString<64> MangledName;
+ llvm::raw_svector_ostream Out(MangledName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty.getUnqualifiedType(),
+ Out);
+ llvm::hash_code TypeHash = hash_value(Out.str());
+
+ // Load the vptr, and compute hash_16_bytes(TypeHash, vptr).
+ llvm::Value *Low = llvm::ConstantInt::get(Int64Ty, TypeHash);
+ llvm::Type *VPtrTy = llvm::PointerType::get(IntPtrTy, 0);
+ llvm::Value *VPtrAddr = Builder.CreateBitCast(Address, VPtrTy);
+ llvm::Value *VPtrVal = Builder.CreateLoad(VPtrAddr);
+ llvm::Value *High = Builder.CreateZExt(VPtrVal, Int64Ty);
+
+ llvm::Value *Hash = emitHash16Bytes(Builder, Low, High);
+ Hash = Builder.CreateTrunc(Hash, IntPtrTy);
+
+ // Look the hash up in our cache.
+ const int CacheSize = 128;
+ llvm::Type *HashTable = llvm::ArrayType::get(IntPtrTy, CacheSize);
+ llvm::Value *Cache = CGM.CreateRuntimeVariable(HashTable,
+ "__ubsan_vptr_type_cache");
+ llvm::Value *Slot = Builder.CreateAnd(Hash,
+ llvm::ConstantInt::get(IntPtrTy,
+ CacheSize-1));
+ llvm::Value *Indices[] = { Builder.getInt32(0), Slot };
+ llvm::Value *CacheVal =
+ Builder.CreateLoad(Builder.CreateInBoundsGEP(Cache, Indices));
+
+ // If the hash isn't in the cache, call a runtime handler to perform the
+ // 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::Constant *StaticData[] = {
+ EmitCheckSourceLocation(Loc),
+ EmitCheckTypeDescriptor(Ty),
+ CGM.GetAddrOfRTTIDescriptor(Ty.getUnqualifiedType()),
+ llvm::ConstantInt::get(Int8Ty, TCK)
+ };
+ llvm::Value *DynamicData[] = { Address, Hash };
+ EmitCheck(Builder.CreateICmpEQ(CacheVal, Hash),
+ "dynamic_type_cache_miss", StaticData, DynamicData, true);
+ }
}
@@ -641,11 +664,11 @@ LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E,
return MakeAddrLValue(llvm::UndefValue::get(Ty), E->getType());
}
-LValue CodeGenFunction::EmitCheckedLValue(const Expr *E) {
+LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) {
LValue LV = EmitLValue(E);
if (!isa<DeclRefExpr>(E) && !LV.isBitField() && LV.isSimple())
- EmitCheck(LV.getAddress(),
- getContext().getTypeSizeInChars(E->getType()).getQuantity());
+ EmitTypeCheck(TCK, E->getExprLoc(), LV.getAddress(),
+ E->getType(), LV.getAlignment());
return LV;
}
@@ -672,7 +695,7 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
llvm_unreachable("cannot emit a property reference directly");
case Expr::ObjCSelectorExprClass:
- return EmitObjCSelectorLValue(cast<ObjCSelectorExpr>(E));
+ return EmitObjCSelectorLValue(cast<ObjCSelectorExpr>(E));
case Expr::ObjCIsaExprClass:
return EmitObjCIsaExpr(cast<ObjCIsaExpr>(E));
case Expr::BinaryOperatorClass:
@@ -709,6 +732,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
return EmitCXXConstructLValue(cast<CXXConstructExpr>(E));
case Expr::CXXBindTemporaryExprClass:
return EmitCXXBindTemporaryLValue(cast<CXXBindTemporaryExpr>(E));
+ case Expr::CXXUuidofExprClass:
+ return EmitCXXUuidofLValue(cast<CXXUuidofExpr>(E));
case Expr::LambdaExprClass:
return EmitLambdaLValue(cast<LambdaExpr>(E));
@@ -1124,7 +1149,7 @@ RValue CodeGenFunction::EmitLoadOfBitfieldLValue(LValue LV) {
// Get the output type.
llvm::Type *ResLTy = ConvertType(LV.getType());
- unsigned ResSizeInBits = CGM.getTargetData().getTypeSizeInBits(ResLTy);
+ unsigned ResSizeInBits = CGM.getDataLayout().getTypeSizeInBits(ResLTy);
// Compute the result as an OR of all of the individual component accesses.
llvm::Value *Res = 0;
@@ -1322,7 +1347,7 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
// Get the output type.
llvm::Type *ResLTy = ConvertTypeForMem(Dst.getType());
- unsigned ResSizeInBits = CGM.getTargetData().getTypeSizeInBits(ResLTy);
+ unsigned ResSizeInBits = CGM.getDataLayout().getTypeSizeInBits(ResLTy);
// Get the source value, truncated to the width of the bit-field.
llvm::Value *SrcVal = Src.getScalarVal();
@@ -1645,6 +1670,21 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
CharUnits Alignment = getContext().getDeclAlign(ND);
QualType T = E->getType();
+ // A DeclRefExpr for a reference initialized by a constant expression can
+ // appear without being odr-used. Directly emit the constant initializer.
+ if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+ const Expr *Init = VD->getAnyInitializer(VD);
+ if (Init && !isa<ParmVarDecl>(VD) && VD->getType()->isReferenceType() &&
+ VD->isUsableInConstantExpressions(getContext()) &&
+ VD->checkInitIsICE()) {
+ llvm::Constant *Val =
+ CGM.EmitConstantValue(*VD->evaluateValue(), VD->getType(), this);
+ assert(Val && "failed to emit reference constant expression");
+ // FIXME: Eventually we will want to emit vector element references.
+ return MakeAddrLValue(Val, T, Alignment);
+ }
+ }
+
// FIXME: We should be able to assert this for FunctionDecls as well!
// FIXME: We should be able to assert this for all DeclRefExprs, not just
// those with a valid source location.
@@ -1655,7 +1695,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
if (ND->hasAttr<WeakRefAttr>()) {
const ValueDecl *VD = cast<ValueDecl>(ND);
llvm::Constant *Aliasee = CGM.GetWeakRefReference(VD);
- return MakeAddrLValue(Aliasee, E->getType(), Alignment);
+ return MakeAddrLValue(Aliasee, T, Alignment);
}
if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
@@ -1683,9 +1723,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
}
assert(isa<BlockDecl>(CurCodeDecl) && E->refersToEnclosingLocal());
- CharUnits alignment = getContext().getDeclAlign(VD);
return MakeAddrLValue(GetAddrOfBlockDecl(VD, isBlockVariable),
- E->getType(), alignment);
+ T, Alignment);
}
assert(V && "DeclRefExpr not entered in LocalDeclMap?");
@@ -1736,8 +1775,8 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
// of a pointer to object; as in void foo (__weak id *param); *param = 0;
// But, we continue to generate __strong write barrier on indirect write
// into a pointer to object.
- if (getContext().getLangOpts().ObjC1 &&
- getContext().getLangOpts().getGC() != LangOptions::NonGC &&
+ if (getLangOpts().ObjC1 &&
+ getLangOpts().getGC() != LangOptions::NonGC &&
LV.isObjCWeak())
LV.setNonGC(!E->isOBJCGCCandidate(getContext()));
return LV;
@@ -1815,8 +1854,9 @@ GetAddrOfConstantWideString(StringRef Str,
static void ConvertUTF8ToWideString(unsigned CharByteWidth, StringRef Source,
SmallString<32>& Target) {
Target.resize(CharByteWidth * (Source.size() + 1));
- char* ResultPtr = &Target[0];
- bool success = ConvertUTF8toWide(CharByteWidth, Source, ResultPtr);
+ char *ResultPtr = &Target[0];
+ const UTF8 *ErrorPtr;
+ bool success = ConvertUTF8toWide(CharByteWidth, Source, ResultPtr, ErrorPtr);
(void)success;
assert(success);
Target.resize(ResultPtr - &Target[0]);
@@ -1888,33 +1928,167 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
}
}
-llvm::BasicBlock *CodeGenFunction::getTrapBB() {
- const CodeGenOptions &GCO = CGM.getCodeGenOpts();
+/// Emit a type description suitable for use by a runtime sanitizer library. The
+/// format of a type descriptor is
+///
+/// \code
+/// { i16 TypeKind, i16 TypeInfo }
+/// \endcode
+///
+/// followed by an array of i8 containing the type name. TypeKind is 0 for an
+/// integer, 1 for a floating point value, and -1 for anything else.
+llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) {
+ // FIXME: Only emit each type's descriptor once.
+ uint16_t TypeKind = -1;
+ uint16_t TypeInfo = 0;
+
+ if (T->isIntegerType()) {
+ TypeKind = 0;
+ TypeInfo = (llvm::Log2_32(getContext().getTypeSize(T)) << 1) |
+ T->isSignedIntegerType();
+ } else if (T->isFloatingType()) {
+ TypeKind = 1;
+ TypeInfo = getContext().getTypeSize(T);
+ }
+
+ // Format the type name as if for a diagnostic, including quotes and
+ // optionally an 'aka'.
+ llvm::SmallString<32> Buffer;
+ CGM.getDiags().ConvertArgToString(DiagnosticsEngine::ak_qualtype,
+ (intptr_t)T.getAsOpaquePtr(),
+ 0, 0, 0, 0, 0, 0, Buffer,
+ ArrayRef<intptr_t>());
+
+ llvm::Constant *Components[] = {
+ Builder.getInt16(TypeKind), Builder.getInt16(TypeInfo),
+ llvm::ConstantDataArray::getString(getLLVMContext(), Buffer)
+ };
+ llvm::Constant *Descriptor = llvm::ConstantStruct::getAnon(Components);
+
+ llvm::GlobalVariable *GV =
+ new llvm::GlobalVariable(CGM.getModule(), Descriptor->getType(),
+ /*isConstant=*/true,
+ llvm::GlobalVariable::PrivateLinkage,
+ Descriptor);
+ GV->setUnnamedAddr(true);
+ return GV;
+}
- // If we are not optimzing, don't collapse all calls to trap in the function
- // to the same call, that way, in the debugger they can see which operation
- // did in fact fail. If we are optimizing, we collapse all calls to trap down
- // to just one per function to save on codesize.
- if (GCO.OptimizationLevel && TrapBB)
- return TrapBB;
+llvm::Value *CodeGenFunction::EmitCheckValue(llvm::Value *V) {
+ llvm::Type *TargetTy = IntPtrTy;
+
+ // Integers which fit in intptr_t are zero-extended and passed directly.
+ if (V->getType()->isIntegerTy() &&
+ V->getType()->getIntegerBitWidth() <= TargetTy->getIntegerBitWidth())
+ return Builder.CreateZExt(V, TargetTy);
+
+ // Pointers are passed directly, everything else is passed by address.
+ if (!V->getType()->isPointerTy()) {
+ llvm::Value *Ptr = Builder.CreateAlloca(V->getType());
+ Builder.CreateStore(V, Ptr);
+ V = Ptr;
+ }
+ return Builder.CreatePtrToInt(V, TargetTy);
+}
+
+/// \brief Emit a representation of a SourceLocation for passing to a handler
+/// in a sanitizer runtime library. The format for this data is:
+/// \code
+/// struct SourceLocation {
+/// const char *Filename;
+/// int32_t Line, Column;
+/// };
+/// \endcode
+/// For an invalid SourceLocation, the Filename pointer is null.
+llvm::Constant *CodeGenFunction::EmitCheckSourceLocation(SourceLocation Loc) {
+ PresumedLoc PLoc = getContext().getSourceManager().getPresumedLoc(Loc);
+
+ llvm::Constant *Data[] = {
+ // FIXME: Only emit each file name once.
+ PLoc.isValid() ? cast<llvm::Constant>(
+ Builder.CreateGlobalStringPtr(PLoc.getFilename()))
+ : llvm::Constant::getNullValue(Int8PtrTy),
+ Builder.getInt32(PLoc.getLine()),
+ Builder.getInt32(PLoc.getColumn())
+ };
- llvm::BasicBlock *Cont = 0;
- if (HaveInsertPoint()) {
- Cont = createBasicBlock("cont");
- EmitBranch(Cont);
+ return llvm::ConstantStruct::getAnon(Data);
+}
+
+void CodeGenFunction::EmitCheck(llvm::Value *Checked, StringRef CheckName,
+ llvm::ArrayRef<llvm::Constant *> StaticArgs,
+ llvm::ArrayRef<llvm::Value *> DynamicArgs,
+ bool Recoverable) {
+ llvm::BasicBlock *Cont = createBasicBlock("cont");
+
+ llvm::BasicBlock *Handler = createBasicBlock("handler." + CheckName);
+ Builder.CreateCondBr(Checked, Cont, Handler);
+ EmitBlock(Handler);
+
+ llvm::Constant *Info = llvm::ConstantStruct::getAnon(StaticArgs);
+ llvm::GlobalValue *InfoPtr =
+ new llvm::GlobalVariable(CGM.getModule(), Info->getType(), true,
+ llvm::GlobalVariable::PrivateLinkage, Info);
+ InfoPtr->setUnnamedAddr(true);
+
+ llvm::SmallVector<llvm::Value *, 4> Args;
+ llvm::SmallVector<llvm::Type *, 4> ArgTypes;
+ Args.reserve(DynamicArgs.size() + 1);
+ ArgTypes.reserve(DynamicArgs.size() + 1);
+
+ // Handler functions take an i8* pointing to the (handler-specific) static
+ // information block, followed by a sequence of intptr_t arguments
+ // representing operand values.
+ Args.push_back(Builder.CreateBitCast(InfoPtr, Int8PtrTy));
+ ArgTypes.push_back(Int8PtrTy);
+ for (size_t i = 0, n = DynamicArgs.size(); i != n; ++i) {
+ Args.push_back(EmitCheckValue(DynamicArgs[i]));
+ ArgTypes.push_back(IntPtrTy);
+ }
+
+ llvm::FunctionType *FnType =
+ llvm::FunctionType::get(CGM.VoidTy, ArgTypes, false);
+ llvm::AttrBuilder B;
+ if (!Recoverable) {
+ B.addAttribute(llvm::Attributes::NoReturn)
+ .addAttribute(llvm::Attributes::NoUnwind);
+ }
+ B.addAttribute(llvm::Attributes::UWTable);
+ llvm::Value *Fn = CGM.CreateRuntimeFunction(FnType,
+ ("__ubsan_handle_" + CheckName).str(),
+ llvm::Attributes::get(getLLVMContext(),
+ B));
+ llvm::CallInst *HandlerCall = Builder.CreateCall(Fn, Args);
+ if (Recoverable) {
+ Builder.CreateBr(Cont);
+ } else {
+ HandlerCall->setDoesNotReturn();
+ HandlerCall->setDoesNotThrow();
+ Builder.CreateUnreachable();
}
- TrapBB = createBasicBlock("trap");
- EmitBlock(TrapBB);
- llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::trap);
- llvm::CallInst *TrapCall = Builder.CreateCall(F);
- TrapCall->setDoesNotReturn();
- TrapCall->setDoesNotThrow();
- Builder.CreateUnreachable();
+ EmitBlock(Cont);
+}
- if (Cont)
- EmitBlock(Cont);
- return TrapBB;
+void CodeGenFunction::EmitTrapvCheck(llvm::Value *Checked) {
+ llvm::BasicBlock *Cont = createBasicBlock("cont");
+
+ // If we're optimizing, collapse all calls to trap down to just one per
+ // function to save on code size.
+ if (!CGM.getCodeGenOpts().OptimizationLevel || !TrapBB) {
+ TrapBB = createBasicBlock("trap");
+ Builder.CreateCondBr(Checked, Cont, TrapBB);
+ EmitBlock(TrapBB);
+ llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::trap);
+ llvm::CallInst *TrapCall = Builder.CreateCall(F);
+ TrapCall->setDoesNotReturn();
+ TrapCall->setDoesNotThrow();
+ Builder.CreateUnreachable();
+ } else {
+ Builder.CreateCondBr(Checked, Cont, TrapBB);
+ }
+
+ EmitBlock(Cont);
}
/// isSimpleArrayDecayOperand - If the specified expr is a simple decay from an
@@ -2007,14 +2181,14 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
// Propagate the alignment from the array itself to the result.
ArrayAlignment = ArrayLV.getAlignment();
- if (getContext().getLangOpts().isSignedOverflowDefined())
+ if (getLangOpts().isSignedOverflowDefined())
Address = Builder.CreateGEP(ArrayPtr, Args, "arrayidx");
else
Address = Builder.CreateInBoundsGEP(ArrayPtr, Args, "arrayidx");
} else {
// The base must be a pointer, which is not an aggregate. Emit it.
llvm::Value *Base = EmitScalarExpr(E->getBase());
- if (getContext().getLangOpts().isSignedOverflowDefined())
+ if (getLangOpts().isSignedOverflowDefined())
Address = Builder.CreateGEP(Base, Idx, "arrayidx");
else
Address = Builder.CreateInBoundsGEP(Base, Idx, "arrayidx");
@@ -2037,8 +2211,8 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E) {
LV.getQuals().setAddressSpace(E->getBase()->getType().getAddressSpace());
- if (getContext().getLangOpts().ObjC1 &&
- getContext().getLangOpts().getGC() != LangOptions::NonGC) {
+ if (getLangOpts().ObjC1 &&
+ getLangOpts().getGC() != LangOptions::NonGC) {
LV.setNonGC(!E->isOBJCGCCandidate(getContext()));
setObjCGCLValueClass(getContext(), E, LV);
}
@@ -2114,11 +2288,13 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
LValue BaseLV;
- if (E->isArrow())
- BaseLV = MakeNaturalAlignAddrLValue(EmitScalarExpr(BaseExpr),
- BaseExpr->getType()->getPointeeType());
- else
- BaseLV = EmitLValue(BaseExpr);
+ if (E->isArrow()) {
+ llvm::Value *Ptr = EmitScalarExpr(BaseExpr);
+ QualType PtrTy = BaseExpr->getType()->getPointeeType();
+ EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Ptr, PtrTy);
+ BaseLV = MakeNaturalAlignAddrLValue(Ptr, PtrTy);
+ } else
+ BaseLV = EmitCheckedLValue(BaseExpr, TCK_MemberAccess);
NamedDecl *ND = E->getMemberDecl();
if (FieldDecl *Field = dyn_cast<FieldDecl>(ND)) {
@@ -2355,7 +2531,10 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
case CK_Dependent:
llvm_unreachable("dependent cast kind in IR gen!");
-
+
+ case CK_BuiltinFnToFnPtr:
+ llvm_unreachable("builtin functions are handled elsewhere");
+
// These two casts are currently treated as no-ops, although they could
// potentially be real operations depending on the target's ABI.
case CK_NonAtomicToAtomic:
@@ -2546,7 +2725,7 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
if (const CXXPseudoDestructorExpr *PseudoDtor
= dyn_cast<CXXPseudoDestructorExpr>(E->getCallee()->IgnoreParens())) {
QualType DestroyedType = PseudoDtor->getDestroyedType();
- if (getContext().getLangOpts().ObjCAutoRefCount &&
+ if (getLangOpts().ObjCAutoRefCount &&
DestroyedType->isObjCLifetimeType() &&
(DestroyedType.getObjCLifetime() == Qualifiers::OCL_Strong ||
DestroyedType.getObjCLifetime() == Qualifiers::OCL_Weak)) {
@@ -2635,7 +2814,7 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {
}
RValue RV = EmitAnyExpr(E->getRHS());
- LValue LV = EmitLValue(E->getLHS());
+ LValue LV = EmitCheckedLValue(E->getLHS(), TCK_Store);
EmitStoreThroughLValue(RV, LV);
return LV;
}
@@ -2677,6 +2856,14 @@ CodeGenFunction::EmitCXXTypeidLValue(const CXXTypeidExpr *E) {
return MakeAddrLValue(EmitCXXTypeidExpr(E), E->getType());
}
+llvm::Value *CodeGenFunction::EmitCXXUuidofExpr(const CXXUuidofExpr *E) {
+ return CGM.GetAddrOfUuidDescriptor(E);
+}
+
+LValue CodeGenFunction::EmitCXXUuidofLValue(const CXXUuidofExpr *E) {
+ return MakeAddrLValue(EmitCXXUuidofExpr(E), E->getType());
+}
+
LValue
CodeGenFunction::EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E) {
AggValueSlot Slot = CreateAggTemp(E->getType(), "temp.lvalue");
@@ -2977,11 +3164,10 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
uint64_t Size = sizeChars.getQuantity();
CharUnits alignChars = getContext().getTypeAlignInChars(AtomicTy);
unsigned Align = alignChars.getQuantity();
- unsigned MaxInlineWidth =
- getContext().getTargetInfo().getMaxAtomicInlineWidth();
- bool UseLibcall = (Size != Align || Size > MaxInlineWidth);
-
-
+ unsigned MaxInlineWidthInBits =
+ getContext().getTargetInfo().getMaxAtomicInlineWidth();
+ bool UseLibcall = (Size != Align ||
+ getContext().toBits(sizeChars) > MaxInlineWidthInBits);
llvm::Value *Ptr, *Order, *OrderFail = 0, *Val1 = 0, *Val2 = 0;
Ptr = EmitScalarExpr(E->getPtr());
@@ -3177,6 +3363,13 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
return ConvertTempToRValue(*this, E->getType(), Dest);
}
+ bool IsStore = E->getOp() == AtomicExpr::AO__c11_atomic_store ||
+ E->getOp() == AtomicExpr::AO__atomic_store ||
+ E->getOp() == AtomicExpr::AO__atomic_store_n;
+ bool IsLoad = E->getOp() == AtomicExpr::AO__c11_atomic_load ||
+ E->getOp() == AtomicExpr::AO__atomic_load ||
+ E->getOp() == AtomicExpr::AO__atomic_load_n;
+
llvm::Type *IPtrTy =
llvm::IntegerType::get(getLLVMContext(), Size * 8)->getPointerTo();
llvm::Value *OrigDest = Dest;
@@ -3194,14 +3387,20 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
break;
case 1: // memory_order_consume
case 2: // memory_order_acquire
+ if (IsStore)
+ break; // Avoid crashing on code with undefined behavior
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, Size, Align,
llvm::Acquire);
break;
case 3: // memory_order_release
+ if (IsLoad)
+ break; // Avoid crashing on code with undefined behavior
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, Size, Align,
llvm::Release);
break;
case 4: // memory_order_acq_rel
+ if (IsLoad || IsStore)
+ break; // Avoid crashing on code with undefined behavior
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, Size, Align,
llvm::AcquireRelease);
break;
@@ -3221,13 +3420,6 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) {
// Long case, when Order isn't obviously constant.
- bool IsStore = E->getOp() == AtomicExpr::AO__c11_atomic_store ||
- E->getOp() == AtomicExpr::AO__atomic_store ||
- E->getOp() == AtomicExpr::AO__atomic_store_n;
- bool IsLoad = E->getOp() == AtomicExpr::AO__c11_atomic_load ||
- E->getOp() == AtomicExpr::AO__atomic_load ||
- E->getOp() == AtomicExpr::AO__atomic_load_n;
-
// Create all the relevant BB's
llvm::BasicBlock *MonotonicBB = 0, *AcquireBB = 0, *ReleaseBB = 0,
*AcqRelBB = 0, *SeqCstBB = 0;
OpenPOWER on IntegriCloud