aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGExpr.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-12-09 13:28:42 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-12-09 13:28:42 +0000
commitb1c73532ee8997fe5dfbeb7d223027bdf99758a0 (patch)
tree7d6e51c294ab6719475d660217aa0c0ad0526292 /clang/lib/CodeGen/CGExpr.cpp
parent7fa27ce4a07f19b07799a767fc29416f3b625afb (diff)
downloadsrc-b1c73532ee8997fe5dfbeb7d223027bdf99758a0.tar.gz
src-b1c73532ee8997fe5dfbeb7d223027bdf99758a0.zip
Vendor import of llvm-project main llvmorg-18-init-14265-ga17671084db1.vendor/llvm-project/llvmorg-18-init-14265-ga17671084db1
Diffstat (limited to 'clang/lib/CodeGen/CGExpr.cpp')
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp390
1 files changed, 289 insertions, 101 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index ed6095f7cfeb..69cf7f76be9a 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -30,6 +30,7 @@
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Intrinsics.h"
@@ -51,6 +52,12 @@
using namespace clang;
using namespace CodeGen;
+// Experiment to make sanitizers easier to debug
+static llvm::cl::opt<bool> ClSanitizeDebugDeoptimization(
+ "ubsan-unique-traps", llvm::cl::Optional,
+ llvm::cl::desc("Deoptimize traps for UBSAN so there is 1 trap per check"),
+ llvm::cl::init(false));
+
//===--------------------------------------------------------------------===//
// Miscellaneous Helper Methods
//===--------------------------------------------------------------------===//
@@ -140,9 +147,8 @@ Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align,
auto *VectorTy = llvm::FixedVectorType::get(ArrayTy->getElementType(),
ArrayTy->getNumElements());
- Result = Address(
- Builder.CreateBitCast(Result.getPointer(), VectorTy->getPointerTo()),
- VectorTy, Result.getAlignment(), KnownNonNull);
+ Result = Address(Result.getPointer(), VectorTy, Result.getAlignment(),
+ KnownNonNull);
}
return Result;
}
@@ -392,7 +398,7 @@ static Address createReferenceTemporary(CodeGenFunction &CGF,
QualType Ty = Inner->getType();
if (CGF.CGM.getCodeGenOpts().MergeAllConstants &&
(Ty->isArrayType() || Ty->isRecordType()) &&
- CGF.CGM.isTypeConstant(Ty, true, false))
+ Ty.isConstantStorage(CGF.getContext(), true, false))
if (auto Init = ConstantEmitter(CGF).tryEmitAbstract(Inner, Ty)) {
auto AS = CGF.CGM.GetGlobalConstantAddressSpace();
auto *GV = new llvm::GlobalVariable(
@@ -444,9 +450,7 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
Address Object = createReferenceTemporary(*this, M, E);
if (auto *Var = dyn_cast<llvm::GlobalVariable>(Object.getPointer())) {
llvm::Type *Ty = ConvertTypeForMem(E->getType());
- Object = Address(llvm::ConstantExpr::getBitCast(
- Var, Ty->getPointerTo(Object.getAddressSpace())),
- Ty, Object.getAlignment());
+ Object = Object.withElementType(Ty);
// createReferenceTemporary will promote the temporary to a global with a
// constant initializer if it can. It can only do this to a value of
@@ -502,11 +506,7 @@ EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *M) {
if (auto *Var = dyn_cast<llvm::GlobalVariable>(
Object.getPointer()->stripPointerCasts())) {
llvm::Type *TemporaryType = ConvertTypeForMem(E->getType());
- Object = Address(llvm::ConstantExpr::getBitCast(
- cast<llvm::Constant>(Object.getPointer()),
- TemporaryType->getPointerTo()),
- TemporaryType,
- Object.getAlignment());
+ Object = Object.withElementType(TemporaryType);
// If the temporary is a global and has a constant initializer or is a
// constant temporary that we promoted to a global, we may have already
// initialized it.
@@ -746,9 +746,8 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
llvm::Value *Min = Builder.getFalse();
llvm::Value *NullIsUnknown = Builder.getFalse();
llvm::Value *Dynamic = Builder.getFalse();
- llvm::Value *CastAddr = Builder.CreateBitCast(Ptr, Int8PtrTy);
llvm::Value *LargeEnough = Builder.CreateICmpUGE(
- Builder.CreateCall(F, {CastAddr, Min, NullIsUnknown, Dynamic}), Size);
+ Builder.CreateCall(F, {Ptr, Min, NullIsUnknown, Dynamic}), Size);
Checks.push_back(std::make_pair(LargeEnough, SanitizerKind::ObjectSize));
}
}
@@ -825,9 +824,7 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
// 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);
- Address VPtrAddr(Builder.CreateBitCast(Ptr, VPtrTy), IntPtrTy,
- getPointerAlign());
+ Address VPtrAddr(Ptr, IntPtrTy, getPointerAlign());
llvm::Value *VPtrVal = Builder.CreateLoad(VPtrAddr);
llvm::Value *High = Builder.CreateZExt(VPtrVal, Int64Ty);
@@ -929,16 +926,27 @@ static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF,
if (CE->getCastKind() == CK_ArrayToPointerDecay &&
!CE->getSubExpr()->isFlexibleArrayMemberLike(CGF.getContext(),
StrictFlexArraysLevel)) {
+ CodeGenFunction::SanitizerScope SanScope(&CGF);
+
IndexedType = CE->getSubExpr()->getType();
const ArrayType *AT = IndexedType->castAsArrayTypeUnsafe();
if (const auto *CAT = dyn_cast<ConstantArrayType>(AT))
return CGF.Builder.getInt(CAT->getSize());
- else if (const auto *VAT = dyn_cast<VariableArrayType>(AT))
+
+ if (const auto *VAT = dyn_cast<VariableArrayType>(AT))
return CGF.getVLASize(VAT).NumElts;
// Ignore pass_object_size here. It's not applicable on decayed pointers.
}
+
+ if (const ValueDecl *VD = CGF.FindCountedByField(Base)) {
+ IndexedType = Base->getType();
+ const Expr *E = CGF.BuildCountedByFieldExpr(Base, VD);
+ return CGF.EmitAnyExprToTemp(E).getScalarVal();
+ }
}
+ CodeGenFunction::SanitizerScope SanScope(&CGF);
+
QualType EltTy{Base->getType()->getPointeeOrArrayElementType(), 0};
if (llvm::Value *POS = CGF.LoadPassedObjectSize(Base, EltTy)) {
IndexedType = Base->getType();
@@ -948,13 +956,122 @@ static llvm::Value *getArrayIndexingBound(CodeGenFunction &CGF,
return nullptr;
}
+const Expr *
+CodeGenFunction::BuildCountedByFieldExpr(const Expr *Base,
+ const ValueDecl *CountedByVD) {
+ // Find the outer struct expr (i.e. p in p->a.b.c.d).
+ Expr *CountedByExpr = const_cast<Expr *>(Base)->IgnoreParenImpCasts();
+
+ // Work our way up the expression until we reach the DeclRefExpr.
+ while (!isa<DeclRefExpr>(CountedByExpr))
+ if (const auto *ME = dyn_cast<MemberExpr>(CountedByExpr))
+ CountedByExpr = ME->getBase()->IgnoreParenImpCasts();
+
+ // Add back an implicit cast to create the required pr-value.
+ CountedByExpr = ImplicitCastExpr::Create(
+ getContext(), CountedByExpr->getType(), CK_LValueToRValue, CountedByExpr,
+ nullptr, VK_PRValue, FPOptionsOverride());
+
+ if (const auto *IFD = dyn_cast<IndirectFieldDecl>(CountedByVD)) {
+ // The counted_by field is inside an anonymous struct / union. The
+ // IndirectFieldDecl has the correct order of FieldDecls to build this
+ // easily. (Yay!)
+ for (NamedDecl *ND : IFD->chain()) {
+ auto *VD = cast<ValueDecl>(ND);
+ CountedByExpr =
+ MemberExpr::CreateImplicit(getContext(), CountedByExpr,
+ CountedByExpr->getType()->isPointerType(),
+ VD, VD->getType(), VK_LValue, OK_Ordinary);
+ }
+ } else {
+ CountedByExpr = MemberExpr::CreateImplicit(
+ getContext(), const_cast<Expr *>(CountedByExpr),
+ CountedByExpr->getType()->isPointerType(),
+ const_cast<ValueDecl *>(CountedByVD), CountedByVD->getType(), VK_LValue,
+ OK_Ordinary);
+ }
+
+ return CountedByExpr;
+}
+
+const ValueDecl *
+CodeGenFunction::FindFlexibleArrayMemberField(ASTContext &Ctx,
+ const RecordDecl *RD) {
+ const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
+ getLangOpts().getStrictFlexArraysLevel();
+
+ for (const Decl *D : RD->decls()) {
+ if (const auto *VD = dyn_cast<ValueDecl>(D);
+ VD && Decl::isFlexibleArrayMemberLike(
+ Ctx, VD, VD->getType(), StrictFlexArraysLevel,
+ /*IgnoreTemplateOrMacroSubstitution=*/true))
+ return VD;
+
+ if (const auto *Record = dyn_cast<RecordDecl>(D))
+ if (const ValueDecl *VD = FindFlexibleArrayMemberField(Ctx, Record))
+ return VD;
+ }
+
+ return nullptr;
+}
+
+const ValueDecl *CodeGenFunction::FindCountedByField(const Expr *Base) {
+ ASTContext &Ctx = getContext();
+ const RecordDecl *OuterRD = nullptr;
+ const FieldDecl *FD = nullptr;
+
+ Base = Base->IgnoreParenImpCasts();
+
+ // Get the outer-most lexical RecordDecl.
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
+ QualType Ty = DRE->getDecl()->getType();
+ if (Ty->isPointerType())
+ Ty = Ty->getPointeeType();
+
+ if (const auto *RD = Ty->getAsRecordDecl())
+ OuterRD = RD->getOuterLexicalRecordContext();
+ } else if (const auto *ME = dyn_cast<MemberExpr>(Base)) {
+ if (const ValueDecl *MD = ME->getMemberDecl()) {
+ OuterRD = MD->getDeclContext()->getOuterLexicalRecordContext();
+
+ const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
+ getLangOpts().getStrictFlexArraysLevel();
+ if (Decl::isFlexibleArrayMemberLike(
+ Ctx, MD, MD->getType(), StrictFlexArraysLevel,
+ /*IgnoreTemplateOrMacroSubstitution=*/true))
+ // Base is referencing the FAM itself.
+ FD = dyn_cast<FieldDecl>(MD);
+ }
+ }
+
+ if (!OuterRD)
+ return nullptr;
+
+ if (!FD) {
+ const ValueDecl *VD = FindFlexibleArrayMemberField(Ctx, OuterRD);
+ FD = dyn_cast_if_present<FieldDecl>(VD);
+ if (!FD)
+ return nullptr;
+ }
+
+ const auto *CBA = FD->getAttr<CountedByAttr>();
+ if (!CBA)
+ return nullptr;
+
+ DeclarationName DName(CBA->getCountedByField());
+ DeclContext::lookup_result Lookup = OuterRD->lookup(DName);
+
+ if (Lookup.empty())
+ return nullptr;
+
+ return dyn_cast<ValueDecl>(Lookup.front());
+}
+
void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base,
llvm::Value *Index, QualType IndexType,
bool Accessed) {
assert(SanOpts.has(SanitizerKind::ArrayBounds) &&
"should not be called unless adding bounds checks");
- SanitizerScope SanScope(this);
-
const LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
getLangOpts().getStrictFlexArraysLevel();
@@ -964,6 +1081,8 @@ void CodeGenFunction::EmitBoundsCheck(const Expr *E, const Expr *Base,
if (!Bound)
return;
+ SanitizerScope SanScope(this);
+
bool IndexSigned = IndexType->isSignedIntegerOrEnumerationType();
llvm::Value *IndexVal = Builder.CreateIntCast(Index, SizeTy, IndexSigned);
llvm::Value *BoundVal = Builder.CreateIntCast(Bound, SizeTy, false);
@@ -1216,7 +1335,7 @@ LValue CodeGenFunction::EmitUnsupportedLValue(const Expr *E,
const char *Name) {
ErrorUnsupported(E, Name);
llvm::Type *ElTy = ConvertType(E->getType());
- llvm::Type *Ty = llvm::PointerType::getUnqual(ElTy);
+ llvm::Type *Ty = UnqualPtrTy;
return MakeAddrLValue(
Address(llvm::UndefValue::get(Ty), ElTy, CharUnits::One()), E->getType());
}
@@ -2039,6 +2158,14 @@ RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV) {
llvm::Value *Vec = Builder.CreateLoad(LV.getExtVectorAddress(),
LV.isVolatileQualified());
+ // HLSL allows treating scalars as one-element vectors. Converting the scalar
+ // IR value to a vector here allows the rest of codegen to behave as normal.
+ if (getLangOpts().HLSL && !Vec->getType()->isVectorTy()) {
+ llvm::Type *DstTy = llvm::FixedVectorType::get(Vec->getType(), 1);
+ llvm::Value *Zero = llvm::Constant::getNullValue(CGM.Int64Ty);
+ Vec = Builder.CreateInsertElement(DstTy, Vec, Zero, "cast.splat");
+ }
+
const llvm::Constant *Elts = LV.getExtVectorElts();
// If the result of the expression is a non-vector type, we must be extracting
@@ -2308,10 +2435,20 @@ void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
LValue Dst) {
+ // HLSL allows storing to scalar values through ExtVector component LValues.
+ // To support this we need to handle the case where the destination address is
+ // a scalar.
+ Address DstAddr = Dst.getExtVectorAddress();
+ if (!DstAddr.getElementType()->isVectorTy()) {
+ assert(!Dst.getType()->isVectorType() &&
+ "this should only occur for non-vector l-values");
+ Builder.CreateStore(Src.getScalarVal(), DstAddr, Dst.isVolatileQualified());
+ return;
+ }
+
// This access turns into a read/modify/write of the vector. Load the input
// value now.
- llvm::Value *Vec = Builder.CreateLoad(Dst.getExtVectorAddress(),
- Dst.isVolatileQualified());
+ llvm::Value *Vec = Builder.CreateLoad(DstAddr, Dst.isVolatileQualified());
const llvm::Constant *Elts = Dst.getExtVectorElts();
llvm::Value *SrcVal = Src.getScalarVal();
@@ -2359,7 +2496,8 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
llvm_unreachable("unexpected shorten vector length");
}
} else {
- // If the Src is a scalar (not a vector) it must be updating one element.
+ // If the Src is a scalar (not a vector), and the target is a vector it must
+ // be updating one element.
unsigned InIdx = getAccessedFieldNo(0, Elts);
llvm::Value *Elt = llvm::ConstantInt::get(SizeTy, InIdx);
Vec = Builder.CreateInsertElement(Vec, SrcVal, Elt);
@@ -2492,14 +2630,6 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
}
}
-static llvm::Value *
-EmitBitCastOfLValueToProperType(CodeGenFunction &CGF,
- llvm::Value *V, llvm::Type *IRType,
- StringRef Name = StringRef()) {
- unsigned AS = cast<llvm::PointerType>(V->getType())->getAddressSpace();
- return CGF.Builder.CreateBitCast(V, IRType->getPointerTo(AS), Name);
-}
-
static LValue EmitThreadPrivateVarDeclLValue(
CodeGenFunction &CGF, const VarDecl *VD, QualType T, Address Addr,
llvm::Type *RealVarTy, SourceLocation Loc) {
@@ -2600,7 +2730,6 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF,
V = CGF.Builder.CreateThreadLocalAddress(V);
llvm::Type *RealVarTy = CGF.getTypes().ConvertTypeForMem(VD->getType());
- V = EmitBitCastOfLValueToProperType(CGF, V, RealVarTy);
CharUnits Alignment = CGF.getContext().getDeclAlign(VD);
Address Addr(V, RealVarTy, Alignment);
// Emit reference to the private copy of the variable if it is an OpenMP
@@ -2627,19 +2756,6 @@ static llvm::Constant *EmitFunctionDeclPointer(CodeGenModule &CGM,
}
llvm::Constant *V = CGM.GetAddrOfFunction(GD);
- if (!FD->hasPrototype()) {
- if (const FunctionProtoType *Proto =
- FD->getType()->getAs<FunctionProtoType>()) {
- // Ugly case: for a K&R-style definition, the type of the definition
- // isn't the same as the type of a use. Correct for this with a
- // bitcast.
- QualType NoProtoType =
- CGM.getContext().getFunctionNoProtoType(Proto->getReturnType());
- NoProtoType = CGM.getContext().getPointerType(NoProtoType);
- V = llvm::ConstantExpr::getBitCast(V,
- CGM.getTypes().ConvertType(NoProtoType));
- }
- }
return V;
}
@@ -2654,9 +2770,8 @@ static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF, const Expr *E,
static LValue EmitCapturedFieldLValue(CodeGenFunction &CGF, const FieldDecl *FD,
llvm::Value *ThisValue) {
- QualType TagType = CGF.getContext().getTagDeclType(FD->getParent());
- LValue LV = CGF.MakeNaturalAlignAddrLValue(ThisValue, TagType);
- return CGF.EmitLValueForField(LV, FD);
+
+ return CGF.EmitLValueForLambdaField(FD, ThisValue);
}
/// Named Registers are named metadata pointing to the register name
@@ -2692,8 +2807,7 @@ static LValue EmitGlobalNamedRegister(const VarDecl *VD, CodeGenModule &CGM) {
/// this context.
static bool canEmitSpuriousReferenceToVariable(CodeGenFunction &CGF,
const DeclRefExpr *E,
- const VarDecl *VD,
- bool IsConstant) {
+ const VarDecl *VD) {
// For a variable declared in an enclosing scope, do not emit a spurious
// reference even if we have a capture, as that will emit an unwarranted
// reference to our capture state, and will likely generate worse code than
@@ -2726,7 +2840,7 @@ static bool canEmitSpuriousReferenceToVariable(CodeGenFunction &CGF,
// We can emit a spurious reference only if the linkage implies that we'll
// be emitting a non-interposable symbol that will be retained until link
// time.
- switch (CGF.CGM.getLLVMLinkageVarDefinition(VD, IsConstant)) {
+ switch (CGF.CGM.getLLVMLinkageVarDefinition(VD)) {
case llvm::GlobalValue::ExternalLinkage:
case llvm::GlobalValue::LinkOnceODRLinkage:
case llvm::GlobalValue::WeakODRLinkage:
@@ -2757,7 +2871,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
// constant value directly instead.
if (E->isNonOdrUse() == NOUR_Constant &&
(VD->getType()->isReferenceType() ||
- !canEmitSpuriousReferenceToVariable(*this, E, VD, true))) {
+ !canEmitSpuriousReferenceToVariable(*this, E, VD))) {
VD->getAnyInitializer(VD);
llvm::Constant *Val = ConstantEmitter(*this).emitAbstract(
E->getLocation(), *VD->evaluateValue(), VD->getType());
@@ -2859,7 +2973,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
// some reason; most likely, because it's in an outer function.
} else if (VD->isStaticLocal()) {
llvm::Constant *var = CGM.getOrCreateStaticVarDecl(
- *VD, CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false));
+ *VD, CGM.getLLVMLinkageVarDefinition(VD));
addr = Address(
var, ConvertTypeForMem(VD->getType()), getContext().getDeclAlign(VD));
@@ -2943,9 +3057,20 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
return MakeAddrLValue(CGM.GetAddrOfMSGuidDecl(GD), T,
AlignmentSource::Decl);
- if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND))
- return MakeAddrLValue(CGM.GetAddrOfTemplateParamObject(TPO), T,
- AlignmentSource::Decl);
+ if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) {
+ auto ATPO = CGM.GetAddrOfTemplateParamObject(TPO);
+ auto AS = getLangASFromTargetAS(ATPO.getAddressSpace());
+
+ if (AS != T.getAddressSpace()) {
+ auto TargetAS = getContext().getTargetAddressSpace(T.getAddressSpace());
+ auto PtrTy = ATPO.getElementType()->getPointerTo(TargetAS);
+ auto ASC = getTargetHooks().performAddrSpaceCast(
+ CGM, ATPO.getPointer(), AS, T.getAddressSpace(), PtrTy);
+ ATPO = ConstantAddress(ASC, ATPO.getElementType(), ATPO.getAlignment());
+ }
+
+ return MakeAddrLValue(ATPO, T, AlignmentSource::Decl);
+ }
llvm_unreachable("Unhandled DeclRefExpr");
}
@@ -3421,8 +3546,7 @@ void CodeGenFunction::EmitCfiSlowPathCheck(
"__cfi_slowpath_diag",
llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy, Int8PtrTy},
false));
- CheckCall = Builder.CreateCall(
- SlowPathFn, {TypeId, Ptr, Builder.CreateBitCast(InfoPtr, Int8PtrTy)});
+ CheckCall = Builder.CreateCall(SlowPathFn, {TypeId, Ptr, InfoPtr});
} else {
SlowPathFn = CGM.getModule().getOrInsertFunction(
"__cfi_slowpath",
@@ -3445,14 +3569,12 @@ void CodeGenFunction::EmitCfiCheckStub() {
llvm::Function *F = llvm::Function::Create(
llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy, Int8PtrTy}, false),
llvm::GlobalValue::WeakAnyLinkage, "__cfi_check", M);
+ F->setAlignment(llvm::Align(4096));
CGM.setDSOLocal(F);
llvm::BasicBlock *BB = llvm::BasicBlock::Create(Ctx, "entry", F);
- // FIXME: consider emitting an intrinsic call like
- // call void @llvm.cfi_check(i64 %0, i8* %1, i8* %2)
- // which can be lowered in CrossDSOCFI pass to the actual contents of
- // __cfi_check. This would allow inlining of __cfi_check calls.
- llvm::CallInst::Create(
- llvm::Intrinsic::getDeclaration(M, llvm::Intrinsic::trap), "", BB);
+ // CrossDSOCFI pass is not executed if there is no executable code.
+ SmallVector<llvm::Value*> Args{F->getArg(2), F->getArg(1)};
+ llvm::CallInst::Create(M->getFunction("__cfi_check_fail"), Args, "", BB);
llvm::ReturnInst::Create(Ctx, nullptr, BB);
}
@@ -3467,9 +3589,9 @@ void CodeGenFunction::EmitCfiCheckFail() {
SanitizerScope SanScope(this);
FunctionArgList Args;
ImplicitParamDecl ArgData(getContext(), getContext().VoidPtrTy,
- ImplicitParamDecl::Other);
+ ImplicitParamKind::Other);
ImplicitParamDecl ArgAddr(getContext(), getContext().VoidPtrTy,
- ImplicitParamDecl::Other);
+ ImplicitParamKind::Other);
Args.push_back(&ArgData);
Args.push_back(&ArgAddr);
@@ -3570,17 +3692,28 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked,
// check-type per function to save on code size.
if (TrapBBs.size() <= CheckHandlerID)
TrapBBs.resize(CheckHandlerID + 1);
+
llvm::BasicBlock *&TrapBB = TrapBBs[CheckHandlerID];
- if (!CGM.getCodeGenOpts().OptimizationLevel || !TrapBB ||
- (CurCodeDecl && CurCodeDecl->hasAttr<OptimizeNoneAttr>())) {
+ if (!ClSanitizeDebugDeoptimization &&
+ CGM.getCodeGenOpts().OptimizationLevel && TrapBB &&
+ (!CurCodeDecl || !CurCodeDecl->hasAttr<OptimizeNoneAttr>())) {
+ auto Call = TrapBB->begin();
+ assert(isa<llvm::CallInst>(Call) && "Expected call in trap BB");
+
+ Call->applyMergedLocation(Call->getDebugLoc(),
+ Builder.getCurrentDebugLocation());
+ Builder.CreateCondBr(Checked, Cont, TrapBB);
+ } else {
TrapBB = createBasicBlock("trap");
Builder.CreateCondBr(Checked, Cont, TrapBB);
EmitBlock(TrapBB);
- llvm::CallInst *TrapCall =
- Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::ubsantrap),
- llvm::ConstantInt::get(CGM.Int8Ty, CheckHandlerID));
+ llvm::CallInst *TrapCall = Builder.CreateCall(
+ CGM.getIntrinsic(llvm::Intrinsic::ubsantrap),
+ llvm::ConstantInt::get(CGM.Int8Ty, ClSanitizeDebugDeoptimization
+ ? TrapBB->getParent()->size()
+ : CheckHandlerID));
if (!CGM.getCodeGenOpts().TrapFuncName.empty()) {
auto A = llvm::Attribute::get(getLLVMContext(), "trap-func-name",
@@ -3590,13 +3723,6 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked,
TrapCall->setDoesNotReturn();
TrapCall->setDoesNotThrow();
Builder.CreateUnreachable();
- } else {
- auto Call = TrapBB->begin();
- assert(isa<llvm::CallInst>(Call) && "Expected call in trap BB");
-
- Call->applyMergedLocation(Call->getDebugLoc(),
- Builder.getCurrentDebugLocation());
- Builder.CreateCondBr(Checked, Cont, TrapBB);
}
EmitBlock(Cont);
@@ -3707,6 +3833,33 @@ static QualType getFixedSizeElementType(const ASTContext &ctx,
return eltType;
}
+static bool hasBPFPreserveStaticOffset(const RecordDecl *D) {
+ return D && D->hasAttr<BPFPreserveStaticOffsetAttr>();
+}
+
+static bool hasBPFPreserveStaticOffset(const Expr *E) {
+ if (!E)
+ return false;
+ QualType PointeeType = E->getType()->getPointeeType();
+ if (PointeeType.isNull())
+ return false;
+ if (const auto *BaseDecl = PointeeType->getAsRecordDecl())
+ return hasBPFPreserveStaticOffset(BaseDecl);
+ return false;
+}
+
+// Wraps Addr with a call to llvm.preserve.static.offset intrinsic.
+static Address wrapWithBPFPreserveStaticOffset(CodeGenFunction &CGF,
+ Address &Addr) {
+ if (!CGF.getTarget().getTriple().isBPF())
+ return Addr;
+
+ llvm::Function *Fn =
+ CGF.CGM.getIntrinsic(llvm::Intrinsic::preserve_static_offset);
+ llvm::CallInst *Call = CGF.Builder.CreateCall(Fn, {Addr.getPointer()});
+ return Address(Call, Addr.getElementType(), Addr.getAlignment());
+}
+
/// Given an array base, check whether its member access belongs to a record
/// with preserve_access_index attribute or not.
static bool IsPreserveAIArrayBase(CodeGenFunction &CGF, const Expr *ArrayBase) {
@@ -3768,6 +3921,9 @@ static Address emitArraySubscriptGEP(CodeGenFunction &CGF, Address addr,
CharUnits eltAlign =
getArrayElementAlign(addr.getAlignment(), indices.back(), eltSize);
+ if (hasBPFPreserveStaticOffset(Base))
+ addr = wrapWithBPFPreserveStaticOffset(CGF, addr);
+
llvm::Value *eltPtr;
auto LastIndex = dyn_cast<llvm::ConstantInt>(indices.back());
if (!LastIndex ||
@@ -4269,17 +4425,38 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
/// Given that we are currently emitting a lambda, emit an l-value for
/// one of its members.
-LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field) {
- if (CurCodeDecl) {
- assert(cast<CXXMethodDecl>(CurCodeDecl)->getParent()->isLambda());
- assert(cast<CXXMethodDecl>(CurCodeDecl)->getParent() == Field->getParent());
+///
+LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field,
+ llvm::Value *ThisValue) {
+ bool HasExplicitObjectParameter = false;
+ if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(CurCodeDecl)) {
+ HasExplicitObjectParameter = MD->isExplicitObjectMemberFunction();
+ assert(MD->getParent()->isLambda());
+ assert(MD->getParent() == Field->getParent());
+ }
+ LValue LambdaLV;
+ if (HasExplicitObjectParameter) {
+ const VarDecl *D = cast<CXXMethodDecl>(CurCodeDecl)->getParamDecl(0);
+ auto It = LocalDeclMap.find(D);
+ assert(It != LocalDeclMap.end() && "explicit parameter not loaded?");
+ Address AddrOfExplicitObject = It->getSecond();
+ if (D->getType()->isReferenceType())
+ LambdaLV = EmitLoadOfReferenceLValue(AddrOfExplicitObject, D->getType(),
+ AlignmentSource::Decl);
+ else
+ LambdaLV = MakeNaturalAlignAddrLValue(AddrOfExplicitObject.getPointer(),
+ D->getType().getNonReferenceType());
+ } else {
+ QualType LambdaTagType = getContext().getTagDeclType(Field->getParent());
+ LambdaLV = MakeNaturalAlignAddrLValue(ThisValue, LambdaTagType);
}
- QualType LambdaTagType =
- getContext().getTagDeclType(Field->getParent());
- LValue LambdaLV = MakeNaturalAlignAddrLValue(CXXABIThisValue, LambdaTagType);
return EmitLValueForField(LambdaLV, Field);
}
+LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field) {
+ return EmitLValueForLambdaField(Field, CXXABIThisValue);
+}
+
/// Get the field index in the debug info. The debug info structure/union
/// will ignore the unnamed bitfields.
unsigned CodeGenFunction::getDebugInfoFIndex(const RecordDecl *Rec,
@@ -4375,6 +4552,8 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
Address Addr = base.getAddress(*this);
unsigned Idx = RL.getLLVMFieldNo(field);
const RecordDecl *rec = field->getParent();
+ if (hasBPFPreserveStaticOffset(rec))
+ Addr = wrapWithBPFPreserveStaticOffset(*this, Addr);
if (!UseVolatile) {
if (!IsInPreservedAIRegion &&
(!getDebugInfo() || !rec->hasAttr<BPFPreserveAccessIndexAttr>())) {
@@ -4447,6 +4626,8 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
}
Address addr = base.getAddress(*this);
+ if (hasBPFPreserveStaticOffset(rec))
+ addr = wrapWithBPFPreserveStaticOffset(*this, addr);
if (auto *ClassDef = dyn_cast<CXXRecordDecl>(rec)) {
if (CGM.getCodeGenOpts().StrictVTablePointers &&
ClassDef->isDynamicClass()) {
@@ -4616,7 +4797,7 @@ std::optional<LValue> HandleConditionalOperatorLValueSimpleCase(
if (auto *ThrowExpr = dyn_cast<CXXThrowExpr>(Live->IgnoreParens())) {
CGF.EmitCXXThrowExpr(ThrowExpr);
llvm::Type *ElemTy = CGF.ConvertType(Dead->getType());
- llvm::Type *Ty = llvm::PointerType::getUnqual(ElemTy);
+ llvm::Type *Ty = CGF.UnqualPtrTy;
return CGF.MakeAddrLValue(
Address(llvm::UndefValue::get(Ty), ElemTy, CharUnits::One()),
Dead->getType());
@@ -4751,7 +4932,6 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
case CK_IntegralToPointer:
case CK_PointerToIntegral:
case CK_PointerToBoolean:
- case CK_VectorSplat:
case CK_IntegralCast:
case CK_BooleanToSignedIntegral:
case CK_IntegralToBoolean:
@@ -4819,6 +4999,9 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
// bound and change the IR type.
// FIXME: Once pointee types are removed from IR, remove this.
LValue LV = EmitLValue(E->getSubExpr());
+ // Propagate the volatile qualifer to LValue, if exist in E.
+ if (E->changesVolatileQualification())
+ LV.getQuals() = E->getType().getQualifiers();
if (LV.isSimple()) {
Address V = LV.getAddress(*this);
if (V.isValid()) {
@@ -4913,6 +5096,13 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
}
case CK_ZeroToOCLOpaqueType:
llvm_unreachable("NULL to OpenCL opaque type lvalue cast is not valid");
+
+ case CK_VectorSplat: {
+ // LValue results of vector splats are only supported in HLSL.
+ if (!getLangOpts().HLSL)
+ return EmitUnsupportedLValue(E, "unexpected cast lvalue");
+ return EmitLValue(E->getSubExpr());
+ }
}
llvm_unreachable("Unhandled lvalue cast kind?");
@@ -4991,9 +5181,12 @@ RValue CodeGenFunction::EmitCallExpr(const CallExpr *E,
if (const auto *CE = dyn_cast<CUDAKernelCallExpr>(E))
return EmitCUDAKernelCallExpr(CE, ReturnValue);
+ // A CXXOperatorCallExpr is created even for explicit object methods, but
+ // these should be treated like static function call.
if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(E))
- if (const CXXMethodDecl *MD =
- dyn_cast_or_null<CXXMethodDecl>(CE->getCalleeDecl()))
+ if (const auto *MD =
+ dyn_cast_if_present<CXXMethodDecl>(CE->getCalleeDecl());
+ MD && MD->isImplicitObjectMemberFunction())
return EmitCXXOperatorMemberCallExpr(CE, MD, ReturnValue);
CGCallee callee = EmitCallee(E->getCallee());
@@ -5365,8 +5558,7 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
AlignedCalleePtr = CalleePtr;
}
- llvm::Value *CalleePrefixStruct = Builder.CreateBitCast(
- AlignedCalleePtr, llvm::PointerType::getUnqual(PrefixStructTy));
+ llvm::Value *CalleePrefixStruct = AlignedCalleePtr;
llvm::Value *CalleeSigPtr =
Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, -1, 0);
llvm::Value *CalleeSig =
@@ -5413,9 +5605,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD);
llvm::Value *CalleePtr = Callee.getFunctionPointer();
- llvm::Value *CastedCallee = Builder.CreateBitCast(CalleePtr, Int8PtrTy);
llvm::Value *TypeTest = Builder.CreateCall(
- CGM.getIntrinsic(llvm::Intrinsic::type_test), {CastedCallee, TypeId});
+ CGM.getIntrinsic(llvm::Intrinsic::type_test), {CalleePtr, TypeId});
auto CrossDsoTypeId = CGM.CreateCrossDsoCfiTypeId(MD);
llvm::Constant *StaticData[] = {
@@ -5425,18 +5616,17 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
};
if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) {
EmitCfiSlowPathCheck(SanitizerKind::CFIICall, TypeTest, CrossDsoTypeId,
- CastedCallee, StaticData);
+ CalleePtr, StaticData);
} else {
EmitCheck(std::make_pair(TypeTest, SanitizerKind::CFIICall),
SanitizerHandler::CFICheckFail, StaticData,
- {CastedCallee, llvm::UndefValue::get(IntPtrTy)});
+ {CalleePtr, llvm::UndefValue::get(IntPtrTy)});
}
}
CallArgList Args;
if (Chain)
- Args.add(RValue::get(Builder.CreateBitCast(Chain, CGM.VoidPtrTy)),
- CGM.getContext().VoidPtrTy);
+ Args.add(RValue::get(Chain), CGM.getContext().VoidPtrTy);
// C++17 requires that we evaluate arguments to a call using assignment syntax
// right-to-left, and that we evaluate arguments to certain other operators
@@ -5507,10 +5697,8 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, const CGCallee &OrigCallee
isa<CUDAKernelCallExpr>(E) &&
(!TargetDecl || !isa<FunctionDecl>(TargetDecl))) {
llvm::Value *Handle = Callee.getFunctionPointer();
- auto *Cast =
- Builder.CreateBitCast(Handle, Handle->getType()->getPointerTo());
auto *Stub = Builder.CreateLoad(
- Address(Cast, Handle->getType(), CGM.getPointerAlign()));
+ Address(Handle, Handle->getType(), CGM.getPointerAlign()));
Callee.setFunctionPointer(Stub);
}
llvm::CallBase *CallOrInvoke = nullptr;