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.cpp439
1 files changed, 328 insertions, 111 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
index 507ce3d..5f3b290 100644
--- a/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
+++ b/contrib/llvm/tools/clang/lib/CodeGen/CGExpr.cpp
@@ -11,13 +11,14 @@
//
//===----------------------------------------------------------------------===//
-#include "CodeGenFunction.h"
#include "CGCXXABI.h"
#include "CGCall.h"
+#include "CGCleanup.h"
#include "CGDebugInfo.h"
#include "CGObjCRuntime.h"
#include "CGOpenMPRuntime.h"
#include "CGRecordLayout.h"
+#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
@@ -32,6 +33,8 @@
#include "llvm/IR/MDBuilder.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Transforms/Utils/SanitizerStats.h"
using namespace clang;
using namespace CodeGen;
@@ -65,8 +68,6 @@ Address CodeGenFunction::CreateTempAlloca(llvm::Type *Ty, CharUnits Align,
/// block.
llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(llvm::Type *Ty,
const Twine &Name) {
- if (!Builder.isNamePreserving())
- return new llvm::AllocaInst(Ty, nullptr, "", AllocaInsertPt);
return new llvm::AllocaInst(Ty, nullptr, Name, AllocaInsertPt);
}
@@ -361,9 +362,16 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
ConvertTypeForMem(E->getType())
->getPointerTo(Object.getAddressSpace())),
Object.getAlignment());
- // We should not have emitted the initializer for this temporary as a
- // constant.
- assert(!Var->hasInitializer());
+
+ // createReferenceTemporary will promote the temporary to a global with a
+ // constant initializer if it can. It can only do this to a value of
+ // ARC-manageable type if the value is global and therefore "immune" to
+ // ref-counting operations. Therefore we have no need to emit either a
+ // dynamic initialization or a cleanup and we can just return the address
+ // of the temporary.
+ if (Var->hasInitializer())
+ return MakeAddrLValue(Object, M->getType(), AlignmentSource::Decl);
+
Var->setInitializer(CGM.EmitNullConstant(E->getType()));
}
LValue RefTempDst = MakeAddrLValue(Object, M->getType(),
@@ -416,6 +424,23 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true);
}
} else {
+ switch (M->getStorageDuration()) {
+ case SD_Automatic:
+ case SD_FullExpression:
+ if (auto *Size = EmitLifetimeStart(
+ CGM.getDataLayout().getTypeAllocSize(Object.getElementType()),
+ Object.getPointer())) {
+ if (M->getStorageDuration() == SD_Automatic)
+ pushCleanupAfterFullExpr<CallLifetimeEnd>(NormalEHLifetimeMarker,
+ Object, Size);
+ else
+ pushFullExprCleanup<CallLifetimeEnd>(NormalEHLifetimeMarker, Object,
+ Size);
+ }
+ break;
+ default:
+ break;
+ }
EmitAnyExprToMem(E, Object, Qualifiers(), /*IsInit*/true);
}
pushTemporaryCleanup(*this, M, E, Object);
@@ -577,7 +602,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
if (Checks.size() > 0) {
llvm::Constant *StaticData[] = {
- EmitCheckSourceLocation(Loc),
+ EmitCheckSourceLocation(Loc),
EmitCheckTypeDescriptor(Ty),
llvm::ConstantInt::get(SizeTy, AlignVal),
llvm::ConstantInt::get(Int8Ty, TCK)
@@ -824,7 +849,8 @@ Address CodeGenFunction::EmitPointerWithAlignment(const Expr *E,
getNaturalPointeeTypeAlignment(E->getType(), Source));
}
- if (SanOpts.has(SanitizerKind::CFIUnrelatedCast)) {
+ if (SanOpts.has(SanitizerKind::CFIUnrelatedCast) &&
+ CE->getCastKind() == CK_BitCast) {
if (auto PT = E->getType()->getAs<PointerType>())
EmitVTablePtrCheckForCast(PT->getPointeeType(), Addr.getPointer(),
/*MayBeNull=*/true,
@@ -1265,10 +1291,10 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
}
// Atomic operations have to be done on integral types.
- if (Ty->isAtomicType() || typeIsSuitableForInlineAtomic(Ty, Volatile)) {
- LValue lvalue =
+ LValue AtomicLValue =
LValue::MakeAddr(Addr, Ty, getContext(), AlignSource, TBAAInfo);
- return EmitAtomicLoad(lvalue, Loc).getScalarVal();
+ if (Ty->isAtomicType() || LValueIsSuitableForInlineAtomic(AtomicLValue)) {
+ return EmitAtomicLoad(AtomicLValue, Loc).getScalarVal();
}
llvm::LoadInst *Load = Builder.CreateLoad(Addr, Volatile);
@@ -1376,12 +1402,11 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr,
Value = EmitToMemory(Value, Ty);
+ LValue AtomicLValue =
+ LValue::MakeAddr(Addr, Ty, getContext(), AlignSource, TBAAInfo);
if (Ty->isAtomicType() ||
- (!isInit && typeIsSuitableForInlineAtomic(Ty, Volatile))) {
- EmitAtomicStore(RValue::get(Value),
- LValue::MakeAddr(Addr, Ty, getContext(),
- AlignSource, TBAAInfo),
- isInit);
+ (!isInit && LValueIsSuitableForInlineAtomic(AtomicLValue))) {
+ EmitAtomicStore(RValue::get(Value), AtomicLValue, isInit);
return;
}
@@ -1733,8 +1758,7 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
if (const VectorType *VTy = Dst.getType()->getAs<VectorType>()) {
unsigned NumSrcElts = VTy->getNumElements();
- unsigned NumDstElts =
- cast<llvm::VectorType>(Vec->getType())->getNumElements();
+ unsigned NumDstElts = Vec->getType()->getVectorNumElements();
if (NumDstElts == NumSrcElts) {
// Use shuffle vector is the src and destination are the same number of
// elements and restore the vector mask since it is on the side it will be
@@ -1947,6 +1971,21 @@ LValue CodeGenFunction::EmitLoadOfReferenceLValue(Address RefAddr,
return MakeAddrLValue(Addr, RefTy->getPointeeType(), Source);
}
+Address CodeGenFunction::EmitLoadOfPointer(Address Ptr,
+ const PointerType *PtrTy,
+ AlignmentSource *Source) {
+ llvm::Value *Addr = Builder.CreateLoad(Ptr);
+ return Address(Addr, getNaturalTypeAlignment(PtrTy->getPointeeType(), Source,
+ /*forPointeeType=*/true));
+}
+
+LValue CodeGenFunction::EmitLoadOfPointerLValue(Address PtrAddr,
+ const PointerType *PtrTy) {
+ AlignmentSource Source;
+ Address Addr = EmitLoadOfPointer(PtrAddr, PtrTy, &Source);
+ return MakeAddrLValue(Addr, PtrTy->getPointeeType(), Source);
+}
+
static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
const Expr *E, const VarDecl *VD) {
QualType T = E->getType();
@@ -2066,12 +2105,11 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
if (auto *FD = LambdaCaptureFields.lookup(VD))
return EmitCapturedFieldLValue(*this, FD, CXXABIThisValue);
else if (CapturedStmtInfo) {
- auto it = LocalDeclMap.find(VD);
- if (it != LocalDeclMap.end()) {
- if (auto RefTy = VD->getType()->getAs<ReferenceType>()) {
- return EmitLoadOfReferenceLValue(it->second, RefTy);
- }
- return MakeAddrLValue(it->second, T);
+ auto I = LocalDeclMap.find(VD);
+ if (I != LocalDeclMap.end()) {
+ if (auto RefTy = VD->getType()->getAs<ReferenceType>())
+ return EmitLoadOfReferenceLValue(I->second, RefTy);
+ return MakeAddrLValue(I->second, T);
}
LValue CapLVal =
EmitCapturedFieldLValue(*this, CapturedStmtInfo->lookup(VD),
@@ -2210,13 +2248,15 @@ LValue CodeGenFunction::EmitUnaryOpLValue(const UnaryOperator *E) {
return LV;
}
- assert(E->getSubExpr()->getType()->isAnyComplexType());
+ QualType T = ExprTy->castAs<ComplexType>()->getElementType();
Address Component =
(E->getOpcode() == UO_Real
? emitAddrOfRealComponent(LV.getAddress(), LV.getType())
: emitAddrOfImagComponent(LV.getAddress(), LV.getType()));
- return MakeAddrLValue(Component, ExprTy, LV.getAlignmentSource());
+ LValue ElemLV = MakeAddrLValue(Component, T, LV.getAlignmentSource());
+ ElemLV.getQuals().addQualifiers(LV.getQuals());
+ return ElemLV;
}
case UO_PreInc:
case UO_PreDec: {
@@ -2302,7 +2342,7 @@ llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) {
auto *GV = new llvm::GlobalVariable(
CGM.getModule(), Descriptor->getType(),
/*isConstant=*/true, llvm::GlobalVariable::PrivateLinkage, Descriptor);
- GV->setUnnamedAddr(true);
+ GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
CGM.getSanitizerMetadata()->disableSanitizerForGlobal(GV);
// Remember the descriptor for this type.
@@ -2352,7 +2392,33 @@ llvm::Constant *CodeGenFunction::EmitCheckSourceLocation(SourceLocation Loc) {
PresumedLoc PLoc = getContext().getSourceManager().getPresumedLoc(Loc);
if (PLoc.isValid()) {
- auto FilenameGV = CGM.GetAddrOfConstantCString(PLoc.getFilename(), ".src");
+ StringRef FilenameString = PLoc.getFilename();
+
+ int PathComponentsToStrip =
+ CGM.getCodeGenOpts().EmitCheckPathComponentsToStrip;
+ if (PathComponentsToStrip < 0) {
+ assert(PathComponentsToStrip != INT_MIN);
+ int PathComponentsToKeep = -PathComponentsToStrip;
+ auto I = llvm::sys::path::rbegin(FilenameString);
+ auto E = llvm::sys::path::rend(FilenameString);
+ while (I != E && --PathComponentsToKeep)
+ ++I;
+
+ FilenameString = FilenameString.substr(I - E);
+ } else if (PathComponentsToStrip > 0) {
+ auto I = llvm::sys::path::begin(FilenameString);
+ auto E = llvm::sys::path::end(FilenameString);
+ while (I != E && PathComponentsToStrip--)
+ ++I;
+
+ if (I != E)
+ FilenameString =
+ FilenameString.substr(I - llvm::sys::path::begin(FilenameString));
+ else
+ FilenameString = llvm::sys::path::filename(FilenameString);
+ }
+
+ auto FilenameGV = CGM.GetAddrOfConstantCString(FilenameString, ".src");
CGM.getSanitizerMetadata()->disableSanitizerForGlobal(
cast<llvm::GlobalVariable>(FilenameGV.getPointer()));
Filename = FilenameGV.getPointer();
@@ -2483,24 +2549,26 @@ void CodeGenFunction::EmitCheck(
Branch->setMetadata(llvm::LLVMContext::MD_prof, Node);
EmitBlock(Handlers);
- // Emit handler arguments and create handler function type.
- llvm::Constant *Info = llvm::ConstantStruct::getAnon(StaticArgs);
- auto *InfoPtr =
- new llvm::GlobalVariable(CGM.getModule(), Info->getType(), false,
- llvm::GlobalVariable::PrivateLinkage, Info);
- InfoPtr->setUnnamedAddr(true);
- CGM.getSanitizerMetadata()->disableSanitizerForGlobal(InfoPtr);
-
+ // Handler functions take an i8* pointing to the (handler-specific) static
+ // information block, followed by a sequence of intptr_t arguments
+ // representing operand values.
SmallVector<llvm::Value *, 4> Args;
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);
+ // Emit handler arguments and create handler function type.
+ if (!StaticArgs.empty()) {
+ llvm::Constant *Info = llvm::ConstantStruct::getAnon(StaticArgs);
+ auto *InfoPtr =
+ new llvm::GlobalVariable(CGM.getModule(), Info->getType(), false,
+ llvm::GlobalVariable::PrivateLinkage, Info);
+ InfoPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ CGM.getSanitizerMetadata()->disableSanitizerForGlobal(InfoPtr);
+ 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);
@@ -2532,10 +2600,9 @@ void CodeGenFunction::EmitCheck(
EmitBlock(Cont);
}
-void CodeGenFunction::EmitCfiSlowPathCheck(llvm::Value *Cond,
- llvm::ConstantInt *TypeId,
- llvm::Value *Ptr) {
- auto &Ctx = getLLVMContext();
+void CodeGenFunction::EmitCfiSlowPathCheck(
+ SanitizerMask Kind, llvm::Value *Cond, llvm::ConstantInt *TypeId,
+ llvm::Value *Ptr, ArrayRef<llvm::Constant *> StaticArgs) {
llvm::BasicBlock *Cont = createBasicBlock("cfi.cont");
llvm::BasicBlock *CheckBB = createBasicBlock("cfi.slowpath");
@@ -2547,19 +2614,122 @@ void CodeGenFunction::EmitCfiSlowPathCheck(llvm::Value *Cond,
EmitBlock(CheckBB);
- llvm::Constant *SlowPathFn = CGM.getModule().getOrInsertFunction(
- "__cfi_slowpath",
- llvm::FunctionType::get(
- llvm::Type::getVoidTy(Ctx),
- {llvm::Type::getInt64Ty(Ctx),
- llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(Ctx))},
- false));
- llvm::CallInst *CheckCall = Builder.CreateCall(SlowPathFn, {TypeId, Ptr});
+ bool WithDiag = !CGM.getCodeGenOpts().SanitizeTrap.has(Kind);
+
+ llvm::CallInst *CheckCall;
+ if (WithDiag) {
+ llvm::Constant *Info = llvm::ConstantStruct::getAnon(StaticArgs);
+ auto *InfoPtr =
+ new llvm::GlobalVariable(CGM.getModule(), Info->getType(), false,
+ llvm::GlobalVariable::PrivateLinkage, Info);
+ InfoPtr->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+ CGM.getSanitizerMetadata()->disableSanitizerForGlobal(InfoPtr);
+
+ llvm::Constant *SlowPathDiagFn = CGM.getModule().getOrInsertFunction(
+ "__cfi_slowpath_diag",
+ llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy, Int8PtrTy},
+ false));
+ CheckCall = Builder.CreateCall(
+ SlowPathDiagFn,
+ {TypeId, Ptr, Builder.CreateBitCast(InfoPtr, Int8PtrTy)});
+ } else {
+ llvm::Constant *SlowPathFn = CGM.getModule().getOrInsertFunction(
+ "__cfi_slowpath",
+ llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy}, false));
+ CheckCall = Builder.CreateCall(SlowPathFn, {TypeId, Ptr});
+ }
+
CheckCall->setDoesNotThrow();
EmitBlock(Cont);
}
+// This function is basically a switch over the CFI failure kind, which is
+// extracted from CFICheckFailData (1st function argument). Each case is either
+// llvm.trap or a call to one of the two runtime handlers, based on
+// -fsanitize-trap and -fsanitize-recover settings. Default case (invalid
+// failure kind) traps, but this should really never happen. CFICheckFailData
+// can be nullptr if the calling module has -fsanitize-trap behavior for this
+// check kind; in this case __cfi_check_fail traps as well.
+void CodeGenFunction::EmitCfiCheckFail() {
+ SanitizerScope SanScope(this);
+ FunctionArgList Args;
+ ImplicitParamDecl ArgData(getContext(), nullptr, SourceLocation(), nullptr,
+ getContext().VoidPtrTy);
+ ImplicitParamDecl ArgAddr(getContext(), nullptr, SourceLocation(), nullptr,
+ getContext().VoidPtrTy);
+ Args.push_back(&ArgData);
+ Args.push_back(&ArgAddr);
+
+ const CGFunctionInfo &FI =
+ CGM.getTypes().arrangeBuiltinFunctionDeclaration(getContext().VoidTy, Args);
+
+ llvm::Function *F = llvm::Function::Create(
+ llvm::FunctionType::get(VoidTy, {VoidPtrTy, VoidPtrTy}, false),
+ llvm::GlobalValue::WeakODRLinkage, "__cfi_check_fail", &CGM.getModule());
+ F->setVisibility(llvm::GlobalValue::HiddenVisibility);
+
+ StartFunction(GlobalDecl(), CGM.getContext().VoidTy, F, FI, Args,
+ SourceLocation());
+
+ llvm::Value *Data =
+ EmitLoadOfScalar(GetAddrOfLocalVar(&ArgData), /*Volatile=*/false,
+ CGM.getContext().VoidPtrTy, ArgData.getLocation());
+ llvm::Value *Addr =
+ EmitLoadOfScalar(GetAddrOfLocalVar(&ArgAddr), /*Volatile=*/false,
+ CGM.getContext().VoidPtrTy, ArgAddr.getLocation());
+
+ // Data == nullptr means the calling module has trap behaviour for this check.
+ llvm::Value *DataIsNotNullPtr =
+ Builder.CreateICmpNE(Data, llvm::ConstantPointerNull::get(Int8PtrTy));
+ EmitTrapCheck(DataIsNotNullPtr);
+
+ llvm::StructType *SourceLocationTy =
+ llvm::StructType::get(VoidPtrTy, Int32Ty, Int32Ty, nullptr);
+ llvm::StructType *CfiCheckFailDataTy =
+ llvm::StructType::get(Int8Ty, SourceLocationTy, VoidPtrTy, nullptr);
+
+ llvm::Value *V = Builder.CreateConstGEP2_32(
+ CfiCheckFailDataTy,
+ Builder.CreatePointerCast(Data, CfiCheckFailDataTy->getPointerTo(0)), 0,
+ 0);
+ Address CheckKindAddr(V, getIntAlign());
+ llvm::Value *CheckKind = Builder.CreateLoad(CheckKindAddr);
+
+ llvm::Value *AllVtables = llvm::MetadataAsValue::get(
+ CGM.getLLVMContext(),
+ llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));
+ llvm::Value *ValidVtable = Builder.CreateZExt(
+ Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::type_test),
+ {Addr, AllVtables}),
+ IntPtrTy);
+
+ const std::pair<int, SanitizerMask> CheckKinds[] = {
+ {CFITCK_VCall, SanitizerKind::CFIVCall},
+ {CFITCK_NVCall, SanitizerKind::CFINVCall},
+ {CFITCK_DerivedCast, SanitizerKind::CFIDerivedCast},
+ {CFITCK_UnrelatedCast, SanitizerKind::CFIUnrelatedCast},
+ {CFITCK_ICall, SanitizerKind::CFIICall}};
+
+ SmallVector<std::pair<llvm::Value *, SanitizerMask>, 5> Checks;
+ for (auto CheckKindMaskPair : CheckKinds) {
+ int Kind = CheckKindMaskPair.first;
+ SanitizerMask Mask = CheckKindMaskPair.second;
+ llvm::Value *Cond =
+ Builder.CreateICmpNE(CheckKind, llvm::ConstantInt::get(Int8Ty, Kind));
+ if (CGM.getLangOpts().Sanitize.has(Mask))
+ EmitCheck(std::make_pair(Cond, Mask), "cfi_check_fail", {},
+ {Data, Addr, ValidVtable});
+ else
+ EmitTrapCheck(Cond);
+ }
+
+ FinishFunction();
+ // The only reference to this function will be created during LTO link.
+ // Make sure it survives until then.
+ CGM.addUsedGlobal(F);
+}
+
void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) {
llvm::BasicBlock *Cont = createBasicBlock("cont");
@@ -2827,22 +2997,55 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
return LV;
}
+static Address emitOMPArraySectionBase(CodeGenFunction &CGF, const Expr *Base,
+ AlignmentSource &AlignSource,
+ QualType BaseTy, QualType ElTy,
+ bool IsLowerBound) {
+ LValue BaseLVal;
+ if (auto *ASE = dyn_cast<OMPArraySectionExpr>(Base->IgnoreParenImpCasts())) {
+ BaseLVal = CGF.EmitOMPArraySectionExpr(ASE, IsLowerBound);
+ if (BaseTy->isArrayType()) {
+ Address Addr = BaseLVal.getAddress();
+ AlignSource = BaseLVal.getAlignmentSource();
+
+ // If the array type was an incomplete type, we need to make sure
+ // the decay ends up being the right type.
+ llvm::Type *NewTy = CGF.ConvertType(BaseTy);
+ Addr = CGF.Builder.CreateElementBitCast(Addr, NewTy);
+
+ // Note that VLA pointers are always decayed, so we don't need to do
+ // anything here.
+ if (!BaseTy->isVariableArrayType()) {
+ assert(isa<llvm::ArrayType>(Addr.getElementType()) &&
+ "Expected pointer to array");
+ Addr = CGF.Builder.CreateStructGEP(Addr, 0, CharUnits::Zero(),
+ "arraydecay");
+ }
+
+ return CGF.Builder.CreateElementBitCast(Addr,
+ CGF.ConvertTypeForMem(ElTy));
+ }
+ CharUnits Align = CGF.getNaturalTypeAlignment(ElTy, &AlignSource);
+ return Address(CGF.Builder.CreateLoad(BaseLVal.getAddress()), Align);
+ }
+ return CGF.EmitPointerWithAlignment(Base, &AlignSource);
+}
+
LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
bool IsLowerBound) {
- LValue Base;
+ QualType BaseTy;
if (auto *ASE =
dyn_cast<OMPArraySectionExpr>(E->getBase()->IgnoreParenImpCasts()))
- Base = EmitOMPArraySectionExpr(ASE, IsLowerBound);
+ BaseTy = OMPArraySectionExpr::getBaseOriginalType(ASE);
else
- Base = EmitLValue(E->getBase());
- QualType BaseTy = Base.getType();
- llvm::Value *Idx = nullptr;
+ BaseTy = E->getBase()->getType();
QualType ResultExprTy;
if (auto *AT = getContext().getAsArrayType(BaseTy))
ResultExprTy = AT->getElementType();
else
ResultExprTy = BaseTy->getPointeeType();
- if (IsLowerBound || (!IsLowerBound && E->getColonLoc().isInvalid())) {
+ llvm::Value *Idx = nullptr;
+ if (IsLowerBound || E->getColonLoc().isInvalid()) {
// Requesting lower bound or upper bound, but without provided length and
// without ':' symbol for the default length -> length = 1.
// Idx = LowerBound ?: 0;
@@ -2853,9 +3056,9 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
} else
Idx = llvm::ConstantInt::getNullValue(IntPtrTy);
} else {
- // Try to emit length or lower bound as constant. If this is possible, 1 is
- // subtracted from constant length or lower bound. Otherwise, emit LLVM IR
- // (LB + Len) - 1.
+ // Try to emit length or lower bound as constant. If this is possible, 1
+ // is subtracted from constant length or lower bound. Otherwise, emit LLVM
+ // IR (LB + Len) - 1.
auto &C = CGM.getContext();
auto *Length = E->getLength();
llvm::APSInt ConstLength;
@@ -2901,12 +3104,15 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
Idx = llvm::ConstantInt::get(IntPtrTy, ConstLength + ConstLowerBound);
} else {
// Idx = ArraySize - 1;
- if (auto *VAT = C.getAsVariableArrayType(BaseTy)) {
+ QualType ArrayTy = BaseTy->isPointerType()
+ ? E->getBase()->IgnoreParenImpCasts()->getType()
+ : BaseTy;
+ if (auto *VAT = C.getAsVariableArrayType(ArrayTy)) {
Length = VAT->getSizeExpr();
if (Length->isIntegerConstantExpr(ConstLength, C))
Length = nullptr;
} else {
- auto *CAT = C.getAsConstantArrayType(BaseTy);
+ auto *CAT = C.getAsConstantArrayType(ArrayTy);
ConstLength = CAT->getSize();
}
if (Length) {
@@ -2925,52 +3131,56 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E,
}
assert(Idx);
- llvm::Value *EltPtr;
- QualType FixedSizeEltType = ResultExprTy;
+ Address EltPtr = Address::invalid();
+ AlignmentSource AlignSource;
if (auto *VLA = getContext().getAsVariableArrayType(ResultExprTy)) {
+ // The base must be a pointer, which is not an aggregate. Emit
+ // it. It needs to be emitted first in case it's what captures
+ // the VLA bounds.
+ Address Base =
+ emitOMPArraySectionBase(*this, E->getBase(), AlignSource, BaseTy,
+ VLA->getElementType(), IsLowerBound);
// The element count here is the total number of non-VLA elements.
- llvm::Value *numElements = getVLASize(VLA).first;
- FixedSizeEltType = getFixedSizeElementType(getContext(), VLA);
+ llvm::Value *NumElements = getVLASize(VLA).first;
// Effectively, the multiply by the VLA size is part of the GEP.
// GEP indexes are signed, and scaling an index isn't permitted to
// signed-overflow, so we use the same semantics for our explicit
// multiply. We suppress this if overflow is not undefined behavior.
- if (getLangOpts().isSignedOverflowDefined()) {
- Idx = Builder.CreateMul(Idx, numElements);
- EltPtr = Builder.CreateGEP(Base.getPointer(), Idx, "arrayidx");
- } else {
- Idx = Builder.CreateNSWMul(Idx, numElements);
- EltPtr = Builder.CreateInBoundsGEP(Base.getPointer(), Idx, "arrayidx");
- }
- } else if (BaseTy->isConstantArrayType()) {
- llvm::Value *ArrayPtr = Base.getPointer();
- llvm::Value *Zero = llvm::ConstantInt::getNullValue(IntPtrTy);
- llvm::Value *Args[] = {Zero, Idx};
-
if (getLangOpts().isSignedOverflowDefined())
- EltPtr = Builder.CreateGEP(ArrayPtr, Args, "arrayidx");
+ Idx = Builder.CreateMul(Idx, NumElements);
else
- EltPtr = Builder.CreateInBoundsGEP(ArrayPtr, Args, "arrayidx");
- } else {
- // The base must be a pointer, which is not an aggregate. Emit it.
- if (getLangOpts().isSignedOverflowDefined())
- EltPtr = Builder.CreateGEP(Base.getPointer(), Idx, "arrayidx");
+ Idx = Builder.CreateNSWMul(Idx, NumElements);
+ EltPtr = emitArraySubscriptGEP(*this, Base, Idx, VLA->getElementType(),
+ !getLangOpts().isSignedOverflowDefined());
+ } else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) {
+ // If this is A[i] where A is an array, the frontend will have decayed the
+ // base to be a ArrayToPointerDecay implicit cast. While correct, it is
+ // inefficient at -O0 to emit a "gep A, 0, 0" when codegen'ing it, then a
+ // "gep x, i" here. Emit one "gep A, 0, i".
+ assert(Array->getType()->isArrayType() &&
+ "Array to pointer decay must have array source type!");
+ LValue ArrayLV;
+ // For simple multidimensional array indexing, set the 'accessed' flag for
+ // better bounds-checking of the base expression.
+ if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Array))
+ ArrayLV = EmitArraySubscriptExpr(ASE, /*Accessed*/ true);
else
- EltPtr = Builder.CreateInBoundsGEP(Base.getPointer(), Idx, "arrayidx");
- }
-
- CharUnits EltAlign =
- Base.getAlignment().alignmentOfArrayElement(
- getContext().getTypeSizeInChars(FixedSizeEltType));
-
- // Limit the alignment to that of the result type.
- LValue LV = MakeAddrLValue(Address(EltPtr, EltAlign), ResultExprTy,
- Base.getAlignmentSource());
+ ArrayLV = EmitLValue(Array);
- LV.getQuals().setAddressSpace(BaseTy.getAddressSpace());
+ // Propagate the alignment from the array itself to the result.
+ EltPtr = emitArraySubscriptGEP(
+ *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx},
+ ResultExprTy, !getLangOpts().isSignedOverflowDefined());
+ AlignSource = ArrayLV.getAlignmentSource();
+ } else {
+ Address Base = emitOMPArraySectionBase(*this, E->getBase(), AlignSource,
+ BaseTy, ResultExprTy, IsLowerBound);
+ EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy,
+ !getLangOpts().isSignedOverflowDefined());
+ }
- return LV;
+ return MakeAddrLValue(EltPtr, ResultExprTy, AlignSource);
}
LValue CodeGenFunction::
@@ -3508,6 +3718,10 @@ RValue CodeGenFunction::EmitRValueForField(LValue LV,
case TEK_Aggregate:
return FieldLV.asAggregateRValue();
case TEK_Scalar:
+ // This routine is used to load fields one-by-one to perform a copy, so
+ // don't load reference fields.
+ if (FD->getType()->isReferenceType())
+ return RValue::get(FieldLV.getPointer());
return EmitLoadOfLValue(FieldLV, Loc);
}
llvm_unreachable("bad evaluation kind");
@@ -3851,25 +4065,28 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
if (SanOpts.has(SanitizerKind::CFIICall) &&
(!TargetDecl || !isa<FunctionDecl>(TargetDecl))) {
SanitizerScope SanScope(this);
+ EmitSanitizerStatReport(llvm::SanStat_CFI_ICall);
llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(QualType(FnType, 0));
- llvm::Value *BitSetName = llvm::MetadataAsValue::get(getLLVMContext(), MD);
+ llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD);
llvm::Value *CastedCallee = Builder.CreateBitCast(Callee, Int8PtrTy);
- llvm::Value *BitSetTest =
- Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::bitset_test),
- {CastedCallee, BitSetName});
+ llvm::Value *TypeTest = Builder.CreateCall(
+ CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedCallee, TypeId});
- auto TypeId = CGM.CreateCfiIdForTypeMetadata(MD);
- if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && TypeId) {
- EmitCfiSlowPathCheck(BitSetTest, TypeId, CastedCallee);
+ auto CrossDsoTypeId = CGM.CreateCrossDsoCfiTypeId(MD);
+ llvm::Constant *StaticData[] = {
+ llvm::ConstantInt::get(Int8Ty, CFITCK_ICall),
+ EmitCheckSourceLocation(E->getLocStart()),
+ EmitCheckTypeDescriptor(QualType(FnType, 0)),
+ };
+ if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) {
+ EmitCfiSlowPathCheck(SanitizerKind::CFIICall, TypeTest, CrossDsoTypeId,
+ CastedCallee, StaticData);
} else {
- llvm::Constant *StaticData[] = {
- EmitCheckSourceLocation(E->getLocStart()),
- EmitCheckTypeDescriptor(QualType(FnType, 0)),
- };
- EmitCheck(std::make_pair(BitSetTest, SanitizerKind::CFIICall),
- "cfi_bad_icall", StaticData, CastedCallee);
+ EmitCheck(std::make_pair(TypeTest, SanitizerKind::CFIICall),
+ "cfi_check_fail", StaticData,
+ {CastedCallee, llvm::UndefValue::get(IntPtrTy)});
}
}
OpenPOWER on IntegriCloud