diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-12-09 13:28:42 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-12-09 13:28:42 +0000 |
commit | b1c73532ee8997fe5dfbeb7d223027bdf99758a0 (patch) | |
tree | 7d6e51c294ab6719475d660217aa0c0ad0526292 /clang/lib/CodeGen/CGExpr.cpp | |
parent | 7fa27ce4a07f19b07799a767fc29416f3b625afb (diff) | |
download | src-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.cpp | 390 |
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; |