From 938d8f030a12a18c1a316aaa8dbc5c24a2c69296 Mon Sep 17 00:00:00 2001 From: Ahmed Bougacha Date: Mon, 27 Sep 2021 08:00:00 -0700 Subject: [PATCH 1/7] [clang][CodeGen] Teach RawAddress/Address about ptrauth. --- clang/lib/CodeGen/Address.h | 43 ++++++++++++++++++++++++++--- clang/lib/CodeGen/CGBlocks.cpp | 4 +-- clang/lib/CodeGen/CGBuilder.h | 46 ++++++++++++++++++++++--------- clang/lib/CodeGen/CGCall.cpp | 13 +++++---- clang/lib/CodeGen/CGException.cpp | 4 +-- clang/lib/CodeGen/CGObjCMac.cpp | 2 +- 6 files changed, 85 insertions(+), 27 deletions(-) diff --git a/clang/lib/CodeGen/Address.h b/clang/lib/CodeGen/Address.h index 35ec370a139c9..3b677c9159e22 100644 --- a/clang/lib/CodeGen/Address.h +++ b/clang/lib/CodeGen/Address.h @@ -108,6 +108,22 @@ class RawAddress { /// Like RawAddress, an abstract representation of an aligned address, but the /// pointer contained in this class is possibly signed. +/// +/// This is designed to be an IR-level abstraction, carrying just the +/// information necessary to perform IR operations on an address like loads and +/// stores. In particular, it doesn't carry C type information or allow the +/// representation of things like bit-fields; clients working at that level +/// should generally be using `LValue`. +/// +/// An address may be either *raw*, meaning that it's an ordinary machine +/// pointer, or *signed*, meaning that the pointer carries an embedded +/// pointer-authentication signature. Representing signed pointers directly in +/// this abstraction allows the authentication to be delayed as long as possible +/// without forcing IRGen to use totally different code paths for signed and +/// unsigned values or to separately propagate signature information through +/// every API that manipulates addresses. Pointer arithmetic on signed addresses +/// (e.g. drilling down to a struct field) is accumulated into a separate offset +/// which is applied when the address is finally accessed. class Address { friend class CGBuilderTy; @@ -117,6 +133,10 @@ class Address { /// The expected IR type of the pointer. Carrying accurate element type /// information in Address makes it more convenient to work with Address /// values and allows frontend assertions to catch simple mistakes. + /// + /// When the address is a raw pointer, this is currently redundant with the + /// pointer's type, but for signed pointers it is useful if the pointer has + /// been offsetted or cast from the original type. llvm::Type *ElementType = nullptr; CharUnits Alignment; @@ -153,6 +173,11 @@ class Address { static Address invalid() { return Address(nullptr); } bool isValid() const { return Pointer.getPointer() != nullptr; } + llvm::Value *getPointerIfNotSigned() const { + assert(isValid() && "pointer isn't valid"); + return Pointer.getPointer(); + } + /// This function is used in situations where the caller is doing some sort of /// opaque "laundering" of the pointer. void replaceBasePointer(llvm::Value *P) { @@ -172,6 +197,8 @@ class Address { return Pointer.getPointer(); } + llvm::Value *getUnsignedPointer() const { return getBasePointer(); } + /// Return the type of the pointer value. llvm::PointerType *getType() const { return llvm::PointerType::get( @@ -211,6 +238,14 @@ class Address { return *this; } + /// Add a constant offset. + void addOffset(CharUnits V, llvm::Type *Ty, CGBuilderTy &Builder); + + /// Add a variable offset. + /// \param V An llvm value holding a variable offset. + void addOffset(llvm::Value *V, llvm::Type *Ty, CGBuilderTy &Builder, + CharUnits NewAlignment); + bool hasOffset() const { return Offset; } llvm::Value *getOffset() const { return Offset; } @@ -218,7 +253,7 @@ class Address { /// Return the pointer contained in this class after authenticating it and /// adding offset to it if necessary. llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { - return getBasePointer(); + return getUnsignedPointer(); } /// Return address with different pointer, but same element type and @@ -249,9 +284,9 @@ class Address { }; inline RawAddress::RawAddress(Address Addr) - : PointerAndKnownNonNull(Addr.isValid() ? Addr.getBasePointer() : nullptr, - Addr.isValid() ? Addr.isKnownNonNull() - : NotKnownNonNull), + : PointerAndKnownNonNull( + Addr.isValid() ? Addr.getUnsignedPointer() : nullptr, + Addr.isValid() ? Addr.isKnownNonNull() : NotKnownNonNull), ElementType(Addr.isValid() ? Addr.getElementType() : nullptr), Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {} diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 066139b1c78c7..2affd93c6b9a2 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -1974,8 +1974,8 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { // it. It's not quite worth the annoyance to avoid creating it in the // first place. if (!needsEHCleanup(captureType.isDestructedType())) - if (auto *I = - cast_or_null(dstField.getBasePointer())) + if (auto *I = cast_or_null( + dstField.getPointerIfNotSigned())) I->eraseFromParent(); } break; diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h index 0bc4fda62979c..752bfc6c0c058 100644 --- a/clang/lib/CodeGen/CGBuilder.h +++ b/clang/lib/CodeGen/CGBuilder.h @@ -15,6 +15,7 @@ #include "llvm/Analysis/Utils/Local.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Module.h" #include "llvm/IR/Type.h" namespace clang { @@ -56,7 +57,24 @@ class CGBuilderTy : public CGBuilderBaseTy { CodeGenFunction *getCGF() const { return getInserter().CGF; } llvm::Value *emitRawPointerFromAddress(Address Addr) const { - return Addr.getBasePointer(); + return Addr.getUnsignedPointer(); + } + + /// Helper function to compute a GEP's offset and add it to Addr. + Address addGEPOffset(Address Addr, ArrayRef IdxList, + CharUnits Align, bool IsInBounds, const Twine &Name) { + typedef ArrayRef::const_iterator IdxItTy; + typedef llvm::generic_gep_type_iterator GEPTypeIt; + const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); + GEPTypeIt GTI = GEPTypeIt::begin(Addr.getElementType(), IdxList.begin()); + IdxItTy IdxBegin = IdxList.begin(), IdxEnd = IdxList.end(); + llvm::Type *GEPType = Addr.getType(); + SmallString<12> Buffer; + StringRef GEPName = Name.toStringRef(Buffer); + std::pair OffsetAndType = llvm::EmitGEPOffset( + this, DL, GTI, IdxBegin, IdxEnd, GEPType, GEPName, IsInBounds, false); + Addr.addOffset(OffsetAndType.first, OffsetAndType.second, *this, Align); + return Addr; } template @@ -222,8 +240,8 @@ class CGBuilderTy : public CGBuilderBaseTy { const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); - return Address(CreateStructGEP(Addr.getElementType(), Addr.getBasePointer(), - Index, Name), + return Address(CreateStructGEP(Addr.getElementType(), + Addr.getUnsignedPointer(), Index, Name), ElTy->getElementType(Index), Addr.getAlignment().alignmentAtOffset(Offset), Addr.isKnownNonNull()); @@ -245,7 +263,7 @@ class CGBuilderTy : public CGBuilderBaseTy { CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType())); return Address( - CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(), + CreateInBoundsGEP(Addr.getElementType(), Addr.getUnsignedPointer(), {getSize(CharUnits::Zero()), getSize(Index)}, Name), ElTy->getElementType(), Addr.getAlignment().alignmentAtOffset(Index * EltSize), @@ -263,10 +281,10 @@ class CGBuilderTy : public CGBuilderBaseTy { const llvm::DataLayout &DL = BB->getDataLayout(); CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); - return Address( - CreateInBoundsGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name), - ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize), - Addr.isKnownNonNull()); + return Address(CreateInBoundsGEP(ElTy, Addr.getUnsignedPointer(), + getSize(Index), Name), + ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize), + Addr.isKnownNonNull()); } /// Given @@ -280,9 +298,10 @@ class CGBuilderTy : public CGBuilderBaseTy { const llvm::DataLayout &DL = BB->getDataLayout(); CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); - return Address(CreateGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name), - Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Index * EltSize)); + return Address( + CreateGEP(ElTy, Addr.getUnsignedPointer(), getSize(Index), Name), + Addr.getElementType(), + Addr.getAlignment().alignmentAtOffset(Index * EltSize)); } /// Create GEP with single dynamic index. The address alignment is reduced @@ -305,7 +324,7 @@ class CGBuilderTy : public CGBuilderBaseTy { const llvm::Twine &Name = "") { assert(Addr.getElementType() == TypeCache.Int8Ty); return Address( - CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(), + CreateInBoundsGEP(Addr.getElementType(), Addr.getUnsignedPointer(), getSize(Offset), Name), Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset), Addr.isKnownNonNull()); @@ -314,7 +333,8 @@ class CGBuilderTy : public CGBuilderBaseTy { Address CreateConstByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name = "") { assert(Addr.getElementType() == TypeCache.Int8Ty); - return Address(CreateGEP(Addr.getElementType(), Addr.getBasePointer(), + + return Address(CreateGEP(Addr.getElementType(), Addr.getUnsignedPointer(), getSize(Offset), Name), Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset)); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index a38484941ba24..333771160cabf 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3508,7 +3508,8 @@ static llvm::Value *tryRemoveRetainOfSelf(CodeGenFunction &CGF, llvm::LoadInst *load = dyn_cast(retainedValue->stripPointerCasts()); if (!load || load->isAtomic() || load->isVolatile() || - load->getPointerOperand() != CGF.GetAddrOfLocalVar(self).getBasePointer()) + load->getPointerOperand() != + CGF.GetAddrOfLocalVar(self).getPointerIfNotSigned()) return nullptr; // Okay! Burn it all down. This relies for correctness on the @@ -3545,7 +3546,8 @@ static llvm::Value *emitAutoreleaseOfResult(CodeGenFunction &CGF, /// Heuristically search for a dominating store to the return-value slot. static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { - llvm::Value *ReturnValuePtr = CGF.ReturnValue.getBasePointer(); + // This function shouldn't be called when ReturnValue is signed. + llvm::Value *ReturnValuePtr = CGF.ReturnValue.getUnsignedPointer(); // Check if a User is a store which pointerOperand is the ReturnValue. // We are looking for stores to the ReturnValue, not for stores of the @@ -4133,7 +4135,8 @@ static bool isProvablyNull(llvm::Value *addr) { } static bool isProvablyNonNull(Address Addr, CodeGenFunction &CGF) { - return llvm::isKnownNonZero(Addr.getBasePointer(), CGF.CGM.getDataLayout()); + return llvm::isKnownNonZero(Addr.getUnsignedPointer(), + CGF.CGM.getDataLayout()); } /// Emit the actual writing-back of a writeback. @@ -4141,7 +4144,7 @@ static void emitWriteback(CodeGenFunction &CGF, const CallArgList::Writeback &writeback) { const LValue &srcLV = writeback.Source; Address srcAddr = srcLV.getAddress(); - assert(!isProvablyNull(srcAddr.getBasePointer()) && + assert(!isProvablyNull(srcAddr.getPointerIfNotSigned()) && "shouldn't have writeback for provably null argument"); llvm::BasicBlock *contBB = nullptr; @@ -4258,7 +4261,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, CGF.ConvertTypeForMem(CRE->getType()->getPointeeType()); // If the address is a constant null, just pass the appropriate null. - if (isProvablyNull(srcAddr.getBasePointer())) { + if (isProvablyNull(srcAddr.getPointerIfNotSigned())) { args.add(RValue::get(llvm::ConstantPointerNull::get(destType)), CRE->getType()); return; diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index bb2ed237ee9f3..2de85963437f5 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -1835,8 +1835,8 @@ Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, llvm::Value *ParentFP) { llvm::CallInst *RecoverCall = nullptr; CGBuilderTy Builder(*this, AllocaInsertPt); - if (auto *ParentAlloca = - dyn_cast_or_null(ParentVar.getBasePointer())) { + if (auto *ParentAlloca = dyn_cast_or_null( + ParentVar.getPointerIfNotSigned())) { // Mark the variable escaped if nobody else referenced it and compute the // localescape index. auto InsertPair = ParentCGF.EscapedLocals.insert( diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 30f3911a8b03c..7395370259fe9 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -4425,7 +4425,7 @@ void FragileHazards::emitHazardsInNewBlocks() { static void addIfPresent(llvm::DenseSet &S, Address V) { if (V.isValid()) - if (llvm::Value *Ptr = V.getBasePointer()) + if (llvm::Value *Ptr = V.getPointerIfNotSigned()) S.insert(Ptr); } From a147bcebdd879fec4f7e26339c20ed84dd012136 Mon Sep 17 00:00:00 2001 From: Ahmed Bougacha Date: Wed, 15 May 2024 13:37:17 -0700 Subject: [PATCH 2/7] [clang][CodeGen] Set KnownNonNull in more places. --- clang/lib/CodeGen/CGExpr.cpp | 15 ++++++++++---- clang/lib/CodeGen/CGExprAgg.cpp | 3 +++ clang/lib/CodeGen/CGExprCXX.cpp | 9 +++++---- clang/lib/CodeGen/CGValue.h | 10 ++------- clang/lib/CodeGen/CodeGenFunction.cpp | 29 ++++++++++++++++++--------- clang/lib/CodeGen/CodeGenFunction.h | 4 +++- clang/lib/CodeGen/ItaniumCXXABI.cpp | 2 +- 7 files changed, 45 insertions(+), 27 deletions(-) diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index ddb82571f53d7..d5c3732a4e270 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1941,6 +1941,9 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile, Addr = Addr.withPointer(Builder.CreateThreadLocalAddress(GV), NotKnownNonNull); + if (!CGM.getCodeGenOpts().NullPointerIsValid) + Addr = Addr.setKnownNonNull(); + if (const auto *ClangVecTy = Ty->getAs()) { // Boolean vectors use `iN` as storage type. if (ClangVecTy->isExtVectorBoolType()) { @@ -2090,6 +2093,9 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr, Addr = Addr.withPointer(Builder.CreateThreadLocalAddress(GV), NotKnownNonNull); + if (!CGM.getCodeGenOpts().NullPointerIsValid) + Addr = Addr.setKnownNonNull(); + llvm::Type *SrcTy = Value->getType(); if (const auto *ClangVecTy = Ty->getAs()) { auto *VecTy = dyn_cast(SrcTy); @@ -2791,9 +2797,9 @@ CodeGenFunction::EmitLoadOfReference(LValue RefLVal, llvm::LoadInst *Load = Builder.CreateLoad(RefLVal.getAddress(), RefLVal.isVolatile()); CGM.DecorateInstructionWithTBAA(Load, RefLVal.getTBAAInfo()); - return makeNaturalAddressForPointer(Load, RefLVal.getType()->getPointeeType(), - CharUnits(), /*ForPointeeType=*/true, - PointeeBaseInfo, PointeeTBAAInfo); + return makeNaturalAddressForPointer( + Load, RefLVal.getType()->getPointeeType(), CharUnits(), + /*ForPointeeType=*/true, PointeeBaseInfo, PointeeTBAAInfo, KnownNonNull); } LValue CodeGenFunction::EmitLoadOfReferenceLValue(LValue RefLVal) { @@ -4706,7 +4712,8 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field, } } else { QualType LambdaTagType = getContext().getTagDeclType(Field->getParent()); - LambdaLV = MakeNaturalAlignAddrLValue(ThisValue, LambdaTagType); + LambdaLV = MakeNaturalAlignAddrLValue(ThisValue, LambdaTagType, + KnownNonNull); } return EmitLValueForField(LambdaLV, Field); } diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index c3c10e73ff05e..d70701f0856cf 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -253,6 +253,9 @@ class AggExprEmitter : public StmtVisitor { void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) { LValue LV = CGF.EmitLValue(E); + if (!CGF.CGM.getCodeGenOpts().NullPointerIsValid) + LV = LV.setKnownNonNull(); + // If the type of the l-value is atomic, then do an atomic load. if (LV.getType()->isAtomicType() || CGF.LValueIsSuitableForInlineAtomic(LV)) { CGF.EmitAtomicLoad(LV, E->getExprLoc(), Dest); diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 8eb6ab7381acb..db4a70f5316f8 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -265,7 +265,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( if (auto *OCE = dyn_cast(CE)) { if (OCE->isAssignmentOp()) { if (TrivialAssignment) { - TrivialAssignmentRHS = EmitLValue(CE->getArg(1)); + TrivialAssignmentRHS = EmitLValue(CE->getArg(1), KnownNonNull); } else { RtlArgs = &RtlArgStorage; EmitCallArgs(*RtlArgs, MD->getType()->castAs(), @@ -279,11 +279,12 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( if (IsArrow) { LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; - Address ThisValue = EmitPointerWithAlignment(Base, &BaseInfo, &TBAAInfo); + Address ThisValue = EmitPointerWithAlignment( + Base, &BaseInfo, &TBAAInfo, KnownNonNull); This = MakeAddrLValue(ThisValue, Base->getType()->getPointeeType(), BaseInfo, TBAAInfo); } else { - This = EmitLValue(Base); + This = EmitLValue(Base, KnownNonNull); } if (const CXXConstructorDecl *Ctor = dyn_cast(MD)) { @@ -316,7 +317,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( // the RHS. LValue RHS = isa(CE) ? TrivialAssignmentRHS - : EmitLValue(*CE->arg_begin()); + : EmitLValue(*CE->arg_begin(), KnownNonNull); EmitAggregateAssign(This, RHS, CE->getType()); return RValue::get(This.getPointer(*this)); } diff --git a/clang/lib/CodeGen/CGValue.h b/clang/lib/CodeGen/CGValue.h index f1ba3cf95ae59..6ed94bd9c7592 100644 --- a/clang/lib/CodeGen/CGValue.h +++ b/clang/lib/CodeGen/CGValue.h @@ -233,9 +233,6 @@ class LValue { // this lvalue. bool Nontemporal : 1; - // The pointer is known not to be null. - bool IsKnownNonNull : 1; - LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; @@ -263,7 +260,6 @@ class LValue { this->ImpreciseLifetime = false; this->Nontemporal = false; this->ThreadLocalRef = false; - this->IsKnownNonNull = false; this->BaseIvarExp = nullptr; } @@ -349,11 +345,9 @@ class LValue { LValueBaseInfo getBaseInfo() const { return BaseInfo; } void setBaseInfo(LValueBaseInfo Info) { BaseInfo = Info; } - KnownNonNull_t isKnownNonNull() const { - return (KnownNonNull_t)IsKnownNonNull; - } + KnownNonNull_t isKnownNonNull() const { return Addr.isKnownNonNull(); } LValue setKnownNonNull() { - IsKnownNonNull = true; + Addr.setKnownNonNull(); return *this; } diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 26deeca95d326..a222bc05e8dab 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -195,34 +195,45 @@ CodeGenFunction::CGFPOptionsRAII::~CGFPOptionsRAII() { CGF.Builder.setDefaultConstrainedRounding(OldRounding); } -static LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, - bool ForPointeeType, - CodeGenFunction &CGF) { +static LValue +MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, bool ForPointeeType, + bool MightBeSigned, CodeGenFunction &CGF, + KnownNonNull_t IsKnownNonNull = NotKnownNonNull) { LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; CharUnits Alignment = CGF.CGM.getNaturalTypeAlignment(T, &BaseInfo, &TBAAInfo, ForPointeeType); - Address Addr = Address(V, CGF.ConvertTypeForMem(T), Alignment); + Address Addr = + MightBeSigned + ? CGF.makeNaturalAddressForPointer(V, T, Alignment, false, nullptr, + nullptr, IsKnownNonNull) + : Address(V, CGF.ConvertTypeForMem(T), Alignment, IsKnownNonNull); return CGF.MakeAddrLValue(Addr, T, BaseInfo, TBAAInfo); } -LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) { - return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, *this); +LValue +CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, + KnownNonNull_t IsKnownNonNull) { + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, + /*IsSigned*/ true, *this, IsKnownNonNull); } LValue CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) { - return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, *this); + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, + /*IsSigned*/ true, *this); } LValue CodeGenFunction::MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T) { - return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, *this); + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, + /*IsSigned*/ false, *this); } LValue CodeGenFunction::MakeNaturalAlignPointeeRawAddrLValue(llvm::Value *V, QualType T) { - return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, *this); + return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, + /*IsSigned*/ false, *this); } llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 13f12b5d878a6..5268cc7eda4a2 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2728,7 +2728,9 @@ class CodeGenFunction : public CodeGenTypeCache { /// an l-value with the natural pointee alignment of T. LValue MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T); - LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T); + LValue + MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, + KnownNonNull_t IsKnownNonNull = NotKnownNonNull); /// Same as MakeNaturalAlignPointeeAddrLValue except that the pointer is known /// to be unsigned. diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 6e5fa0faf73d7..1609ae19696c7 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -4711,7 +4711,7 @@ static void InitCatchParam(CodeGenFunction &CGF, // Cast that to the appropriate type. Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy), - LLVMCatchTy, caughtExnAlignment); + LLVMCatchTy, caughtExnAlignment, KnownNonNull); // The copy expression is defined in terms of an OpaqueValueExpr. // Find it and map it to the adjusted expression. From 4110867a3b0a20a7685aeae9ceaa64d65c365f4f Mon Sep 17 00:00:00 2001 From: Ahmed Bougacha Date: Thu, 27 Jun 2024 16:00:35 -0700 Subject: [PATCH 3/7] [clang] Resign type-discriminated function pointers on cast. --- clang/include/clang/AST/ASTContext.h | 2 +- clang/include/clang/AST/Type.h | 5 +- clang/lib/AST/ASTContext.cpp | 12 +- clang/lib/CodeGen/Address.h | 39 ++- clang/lib/CodeGen/CGBuilder.h | 94 ++++-- clang/lib/CodeGen/CGBuiltin.cpp | 3 +- clang/lib/CodeGen/CGCall.cpp | 6 +- clang/lib/CodeGen/CGExpr.cpp | 10 +- clang/lib/CodeGen/CGExprAgg.cpp | 4 +- clang/lib/CodeGen/CGExprConstant.cpp | 16 +- clang/lib/CodeGen/CGExprScalar.cpp | 29 +- clang/lib/CodeGen/CGPointerAuth.cpp | 318 ++++++++++++++++++ clang/lib/CodeGen/CGValue.h | 29 +- clang/lib/CodeGen/CodeGenFunction.cpp | 60 +++- clang/lib/CodeGen/CodeGenFunction.h | 73 +++- clang/lib/CodeGen/CodeGenModule.h | 3 + clang/lib/Headers/ptrauth.h | 15 + .../ptrauth-function-lvalue-cast-disc.c | 55 +++ ...ptrauth-function-type-discriminator-cast.c | 85 +++++ clang/test/CodeGen/ptrauth.c | 77 +++++ clang/test/Preprocessor/ptrauth_feature.c | 10 + .../ptrauth-function-type-discriminatior.c | 65 ++++ 22 files changed, 907 insertions(+), 103 deletions(-) create mode 100644 clang/test/CodeGen/ptrauth-function-lvalue-cast-disc.c create mode 100644 clang/test/CodeGen/ptrauth-function-type-discriminator-cast.c create mode 100644 clang/test/CodeGen/ptrauth.c create mode 100644 clang/test/Sema/ptrauth-function-type-discriminatior.c diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 57022e75073fe..8ba0c943a9c86 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1284,7 +1284,7 @@ class ASTContext : public RefCountedBase { getPointerAuthVTablePointerDiscriminator(const CXXRecordDecl *RD); /// Return the "other" type-specific discriminator for the given type. - uint16_t getPointerAuthTypeDiscriminator(QualType T) const; + uint16_t getPointerAuthTypeDiscriminator(QualType T); /// Apply Objective-C protocol qualifiers to the given type. /// \param allowOnPointerType specifies if we can apply protocol diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 3aa0f05b0ab60..bf242debe479a 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2507,6 +2507,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { bool isFunctionProtoType() const { return getAs(); } bool isPointerType() const; bool isSignableType() const; + bool isSignablePointerType() const; bool isAnyPointerType() const; // Any C pointer or ObjC object pointer bool isCountAttributedType() const; bool isBlockPointerType() const; @@ -8002,7 +8003,9 @@ inline bool Type::isAnyPointerType() const { return isPointerType() || isObjCObjectPointerType(); } -inline bool Type::isSignableType() const { return isPointerType(); } +inline bool Type::isSignableType() const { return isSignablePointerType(); } + +inline bool Type::isSignablePointerType() const { return isPointerType(); } inline bool Type::isBlockPointerType() const { return isa(CanonicalType); diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 497579dcc56b6..18dfe51e167e0 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3400,7 +3400,7 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx, } } -uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) const { +uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) { assert(!T->isDependentType() && "cannot compute type discriminator of a dependent type"); @@ -3410,11 +3410,13 @@ uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) const { if (T->isFunctionPointerType() || T->isFunctionReferenceType()) T = T->getPointeeType(); - if (T->isFunctionType()) + if (T->isFunctionType()) { encodeTypeForFunctionPointerAuth(*this, Out, T); - else - llvm_unreachable( - "type discrimination of non-function type not implemented yet"); + } else { + T = T.getUnqualifiedType(); + std::unique_ptr MC(createMangleContext()); + MC->mangleCanonicalTypeName(T, Out); + } return llvm::getPointerAuthStableSipHash(Str); } diff --git a/clang/lib/CodeGen/Address.h b/clang/lib/CodeGen/Address.h index 3b677c9159e22..1d2c453f25523 100644 --- a/clang/lib/CodeGen/Address.h +++ b/clang/lib/CodeGen/Address.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_LIB_CODEGEN_ADDRESS_H #define LLVM_CLANG_LIB_CODEGEN_ADDRESS_H +#include "CGPointerAuthInfo.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Type.h" #include "llvm/ADT/PointerIntPair.h" @@ -141,7 +142,11 @@ class Address { CharUnits Alignment; - /// Offset from the base pointer. + /// The ptrauth information needed to authenticate the base pointer. + CGPointerAuthInfo PtrAuthInfo; + + /// Offset from the base pointer. This is non-null only when the base + /// pointer is signed. llvm::Value *Offset = nullptr; llvm::Value *emitRawPointerSlow(CodeGenFunction &CGF) const; @@ -160,12 +165,14 @@ class Address { } Address(llvm::Value *BasePtr, llvm::Type *ElementType, CharUnits Alignment, - llvm::Value *Offset, KnownNonNull_t IsKnownNonNull = NotKnownNonNull) + CGPointerAuthInfo PtrAuthInfo, llvm::Value *Offset, + KnownNonNull_t IsKnownNonNull = NotKnownNonNull) : Pointer(BasePtr, IsKnownNonNull), ElementType(ElementType), - Alignment(Alignment), Offset(Offset) {} + Alignment(Alignment), PtrAuthInfo(PtrAuthInfo), Offset(Offset) {} Address(RawAddress RawAddr) - : Pointer(RawAddr.isValid() ? RawAddr.getPointer() : nullptr), + : Pointer(RawAddr.isValid() ? RawAddr.getPointer() : nullptr, + RawAddr.isValid() ? RawAddr.isKnownNonNull() : NotKnownNonNull), ElementType(RawAddr.isValid() ? RawAddr.getElementType() : nullptr), Alignment(RawAddr.isValid() ? RawAddr.getAlignment() : CharUnits::Zero()) {} @@ -175,7 +182,7 @@ class Address { llvm::Value *getPointerIfNotSigned() const { assert(isValid() && "pointer isn't valid"); - return Pointer.getPointer(); + return !isSigned() ? Pointer.getPointer() : nullptr; } /// This function is used in situations where the caller is doing some sort of @@ -197,7 +204,10 @@ class Address { return Pointer.getPointer(); } - llvm::Value *getUnsignedPointer() const { return getBasePointer(); } + llvm::Value *getUnsignedPointer() const { + assert(!isSigned() && "cannot call this function if pointer is signed"); + return getBasePointer(); + } /// Return the type of the pointer value. llvm::PointerType *getType() const { @@ -219,6 +229,9 @@ class Address { /// Return the IR name of the pointer value. llvm::StringRef getName() const { return Pointer.getPointer()->getName(); } + const CGPointerAuthInfo &getPointerAuthInfo() const { return PtrAuthInfo; } + void setPointerAuthInfo(const CGPointerAuthInfo &Info) { PtrAuthInfo = Info; } + // This function is called only in CGBuilderBaseTy::CreateElementBitCast. void setElementType(llvm::Type *Ty) { assert(hasOffset() && @@ -226,7 +239,8 @@ class Address { ElementType = Ty; } - /// Whether the pointer is known not to be null. + bool isSigned() const { return PtrAuthInfo.isSigned(); } + KnownNonNull_t isKnownNonNull() const { assert(isValid()); return (KnownNonNull_t)Pointer.getInt(); @@ -250,10 +264,15 @@ class Address { llvm::Value *getOffset() const { return Offset; } + Address getResignedAddress(const CGPointerAuthInfo &NewInfo, + CodeGenFunction &CGF) const; + /// Return the pointer contained in this class after authenticating it and /// adding offset to it if necessary. llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { - return getUnsignedPointer(); + if (!isSigned()) + return getUnsignedPointer(); + return emitRawPointerSlow(CGF); } /// Return address with different pointer, but same element type and @@ -275,8 +294,8 @@ class Address { /// alignment. Address withElementType(llvm::Type *ElemTy) const { if (!hasOffset()) - return Address(getBasePointer(), ElemTy, getAlignment(), nullptr, - isKnownNonNull()); + return Address(getBasePointer(), ElemTy, getAlignment(), + getPointerAuthInfo(), nullptr, isKnownNonNull()); Address A(*this); A.ElementType = ElemTy; return A; diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h index 752bfc6c0c058..48b3067494062 100644 --- a/clang/lib/CodeGen/CGBuilder.h +++ b/clang/lib/CodeGen/CGBuilder.h @@ -57,7 +57,10 @@ class CGBuilderTy : public CGBuilderBaseTy { CodeGenFunction *getCGF() const { return getInserter().CGF; } llvm::Value *emitRawPointerFromAddress(Address Addr) const { - return Addr.getUnsignedPointer(); + if (!Addr.isSigned()) + return Addr.getUnsignedPointer(); + assert(getCGF() && "CGF not set"); + return Addr.emitRawPointerSlow(*getCGF()); } /// Helper function to compute a GEP's offset and add it to Addr. @@ -208,8 +211,8 @@ class CGBuilderTy : public CGBuilderBaseTy { const llvm::Twine &Name = "") { if (!Addr.hasOffset()) return Address(CreateAddrSpaceCast(Addr.getBasePointer(), Ty, Name), - ElementTy, Addr.getAlignment(), nullptr, - Addr.isKnownNonNull()); + ElementTy, Addr.getAlignment(), Addr.getPointerAuthInfo(), + nullptr, Addr.isKnownNonNull()); // Eagerly force a raw address if these is an offset. return RawAddress( CreateAddrSpaceCast(Addr.emitRawPointer(*getCGF()), Ty, Name), @@ -240,11 +243,14 @@ class CGBuilderTy : public CGBuilderBaseTy { const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); - return Address(CreateStructGEP(Addr.getElementType(), - Addr.getUnsignedPointer(), Index, Name), - ElTy->getElementType(Index), - Addr.getAlignment().alignmentAtOffset(Offset), - Addr.isKnownNonNull()); + if (!Addr.isSigned()) + return Address(CreateStructGEP(Addr.getElementType(), + Addr.getUnsignedPointer(), Index, Name), + ElTy->getElementType(Index), + Addr.getAlignment().alignmentAtOffset(Offset), + Addr.isKnownNonNull()); + Addr.addOffset(Offset, ElTy->getTypeAtIndex(Index), *this); + return Addr; } /// Given @@ -262,12 +268,15 @@ class CGBuilderTy : public CGBuilderBaseTy { CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType())); - return Address( - CreateInBoundsGEP(Addr.getElementType(), Addr.getUnsignedPointer(), - {getSize(CharUnits::Zero()), getSize(Index)}, Name), - ElTy->getElementType(), - Addr.getAlignment().alignmentAtOffset(Index * EltSize), - Addr.isKnownNonNull()); + if (!Addr.isSigned()) + return Address( + CreateInBoundsGEP(Addr.getElementType(), Addr.getUnsignedPointer(), + {getSize(CharUnits::Zero()), getSize(Index)}, Name), + ElTy->getElementType(), + Addr.getAlignment().alignmentAtOffset(Index * EltSize), + Addr.isKnownNonNull()); + Addr.addOffset(Index * EltSize, ElTy, *this); + return Addr; } /// Given @@ -281,10 +290,14 @@ class CGBuilderTy : public CGBuilderBaseTy { const llvm::DataLayout &DL = BB->getDataLayout(); CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); - return Address(CreateInBoundsGEP(ElTy, Addr.getUnsignedPointer(), - getSize(Index), Name), - ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize), - Addr.isKnownNonNull()); + if (!Addr.isSigned()) + return Address(CreateInBoundsGEP(ElTy, Addr.getUnsignedPointer(), + getSize(Index), Name), + ElTy, + Addr.getAlignment().alignmentAtOffset(Index * EltSize), + Addr.isKnownNonNull()); + Addr.addOffset(Index * EltSize, ElTy, *this); + return Addr; } /// Given @@ -298,10 +311,12 @@ class CGBuilderTy : public CGBuilderBaseTy { const llvm::DataLayout &DL = BB->getDataLayout(); CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); - return Address( - CreateGEP(ElTy, Addr.getUnsignedPointer(), getSize(Index), Name), - Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Index * EltSize)); + if (!Addr.isSigned()) + return Address( + CreateGEP(ElTy, Addr.getUnsignedPointer(), getSize(Index), Name), + ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize)); + Addr.addOffset(Index * EltSize, ElTy, *this); + return Addr; } /// Create GEP with single dynamic index. The address alignment is reduced @@ -323,21 +338,28 @@ class CGBuilderTy : public CGBuilderBaseTy { Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name = "") { assert(Addr.getElementType() == TypeCache.Int8Ty); - return Address( - CreateInBoundsGEP(Addr.getElementType(), Addr.getUnsignedPointer(), - getSize(Offset), Name), - Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset), - Addr.isKnownNonNull()); + + if (!Addr.isSigned()) + return Address( + CreateInBoundsGEP(Addr.getElementType(), Addr.getUnsignedPointer(), + getSize(Offset), Name), + Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset), + Addr.isKnownNonNull()); + Addr.addOffset(Offset, TypeCache.Int8Ty, *this); + return Addr; } Address CreateConstByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name = "") { assert(Addr.getElementType() == TypeCache.Int8Ty); - return Address(CreateGEP(Addr.getElementType(), Addr.getUnsignedPointer(), - getSize(Offset), Name), - Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Offset)); + if (!Addr.isSigned()) + return Address(CreateGEP(Addr.getElementType(), Addr.getUnsignedPointer(), + getSize(Offset), Name), + Addr.getElementType(), + Addr.getAlignment().alignmentAtOffset(Offset)); + Addr.addOffset(Offset, TypeCache.Int8Ty, *this); + return Addr; } using CGBuilderBaseTy::CreateConstInBoundsGEP2_32; @@ -364,10 +386,12 @@ class CGBuilderTy : public CGBuilderBaseTy { Address CreateInBoundsGEP(Address Addr, ArrayRef IdxList, llvm::Type *ElementType, CharUnits Align, const Twine &Name = "") { - return RawAddress(CreateInBoundsGEP(Addr.getElementType(), - emitRawPointerFromAddress(Addr), - IdxList, Name), - ElementType, Align, Addr.isKnownNonNull()); + if (!Addr.isSigned()) + return RawAddress(CreateInBoundsGEP(Addr.getElementType(), + emitRawPointerFromAddress(Addr), + IdxList, Name), + ElementType, Align, Addr.isKnownNonNull()); + return addGEPOffset(Addr, IdxList, Align, true, Name); } using CGBuilderBaseTy::CreateIsNull; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 6cc0d9485720c..494891ce4740d 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2151,7 +2151,8 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { // Ignore argument 1, the format string. It is not currently used. CallArgList Args; - Args.add(RValue::get(BufAddr.emitRawPointer(*this)), Ctx.VoidPtrTy); + Args.add(RValue::get(getAsNaturalPointerTo(BufAddr, Ctx.VoidTy)), + Ctx.VoidPtrTy); for (const auto &Item : Layout.Items) { int Size = Item.getSizeByte(); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 333771160cabf..b60f5b3a65868 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -4135,8 +4135,8 @@ static bool isProvablyNull(llvm::Value *addr) { } static bool isProvablyNonNull(Address Addr, CodeGenFunction &CGF) { - return llvm::isKnownNonZero(Addr.getUnsignedPointer(), - CGF.CGM.getDataLayout()); + return !Addr.isSigned() && llvm::isKnownNonZero(Addr.getUnsignedPointer(), + CGF.CGM.getDataLayout()); } /// Emit the actual writing-back of a writeback. @@ -5101,7 +5101,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::Value *UnusedReturnSizePtr = nullptr; if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) { if (!ReturnValue.isNull()) { - SRetPtr = ReturnValue.getAddress(); + SRetPtr = ReturnValue.getValue(); } else { SRetPtr = CreateMemTemp(RetTy, "tmp", &SRetAlloca); if (HaveInsertPoint() && ReturnValue.isUnused()) { diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index d5c3732a4e270..c3bf7d960410a 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1311,7 +1311,8 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, if (CE->getCastKind() == CK_AddressSpaceConversion) Addr = CGF.Builder.CreateAddrSpaceCast( Addr, CGF.ConvertType(E->getType()), ElemTy); - return Addr; + return CGF.AuthPointerToPointerCast(Addr, CE->getSubExpr()->getType(), + CE->getType()); } break; @@ -1785,8 +1786,11 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) { } // Emit as a constant. - auto C = ConstantEmitter(*this).emitAbstract(refExpr->getLocation(), - result.Val, resultType); + // Try to emit as a constant. + llvm::Constant *C = + ConstantEmitter(*this).tryEmitAbstract(result.Val, resultType); + if (!C) + return ConstantEmission(); // Make sure we emit a debug reference to the global variable. // This should probably fire even for diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index d70701f0856cf..14fee2eee8250 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -330,8 +330,8 @@ void AggExprEmitter::withReturnValueSlot( if (!UseTemp) return; - assert(Dest.isIgnored() || Dest.emitRawPointer(CGF) != - Src.getAggregatePointer(E->getType(), CGF)); + assert(Dest.getAddress().isSigned() || Dest.isIgnored() || + Dest.emitRawPointer(CGF) != Src.getAggregatePointer(E->getType(), CGF)); EmitFinalDestCopy(E->getType(), Src); if (!RequiresDestruction && LifetimeStartInst) { diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 00a5a7e6898a8..534f7c0407f61 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -2074,14 +2074,24 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) { if (D->hasAttr()) return CGM.GetWeakRefReference(D).getPointer(); - auto PtrAuthSign = [&](llvm::Constant *C) { + auto PtrAuthSign = [&](llvm::Constant *C, bool IsFunction) { CGPointerAuthInfo AuthInfo; if (EnablePtrAuthFunctionTypeDiscrimination) AuthInfo = CGM.getFunctionPointerAuthInfo(DestType); + else { + // FIXME: getPointerAuthInfoForType should be able to return the pointer + // auth info of reference types. + if (auto *RT = DestType->getAs()) + DestType = CGM.getContext().getPointerType(RT->getPointeeType()); + // Don't emit a signed pointer if the destination is a function pointer + // type. + if (DestType->isSignableType() && !DestType->isFunctionPointerType()) + AuthInfo = CGM.getPointerAuthInfoForType(DestType); + } if (AuthInfo) { - if (hasNonZeroOffset()) + if (IsFunction && hasNonZeroOffset()) return ConstantLValue(nullptr); C = applyOffset(C); @@ -2095,7 +2105,7 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) { }; if (const auto *FD = dyn_cast(D)) - return PtrAuthSign(CGM.getRawFunctionPointer(FD)); + return PtrAuthSign(CGM.getRawFunctionPointer(FD), true); if (const auto *VD = dyn_cast(D)) { // We can never refer to a variable with local storage. diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index f40f3c273206b..65acb3b067f91 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2373,7 +2373,9 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { DestLV.setTBAAInfo(TBAAAccessInfo::getMayAliasInfo()); return EmitLoadOfLValue(DestLV, CE->getExprLoc()); } - return Builder.CreateBitCast(Src, DstTy); + + llvm::Value *Result = Builder.CreateBitCast(Src, DstTy); + return CGF.AuthPointerToPointerCast(Result, E->getType(), DestTy); } case CK_AddressSpaceConversion: { Expr::EvalResult Result; @@ -2523,6 +2525,8 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { if (DestTy.mayBeDynamicClass()) IntToPtr = Builder.CreateLaunderInvariantGroup(IntToPtr); } + + IntToPtr = CGF.AuthPointerToPointerCast(IntToPtr, E->getType(), DestTy); return IntToPtr; } case CK_PointerToIntegral: { @@ -2538,6 +2542,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { PtrExpr = Builder.CreateStripInvariantGroup(PtrExpr); } + PtrExpr = CGF.AuthPointerToPointerCast(PtrExpr, E->getType(), DestTy); return Builder.CreatePtrToInt(PtrExpr, ConvertType(DestTy)); } case CK_ToVoid: { @@ -2850,10 +2855,11 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, Builder.SetInsertPoint(opBB); atomicPHI = Builder.CreatePHI(value->getType(), 2); atomicPHI->addIncoming(value, startBB); - value = atomicPHI; + value = CGF.EmitPointerAuthAuth(type->getPointeeType(), atomicPHI); } else { value = EmitLoadOfLValue(LV, E->getExprLoc()); input = value; + value = CGF.EmitPointerAuthAuth(type->getPointeeType(), value); } // Special case of integer increment that we have to check first: bool++. @@ -3095,6 +3101,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, if (atomicPHI) { llvm::BasicBlock *curBlock = Builder.GetInsertBlock(); llvm::BasicBlock *contBB = CGF.createBasicBlock("atomic_cont", CGF.CurFn); + value = CGF.EmitPointerAuthSign(type->getPointeeType(), value); auto Pair = CGF.EmitAtomicCompareExchange( LV, RValue::get(atomicPHI), RValue::get(value), E->getExprLoc()); llvm::Value *old = CGF.EmitToMemory(Pair.first.getScalarVal(), type); @@ -3106,6 +3113,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, } // Store the updated result through the lvalue. + value = CGF.EmitPointerAuthSign(type->getPointeeType(), value); if (LV.isBitField()) { Value *Src = Previous ? Previous : value; CGF.EmitStoreThroughBitfieldLValue(RValue::get(value), LV, &value); @@ -3966,6 +3974,10 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, return CGF.Builder.CreateBitCast(result, pointer->getType()); } + CGPointerAuthInfo PtrAuthInfo = CGF.CGM.getPointerAuthInfoForType(op.Ty); + if (PtrAuthInfo) + pointer = CGF.EmitPointerAuthAuth(PtrAuthInfo, pointer); + QualType elementType = pointerType->getPointeeType(); if (const VariableArrayType *vla = CGF.getContext().getAsVariableArrayType(elementType)) { @@ -3986,7 +3998,8 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, elemTy, pointer, index, isSigned, isSubtraction, op.E->getExprLoc(), "add.ptr"); } - return pointer; + return PtrAuthInfo ? CGF.EmitPointerAuthSign(PtrAuthInfo, pointer) + : pointer; } // Explicitly handle GNU void* and function pointer arithmetic extensions. The @@ -3999,11 +4012,13 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, elemTy = CGF.ConvertTypeForMem(elementType); if (CGF.getLangOpts().isSignedOverflowDefined()) - return CGF.Builder.CreateGEP(elemTy, pointer, index, "add.ptr"); + pointer = CGF.Builder.CreateGEP(elemTy, pointer, index, "add.ptr"); + else + pointer = CGF.EmitCheckedInBoundsGEP(elemTy, pointer, index, isSigned, + isSubtraction, op.E->getExprLoc(), + "add.ptr"); - return CGF.EmitCheckedInBoundsGEP( - elemTy, pointer, index, isSigned, isSubtraction, op.E->getExprLoc(), - "add.ptr"); + return PtrAuthInfo ? CGF.EmitPointerAuthSign(PtrAuthInfo, pointer) : pointer; } // Construct an fmuladd intrinsic to represent a fused mul-add of MulOp and diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp b/clang/lib/CodeGen/CGPointerAuth.cpp index 621d567dde721..c069b3fa72fba 100644 --- a/clang/lib/CodeGen/CGPointerAuth.cpp +++ b/clang/lib/CodeGen/CGPointerAuth.cpp @@ -15,6 +15,7 @@ #include "CodeGenModule.h" #include "clang/CodeGen/CodeGenABITypes.h" #include "clang/CodeGen/ConstantInitBuilder.h" +#include "llvm/Analysis/ValueTracking.h" #include "llvm/Support/SipHash.h" using namespace clang; @@ -89,6 +90,7 @@ CGPointerAuthInfo CodeGenModule::getFunctionPointerAuthInfo(QualType T) { Discriminator); } + llvm::Value * CodeGenFunction::EmitPointerAuthBlendDiscriminator(llvm::Value *StorageAddress, llvm::Value *Discriminator) { @@ -165,6 +167,130 @@ CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForType(QualType T) { return ::getPointerAuthInfoForType(*this, T); } +Address CodeGenFunction::mergeAddressesInConditionalExpr( + Address LHS, Address RHS, llvm::BasicBlock *LHSBlock, + llvm::BasicBlock *RHSBlock, llvm::BasicBlock *MergeBlock, + QualType MergedType) { + CGPointerAuthInfo LHSInfo = LHS.getPointerAuthInfo(); + CGPointerAuthInfo RHSInfo = RHS.getPointerAuthInfo(); + + if (LHSInfo || RHSInfo) { + if (LHSInfo != RHSInfo || LHS.getOffset() != RHS.getOffset() || + LHS.getBasePointer()->getType() != RHS.getBasePointer()->getType()) { + // If the LHS and RHS have different signing information, offsets, or base + // pointer types, resign both sides and clear out the offsets. + CGPointerAuthInfo NewInfo = + CGM.getPointerAuthInfoForPointeeType(MergedType); + LHSBlock->getTerminator()->eraseFromParent(); + Builder.SetInsertPoint(LHSBlock); + LHS = LHS.getResignedAddress(NewInfo, *this); + Builder.CreateBr(MergeBlock); + LHSBlock = Builder.GetInsertBlock(); + RHSBlock->getTerminator()->eraseFromParent(); + Builder.SetInsertPoint(RHSBlock); + RHS = RHS.getResignedAddress(NewInfo, *this); + Builder.CreateBr(MergeBlock); + RHSBlock = Builder.GetInsertBlock(); + } + + assert(LHS.getPointerAuthInfo() == RHS.getPointerAuthInfo() && + LHS.getOffset() == RHS.getOffset() && + LHS.getBasePointer()->getType() == RHS.getBasePointer()->getType() && + "lhs and rhs must have the same signing information, offsets, and " + "base pointer types"); + } + + Builder.SetInsertPoint(MergeBlock); + llvm::PHINode *PtrPhi = Builder.CreatePHI(LHS.getType(), 2, "cond"); + PtrPhi->addIncoming(LHS.getBasePointer(), LHSBlock); + PtrPhi->addIncoming(RHS.getBasePointer(), RHSBlock); + LHS.replaceBasePointer(PtrPhi); + LHS.setAlignment(std::min(LHS.getAlignment(), RHS.getAlignment())); + return LHS; +} + +static bool isZeroConstant(llvm::Value *value) { + if (auto ci = dyn_cast(value)) + return ci->isZero(); + return false; +} + +static bool equalAuthPolicies(const CGPointerAuthInfo &left, + const CGPointerAuthInfo &right) { + if (left.isSigned() != right.isSigned()) + return false; + assert(left.isSigned() && right.isSigned() && + "should only be called with non-null auth policies"); + return left.getKey() == right.getKey() && + left.getAuthenticationMode() == right.getAuthenticationMode(); +} + +llvm::Value *CodeGenFunction::EmitPointerAuthResign( + llvm::Value *value, QualType type, const CGPointerAuthInfo &curAuthInfo, + const CGPointerAuthInfo &newAuthInfo, bool isKnownNonNull) { + // Fast path: if neither schema wants a signature, we're done. + if (!curAuthInfo && !newAuthInfo) + return value; + + llvm::Value *null = nullptr; + // If the value is obviously null, we're done. + if (auto pointerValue = dyn_cast(value->getType())) { + null = CGM.getNullPointer(pointerValue, type); + } else { + assert(value->getType()->isIntegerTy()); + null = llvm::ConstantInt::get(IntPtrTy, 0); + } + if (value == null) { + return value; + } + + // If both schemas sign the same way, we're done. + if (equalAuthPolicies(curAuthInfo, newAuthInfo)) { + auto curD = curAuthInfo.getDiscriminator(); + auto newD = newAuthInfo.getDiscriminator(); + if (curD == newD) + return value; + + if ((curD == nullptr && isZeroConstant(newD)) || + (newD == nullptr && isZeroConstant(curD))) + return value; + } + + llvm::BasicBlock *initBB = Builder.GetInsertBlock(); + llvm::BasicBlock *resignBB = nullptr, *contBB = nullptr; + + // Null pointers have to be mapped to null, and the ptrauth_resign + // intrinsic doesn't do that. + if (!isKnownNonNull && !llvm::isKnownNonZero(value, CGM.getDataLayout())) { + contBB = createBasicBlock("resign.cont"); + resignBB = createBasicBlock("resign.nonnull"); + + auto isNonNull = Builder.CreateICmpNE(value, null); + Builder.CreateCondBr(isNonNull, resignBB, contBB); + EmitBlock(resignBB); + } + + // Perform the auth/sign/resign operation. + if (!newAuthInfo) { + value = EmitPointerAuthAuth(curAuthInfo, value); + } else if (!curAuthInfo) { + value = EmitPointerAuthSign(newAuthInfo, value); + } else { + value = EmitPointerAuthResignCall(value, curAuthInfo, newAuthInfo); + } + + // Clean up with a phi if we branched before. + if (contBB) { + EmitBlock(contBB); + auto phi = Builder.CreatePHI(value->getType(), 2); + phi->addIncoming(null, initBB); + phi->addIncoming(value, resignBB); + value = phi; + } + + return value; +} + llvm::Constant * CodeGenModule::getConstantSignedPointer(llvm::Constant *Pointer, unsigned Key, llvm::Constant *StorageAddress, @@ -211,6 +337,16 @@ llvm::Constant *CodeGenModule::getConstantSignedPointer( OtherDiscriminator); } +llvm::Constant *CodeGenModule::getConstantSignedPointer(llvm::Constant *Pointer, + QualType PointeeType) { + CGPointerAuthInfo Info = getPointerAuthInfoForPointeeType(PointeeType); + if (!Info.shouldSign()) + return Pointer; + return getConstantSignedPointer( + Pointer, Info.getKey(), nullptr, + cast(Info.getDiscriminator())); +} + /// If applicable, sign a given constant function pointer with the ABI rules for /// functionType. llvm::Constant *CodeGenModule::getFunctionPointer(llvm::Constant *Pointer, @@ -351,3 +487,185 @@ CodeGenModule::getVTablePointerAuthInfo(CodeGenFunction *CGF, /* IsIsaPointer */ false, /* AuthenticatesNullValues */ false, Discriminator); } + +llvm::Value *CodeGenFunction::AuthPointerToPointerCast(llvm::Value *ResultPtr, + QualType SourceType, + QualType DestType) { + CGPointerAuthInfo CurAuthInfo, NewAuthInfo; + if (SourceType->isSignableType()) + CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType); + + if (DestType->isSignableType()) + NewAuthInfo = getPointerAuthInfoForType(CGM, DestType); + + if (!CurAuthInfo && !NewAuthInfo) + return ResultPtr; + + // If only one side of the cast is a function pointer, then we still need to + // resign to handle casts to/from opaque pointers. + if (!CurAuthInfo && DestType->isFunctionPointerType()) + CurAuthInfo = CGM.getFunctionPointerAuthInfo(SourceType); + + if (!NewAuthInfo && SourceType->isFunctionPointerType()) + NewAuthInfo = CGM.getFunctionPointerAuthInfo(DestType); + + return EmitPointerAuthResign(ResultPtr, DestType, CurAuthInfo, NewAuthInfo, + /*IsKnownNonNull=*/false); +} + +Address CodeGenFunction::AuthPointerToPointerCast(Address Ptr, + QualType SourceType, + QualType DestType) { + CGPointerAuthInfo CurAuthInfo, NewAuthInfo; + if (SourceType->isSignableType()) + CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType); + + if (DestType->isSignableType()) + NewAuthInfo = getPointerAuthInfoForType(CGM, DestType); + + if (!CurAuthInfo && !NewAuthInfo) + return Ptr; + + if (!CurAuthInfo && DestType->isFunctionPointerType()) { + // When casting a non-signed pointer to a function pointer, just set the + // auth info on Ptr to the assumed schema. The pointer will be resigned to + // the effective type when used. + Ptr.setPointerAuthInfo(CGM.getFunctionPointerAuthInfo(SourceType)); + return Ptr; + } + + if (!NewAuthInfo && SourceType->isFunctionPointerType()) { + NewAuthInfo = CGM.getFunctionPointerAuthInfo(DestType); + Ptr = Ptr.getResignedAddress(NewAuthInfo, *this); + Ptr.setPointerAuthInfo(CGPointerAuthInfo()); + return Ptr; + } + + return Ptr; +} + +Address CodeGenFunction::EmitPointerAuthSign(Address Addr, + QualType PointeeType) { + CGPointerAuthInfo Info = getPointerAuthInfoForPointeeType(CGM, PointeeType); + llvm::Value *Ptr = EmitPointerAuthSign(Info, Addr.emitRawPointer(*this)); + return Address(Ptr, Addr.getElementType(), Addr.getAlignment()); +} + +Address CodeGenFunction::EmitPointerAuthAuth(Address Addr, + QualType PointeeType) { + CGPointerAuthInfo Info = getPointerAuthInfoForPointeeType(CGM, PointeeType); + llvm::Value *Ptr = EmitPointerAuthAuth(Info, Addr.emitRawPointer(*this)); + return Address(Ptr, Addr.getElementType(), Addr.getAlignment()); +} + +Address CodeGenFunction::getAsNaturalAddressOf(Address Addr, + QualType PointeeTy) { + CGPointerAuthInfo Info = + PointeeTy.isNull() ? CGPointerAuthInfo() + : CGM.getPointerAuthInfoForPointeeType(PointeeTy); + return Addr.getResignedAddress(Info, *this); +} + +Address Address::getResignedAddress(const CGPointerAuthInfo &NewInfo, + CodeGenFunction &CGF) const { + assert(isValid() && "pointer isn't valid"); + CGPointerAuthInfo CurInfo = getPointerAuthInfo(); + llvm::Value *Val; + + // Nothing to do if neither the current or the new ptrauth info needs signing. + if (!CurInfo.isSigned() && !NewInfo.isSigned()) + return Address(getUnsignedPointer(), getElementType(), getAlignment(), + isKnownNonNull()); + + assert(ElementType && "Effective type has to be set"); + + // If the current and the new ptrauth infos are the same and the offset is + // null, just cast the base pointer to the effective type. + if (CurInfo == NewInfo && !hasOffset()) + Val = getBasePointer(); + else { + if (Offset) { + assert(isSigned() && "signed pointer expected"); + // Authenticate the base pointer. + Val = CGF.EmitPointerAuthResign(getBasePointer(), QualType(), CurInfo, + CGPointerAuthInfo(), isKnownNonNull()); + + // Add offset to the authenticated pointer. + unsigned AS = cast(getBasePointer()->getType()) + ->getAddressSpace(); + Val = CGF.Builder.CreateBitCast(Val, + llvm::PointerType::get(CGF.Int8Ty, AS)); + Val = CGF.Builder.CreateGEP(CGF.Int8Ty, Val, Offset, "resignedgep"); + + // Sign the pointer using the new ptrauth info. + Val = CGF.EmitPointerAuthResign(Val, QualType(), CGPointerAuthInfo(), + NewInfo, isKnownNonNull()); + } else { + Val = CGF.EmitPointerAuthResign(getBasePointer(), QualType(), CurInfo, + NewInfo, isKnownNonNull()); + } + } + + Val = CGF.Builder.CreateBitCast(Val, getType()); + return Address(Val, getElementType(), getAlignment(), NewInfo, nullptr, + isKnownNonNull()); +} + +void Address::addOffset(CharUnits V, llvm::Type *Ty, CGBuilderTy &Builder) { + assert(isSigned() && + "shouldn't add an offset if the base pointer isn't signed"); + Alignment = Alignment.alignmentAtOffset(V); + llvm::Value *FixedOffset = + llvm::ConstantInt::get(Builder.getCGF()->IntPtrTy, V.getQuantity()); + addOffset(FixedOffset, Ty, Builder, Alignment); +} + +void Address::addOffset(llvm::Value *V, llvm::Type *Ty, CGBuilderTy &Builder, + CharUnits NewAlignment) { + assert(isSigned() && + "shouldn't add an offset if the base pointer isn't signed"); + ElementType = Ty; + Alignment = NewAlignment; + + if (!Offset) { + Offset = V; + return; + } + + Offset = Builder.CreateAdd(Offset, V, "add"); +} + +llvm::Value *Address::emitRawPointerSlow(CodeGenFunction &CGF) const { + return CGF.getAsNaturalPointerTo(*this, QualType()); +} + +llvm::Value *RValue::getAggregatePointer(QualType PointeeType, + CodeGenFunction &CGF) const { + return CGF.getAsNaturalPointerTo(getAggregateAddress(), PointeeType); +} + +llvm::Value *LValue::getPointer(CodeGenFunction &CGF) const { + assert(isSimple()); + return emitResignedPointer(getType(), CGF); +} + +llvm::Value *LValue::emitResignedPointer(QualType PointeeTy, + CodeGenFunction &CGF) const { + assert(isSimple()); + return CGF.getAsNaturalAddressOf(Addr, PointeeTy).getBasePointer(); +} + +llvm::Value *LValue::emitRawPointer(CodeGenFunction &CGF) const { + assert(isSimple()); + return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; +} + +llvm::Value *AggValueSlot::getPointer(QualType PointeeTy, + CodeGenFunction &CGF) const { + Address SignedAddr = CGF.getAsNaturalAddressOf(Addr, PointeeTy); + return SignedAddr.getBasePointer(); +} + +llvm::Value *AggValueSlot::emitRawPointer(CodeGenFunction &CGF) const { + return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; +} diff --git a/clang/lib/CodeGen/CGValue.h b/clang/lib/CodeGen/CGValue.h index 6ed94bd9c7592..27efcf6ac199b 100644 --- a/clang/lib/CodeGen/CGValue.h +++ b/clang/lib/CodeGen/CGValue.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_LIB_CODEGEN_CGVALUE_H #include "Address.h" +#include "CGPointerAuthInfo.h" #include "CodeGenTBAA.h" #include "EHScopeStack.h" #include "clang/AST/ASTContext.h" @@ -78,6 +79,8 @@ class RValue { return std::make_pair(Vals.first, Vals.second); } + bool isSignedAggregate() const { return AggregateAddr.isSigned(); } + /// getAggregateAddr() - Return the Value* of the address of the aggregate. Address getAggregateAddress() const { assert(isAggregate() && "Not an aggregate!"); @@ -85,9 +88,7 @@ class RValue { } llvm::Value *getAggregatePointer(QualType PointeeType, - CodeGenFunction &CGF) const { - return getAggregateAddress().getBasePointer(); - } + CodeGenFunction &CGF) const; static RValue getIgnored() { // FIXME: should we make this a more explicit state? @@ -317,6 +318,8 @@ class LValue { bool isNontemporal() const { return Nontemporal; } void setNontemporal(bool Value) { Nontemporal = Value; } + bool isPointerSigned() const { return Addr.isSigned(); } + bool isObjCWeak() const { return Quals.getObjCGCAttr() == Qualifiers::Weak; } @@ -352,19 +355,19 @@ class LValue { } // simple lvalue - llvm::Value *getPointer(CodeGenFunction &CGF) const { - assert(isSimple()); - return Addr.getBasePointer(); - } - llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { - assert(isSimple()); - return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; - } + llvm::Value *getPointer(CodeGenFunction &CGF) const; + llvm::Value *emitResignedPointer(QualType PointeeTy, + CodeGenFunction &CGF) const; + llvm::Value *emitRawPointer(CodeGenFunction &CGF) const; Address getAddress() const { return Addr; } void setAddress(Address address) { Addr = address; } + CGPointerAuthInfo getPointerAuthInfo() const { + return Addr.getPointerAuthInfo(); + } + // vector elt lvalue Address getVectorAddress() const { assert(isVectorElt()); @@ -636,9 +639,7 @@ class AggValueSlot { llvm::Value *getPointer(QualType PointeeTy, CodeGenFunction &CGF) const; - llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { - return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; - } + llvm::Value *emitRawPointer(CodeGenFunction &CGF) const; Address getAddress() const { return Addr; diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index a222bc05e8dab..9e29cddc6f858 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -18,6 +18,7 @@ #include "CGDebugInfo.h" #include "CGHLSLRuntime.h" #include "CGOpenMPRuntime.h" +#include "CGRecordLayout.h" #include "CodeGenModule.h" #include "CodeGenPGO.h" #include "TargetInfo.h" @@ -558,8 +559,11 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { ReturnBlock.getBlock()->eraseFromParent(); } if (ReturnValue.isValid()) { + // This only matters when ReturnValue isn't signed. ReturnValue is possibly + // signed only when the return is Indirect or InAlloca. In that case, a + // temporary alloca to store the return value isn't created. auto *RetAlloca = - dyn_cast(ReturnValue.emitRawPointer(*this)); + dyn_cast_or_null(ReturnValue.getPointerIfNotSigned()); if (RetAlloca && RetAlloca->use_empty()) { RetAlloca->eraseFromParent(); ReturnValue = Address::invalid(); @@ -3137,3 +3141,57 @@ CodeGenFunction::EmitPointerAuthAuth(const CGPointerAuthInfo &PointerAuth, return EmitPointerAuthCommon(*this, PointerAuth, Pointer, llvm::Intrinsic::ptrauth_auth); } + +llvm::Value *CodeGenFunction::EmitPointerAuthSign(QualType pointeeType, + llvm::Value *pointer) { + CGPointerAuthInfo pointerAuth = + CGM.getPointerAuthInfoForPointeeType(pointeeType); + return EmitPointerAuthSign(pointerAuth, pointer); +} + +llvm::Value *CodeGenFunction::EmitPointerAuthAuth(QualType pointeeType, + llvm::Value *pointer) { + CGPointerAuthInfo pointerAuth = + CGM.getPointerAuthInfoForPointeeType(pointeeType); + return EmitPointerAuthAuth(pointerAuth, pointer); +} + +llvm::Value * +CodeGenFunction::EmitPointerAuthResignCall(llvm::Value *value, + const CGPointerAuthInfo &curAuth, + const CGPointerAuthInfo &newAuth) { + assert(curAuth && newAuth); + + if (curAuth.getAuthenticationMode() != + PointerAuthenticationMode::SignAndAuth || + newAuth.getAuthenticationMode() != + PointerAuthenticationMode::SignAndAuth) { + auto authedValue = EmitPointerAuthAuth(curAuth, value); + return EmitPointerAuthSign(newAuth, authedValue); + } + // Convert the pointer to intptr_t before signing it. + auto origType = value->getType(); + value = Builder.CreatePtrToInt(value, IntPtrTy); + + auto curKey = Builder.getInt32(curAuth.getKey()); + auto newKey = Builder.getInt32(newAuth.getKey()); + + llvm::Value *curDiscriminator = curAuth.getDiscriminator(); + if (!curDiscriminator) + curDiscriminator = Builder.getSize(0); + + llvm::Value *newDiscriminator = newAuth.getDiscriminator(); + if (!newDiscriminator) + newDiscriminator = Builder.getSize(0); + + // call i64 @llvm.ptrauth.resign(i64 %pointer, + // i32 %curKey, i64 %curDiscriminator, + // i32 %newKey, i64 %newDiscriminator) + auto intrinsic = CGM.getIntrinsic(llvm::Intrinsic::ptrauth_resign); + value = EmitRuntimeCall( + intrinsic, {value, curKey, curDiscriminator, newKey, newDiscriminator}); + + // Convert back to the original type. + value = Builder.CreateIntToPtr(value, origType); + return value; +} diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 5268cc7eda4a2..2ce28f3e4681f 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -185,6 +185,11 @@ template <> struct DominatingValue
{ DominatingLLVMValue::saved_type BasePtr; llvm::Type *ElementType; CharUnits Alignment; + unsigned PtrAuthKey : 28; + PointerAuthenticationMode PtrAuthMode : 2; + bool IsIsaPointer : 1; + bool AuthenticatesNullValues : 1; + DominatingLLVMValue::saved_type PtrAuthDiscriminator; DominatingLLVMValue::saved_type Offset; llvm::PointerType *EffectiveType; }; @@ -193,16 +198,36 @@ template <> struct DominatingValue
{ if (DominatingLLVMValue::needsSaving(value.getBasePointer()) || DominatingLLVMValue::needsSaving(value.getOffset())) return true; + CGPointerAuthInfo info = value.getPointerAuthInfo(); + if (info.isSigned() && + DominatingLLVMValue::needsSaving(info.getDiscriminator())) + return true; return false; } static saved_type save(CodeGenFunction &CGF, type value) { + bool isSigned = value.getPointerAuthInfo().isSigned(); return {DominatingLLVMValue::save(CGF, value.getBasePointer()), - value.getElementType(), value.getAlignment(), - DominatingLLVMValue::save(CGF, value.getOffset()), value.getType()}; + value.getElementType(), + value.getAlignment(), + isSigned ? value.getPointerAuthInfo().getKey() : 0, + value.getPointerAuthInfo().getAuthenticationMode(), + value.getPointerAuthInfo().isIsaPointer(), + value.getPointerAuthInfo().authenticatesNullValues(), + isSigned ? DominatingLLVMValue::save( + CGF, value.getPointerAuthInfo().getDiscriminator()) + : DominatingLLVMValue::saved_type(), + DominatingLLVMValue::save(CGF, value.getOffset()), + value.getType()}; } static type restore(CodeGenFunction &CGF, saved_type value) { + CGPointerAuthInfo info; + if (value.PtrAuthMode != PointerAuthenticationMode::None) + info = CGPointerAuthInfo{ + value.PtrAuthKey, value.PtrAuthMode, value.IsIsaPointer, + value.AuthenticatesNullValues, + DominatingLLVMValue::restore(CGF, value.PtrAuthDiscriminator)}; return Address(DominatingLLVMValue::restore(CGF, value.BasePtr), - value.ElementType, value.Alignment, + value.ElementType, value.Alignment, info, DominatingLLVMValue::restore(CGF, value.Offset)); } }; @@ -2665,15 +2690,7 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::BasicBlock *LHSBlock, llvm::BasicBlock *RHSBlock, llvm::BasicBlock *MergeBlock, - QualType MergedType) { - Builder.SetInsertPoint(MergeBlock); - llvm::PHINode *PtrPhi = Builder.CreatePHI(LHS.getType(), 2, "cond"); - PtrPhi->addIncoming(LHS.getBasePointer(), LHSBlock); - PtrPhi->addIncoming(RHS.getBasePointer(), RHSBlock); - LHS.replaceBasePointer(PtrPhi); - LHS.setAlignment(std::min(LHS.getAlignment(), RHS.getAlignment())); - return LHS; - } + QualType MergedType); /// Construct an address with the natural alignment of T. If a pointer to T /// is expected to be signed, the pointer passed to this function must have @@ -2687,7 +2704,8 @@ class CodeGenFunction : public CodeGenTypeCache { if (Alignment.isZero()) Alignment = CGM.getNaturalTypeAlignment(T, BaseInfo, TBAAInfo, ForPointeeType); - return Address(Ptr, ConvertTypeForMem(T), Alignment, nullptr, + return Address(Ptr, ConvertTypeForMem(T), Alignment, + CGM.getPointerAuthInfoForPointeeType(T), nullptr, IsKnownNonNull); } @@ -4423,10 +4441,6 @@ class CodeGenFunction : public CodeGenTypeCache { CXXDtorType Type, const CXXRecordDecl *RD); - llvm::Value *getAsNaturalPointerTo(Address Addr, QualType PointeeType) { - return Addr.getBasePointer(); - } - bool isPointerKnownNonNull(const Expr *E); /// Create the discriminator from the storage address and the entity hash. @@ -4436,16 +4450,41 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Value *StorageAddress, GlobalDecl SchemaDecl, QualType SchemaType); + llvm::Value *EmitPointerAuthSign(QualType PointeeType, llvm::Value *Pointer); llvm::Value *EmitPointerAuthSign(const CGPointerAuthInfo &Info, llvm::Value *Pointer); + + llvm::Value *EmitPointerAuthAuth(QualType PointeeType, llvm::Value *Pointer); llvm::Value *EmitPointerAuthAuth(const CGPointerAuthInfo &Info, llvm::Value *Pointer); + llvm::Value *EmitPointerAuthResign(llvm::Value *Pointer, QualType PointerType, + const CGPointerAuthInfo &CurAuthInfo, + const CGPointerAuthInfo &NewAuthInfo, + bool IsKnownNonNull); + llvm::Value *EmitPointerAuthResignCall(llvm::Value *Pointer, + const CGPointerAuthInfo &CurInfo, + const CGPointerAuthInfo &NewInfo); + void EmitPointerAuthOperandBundle( const CGPointerAuthInfo &Info, SmallVectorImpl &Bundles); + llvm::Value *AuthPointerToPointerCast(llvm::Value *ResultPtr, + QualType SourceType, QualType DestType); + Address AuthPointerToPointerCast(Address Ptr, QualType SourceType, + QualType DestType); + + Address EmitPointerAuthSign(Address Addr, QualType PointeeType); + Address EmitPointerAuthAuth(Address Addr, QualType PointeeType); + + Address getAsNaturalAddressOf(Address Addr, QualType PointeeTy); + + llvm::Value *getAsNaturalPointerTo(Address Addr, QualType PointeeType) { + return getAsNaturalAddressOf(Addr, PointeeType).getBasePointer(); + } + // Return the copy constructor name with the prefix "__copy_constructor_" // removed. static std::string getNonTrivialCopyConstructorStr(QualType QT, diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index caa3786c033b5..7c6078df0af82 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -986,6 +986,9 @@ class CodeGenModule : public CodeGenTypeCache { GlobalDecl SchemaDecl, QualType SchemaType); + llvm::Constant *getConstantSignedPointer(llvm::Constant *Pointer, + QualType PointeeType); + llvm::Constant * getConstantSignedPointer(llvm::Constant *Pointer, unsigned Key, llvm::Constant *StorageAddress, diff --git a/clang/lib/Headers/ptrauth.h b/clang/lib/Headers/ptrauth.h index 40ac6dcac2ab8..e0bc8c4f9acf7 100644 --- a/clang/lib/Headers/ptrauth.h +++ b/clang/lib/Headers/ptrauth.h @@ -58,6 +58,21 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t; /* Authenticating a pointer that was not signed with the given key and extra-data value will (likely) fail by trapping. */ +/* The null function pointer is always the all-zero bit pattern. + Signing an all-zero bit pattern will embed a (likely) non-zero + signature in the result, and so the result will not seem to be + a null function pointer. Authenticating this value will yield + a null function pointer back. However, authenticating an + all-zero bit pattern will probably fail, because the + authentication will expect a (likely) non-zero signature to + embedded in the value. + + Because of this, if a pointer may validly be null, you should + check for null before attempting to authenticate it with one + of these intrinsics. This is not necessary when using the + __ptrauth qualifier; the compiler will perform this check + automatically. */ + #if __has_feature(ptrauth_intrinsics) /* Strip the signature from a value without authenticating it. diff --git a/clang/test/CodeGen/ptrauth-function-lvalue-cast-disc.c b/clang/test/CodeGen/ptrauth-function-lvalue-cast-disc.c new file mode 100644 index 0000000000000..6712a6cf417b9 --- /dev/null +++ b/clang/test/CodeGen/ptrauth-function-lvalue-cast-disc.c @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 %s -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics -emit-llvm -o- -fptrauth-function-pointer-type-discrimination | FileCheck %s + +typedef void (*fptr_t)(void); + +char *cptr; +void (*fptr)(void); + +// CHECK-LABEL: define void @test1 +void test1() { + // CHECK: [[LOAD:%.*]] = load ptr, ptr @cptr + // CHECK: [[TOINT:%.*]] = ptrtoint ptr [[LOAD]] to i64 + // CHECK: call i64 @llvm.ptrauth.resign(i64 [[TOINT]], i32 0, i64 0, i32 0, i64 18983) + // CHECK: call void {{.*}}() [ "ptrauth"(i32 0, i64 18983) ] + + (*(fptr_t)cptr)(); +} + +// CHECK-LABEL: define i8 @test2 +char test2() { + return *(char *)fptr; + + // CHECK: [[LOAD:%.*]] = load ptr, ptr @fptr + // CHECK: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null + + // CHECK: [[TOINT:%.*]] = ptrtoint ptr [[LOAD]] to i64 + // CHECK: call i64 @llvm.ptrauth.resign(i64 [[TOINT]], i32 0, i64 18983, i32 0, i64 0) +} + +// CHECK-LABEL: define void @test4 +void test4() { + (*((fptr_t)(&*((char *)(&*(fptr_t)cptr)))))(); + + // CHECK: [[LOAD:%.*]] = load ptr, ptr @cptr + // CHECK-NEXT: [[CAST4:%.*]] = ptrtoint ptr [[LOAD]] to i64 + // CHECK-NEXT: [[RESIGN:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[CAST4]], i32 0, i64 0, i32 0, i64 18983) + // CHECK-NEXT: [[CAST5:%.*]] = inttoptr i64 [[RESIGN]] to ptr + // CHECK-NEXT: call void [[CAST5]]() [ "ptrauth"(i32 0, i64 18983) ] +} + +void *vptr; +void test5() { + vptr = &*(char *)fptr; + + // CHECK: [[LOAD:%.*]] = load ptr, ptr @fptr + // CHECK-NEXT: [[CMP]] = icmp ne ptr [[LOAD]], null + // CHECK-NEXT: br i1 [[CMP]], label %[[NONNULL:.*]], label %[[CONT:.*]] + + // CHECK: [[NONNULL]]: + // CHECK: [[RESIGN:%.*]] = call i64 @llvm.ptrauth.resign(i64 {{.*}}, i32 0, i64 18983, i32 0, i64 0) + // CHECK: [[CAST:%.*]] = inttoptr i64 [[RESIGN]] to ptr + + // CHECK: [[CONT]]: + // CHECK: [[PHI:%.*]] = phi ptr [ null, {{.*}} ], [ [[CAST]], %[[NONNULL]] ] + // CHECK: store ptr [[PHI]], ptr @vptr +} diff --git a/clang/test/CodeGen/ptrauth-function-type-discriminator-cast.c b/clang/test/CodeGen/ptrauth-function-type-discriminator-cast.c new file mode 100644 index 0000000000000..fa12e2c7ec19c --- /dev/null +++ b/clang/test/CodeGen/ptrauth-function-type-discriminator-cast.c @@ -0,0 +1,85 @@ +// RUN: %clang_cc1 %s -fptrauth-function-pointer-type-discrimination -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics -disable-llvm-passes -emit-llvm -o- | FileCheck %s +// RUN: %clang_cc1 -xc++ %s -fptrauth-function-pointer-type-discrimination -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics -disable-llvm-passes -emit-llvm -o- | FileCheck %s --check-prefixes=CHECK,CHECKCXX + +#ifdef __cplusplus +extern "C" { +#endif + +void f(void); +void f2(int); +void (*fptr)(void); +void *opaque; +unsigned long uintptr; + +#ifdef __cplusplus +struct ptr_member { + void (*fptr_)(int) = 0; +}; +ptr_member pm; +void (*test_member)() = (void (*)())pm.fptr_; + +// CHECKCXX-LABEL: define internal void @__cxx_global_var_init +// CHECKCXX: call i64 @llvm.ptrauth.resign(i64 {{.*}}, i32 0, i64 2712, i32 0, i64 18983) +#endif + + +// CHECK-LABEL: define void @test_cast_to_opaque +void test_cast_to_opaque() { + opaque = (void *)f; + + // CHECK: [[RESIGN_VAL:%.*]] = call i64 @llvm.ptrauth.resign(i64 ptrtoint (ptr ptrauth (ptr @f, i32 0, i64 18983) to i64), i32 0, i64 18983, i32 0, i64 0) + // CHECK: [[RESIGN_PTR:%.*]] = inttoptr i64 [[RESIGN_VAL]] to ptr +} + +// CHECK-LABEL: define void @test_cast_from_opaque +void test_cast_from_opaque() { + fptr = (void (*)(void))opaque; + + // CHECK: [[LOAD:%.*]] = load ptr, ptr @opaque + // CHECK: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null + // CHECK: br i1 [[CMP]], label %[[RESIGN_LAB:.*]], label + + // CHECK: [[RESIGN_LAB]]: + // CHECK: [[INT:%.*]] = ptrtoint ptr [[LOAD]] to i64 + // CHECK: [[RESIGN_INT:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[INT]], i32 0, i64 0, i32 0, i64 18983) +} + +// CHECK-LABEL: define void @test_cast_to_intptr +void test_cast_to_intptr() { + uintptr = (unsigned long)fptr; + + // CHECK: [[ENTRY:.*]]: + // CHECK: [[LOAD:%.*]] = load ptr, ptr @fptr + // CHECK: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null + // CHECK: br i1 [[CMP]], label %[[RESIGN_LAB:.*]], label %[[RESIGN_CONT:.*]] + + // CHECK: [[RESIGN_LAB]]: + // CHECK: [[INT:%.*]] = ptrtoint ptr [[LOAD]] to i64 + // CHECK: [[RESIGN_INT:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[INT]], i32 0, i64 18983, i32 0, i64 0) + // CHECK: [[RESIGN:%.*]] = inttoptr i64 [[RESIGN_INT]] to ptr + // CHECK: br label %[[RESIGN_CONT]] + + // CHECK: [[RESIGN_CONT]]: + // CHECK: phi ptr [ null, %[[ENTRY]] ], [ [[RESIGN]], %[[RESIGN_LAB]] ] +} + +// CHECK-LABEL: define void @test_function_to_function_cast +void test_function_to_function_cast() { + void (*fptr2)(int) = (void (*)(int))fptr; + // CHECK: call i64 @llvm.ptrauth.resign(i64 {{.*}}, i32 0, i64 18983, i32 0, i64 2712) +} + +// CHECK-LABEL: define void @test_call_lvalue_cast +void test_call_lvalue_cast() { + (*(void (*)(int))f)(42); + + // CHECK: entry: + // CHECK-NEXT: [[RESIGN:%.*]] = call i64 @llvm.ptrauth.resign(i64 ptrtoint (ptr ptrauth (ptr @f, i32 0, i64 18983) to i64), i32 0, i64 18983, i32 0, i64 2712) + // CHECK-NEXT: [[RESIGN_INT:%.*]] = inttoptr i64 [[RESIGN]] to ptr + // CHECK-NEXT: call void [[RESIGN_INT]](i32 noundef 42) [ "ptrauth"(i32 0, i64 2712) ] +} + + +#ifdef __cplusplus +} +#endif diff --git a/clang/test/CodeGen/ptrauth.c b/clang/test/CodeGen/ptrauth.c new file mode 100644 index 0000000000000..dff6dbeb8508a --- /dev/null +++ b/clang/test/CodeGen/ptrauth.c @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-llvm %s -o - | FileCheck -check-prefix=CHECK -check-prefix=NOPCH %s +// RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-pch %s -o %t.ast +// RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-llvm -x ast -o - %t.ast | FileCheck -check-prefix=CHECK -check-prefix=PCH %s + +#define FNPTRKEY 0 + +void (*fnptr)(void); +long discriminator; + +extern void external_function(void); +// CHECK: @fptr1 = global ptr ptrauth (ptr @external_function, i32 0, i64 18983) +void (*fptr1)(void) = external_function; +// CHECK: @fptr2 = global ptr ptrauth (ptr @external_function, i32 0, i64 18983) +void (*fptr2)(void) = &external_function; + +// CHECK: @fptr3 = global ptr ptrauth (ptr @external_function, i32 2, i64 26) +void (*fptr3)(void) = __builtin_ptrauth_sign_constant(&external_function, 2, 26); + +// CHECK: @fptr4 = global ptr ptrauth (ptr @external_function, i32 2, i64 26, ptr @fptr4) +void (*fptr4)(void) = __builtin_ptrauth_sign_constant(&external_function, 2, __builtin_ptrauth_blend_discriminator(&fptr4, 26)); + +// CHECK-LABEL: define void @test_call() +void test_call() { + // CHECK: [[T0:%.*]] = load ptr, ptr @fnptr, + // CHECK-NEXT: call void [[T0]]() [ "ptrauth"(i32 0, i64 18983) ] + fnptr(); +} + +// CHECK-LABEL: define void @test_direct_call() +void test_direct_call() { + // CHECK: call void @test_call(){{$}} + test_call(); +} + +void abort(); +// CHECK-LABEL: define void @test_direct_builtin_call() +void test_direct_builtin_call() { + // CHECK: call void @abort() {{#[0-9]+$}} + abort(); +} + +// CHECK-LABEL: define ptr @test_function_pointer() +// CHECK: ret ptr ptrauth (ptr @external_function, i32 0, i64 18983) +void (*test_function_pointer())(void) { + return external_function; +} + +struct InitiallyIncomplete; +extern struct InitiallyIncomplete returns_initially_incomplete(void); +// CHECK-LABEL: define void @use_while_incomplete() +void use_while_incomplete() { + // NOPCH: [[VAR:%.*]] = alloca ptr, + // NOPCH-NEXT: store ptr ptrauth (ptr @returns_initially_incomplete, i32 0, i64 25106), ptr [[VAR]] + // PCH: [[VAR:%.*]] = alloca ptr, + // PCH-NEXT: store ptr ptrauth (ptr @returns_initially_incomplete, i32 0, i64 25106), ptr [[VAR]] + struct InitiallyIncomplete (*fnptr)(void) = &returns_initially_incomplete; +} +struct InitiallyIncomplete { int x; }; +// CHECK-LABEL: define void @use_while_complete() +void use_while_complete() { + // CHECK: [[VAR:%.*]] = alloca ptr, + // CHECK-NEXT: store ptr ptrauth (ptr @returns_initially_incomplete, i32 0, i64 25106), ptr [[VAR]] + // CHECK-NEXT: ret void + struct InitiallyIncomplete (*fnptr)(void) = &returns_initially_incomplete; +} + +// CHECK-LABEL: define void @test_memcpy_inline( +// CHECK-NOT: call{{.*}}memcpy + +extern inline __attribute__((__always_inline__)) +void *memcpy(void *d, const void *s, unsigned long) { + return 0; +} + +void test_memcpy_inline(char *d, char *s) { + memcpy(d, s, 4); +} diff --git a/clang/test/Preprocessor/ptrauth_feature.c b/clang/test/Preprocessor/ptrauth_feature.c index 88b6982c01657..c19ac21d42139 100644 --- a/clang/test/Preprocessor/ptrauth_feature.c +++ b/clang/test/Preprocessor/ptrauth_feature.c @@ -65,6 +65,16 @@ // RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,NOINITFINI,FUNC +// RUN: %clang_cc1 -E %s -triple=aarch64 \ +// RUN: -fptrauth-intrinsics \ +// RUN: -fptrauth-calls \ +// RUN: -fptrauth-returns \ +// RUN: -fptrauth-vtable-pointer-address-discrimination \ +// RUN: -fptrauth-vtable-pointer-type-discrimination \ +// RUN: -fptrauth-function-pointer-type-discrimination | \ +// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,NOINITFINI,FUNC + + #if __has_feature(ptrauth_intrinsics) // INTRIN: has_ptrauth_intrinsics void has_ptrauth_intrinsics() {} diff --git a/clang/test/Sema/ptrauth-function-type-discriminatior.c b/clang/test/Sema/ptrauth-function-type-discriminatior.c new file mode 100644 index 0000000000000..0dacdf35f2038 --- /dev/null +++ b/clang/test/Sema/ptrauth-function-type-discriminatior.c @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 %s -triple arm64e-apple-ios13 -verify -xobjective-c -fblocks +// RUN: %clang_cc1 %s -triple arm64e-apple-ios13 -verify -xc +// RUN: %clang_cc1 %s -triple arm64e-apple-ios13 -verify -xc++ + +// expected-no-diagnostics + +#define discm(x) __builtin_ptrauth_type_discriminator(x) + +struct Complete {}; +struct Incomplete; + +#ifndef __cplusplus +enum EIncomplete; +#endif + +enum EComplete { enumerator }; + +_Static_assert(discm(void(void)) == 18983, ""); +_Static_assert(discm(void()) == discm(void(void)), ""); +_Static_assert(discm(void(int *)) == discm(void(float *)), ""); +_Static_assert(discm(void(int *)) == discm(void(struct Incomplete *)), ""); +_Static_assert(discm(void(struct Complete *)) == discm(void(struct Incomplete *)), ""); +_Static_assert(discm(void(int *)) != discm(void(int)), ""); +_Static_assert(discm(void(int)) != discm(void(int, ...)), ""); +_Static_assert(discm(_Atomic(int *)()) == discm(int *()), ""); +#ifndef __cplusplus +_Static_assert(discm(enum EIncomplete()) == discm(int()), ""); +#endif +_Static_assert(discm(enum EComplete()) == discm(int()), ""); +_Static_assert(discm(unsigned long()) == discm(int()), ""); +_Static_assert(discm(char()) == discm(int()), ""); +_Static_assert(discm(int(int (*)[10])) == discm(int(int (*)[9])), ""); +_Static_assert(discm(void (int[10])) == discm(void (int *)), ""); +_Static_assert(discm(void (int[*])) == discm(void (int *)), ""); +_Static_assert(discm(void (void ())) == discm(void (void (*))), ""); + +#ifndef __cplusplus +typedef struct {} foo; +struct foo {}; +_Static_assert(discm(void(foo)) == discm(void(struct foo)), ""); +#endif + +#ifdef __OBJC__ +@interface I @end +_Static_assert(discm(id()) == discm(I*()), ""); +_Static_assert(discm(id()) == discm(void*()), ""); +_Static_assert(discm(id()) == discm(Class()), ""); +_Static_assert(discm(void(^())()) == discm(id()), ""); +#endif + +#ifdef __cplusplus +_Static_assert(discm(void(Complete &)) != discm(void(Complete *)), ""); +_Static_assert(discm(void(Complete &)) != discm(void(Complete &&)), ""); +_Static_assert(discm(void(Incomplete &)) != discm(void(Incomplete &&)), ""); +/* Descend into array and function types when using references. */ +_Static_assert(discm(void(void (&)())) != discm(void (void (&)(int))), ""); +_Static_assert(discm(void(void (&)())) != discm(void (int (&)())), ""); +_Static_assert(discm(void(int (&)[10])) == discm(void(int (&)[9])), ""); +_Static_assert(discm(void(int (&)[10])) == discm(void(int (&)[])), ""); +_Static_assert(discm(void(int (&)[10])) != discm(void(float (&)[10])), ""); +#endif + +typedef __attribute__((ext_vector_type(4))) float vec4; +typedef __attribute__((ext_vector_type(16))) char char_vec16; +_Static_assert(discm(void (vec4)) == discm(void (char_vec16)), ""); From d6a54ad7fe648e9591a20af68cfc37728a07cd5e Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Sun, 14 Jul 2024 15:58:04 -0700 Subject: [PATCH 4/7] Revert unneeded changes --- clang/include/clang/AST/ASTContext.h | 2 +- clang/include/clang/AST/Type.h | 5 +- clang/lib/AST/ASTContext.cpp | 12 +- clang/lib/CodeGen/Address.h | 32 +---- clang/lib/CodeGen/CGBlocks.cpp | 4 +- clang/lib/CodeGen/CGBuilder.h | 108 +++++----------- clang/lib/CodeGen/CGBuiltin.cpp | 3 +- clang/lib/CodeGen/CGCall.cpp | 15 +-- clang/lib/CodeGen/CGException.cpp | 4 +- clang/lib/CodeGen/CGExpr.cpp | 22 +--- clang/lib/CodeGen/CGExprAgg.cpp | 7 +- clang/lib/CodeGen/CGExprCXX.cpp | 9 +- clang/lib/CodeGen/CGExprConstant.cpp | 16 +-- clang/lib/CodeGen/CGExprScalar.cpp | 22 +--- clang/lib/CodeGen/CGObjCMac.cpp | 2 +- clang/lib/CodeGen/CGPointerAuth.cpp | 121 +----------------- clang/lib/CodeGen/CGValue.h | 12 +- clang/lib/CodeGen/CodeGenFunction.cpp | 6 +- clang/lib/CodeGen/CodeGenFunction.h | 41 ++---- clang/lib/CodeGen/CodeGenModule.h | 3 - clang/lib/CodeGen/ItaniumCXXABI.cpp | 2 +- clang/test/Preprocessor/ptrauth_feature.c | 10 -- .../ptrauth-function-type-discriminatior.c | 65 ---------- 23 files changed, 100 insertions(+), 423 deletions(-) delete mode 100644 clang/test/Sema/ptrauth-function-type-discriminatior.c diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 8ba0c943a9c86..57022e75073fe 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1284,7 +1284,7 @@ class ASTContext : public RefCountedBase { getPointerAuthVTablePointerDiscriminator(const CXXRecordDecl *RD); /// Return the "other" type-specific discriminator for the given type. - uint16_t getPointerAuthTypeDiscriminator(QualType T); + uint16_t getPointerAuthTypeDiscriminator(QualType T) const; /// Apply Objective-C protocol qualifiers to the given type. /// \param allowOnPointerType specifies if we can apply protocol diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index bf242debe479a..3aa0f05b0ab60 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2507,7 +2507,6 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { bool isFunctionProtoType() const { return getAs(); } bool isPointerType() const; bool isSignableType() const; - bool isSignablePointerType() const; bool isAnyPointerType() const; // Any C pointer or ObjC object pointer bool isCountAttributedType() const; bool isBlockPointerType() const; @@ -8003,9 +8002,7 @@ inline bool Type::isAnyPointerType() const { return isPointerType() || isObjCObjectPointerType(); } -inline bool Type::isSignableType() const { return isSignablePointerType(); } - -inline bool Type::isSignablePointerType() const { return isPointerType(); } +inline bool Type::isSignableType() const { return isPointerType(); } inline bool Type::isBlockPointerType() const { return isa(CanonicalType); diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 18dfe51e167e0..497579dcc56b6 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3400,7 +3400,7 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx, } } -uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) { +uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) const { assert(!T->isDependentType() && "cannot compute type discriminator of a dependent type"); @@ -3410,13 +3410,11 @@ uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) { if (T->isFunctionPointerType() || T->isFunctionReferenceType()) T = T->getPointeeType(); - if (T->isFunctionType()) { + if (T->isFunctionType()) encodeTypeForFunctionPointerAuth(*this, Out, T); - } else { - T = T.getUnqualifiedType(); - std::unique_ptr MC(createMangleContext()); - MC->mangleCanonicalTypeName(T, Out); - } + else + llvm_unreachable( + "type discrimination of non-function type not implemented yet"); return llvm::getPointerAuthStableSipHash(Str); } diff --git a/clang/lib/CodeGen/Address.h b/clang/lib/CodeGen/Address.h index 1d2c453f25523..d753250d428d3 100644 --- a/clang/lib/CodeGen/Address.h +++ b/clang/lib/CodeGen/Address.h @@ -134,10 +134,6 @@ class Address { /// The expected IR type of the pointer. Carrying accurate element type /// information in Address makes it more convenient to work with Address /// values and allows frontend assertions to catch simple mistakes. - /// - /// When the address is a raw pointer, this is currently redundant with the - /// pointer's type, but for signed pointers it is useful if the pointer has - /// been offsetted or cast from the original type. llvm::Type *ElementType = nullptr; CharUnits Alignment; @@ -180,11 +176,6 @@ class Address { static Address invalid() { return Address(nullptr); } bool isValid() const { return Pointer.getPointer() != nullptr; } - llvm::Value *getPointerIfNotSigned() const { - assert(isValid() && "pointer isn't valid"); - return !isSigned() ? Pointer.getPointer() : nullptr; - } - /// This function is used in situations where the caller is doing some sort of /// opaque "laundering" of the pointer. void replaceBasePointer(llvm::Value *P) { @@ -204,11 +195,6 @@ class Address { return Pointer.getPointer(); } - llvm::Value *getUnsignedPointer() const { - assert(!isSigned() && "cannot call this function if pointer is signed"); - return getBasePointer(); - } - /// Return the type of the pointer value. llvm::PointerType *getType() const { return llvm::PointerType::get( @@ -252,14 +238,6 @@ class Address { return *this; } - /// Add a constant offset. - void addOffset(CharUnits V, llvm::Type *Ty, CGBuilderTy &Builder); - - /// Add a variable offset. - /// \param V An llvm value holding a variable offset. - void addOffset(llvm::Value *V, llvm::Type *Ty, CGBuilderTy &Builder, - CharUnits NewAlignment); - bool hasOffset() const { return Offset; } llvm::Value *getOffset() const { return Offset; } @@ -270,9 +248,7 @@ class Address { /// Return the pointer contained in this class after authenticating it and /// adding offset to it if necessary. llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { - if (!isSigned()) - return getUnsignedPointer(); - return emitRawPointerSlow(CGF); + return getBasePointer(); } /// Return address with different pointer, but same element type and @@ -303,9 +279,9 @@ class Address { }; inline RawAddress::RawAddress(Address Addr) - : PointerAndKnownNonNull( - Addr.isValid() ? Addr.getUnsignedPointer() : nullptr, - Addr.isValid() ? Addr.isKnownNonNull() : NotKnownNonNull), + : PointerAndKnownNonNull(Addr.isValid() ? Addr.getBasePointer() : nullptr, + Addr.isValid() ? Addr.isKnownNonNull() + : NotKnownNonNull), ElementType(Addr.isValid() ? Addr.getElementType() : nullptr), Alignment(Addr.isValid() ? Addr.getAlignment() : CharUnits::Zero()) {} diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 2affd93c6b9a2..066139b1c78c7 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -1974,8 +1974,8 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { // it. It's not quite worth the annoyance to avoid creating it in the // first place. if (!needsEHCleanup(captureType.isDestructedType())) - if (auto *I = cast_or_null( - dstField.getPointerIfNotSigned())) + if (auto *I = + cast_or_null(dstField.getBasePointer())) I->eraseFromParent(); } break; diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h index 48b3067494062..6625c662e041f 100644 --- a/clang/lib/CodeGen/CGBuilder.h +++ b/clang/lib/CodeGen/CGBuilder.h @@ -15,7 +15,6 @@ #include "llvm/Analysis/Utils/Local.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Module.h" #include "llvm/IR/Type.h" namespace clang { @@ -57,27 +56,7 @@ class CGBuilderTy : public CGBuilderBaseTy { CodeGenFunction *getCGF() const { return getInserter().CGF; } llvm::Value *emitRawPointerFromAddress(Address Addr) const { - if (!Addr.isSigned()) - return Addr.getUnsignedPointer(); - assert(getCGF() && "CGF not set"); - return Addr.emitRawPointerSlow(*getCGF()); - } - - /// Helper function to compute a GEP's offset and add it to Addr. - Address addGEPOffset(Address Addr, ArrayRef IdxList, - CharUnits Align, bool IsInBounds, const Twine &Name) { - typedef ArrayRef::const_iterator IdxItTy; - typedef llvm::generic_gep_type_iterator GEPTypeIt; - const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); - GEPTypeIt GTI = GEPTypeIt::begin(Addr.getElementType(), IdxList.begin()); - IdxItTy IdxBegin = IdxList.begin(), IdxEnd = IdxList.end(); - llvm::Type *GEPType = Addr.getType(); - SmallString<12> Buffer; - StringRef GEPName = Name.toStringRef(Buffer); - std::pair OffsetAndType = llvm::EmitGEPOffset( - this, DL, GTI, IdxBegin, IdxEnd, GEPType, GEPName, IsInBounds, false); - Addr.addOffset(OffsetAndType.first, OffsetAndType.second, *this, Align); - return Addr; + return Addr.getBasePointer(); } template @@ -243,14 +222,11 @@ class CGBuilderTy : public CGBuilderBaseTy { const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); - if (!Addr.isSigned()) - return Address(CreateStructGEP(Addr.getElementType(), - Addr.getUnsignedPointer(), Index, Name), - ElTy->getElementType(Index), - Addr.getAlignment().alignmentAtOffset(Offset), - Addr.isKnownNonNull()); - Addr.addOffset(Offset, ElTy->getTypeAtIndex(Index), *this); - return Addr; + return Address(CreateStructGEP(Addr.getElementType(), Addr.getBasePointer(), + Index, Name), + ElTy->getElementType(Index), + Addr.getAlignment().alignmentAtOffset(Offset), + Addr.isKnownNonNull()); } /// Given @@ -268,15 +244,12 @@ class CGBuilderTy : public CGBuilderBaseTy { CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType())); - if (!Addr.isSigned()) - return Address( - CreateInBoundsGEP(Addr.getElementType(), Addr.getUnsignedPointer(), - {getSize(CharUnits::Zero()), getSize(Index)}, Name), - ElTy->getElementType(), - Addr.getAlignment().alignmentAtOffset(Index * EltSize), - Addr.isKnownNonNull()); - Addr.addOffset(Index * EltSize, ElTy, *this); - return Addr; + return Address( + CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(), + {getSize(CharUnits::Zero()), getSize(Index)}, Name), + ElTy->getElementType(), + Addr.getAlignment().alignmentAtOffset(Index * EltSize), + Addr.isKnownNonNull()); } /// Given @@ -290,14 +263,10 @@ class CGBuilderTy : public CGBuilderBaseTy { const llvm::DataLayout &DL = BB->getDataLayout(); CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); - if (!Addr.isSigned()) - return Address(CreateInBoundsGEP(ElTy, Addr.getUnsignedPointer(), - getSize(Index), Name), - ElTy, - Addr.getAlignment().alignmentAtOffset(Index * EltSize), - Addr.isKnownNonNull()); - Addr.addOffset(Index * EltSize, ElTy, *this); - return Addr; + return Address( + CreateInBoundsGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name), + ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize), + Addr.isKnownNonNull()); } /// Given @@ -311,12 +280,9 @@ class CGBuilderTy : public CGBuilderBaseTy { const llvm::DataLayout &DL = BB->getDataLayout(); CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); - if (!Addr.isSigned()) - return Address( - CreateGEP(ElTy, Addr.getUnsignedPointer(), getSize(Index), Name), - ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize)); - Addr.addOffset(Index * EltSize, ElTy, *this); - return Addr; + return Address(CreateGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name), + Addr.getElementType(), + Addr.getAlignment().alignmentAtOffset(Index * EltSize)); } /// Create GEP with single dynamic index. The address alignment is reduced @@ -338,28 +304,20 @@ class CGBuilderTy : public CGBuilderBaseTy { Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name = "") { assert(Addr.getElementType() == TypeCache.Int8Ty); - - if (!Addr.isSigned()) - return Address( - CreateInBoundsGEP(Addr.getElementType(), Addr.getUnsignedPointer(), - getSize(Offset), Name), - Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset), - Addr.isKnownNonNull()); - Addr.addOffset(Offset, TypeCache.Int8Ty, *this); - return Addr; + return Address( + CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(), + getSize(Offset), Name), + Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset), + Addr.isKnownNonNull()); } Address CreateConstByteGEP(Address Addr, CharUnits Offset, const llvm::Twine &Name = "") { assert(Addr.getElementType() == TypeCache.Int8Ty); - - if (!Addr.isSigned()) - return Address(CreateGEP(Addr.getElementType(), Addr.getUnsignedPointer(), - getSize(Offset), Name), - Addr.getElementType(), - Addr.getAlignment().alignmentAtOffset(Offset)); - Addr.addOffset(Offset, TypeCache.Int8Ty, *this); - return Addr; + return Address(CreateGEP(Addr.getElementType(), Addr.getBasePointer(), + getSize(Offset), Name), + Addr.getElementType(), + Addr.getAlignment().alignmentAtOffset(Offset)); } using CGBuilderBaseTy::CreateConstInBoundsGEP2_32; @@ -386,12 +344,10 @@ class CGBuilderTy : public CGBuilderBaseTy { Address CreateInBoundsGEP(Address Addr, ArrayRef IdxList, llvm::Type *ElementType, CharUnits Align, const Twine &Name = "") { - if (!Addr.isSigned()) - return RawAddress(CreateInBoundsGEP(Addr.getElementType(), - emitRawPointerFromAddress(Addr), - IdxList, Name), - ElementType, Align, Addr.isKnownNonNull()); - return addGEPOffset(Addr, IdxList, Align, true, Name); + return RawAddress(CreateInBoundsGEP(Addr.getElementType(), + emitRawPointerFromAddress(Addr), + IdxList, Name), + ElementType, Align, Addr.isKnownNonNull()); } using CGBuilderBaseTy::CreateIsNull; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 494891ce4740d..6cc0d9485720c 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2151,8 +2151,7 @@ RValue CodeGenFunction::emitBuiltinOSLogFormat(const CallExpr &E) { // Ignore argument 1, the format string. It is not currently used. CallArgList Args; - Args.add(RValue::get(getAsNaturalPointerTo(BufAddr, Ctx.VoidTy)), - Ctx.VoidPtrTy); + Args.add(RValue::get(BufAddr.emitRawPointer(*this)), Ctx.VoidPtrTy); for (const auto &Item : Layout.Items) { int Size = Item.getSizeByte(); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index b60f5b3a65868..a38484941ba24 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3508,8 +3508,7 @@ static llvm::Value *tryRemoveRetainOfSelf(CodeGenFunction &CGF, llvm::LoadInst *load = dyn_cast(retainedValue->stripPointerCasts()); if (!load || load->isAtomic() || load->isVolatile() || - load->getPointerOperand() != - CGF.GetAddrOfLocalVar(self).getPointerIfNotSigned()) + load->getPointerOperand() != CGF.GetAddrOfLocalVar(self).getBasePointer()) return nullptr; // Okay! Burn it all down. This relies for correctness on the @@ -3546,8 +3545,7 @@ static llvm::Value *emitAutoreleaseOfResult(CodeGenFunction &CGF, /// Heuristically search for a dominating store to the return-value slot. static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { - // This function shouldn't be called when ReturnValue is signed. - llvm::Value *ReturnValuePtr = CGF.ReturnValue.getUnsignedPointer(); + llvm::Value *ReturnValuePtr = CGF.ReturnValue.getBasePointer(); // Check if a User is a store which pointerOperand is the ReturnValue. // We are looking for stores to the ReturnValue, not for stores of the @@ -4135,8 +4133,7 @@ static bool isProvablyNull(llvm::Value *addr) { } static bool isProvablyNonNull(Address Addr, CodeGenFunction &CGF) { - return !Addr.isSigned() && llvm::isKnownNonZero(Addr.getUnsignedPointer(), - CGF.CGM.getDataLayout()); + return llvm::isKnownNonZero(Addr.getBasePointer(), CGF.CGM.getDataLayout()); } /// Emit the actual writing-back of a writeback. @@ -4144,7 +4141,7 @@ static void emitWriteback(CodeGenFunction &CGF, const CallArgList::Writeback &writeback) { const LValue &srcLV = writeback.Source; Address srcAddr = srcLV.getAddress(); - assert(!isProvablyNull(srcAddr.getPointerIfNotSigned()) && + assert(!isProvablyNull(srcAddr.getBasePointer()) && "shouldn't have writeback for provably null argument"); llvm::BasicBlock *contBB = nullptr; @@ -4261,7 +4258,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, CGF.ConvertTypeForMem(CRE->getType()->getPointeeType()); // If the address is a constant null, just pass the appropriate null. - if (isProvablyNull(srcAddr.getPointerIfNotSigned())) { + if (isProvablyNull(srcAddr.getBasePointer())) { args.add(RValue::get(llvm::ConstantPointerNull::get(destType)), CRE->getType()); return; @@ -5101,7 +5098,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::Value *UnusedReturnSizePtr = nullptr; if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) { if (!ReturnValue.isNull()) { - SRetPtr = ReturnValue.getValue(); + SRetPtr = ReturnValue.getAddress(); } else { SRetPtr = CreateMemTemp(RetTy, "tmp", &SRetAlloca); if (HaveInsertPoint() && ReturnValue.isUnused()) { diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 2de85963437f5..bb2ed237ee9f3 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -1835,8 +1835,8 @@ Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, llvm::Value *ParentFP) { llvm::CallInst *RecoverCall = nullptr; CGBuilderTy Builder(*this, AllocaInsertPt); - if (auto *ParentAlloca = dyn_cast_or_null( - ParentVar.getPointerIfNotSigned())) { + if (auto *ParentAlloca = + dyn_cast_or_null(ParentVar.getBasePointer())) { // Mark the variable escaped if nobody else referenced it and compute the // localescape index. auto InsertPair = ParentCGF.EscapedLocals.insert( diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index c3bf7d960410a..7ae5f0b1cf760 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1786,11 +1786,8 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) { } // Emit as a constant. - // Try to emit as a constant. - llvm::Constant *C = - ConstantEmitter(*this).tryEmitAbstract(result.Val, resultType); - if (!C) - return ConstantEmission(); + auto C = ConstantEmitter(*this).emitAbstract(refExpr->getLocation(), + result.Val, resultType); // Make sure we emit a debug reference to the global variable. // This should probably fire even for @@ -1945,9 +1942,6 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile, Addr = Addr.withPointer(Builder.CreateThreadLocalAddress(GV), NotKnownNonNull); - if (!CGM.getCodeGenOpts().NullPointerIsValid) - Addr = Addr.setKnownNonNull(); - if (const auto *ClangVecTy = Ty->getAs()) { // Boolean vectors use `iN` as storage type. if (ClangVecTy->isExtVectorBoolType()) { @@ -2097,9 +2091,6 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr, Addr = Addr.withPointer(Builder.CreateThreadLocalAddress(GV), NotKnownNonNull); - if (!CGM.getCodeGenOpts().NullPointerIsValid) - Addr = Addr.setKnownNonNull(); - llvm::Type *SrcTy = Value->getType(); if (const auto *ClangVecTy = Ty->getAs()) { auto *VecTy = dyn_cast(SrcTy); @@ -2801,9 +2792,9 @@ CodeGenFunction::EmitLoadOfReference(LValue RefLVal, llvm::LoadInst *Load = Builder.CreateLoad(RefLVal.getAddress(), RefLVal.isVolatile()); CGM.DecorateInstructionWithTBAA(Load, RefLVal.getTBAAInfo()); - return makeNaturalAddressForPointer( - Load, RefLVal.getType()->getPointeeType(), CharUnits(), - /*ForPointeeType=*/true, PointeeBaseInfo, PointeeTBAAInfo, KnownNonNull); + return makeNaturalAddressForPointer(Load, RefLVal.getType()->getPointeeType(), + CharUnits(), /*ForPointeeType=*/true, + PointeeBaseInfo, PointeeTBAAInfo); } LValue CodeGenFunction::EmitLoadOfReferenceLValue(LValue RefLVal) { @@ -4716,8 +4707,7 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field, } } else { QualType LambdaTagType = getContext().getTagDeclType(Field->getParent()); - LambdaLV = MakeNaturalAlignAddrLValue(ThisValue, LambdaTagType, - KnownNonNull); + LambdaLV = MakeNaturalAlignAddrLValue(ThisValue, LambdaTagType); } return EmitLValueForField(LambdaLV, Field); } diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 14fee2eee8250..c3c10e73ff05e 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -253,9 +253,6 @@ class AggExprEmitter : public StmtVisitor { void AggExprEmitter::EmitAggLoadOfLValue(const Expr *E) { LValue LV = CGF.EmitLValue(E); - if (!CGF.CGM.getCodeGenOpts().NullPointerIsValid) - LV = LV.setKnownNonNull(); - // If the type of the l-value is atomic, then do an atomic load. if (LV.getType()->isAtomicType() || CGF.LValueIsSuitableForInlineAtomic(LV)) { CGF.EmitAtomicLoad(LV, E->getExprLoc(), Dest); @@ -330,8 +327,8 @@ void AggExprEmitter::withReturnValueSlot( if (!UseTemp) return; - assert(Dest.getAddress().isSigned() || Dest.isIgnored() || - Dest.emitRawPointer(CGF) != Src.getAggregatePointer(E->getType(), CGF)); + assert(Dest.isIgnored() || Dest.emitRawPointer(CGF) != + Src.getAggregatePointer(E->getType(), CGF)); EmitFinalDestCopy(E->getType(), Src); if (!RequiresDestruction && LifetimeStartInst) { diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index db4a70f5316f8..8eb6ab7381acb 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -265,7 +265,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( if (auto *OCE = dyn_cast(CE)) { if (OCE->isAssignmentOp()) { if (TrivialAssignment) { - TrivialAssignmentRHS = EmitLValue(CE->getArg(1), KnownNonNull); + TrivialAssignmentRHS = EmitLValue(CE->getArg(1)); } else { RtlArgs = &RtlArgStorage; EmitCallArgs(*RtlArgs, MD->getType()->castAs(), @@ -279,12 +279,11 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( if (IsArrow) { LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; - Address ThisValue = EmitPointerWithAlignment( - Base, &BaseInfo, &TBAAInfo, KnownNonNull); + Address ThisValue = EmitPointerWithAlignment(Base, &BaseInfo, &TBAAInfo); This = MakeAddrLValue(ThisValue, Base->getType()->getPointeeType(), BaseInfo, TBAAInfo); } else { - This = EmitLValue(Base, KnownNonNull); + This = EmitLValue(Base); } if (const CXXConstructorDecl *Ctor = dyn_cast(MD)) { @@ -317,7 +316,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( // the RHS. LValue RHS = isa(CE) ? TrivialAssignmentRHS - : EmitLValue(*CE->arg_begin(), KnownNonNull); + : EmitLValue(*CE->arg_begin()); EmitAggregateAssign(This, RHS, CE->getType()); return RValue::get(This.getPointer(*this)); } diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 534f7c0407f61..00a5a7e6898a8 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -2074,24 +2074,14 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) { if (D->hasAttr()) return CGM.GetWeakRefReference(D).getPointer(); - auto PtrAuthSign = [&](llvm::Constant *C, bool IsFunction) { + auto PtrAuthSign = [&](llvm::Constant *C) { CGPointerAuthInfo AuthInfo; if (EnablePtrAuthFunctionTypeDiscrimination) AuthInfo = CGM.getFunctionPointerAuthInfo(DestType); - else { - // FIXME: getPointerAuthInfoForType should be able to return the pointer - // auth info of reference types. - if (auto *RT = DestType->getAs()) - DestType = CGM.getContext().getPointerType(RT->getPointeeType()); - // Don't emit a signed pointer if the destination is a function pointer - // type. - if (DestType->isSignableType() && !DestType->isFunctionPointerType()) - AuthInfo = CGM.getPointerAuthInfoForType(DestType); - } if (AuthInfo) { - if (IsFunction && hasNonZeroOffset()) + if (hasNonZeroOffset()) return ConstantLValue(nullptr); C = applyOffset(C); @@ -2105,7 +2095,7 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) { }; if (const auto *FD = dyn_cast(D)) - return PtrAuthSign(CGM.getRawFunctionPointer(FD), true); + return PtrAuthSign(CGM.getRawFunctionPointer(FD)); if (const auto *VD = dyn_cast(D)) { // We can never refer to a variable with local storage. diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 65acb3b067f91..14ca9341c5148 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2855,11 +2855,10 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, Builder.SetInsertPoint(opBB); atomicPHI = Builder.CreatePHI(value->getType(), 2); atomicPHI->addIncoming(value, startBB); - value = CGF.EmitPointerAuthAuth(type->getPointeeType(), atomicPHI); + value = atomicPHI; } else { value = EmitLoadOfLValue(LV, E->getExprLoc()); input = value; - value = CGF.EmitPointerAuthAuth(type->getPointeeType(), value); } // Special case of integer increment that we have to check first: bool++. @@ -3101,7 +3100,6 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, if (atomicPHI) { llvm::BasicBlock *curBlock = Builder.GetInsertBlock(); llvm::BasicBlock *contBB = CGF.createBasicBlock("atomic_cont", CGF.CurFn); - value = CGF.EmitPointerAuthSign(type->getPointeeType(), value); auto Pair = CGF.EmitAtomicCompareExchange( LV, RValue::get(atomicPHI), RValue::get(value), E->getExprLoc()); llvm::Value *old = CGF.EmitToMemory(Pair.first.getScalarVal(), type); @@ -3113,7 +3111,6 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, } // Store the updated result through the lvalue. - value = CGF.EmitPointerAuthSign(type->getPointeeType(), value); if (LV.isBitField()) { Value *Src = Previous ? Previous : value; CGF.EmitStoreThroughBitfieldLValue(RValue::get(value), LV, &value); @@ -3974,10 +3971,6 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, return CGF.Builder.CreateBitCast(result, pointer->getType()); } - CGPointerAuthInfo PtrAuthInfo = CGF.CGM.getPointerAuthInfoForType(op.Ty); - if (PtrAuthInfo) - pointer = CGF.EmitPointerAuthAuth(PtrAuthInfo, pointer); - QualType elementType = pointerType->getPointeeType(); if (const VariableArrayType *vla = CGF.getContext().getAsVariableArrayType(elementType)) { @@ -3998,8 +3991,7 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, elemTy, pointer, index, isSigned, isSubtraction, op.E->getExprLoc(), "add.ptr"); } - return PtrAuthInfo ? CGF.EmitPointerAuthSign(PtrAuthInfo, pointer) - : pointer; + return pointer; } // Explicitly handle GNU void* and function pointer arithmetic extensions. The @@ -4012,13 +4004,11 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, elemTy = CGF.ConvertTypeForMem(elementType); if (CGF.getLangOpts().isSignedOverflowDefined()) - pointer = CGF.Builder.CreateGEP(elemTy, pointer, index, "add.ptr"); - else - pointer = CGF.EmitCheckedInBoundsGEP(elemTy, pointer, index, isSigned, - isSubtraction, op.E->getExprLoc(), - "add.ptr"); + return CGF.Builder.CreateGEP(elemTy, pointer, index, "add.ptr"); - return PtrAuthInfo ? CGF.EmitPointerAuthSign(PtrAuthInfo, pointer) : pointer; + return CGF.EmitCheckedInBoundsGEP( + elemTy, pointer, index, isSigned, isSubtraction, op.E->getExprLoc(), + "add.ptr"); } // Construct an fmuladd intrinsic to represent a fused mul-add of MulOp and diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 7395370259fe9..30f3911a8b03c 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -4425,7 +4425,7 @@ void FragileHazards::emitHazardsInNewBlocks() { static void addIfPresent(llvm::DenseSet &S, Address V) { if (V.isValid()) - if (llvm::Value *Ptr = V.getPointerIfNotSigned()) + if (llvm::Value *Ptr = V.getBasePointer()) S.insert(Ptr); } diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp b/clang/lib/CodeGen/CGPointerAuth.cpp index c069b3fa72fba..3d44d697a29da 100644 --- a/clang/lib/CodeGen/CGPointerAuth.cpp +++ b/clang/lib/CodeGen/CGPointerAuth.cpp @@ -90,7 +90,6 @@ CGPointerAuthInfo CodeGenModule::getFunctionPointerAuthInfo(QualType T) { Discriminator); } - llvm::Value * CodeGenFunction::EmitPointerAuthBlendDiscriminator(llvm::Value *StorageAddress, llvm::Value *Discriminator) { @@ -167,48 +166,6 @@ CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForType(QualType T) { return ::getPointerAuthInfoForType(*this, T); } -Address CodeGenFunction::mergeAddressesInConditionalExpr( - Address LHS, Address RHS, llvm::BasicBlock *LHSBlock, - llvm::BasicBlock *RHSBlock, llvm::BasicBlock *MergeBlock, - QualType MergedType) { - CGPointerAuthInfo LHSInfo = LHS.getPointerAuthInfo(); - CGPointerAuthInfo RHSInfo = RHS.getPointerAuthInfo(); - - if (LHSInfo || RHSInfo) { - if (LHSInfo != RHSInfo || LHS.getOffset() != RHS.getOffset() || - LHS.getBasePointer()->getType() != RHS.getBasePointer()->getType()) { - // If the LHS and RHS have different signing information, offsets, or base - // pointer types, resign both sides and clear out the offsets. - CGPointerAuthInfo NewInfo = - CGM.getPointerAuthInfoForPointeeType(MergedType); - LHSBlock->getTerminator()->eraseFromParent(); - Builder.SetInsertPoint(LHSBlock); - LHS = LHS.getResignedAddress(NewInfo, *this); - Builder.CreateBr(MergeBlock); - LHSBlock = Builder.GetInsertBlock(); - RHSBlock->getTerminator()->eraseFromParent(); - Builder.SetInsertPoint(RHSBlock); - RHS = RHS.getResignedAddress(NewInfo, *this); - Builder.CreateBr(MergeBlock); - RHSBlock = Builder.GetInsertBlock(); - } - - assert(LHS.getPointerAuthInfo() == RHS.getPointerAuthInfo() && - LHS.getOffset() == RHS.getOffset() && - LHS.getBasePointer()->getType() == RHS.getBasePointer()->getType() && - "lhs and rhs must have the same signing information, offsets, and " - "base pointer types"); - } - - Builder.SetInsertPoint(MergeBlock); - llvm::PHINode *PtrPhi = Builder.CreatePHI(LHS.getType(), 2, "cond"); - PtrPhi->addIncoming(LHS.getBasePointer(), LHSBlock); - PtrPhi->addIncoming(RHS.getBasePointer(), RHSBlock); - LHS.replaceBasePointer(PtrPhi); - LHS.setAlignment(std::min(LHS.getAlignment(), RHS.getAlignment())); - return LHS; -} - static bool isZeroConstant(llvm::Value *value) { if (auto ci = dyn_cast(value)) return ci->isZero(); @@ -337,16 +294,6 @@ llvm::Constant *CodeGenModule::getConstantSignedPointer( OtherDiscriminator); } -llvm::Constant *CodeGenModule::getConstantSignedPointer(llvm::Constant *Pointer, - QualType PointeeType) { - CGPointerAuthInfo Info = getPointerAuthInfoForPointeeType(PointeeType); - if (!Info.shouldSign()) - return Pointer; - return getConstantSignedPointer( - Pointer, Info.getKey(), nullptr, - cast(Info.getDiscriminator())); -} - /// If applicable, sign a given constant function pointer with the ABI rules for /// functionType. llvm::Constant *CodeGenModule::getFunctionPointer(llvm::Constant *Pointer, @@ -574,7 +521,7 @@ Address Address::getResignedAddress(const CGPointerAuthInfo &NewInfo, // Nothing to do if neither the current or the new ptrauth info needs signing. if (!CurInfo.isSigned() && !NewInfo.isSigned()) - return Address(getUnsignedPointer(), getElementType(), getAlignment(), + return Address(getBasePointer(), getElementType(), getAlignment(), isKnownNonNull()); assert(ElementType && "Effective type has to be set"); @@ -584,26 +531,9 @@ Address Address::getResignedAddress(const CGPointerAuthInfo &NewInfo, if (CurInfo == NewInfo && !hasOffset()) Val = getBasePointer(); else { - if (Offset) { - assert(isSigned() && "signed pointer expected"); - // Authenticate the base pointer. - Val = CGF.EmitPointerAuthResign(getBasePointer(), QualType(), CurInfo, - CGPointerAuthInfo(), isKnownNonNull()); - - // Add offset to the authenticated pointer. - unsigned AS = cast(getBasePointer()->getType()) - ->getAddressSpace(); - Val = CGF.Builder.CreateBitCast(Val, - llvm::PointerType::get(CGF.Int8Ty, AS)); - Val = CGF.Builder.CreateGEP(CGF.Int8Ty, Val, Offset, "resignedgep"); - - // Sign the pointer using the new ptrauth info. - Val = CGF.EmitPointerAuthResign(Val, QualType(), CGPointerAuthInfo(), - NewInfo, isKnownNonNull()); - } else { - Val = CGF.EmitPointerAuthResign(getBasePointer(), QualType(), CurInfo, - NewInfo, isKnownNonNull()); - } + assert(!Offset && "unexpected non-null offset"); + Val = CGF.EmitPointerAuthResign(getBasePointer(), QualType(), CurInfo, + NewInfo, isKnownNonNull()); } Val = CGF.Builder.CreateBitCast(Val, getType()); @@ -611,39 +541,6 @@ Address Address::getResignedAddress(const CGPointerAuthInfo &NewInfo, isKnownNonNull()); } -void Address::addOffset(CharUnits V, llvm::Type *Ty, CGBuilderTy &Builder) { - assert(isSigned() && - "shouldn't add an offset if the base pointer isn't signed"); - Alignment = Alignment.alignmentAtOffset(V); - llvm::Value *FixedOffset = - llvm::ConstantInt::get(Builder.getCGF()->IntPtrTy, V.getQuantity()); - addOffset(FixedOffset, Ty, Builder, Alignment); -} - -void Address::addOffset(llvm::Value *V, llvm::Type *Ty, CGBuilderTy &Builder, - CharUnits NewAlignment) { - assert(isSigned() && - "shouldn't add an offset if the base pointer isn't signed"); - ElementType = Ty; - Alignment = NewAlignment; - - if (!Offset) { - Offset = V; - return; - } - - Offset = Builder.CreateAdd(Offset, V, "add"); -} - -llvm::Value *Address::emitRawPointerSlow(CodeGenFunction &CGF) const { - return CGF.getAsNaturalPointerTo(*this, QualType()); -} - -llvm::Value *RValue::getAggregatePointer(QualType PointeeType, - CodeGenFunction &CGF) const { - return CGF.getAsNaturalPointerTo(getAggregateAddress(), PointeeType); -} - llvm::Value *LValue::getPointer(CodeGenFunction &CGF) const { assert(isSimple()); return emitResignedPointer(getType(), CGF); @@ -659,13 +556,3 @@ llvm::Value *LValue::emitRawPointer(CodeGenFunction &CGF) const { assert(isSimple()); return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; } - -llvm::Value *AggValueSlot::getPointer(QualType PointeeTy, - CodeGenFunction &CGF) const { - Address SignedAddr = CGF.getAsNaturalAddressOf(Addr, PointeeTy); - return SignedAddr.getBasePointer(); -} - -llvm::Value *AggValueSlot::emitRawPointer(CodeGenFunction &CGF) const { - return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; -} diff --git a/clang/lib/CodeGen/CGValue.h b/clang/lib/CodeGen/CGValue.h index 27efcf6ac199b..c4ec8d207d2e3 100644 --- a/clang/lib/CodeGen/CGValue.h +++ b/clang/lib/CodeGen/CGValue.h @@ -79,8 +79,6 @@ class RValue { return std::make_pair(Vals.first, Vals.second); } - bool isSignedAggregate() const { return AggregateAddr.isSigned(); } - /// getAggregateAddr() - Return the Value* of the address of the aggregate. Address getAggregateAddress() const { assert(isAggregate() && "Not an aggregate!"); @@ -88,7 +86,9 @@ class RValue { } llvm::Value *getAggregatePointer(QualType PointeeType, - CodeGenFunction &CGF) const; + CodeGenFunction &CGF) const { + return getAggregateAddress().getBasePointer(); + } static RValue getIgnored() { // FIXME: should we make this a more explicit state? @@ -318,8 +318,6 @@ class LValue { bool isNontemporal() const { return Nontemporal; } void setNontemporal(bool Value) { Nontemporal = Value; } - bool isPointerSigned() const { return Addr.isSigned(); } - bool isObjCWeak() const { return Quals.getObjCGCAttr() == Qualifiers::Weak; } @@ -639,7 +637,9 @@ class AggValueSlot { llvm::Value *getPointer(QualType PointeeTy, CodeGenFunction &CGF) const; - llvm::Value *emitRawPointer(CodeGenFunction &CGF) const; + llvm::Value *emitRawPointer(CodeGenFunction &CGF) const { + return Addr.isValid() ? Addr.emitRawPointer(CGF) : nullptr; + } Address getAddress() const { return Addr; diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 9e29cddc6f858..fab3091f0581c 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -18,7 +18,6 @@ #include "CGDebugInfo.h" #include "CGHLSLRuntime.h" #include "CGOpenMPRuntime.h" -#include "CGRecordLayout.h" #include "CodeGenModule.h" #include "CodeGenPGO.h" #include "TargetInfo.h" @@ -559,11 +558,8 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) { ReturnBlock.getBlock()->eraseFromParent(); } if (ReturnValue.isValid()) { - // This only matters when ReturnValue isn't signed. ReturnValue is possibly - // signed only when the return is Indirect or InAlloca. In that case, a - // temporary alloca to store the return value isn't created. auto *RetAlloca = - dyn_cast_or_null(ReturnValue.getPointerIfNotSigned()); + dyn_cast(ReturnValue.emitRawPointer(*this)); if (RetAlloca && RetAlloca->use_empty()) { RetAlloca->eraseFromParent(); ReturnValue = Address::invalid(); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 2ce28f3e4681f..4a85153cd7830 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -185,11 +185,6 @@ template <> struct DominatingValue
{ DominatingLLVMValue::saved_type BasePtr; llvm::Type *ElementType; CharUnits Alignment; - unsigned PtrAuthKey : 28; - PointerAuthenticationMode PtrAuthMode : 2; - bool IsIsaPointer : 1; - bool AuthenticatesNullValues : 1; - DominatingLLVMValue::saved_type PtrAuthDiscriminator; DominatingLLVMValue::saved_type Offset; llvm::PointerType *EffectiveType; }; @@ -198,36 +193,16 @@ template <> struct DominatingValue
{ if (DominatingLLVMValue::needsSaving(value.getBasePointer()) || DominatingLLVMValue::needsSaving(value.getOffset())) return true; - CGPointerAuthInfo info = value.getPointerAuthInfo(); - if (info.isSigned() && - DominatingLLVMValue::needsSaving(info.getDiscriminator())) - return true; return false; } static saved_type save(CodeGenFunction &CGF, type value) { - bool isSigned = value.getPointerAuthInfo().isSigned(); return {DominatingLLVMValue::save(CGF, value.getBasePointer()), - value.getElementType(), - value.getAlignment(), - isSigned ? value.getPointerAuthInfo().getKey() : 0, - value.getPointerAuthInfo().getAuthenticationMode(), - value.getPointerAuthInfo().isIsaPointer(), - value.getPointerAuthInfo().authenticatesNullValues(), - isSigned ? DominatingLLVMValue::save( - CGF, value.getPointerAuthInfo().getDiscriminator()) - : DominatingLLVMValue::saved_type(), - DominatingLLVMValue::save(CGF, value.getOffset()), - value.getType()}; + value.getElementType(), value.getAlignment(), + DominatingLLVMValue::save(CGF, value.getOffset()), value.getType()}; } static type restore(CodeGenFunction &CGF, saved_type value) { - CGPointerAuthInfo info; - if (value.PtrAuthMode != PointerAuthenticationMode::None) - info = CGPointerAuthInfo{ - value.PtrAuthKey, value.PtrAuthMode, value.IsIsaPointer, - value.AuthenticatesNullValues, - DominatingLLVMValue::restore(CGF, value.PtrAuthDiscriminator)}; return Address(DominatingLLVMValue::restore(CGF, value.BasePtr), - value.ElementType, value.Alignment, info, + value.ElementType, value.Alignment, CGPointerAuthInfo(), DominatingLLVMValue::restore(CGF, value.Offset)); } }; @@ -2690,7 +2665,15 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::BasicBlock *LHSBlock, llvm::BasicBlock *RHSBlock, llvm::BasicBlock *MergeBlock, - QualType MergedType); + QualType MergedType) { + Builder.SetInsertPoint(MergeBlock); + llvm::PHINode *PtrPhi = Builder.CreatePHI(LHS.getType(), 2, "cond"); + PtrPhi->addIncoming(LHS.getBasePointer(), LHSBlock); + PtrPhi->addIncoming(RHS.getBasePointer(), RHSBlock); + LHS.replaceBasePointer(PtrPhi); + LHS.setAlignment(std::min(LHS.getAlignment(), RHS.getAlignment())); + return LHS; + } /// Construct an address with the natural alignment of T. If a pointer to T /// is expected to be signed, the pointer passed to this function must have diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 7c6078df0af82..caa3786c033b5 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -986,9 +986,6 @@ class CodeGenModule : public CodeGenTypeCache { GlobalDecl SchemaDecl, QualType SchemaType); - llvm::Constant *getConstantSignedPointer(llvm::Constant *Pointer, - QualType PointeeType); - llvm::Constant * getConstantSignedPointer(llvm::Constant *Pointer, unsigned Key, llvm::Constant *StorageAddress, diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 1609ae19696c7..6e5fa0faf73d7 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -4711,7 +4711,7 @@ static void InitCatchParam(CodeGenFunction &CGF, // Cast that to the appropriate type. Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy), - LLVMCatchTy, caughtExnAlignment, KnownNonNull); + LLVMCatchTy, caughtExnAlignment); // The copy expression is defined in terms of an OpaqueValueExpr. // Find it and map it to the adjusted expression. diff --git a/clang/test/Preprocessor/ptrauth_feature.c b/clang/test/Preprocessor/ptrauth_feature.c index c19ac21d42139..88b6982c01657 100644 --- a/clang/test/Preprocessor/ptrauth_feature.c +++ b/clang/test/Preprocessor/ptrauth_feature.c @@ -65,16 +65,6 @@ // RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,NOINITFINI,FUNC -// RUN: %clang_cc1 -E %s -triple=aarch64 \ -// RUN: -fptrauth-intrinsics \ -// RUN: -fptrauth-calls \ -// RUN: -fptrauth-returns \ -// RUN: -fptrauth-vtable-pointer-address-discrimination \ -// RUN: -fptrauth-vtable-pointer-type-discrimination \ -// RUN: -fptrauth-function-pointer-type-discrimination | \ -// RUN: FileCheck %s --check-prefixes=INTRIN,CALLS,RETS,VPTR_ADDR_DISCR,VPTR_TYPE_DISCR,NOINITFINI,FUNC - - #if __has_feature(ptrauth_intrinsics) // INTRIN: has_ptrauth_intrinsics void has_ptrauth_intrinsics() {} diff --git a/clang/test/Sema/ptrauth-function-type-discriminatior.c b/clang/test/Sema/ptrauth-function-type-discriminatior.c deleted file mode 100644 index 0dacdf35f2038..0000000000000 --- a/clang/test/Sema/ptrauth-function-type-discriminatior.c +++ /dev/null @@ -1,65 +0,0 @@ -// RUN: %clang_cc1 %s -triple arm64e-apple-ios13 -verify -xobjective-c -fblocks -// RUN: %clang_cc1 %s -triple arm64e-apple-ios13 -verify -xc -// RUN: %clang_cc1 %s -triple arm64e-apple-ios13 -verify -xc++ - -// expected-no-diagnostics - -#define discm(x) __builtin_ptrauth_type_discriminator(x) - -struct Complete {}; -struct Incomplete; - -#ifndef __cplusplus -enum EIncomplete; -#endif - -enum EComplete { enumerator }; - -_Static_assert(discm(void(void)) == 18983, ""); -_Static_assert(discm(void()) == discm(void(void)), ""); -_Static_assert(discm(void(int *)) == discm(void(float *)), ""); -_Static_assert(discm(void(int *)) == discm(void(struct Incomplete *)), ""); -_Static_assert(discm(void(struct Complete *)) == discm(void(struct Incomplete *)), ""); -_Static_assert(discm(void(int *)) != discm(void(int)), ""); -_Static_assert(discm(void(int)) != discm(void(int, ...)), ""); -_Static_assert(discm(_Atomic(int *)()) == discm(int *()), ""); -#ifndef __cplusplus -_Static_assert(discm(enum EIncomplete()) == discm(int()), ""); -#endif -_Static_assert(discm(enum EComplete()) == discm(int()), ""); -_Static_assert(discm(unsigned long()) == discm(int()), ""); -_Static_assert(discm(char()) == discm(int()), ""); -_Static_assert(discm(int(int (*)[10])) == discm(int(int (*)[9])), ""); -_Static_assert(discm(void (int[10])) == discm(void (int *)), ""); -_Static_assert(discm(void (int[*])) == discm(void (int *)), ""); -_Static_assert(discm(void (void ())) == discm(void (void (*))), ""); - -#ifndef __cplusplus -typedef struct {} foo; -struct foo {}; -_Static_assert(discm(void(foo)) == discm(void(struct foo)), ""); -#endif - -#ifdef __OBJC__ -@interface I @end -_Static_assert(discm(id()) == discm(I*()), ""); -_Static_assert(discm(id()) == discm(void*()), ""); -_Static_assert(discm(id()) == discm(Class()), ""); -_Static_assert(discm(void(^())()) == discm(id()), ""); -#endif - -#ifdef __cplusplus -_Static_assert(discm(void(Complete &)) != discm(void(Complete *)), ""); -_Static_assert(discm(void(Complete &)) != discm(void(Complete &&)), ""); -_Static_assert(discm(void(Incomplete &)) != discm(void(Incomplete &&)), ""); -/* Descend into array and function types when using references. */ -_Static_assert(discm(void(void (&)())) != discm(void (void (&)(int))), ""); -_Static_assert(discm(void(void (&)())) != discm(void (int (&)())), ""); -_Static_assert(discm(void(int (&)[10])) == discm(void(int (&)[9])), ""); -_Static_assert(discm(void(int (&)[10])) == discm(void(int (&)[])), ""); -_Static_assert(discm(void(int (&)[10])) != discm(void(float (&)[10])), ""); -#endif - -typedef __attribute__((ext_vector_type(4))) float vec4; -typedef __attribute__((ext_vector_type(16))) char char_vec16; -_Static_assert(discm(void (vec4)) == discm(void (char_vec16)), ""); From 868ec8a6be62f8692d74454b451cf4776342f83e Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Tue, 16 Jul 2024 15:32:36 -0700 Subject: [PATCH 5/7] Address review comments --- clang/lib/CodeGen/Address.h | 4 +- clang/lib/CodeGen/CGBuilder.h | 2 +- clang/lib/CodeGen/CGExpr.cpp | 2 +- clang/lib/CodeGen/CGExprScalar.cpp | 6 +- clang/lib/CodeGen/CGPointerAuth.cpp | 181 ++++++++++-------- clang/lib/CodeGen/CodeGenFunction.cpp | 73 +------ clang/lib/CodeGen/CodeGenFunction.h | 15 +- .../ptrauth-function-lvalue-cast-disc.c | 9 +- 8 files changed, 134 insertions(+), 158 deletions(-) diff --git a/clang/lib/CodeGen/Address.h b/clang/lib/CodeGen/Address.h index d753250d428d3..1c4d2e103b5e7 100644 --- a/clang/lib/CodeGen/Address.h +++ b/clang/lib/CodeGen/Address.h @@ -227,6 +227,7 @@ class Address { bool isSigned() const { return PtrAuthInfo.isSigned(); } + /// Whether the pointer is known not to be null. KnownNonNull_t isKnownNonNull() const { assert(isValid()); return (KnownNonNull_t)Pointer.getInt(); @@ -271,7 +272,8 @@ class Address { Address withElementType(llvm::Type *ElemTy) const { if (!hasOffset()) return Address(getBasePointer(), ElemTy, getAlignment(), - getPointerAuthInfo(), nullptr, isKnownNonNull()); + getPointerAuthInfo(), /*Offset=*/nullptr, + isKnownNonNull()); Address A(*this); A.ElementType = ElemTy; return A; diff --git a/clang/lib/CodeGen/CGBuilder.h b/clang/lib/CodeGen/CGBuilder.h index 6625c662e041f..5d59d5a4ae2c1 100644 --- a/clang/lib/CodeGen/CGBuilder.h +++ b/clang/lib/CodeGen/CGBuilder.h @@ -191,7 +191,7 @@ class CGBuilderTy : public CGBuilderBaseTy { if (!Addr.hasOffset()) return Address(CreateAddrSpaceCast(Addr.getBasePointer(), Ty, Name), ElementTy, Addr.getAlignment(), Addr.getPointerAuthInfo(), - nullptr, Addr.isKnownNonNull()); + /*Offset=*/nullptr, Addr.isKnownNonNull()); // Eagerly force a raw address if these is an offset. return RawAddress( CreateAddrSpaceCast(Addr.emitRawPointer(*getCGF()), Ty, Name), diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 7ae5f0b1cf760..ddc23d8419ce7 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1311,7 +1311,7 @@ static Address EmitPointerWithAlignment(const Expr *E, LValueBaseInfo *BaseInfo, if (CE->getCastKind() == CK_AddressSpaceConversion) Addr = CGF.Builder.CreateAddrSpaceCast( Addr, CGF.ConvertType(E->getType()), ElemTy); - return CGF.AuthPointerToPointerCast(Addr, CE->getSubExpr()->getType(), + return CGF.authPointerToPointerCast(Addr, CE->getSubExpr()->getType(), CE->getType()); } break; diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 14ca9341c5148..158104f365c20 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2375,7 +2375,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { } llvm::Value *Result = Builder.CreateBitCast(Src, DstTy); - return CGF.AuthPointerToPointerCast(Result, E->getType(), DestTy); + return CGF.authPointerToPointerCast(Result, E->getType(), DestTy); } case CK_AddressSpaceConversion: { Expr::EvalResult Result; @@ -2526,7 +2526,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { IntToPtr = Builder.CreateLaunderInvariantGroup(IntToPtr); } - IntToPtr = CGF.AuthPointerToPointerCast(IntToPtr, E->getType(), DestTy); + IntToPtr = CGF.authPointerToPointerCast(IntToPtr, E->getType(), DestTy); return IntToPtr; } case CK_PointerToIntegral: { @@ -2542,7 +2542,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { PtrExpr = Builder.CreateStripInvariantGroup(PtrExpr); } - PtrExpr = CGF.AuthPointerToPointerCast(PtrExpr, E->getType(), DestTy); + PtrExpr = CGF.authPointerToPointerCast(PtrExpr, E->getType(), DestTy); return Builder.CreatePtrToInt(PtrExpr, ConvertType(DestTy)); } case CK_ToVoid: { diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp b/clang/lib/CodeGen/CGPointerAuth.cpp index 3d44d697a29da..1d668c4cce8b3 100644 --- a/clang/lib/CodeGen/CGPointerAuth.cpp +++ b/clang/lib/CodeGen/CGPointerAuth.cpp @@ -166,86 +166,126 @@ CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForType(QualType T) { return ::getPointerAuthInfoForType(*this, T); } -static bool isZeroConstant(llvm::Value *value) { - if (auto ci = dyn_cast(value)) - return ci->isZero(); +static bool isZeroConstant(const llvm::Value *Value) { + if (const auto *CI = dyn_cast(Value)) + return CI->isZero(); return false; } -static bool equalAuthPolicies(const CGPointerAuthInfo &left, - const CGPointerAuthInfo &right) { - if (left.isSigned() != right.isSigned()) +static bool equalAuthPolicies(const CGPointerAuthInfo &Left, + const CGPointerAuthInfo &Right) { + assert((Left.isSigned() || Right.isSigned()) && + "shouldn't be called if neither is signed"); + if (Left.isSigned() != Right.isSigned()) return false; - assert(left.isSigned() && right.isSigned() && - "should only be called with non-null auth policies"); - return left.getKey() == right.getKey() && - left.getAuthenticationMode() == right.getAuthenticationMode(); + return Left.getKey() == Right.getKey() && + Left.getAuthenticationMode() == Right.getAuthenticationMode(); } -llvm::Value *CodeGenFunction::EmitPointerAuthResign( - llvm::Value *value, QualType type, const CGPointerAuthInfo &curAuthInfo, - const CGPointerAuthInfo &newAuthInfo, bool isKnownNonNull) { +// Return the discriminator or return zero if the discriminator is null. +static llvm::Value *getDiscriminatorOrZero(const CGPointerAuthInfo &Info, + CGBuilderTy &Builder) { + llvm::Value *Discriminator = Info.getDiscriminator(); + return Discriminator ? Discriminator : Builder.getSize(0); +} + +llvm::Value * +CodeGenFunction::emitPointerAuthResignCall(llvm::Value *Value, + const CGPointerAuthInfo &CurAuth, + const CGPointerAuthInfo &NewAuth) { + assert(CurAuth && NewAuth); + + if (CurAuth.getAuthenticationMode() != + PointerAuthenticationMode::SignAndAuth || + NewAuth.getAuthenticationMode() != + PointerAuthenticationMode::SignAndAuth) { + llvm::Value *AuthedValue = EmitPointerAuthAuth(CurAuth, Value); + return EmitPointerAuthSign(NewAuth, AuthedValue); + } + // Convert the pointer to intptr_t before signing it. + auto *OrigType = Value->getType(); + Value = Builder.CreatePtrToInt(Value, IntPtrTy); + + auto *CurKey = Builder.getInt32(CurAuth.getKey()); + auto *NewKey = Builder.getInt32(NewAuth.getKey()); + + llvm::Value *CurDiscriminator = getDiscriminatorOrZero(CurAuth, Builder); + llvm::Value *NewDiscriminator = getDiscriminatorOrZero(NewAuth, Builder); + + // call i64 @llvm.ptrauth.resign(i64 %pointer, + // i32 %curKey, i64 %curDiscriminator, + // i32 %newKey, i64 %newDiscriminator) + auto *Intrinsic = CGM.getIntrinsic(llvm::Intrinsic::ptrauth_resign); + Value = EmitRuntimeCall( + Intrinsic, {Value, CurKey, CurDiscriminator, NewKey, NewDiscriminator}); + + // Convert back to the original type. + Value = Builder.CreateIntToPtr(Value, OrigType); + return Value; +} + +llvm::Value *CodeGenFunction::emitPointerAuthResign( + llvm::Value *Value, QualType Type, const CGPointerAuthInfo &CurAuthInfo, + const CGPointerAuthInfo &NewAuthInfo, bool IsKnownNonNull) { // Fast path: if neither schema wants a signature, we're done. - if (!curAuthInfo && !newAuthInfo) - return value; + if (!CurAuthInfo && !NewAuthInfo) + return Value; - llvm::Value *null = nullptr; - // If the value is obviously null, we're done. - if (auto pointerValue = dyn_cast(value->getType())) { - null = CGM.getNullPointer(pointerValue, type); + llvm::Value *Null = nullptr; + // If the Value is obviously null, we're done. + if (auto *PointerValue = dyn_cast(Value->getType())) { + Null = CGM.getNullPointer(PointerValue, Type); } else { - assert(value->getType()->isIntegerTy()); - null = llvm::ConstantInt::get(IntPtrTy, 0); - } - if (value == null) { - return value; + assert(Value->getType()->isIntegerTy()); + Null = llvm::ConstantInt::get(IntPtrTy, 0); } + if (Value == Null) + return Value; // If both schemas sign the same way, we're done. - if (equalAuthPolicies(curAuthInfo, newAuthInfo)) { - auto curD = curAuthInfo.getDiscriminator(); - auto newD = newAuthInfo.getDiscriminator(); - if (curD == newD) - return value; - - if ((curD == nullptr && isZeroConstant(newD)) || - (newD == nullptr && isZeroConstant(curD))) - return value; + if (equalAuthPolicies(CurAuthInfo, NewAuthInfo)) { + const llvm::Value *CurD = CurAuthInfo.getDiscriminator(); + const llvm::Value *NewD = NewAuthInfo.getDiscriminator(); + if (CurD == NewD) + return Value; + + if ((CurD == nullptr && isZeroConstant(NewD)) || + (NewD == nullptr && isZeroConstant(CurD))) + return Value; } - llvm::BasicBlock *initBB = Builder.GetInsertBlock(); - llvm::BasicBlock *resignBB = nullptr, *contBB = nullptr; + llvm::BasicBlock *InitBB = Builder.GetInsertBlock(); + llvm::BasicBlock *ResignBB = nullptr, *ContBB = nullptr; // Null pointers have to be mapped to null, and the ptrauth_resign // intrinsic doesn't do that. - if (!isKnownNonNull && !llvm::isKnownNonZero(value, CGM.getDataLayout())) { - contBB = createBasicBlock("resign.cont"); - resignBB = createBasicBlock("resign.nonnull"); + if (!IsKnownNonNull && !llvm::isKnownNonZero(Value, CGM.getDataLayout())) { + ContBB = createBasicBlock("resign.cont"); + ResignBB = createBasicBlock("resign.nonnull"); - auto isNonNull = Builder.CreateICmpNE(value, null); - Builder.CreateCondBr(isNonNull, resignBB, contBB); - EmitBlock(resignBB); + auto *IsNonNull = Builder.CreateICmpNE(Value, Null); + Builder.CreateCondBr(IsNonNull, ResignBB, ContBB); + EmitBlock(ResignBB); } // Perform the auth/sign/resign operation. - if (!newAuthInfo) { - value = EmitPointerAuthAuth(curAuthInfo, value); - } else if (!curAuthInfo) { - value = EmitPointerAuthSign(newAuthInfo, value); - } else { - value = EmitPointerAuthResignCall(value, curAuthInfo, newAuthInfo); - } + if (!NewAuthInfo) + Value = EmitPointerAuthAuth(CurAuthInfo, Value); + else if (!CurAuthInfo) + Value = EmitPointerAuthSign(NewAuthInfo, Value); + else + Value = emitPointerAuthResignCall(Value, CurAuthInfo, NewAuthInfo); // Clean up with a phi if we branched before. - if (contBB) { - EmitBlock(contBB); - auto phi = Builder.CreatePHI(value->getType(), 2); - phi->addIncoming(null, initBB); - phi->addIncoming(value, resignBB); - value = phi; + if (ContBB) { + EmitBlock(ContBB); + auto *Phi = Builder.CreatePHI(Value->getType(), 2); + Phi->addIncoming(Null, InitBB); + Phi->addIncoming(Value, ResignBB); + Value = Phi; } - return value; + return Value; } llvm::Constant * @@ -435,7 +475,7 @@ CodeGenModule::getVTablePointerAuthInfo(CodeGenFunction *CGF, /* AuthenticatesNullValues */ false, Discriminator); } -llvm::Value *CodeGenFunction::AuthPointerToPointerCast(llvm::Value *ResultPtr, +llvm::Value *CodeGenFunction::authPointerToPointerCast(llvm::Value *ResultPtr, QualType SourceType, QualType DestType) { CGPointerAuthInfo CurAuthInfo, NewAuthInfo; @@ -456,11 +496,11 @@ llvm::Value *CodeGenFunction::AuthPointerToPointerCast(llvm::Value *ResultPtr, if (!NewAuthInfo && SourceType->isFunctionPointerType()) NewAuthInfo = CGM.getFunctionPointerAuthInfo(DestType); - return EmitPointerAuthResign(ResultPtr, DestType, CurAuthInfo, NewAuthInfo, + return emitPointerAuthResign(ResultPtr, DestType, CurAuthInfo, NewAuthInfo, /*IsKnownNonNull=*/false); } -Address CodeGenFunction::AuthPointerToPointerCast(Address Ptr, +Address CodeGenFunction::authPointerToPointerCast(Address Ptr, QualType SourceType, QualType DestType) { CGPointerAuthInfo CurAuthInfo, NewAuthInfo; @@ -491,20 +531,6 @@ Address CodeGenFunction::AuthPointerToPointerCast(Address Ptr, return Ptr; } -Address CodeGenFunction::EmitPointerAuthSign(Address Addr, - QualType PointeeType) { - CGPointerAuthInfo Info = getPointerAuthInfoForPointeeType(CGM, PointeeType); - llvm::Value *Ptr = EmitPointerAuthSign(Info, Addr.emitRawPointer(*this)); - return Address(Ptr, Addr.getElementType(), Addr.getAlignment()); -} - -Address CodeGenFunction::EmitPointerAuthAuth(Address Addr, - QualType PointeeType) { - CGPointerAuthInfo Info = getPointerAuthInfoForPointeeType(CGM, PointeeType); - llvm::Value *Ptr = EmitPointerAuthAuth(Info, Addr.emitRawPointer(*this)); - return Address(Ptr, Addr.getElementType(), Addr.getAlignment()); -} - Address CodeGenFunction::getAsNaturalAddressOf(Address Addr, QualType PointeeTy) { CGPointerAuthInfo Info = @@ -525,20 +551,19 @@ Address Address::getResignedAddress(const CGPointerAuthInfo &NewInfo, isKnownNonNull()); assert(ElementType && "Effective type has to be set"); + assert(!Offset && "unexpected non-null offset"); // If the current and the new ptrauth infos are the same and the offset is // null, just cast the base pointer to the effective type. if (CurInfo == NewInfo && !hasOffset()) Val = getBasePointer(); - else { - assert(!Offset && "unexpected non-null offset"); - Val = CGF.EmitPointerAuthResign(getBasePointer(), QualType(), CurInfo, + else + Val = CGF.emitPointerAuthResign(getBasePointer(), QualType(), CurInfo, NewInfo, isKnownNonNull()); - } Val = CGF.Builder.CreateBitCast(Val, getType()); - return Address(Val, getElementType(), getAlignment(), NewInfo, nullptr, - isKnownNonNull()); + return Address(Val, getElementType(), getAlignment(), NewInfo, + /*Offset=*/nullptr, isKnownNonNull()); } llvm::Value *LValue::getPointer(CodeGenFunction &CGF) const { diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index fab3091f0581c..cee5d138bd5de 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -196,7 +196,7 @@ CodeGenFunction::CGFPOptionsRAII::~CGFPOptionsRAII() { } static LValue -MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, bool ForPointeeType, +makeNaturalAlignAddrLValue(llvm::Value *V, QualType T, bool ForPointeeType, bool MightBeSigned, CodeGenFunction &CGF, KnownNonNull_t IsKnownNonNull = NotKnownNonNull) { LValueBaseInfo BaseInfo; @@ -214,26 +214,27 @@ MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, bool ForPointeeType, LValue CodeGenFunction::MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull) { - return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, - /*IsSigned*/ true, *this, IsKnownNonNull); + return ::makeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, + /*MightBeSigned*/ true, *this, + IsKnownNonNull); } LValue CodeGenFunction::MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T) { - return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, - /*IsSigned*/ true, *this); + return ::makeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, + /*MightBeSigned*/ true, *this); } LValue CodeGenFunction::MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T) { - return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, - /*IsSigned*/ false, *this); + return ::makeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ false, + /*MightBeSigned*/ false, *this); } LValue CodeGenFunction::MakeNaturalAlignPointeeRawAddrLValue(llvm::Value *V, QualType T) { - return ::MakeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, - /*IsSigned*/ false, *this); + return ::makeNaturalAlignAddrLValue(V, T, /*ForPointeeType*/ true, + /*MightBeSigned*/ false, *this); } llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) { @@ -3137,57 +3138,3 @@ CodeGenFunction::EmitPointerAuthAuth(const CGPointerAuthInfo &PointerAuth, return EmitPointerAuthCommon(*this, PointerAuth, Pointer, llvm::Intrinsic::ptrauth_auth); } - -llvm::Value *CodeGenFunction::EmitPointerAuthSign(QualType pointeeType, - llvm::Value *pointer) { - CGPointerAuthInfo pointerAuth = - CGM.getPointerAuthInfoForPointeeType(pointeeType); - return EmitPointerAuthSign(pointerAuth, pointer); -} - -llvm::Value *CodeGenFunction::EmitPointerAuthAuth(QualType pointeeType, - llvm::Value *pointer) { - CGPointerAuthInfo pointerAuth = - CGM.getPointerAuthInfoForPointeeType(pointeeType); - return EmitPointerAuthAuth(pointerAuth, pointer); -} - -llvm::Value * -CodeGenFunction::EmitPointerAuthResignCall(llvm::Value *value, - const CGPointerAuthInfo &curAuth, - const CGPointerAuthInfo &newAuth) { - assert(curAuth && newAuth); - - if (curAuth.getAuthenticationMode() != - PointerAuthenticationMode::SignAndAuth || - newAuth.getAuthenticationMode() != - PointerAuthenticationMode::SignAndAuth) { - auto authedValue = EmitPointerAuthAuth(curAuth, value); - return EmitPointerAuthSign(newAuth, authedValue); - } - // Convert the pointer to intptr_t before signing it. - auto origType = value->getType(); - value = Builder.CreatePtrToInt(value, IntPtrTy); - - auto curKey = Builder.getInt32(curAuth.getKey()); - auto newKey = Builder.getInt32(newAuth.getKey()); - - llvm::Value *curDiscriminator = curAuth.getDiscriminator(); - if (!curDiscriminator) - curDiscriminator = Builder.getSize(0); - - llvm::Value *newDiscriminator = newAuth.getDiscriminator(); - if (!newDiscriminator) - newDiscriminator = Builder.getSize(0); - - // call i64 @llvm.ptrauth.resign(i64 %pointer, - // i32 %curKey, i64 %curDiscriminator, - // i32 %newKey, i64 %newDiscriminator) - auto intrinsic = CGM.getIntrinsic(llvm::Intrinsic::ptrauth_resign); - value = EmitRuntimeCall( - intrinsic, {value, curKey, curDiscriminator, newKey, newDiscriminator}); - - // Convert back to the original type. - value = Builder.CreateIntToPtr(value, origType); - return value; -} diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 4a85153cd7830..04b11cbb89ed4 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2688,7 +2688,7 @@ class CodeGenFunction : public CodeGenTypeCache { Alignment = CGM.getNaturalTypeAlignment(T, BaseInfo, TBAAInfo, ForPointeeType); return Address(Ptr, ConvertTypeForMem(T), Alignment, - CGM.getPointerAuthInfoForPointeeType(T), nullptr, + CGM.getPointerAuthInfoForPointeeType(T), /*Offset=*/nullptr, IsKnownNonNull); } @@ -4434,19 +4434,17 @@ class CodeGenFunction : public CodeGenTypeCache { GlobalDecl SchemaDecl, QualType SchemaType); - llvm::Value *EmitPointerAuthSign(QualType PointeeType, llvm::Value *Pointer); llvm::Value *EmitPointerAuthSign(const CGPointerAuthInfo &Info, llvm::Value *Pointer); - llvm::Value *EmitPointerAuthAuth(QualType PointeeType, llvm::Value *Pointer); llvm::Value *EmitPointerAuthAuth(const CGPointerAuthInfo &Info, llvm::Value *Pointer); - llvm::Value *EmitPointerAuthResign(llvm::Value *Pointer, QualType PointerType, + llvm::Value *emitPointerAuthResign(llvm::Value *Pointer, QualType PointerType, const CGPointerAuthInfo &CurAuthInfo, const CGPointerAuthInfo &NewAuthInfo, bool IsKnownNonNull); - llvm::Value *EmitPointerAuthResignCall(llvm::Value *Pointer, + llvm::Value *emitPointerAuthResignCall(llvm::Value *Pointer, const CGPointerAuthInfo &CurInfo, const CGPointerAuthInfo &NewInfo); @@ -4454,14 +4452,11 @@ class CodeGenFunction : public CodeGenTypeCache { const CGPointerAuthInfo &Info, SmallVectorImpl &Bundles); - llvm::Value *AuthPointerToPointerCast(llvm::Value *ResultPtr, + llvm::Value *authPointerToPointerCast(llvm::Value *ResultPtr, QualType SourceType, QualType DestType); - Address AuthPointerToPointerCast(Address Ptr, QualType SourceType, + Address authPointerToPointerCast(Address Ptr, QualType SourceType, QualType DestType); - Address EmitPointerAuthSign(Address Addr, QualType PointeeType); - Address EmitPointerAuthAuth(Address Addr, QualType PointeeType); - Address getAsNaturalAddressOf(Address Addr, QualType PointeeTy); llvm::Value *getAsNaturalPointerTo(Address Addr, QualType PointeeType) { diff --git a/clang/test/CodeGen/ptrauth-function-lvalue-cast-disc.c b/clang/test/CodeGen/ptrauth-function-lvalue-cast-disc.c index 6712a6cf417b9..8e40f9d3a738a 100644 --- a/clang/test/CodeGen/ptrauth-function-lvalue-cast-disc.c +++ b/clang/test/CodeGen/ptrauth-function-lvalue-cast-disc.c @@ -21,9 +21,15 @@ char test2() { // CHECK: [[LOAD:%.*]] = load ptr, ptr @fptr // CHECK: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null + // CHECK-NEXT: br i1 [[CMP]], label %[[NONNULL:.*]], label %[[CONT:.*]] + // CHECK: [[NONNULL]]: // CHECK: [[TOINT:%.*]] = ptrtoint ptr [[LOAD]] to i64 - // CHECK: call i64 @llvm.ptrauth.resign(i64 [[TOINT]], i32 0, i64 18983, i32 0, i64 0) + // CHECK: [[CALL:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[TOINT]], i32 0, i64 18983, i32 0, i64 0) + // CHECK: [[TOPTR:%.*]] = inttoptr i64 [[CALL]] to ptr + + // CHECK: [[CONT]]: + // CHECK: phi ptr [ null, {{.*}} ], [ [[TOPTR]], %[[NONNULL]] ] } // CHECK-LABEL: define void @test4 @@ -38,6 +44,7 @@ void test4() { } void *vptr; +// CHECK-LABEL: define void @test5 void test5() { vptr = &*(char *)fptr; From aa7e4ecec2b1c8fc12cc8a8db49eaafd3fba4879 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Tue, 16 Jul 2024 18:11:22 -0700 Subject: [PATCH 6/7] Remove unneeded test --- clang/test/CodeGen/ptrauth.c | 77 ------------------------------------ 1 file changed, 77 deletions(-) delete mode 100644 clang/test/CodeGen/ptrauth.c diff --git a/clang/test/CodeGen/ptrauth.c b/clang/test/CodeGen/ptrauth.c deleted file mode 100644 index dff6dbeb8508a..0000000000000 --- a/clang/test/CodeGen/ptrauth.c +++ /dev/null @@ -1,77 +0,0 @@ -// RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-llvm %s -o - | FileCheck -check-prefix=CHECK -check-prefix=NOPCH %s -// RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-pch %s -o %t.ast -// RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-llvm -x ast -o - %t.ast | FileCheck -check-prefix=CHECK -check-prefix=PCH %s - -#define FNPTRKEY 0 - -void (*fnptr)(void); -long discriminator; - -extern void external_function(void); -// CHECK: @fptr1 = global ptr ptrauth (ptr @external_function, i32 0, i64 18983) -void (*fptr1)(void) = external_function; -// CHECK: @fptr2 = global ptr ptrauth (ptr @external_function, i32 0, i64 18983) -void (*fptr2)(void) = &external_function; - -// CHECK: @fptr3 = global ptr ptrauth (ptr @external_function, i32 2, i64 26) -void (*fptr3)(void) = __builtin_ptrauth_sign_constant(&external_function, 2, 26); - -// CHECK: @fptr4 = global ptr ptrauth (ptr @external_function, i32 2, i64 26, ptr @fptr4) -void (*fptr4)(void) = __builtin_ptrauth_sign_constant(&external_function, 2, __builtin_ptrauth_blend_discriminator(&fptr4, 26)); - -// CHECK-LABEL: define void @test_call() -void test_call() { - // CHECK: [[T0:%.*]] = load ptr, ptr @fnptr, - // CHECK-NEXT: call void [[T0]]() [ "ptrauth"(i32 0, i64 18983) ] - fnptr(); -} - -// CHECK-LABEL: define void @test_direct_call() -void test_direct_call() { - // CHECK: call void @test_call(){{$}} - test_call(); -} - -void abort(); -// CHECK-LABEL: define void @test_direct_builtin_call() -void test_direct_builtin_call() { - // CHECK: call void @abort() {{#[0-9]+$}} - abort(); -} - -// CHECK-LABEL: define ptr @test_function_pointer() -// CHECK: ret ptr ptrauth (ptr @external_function, i32 0, i64 18983) -void (*test_function_pointer())(void) { - return external_function; -} - -struct InitiallyIncomplete; -extern struct InitiallyIncomplete returns_initially_incomplete(void); -// CHECK-LABEL: define void @use_while_incomplete() -void use_while_incomplete() { - // NOPCH: [[VAR:%.*]] = alloca ptr, - // NOPCH-NEXT: store ptr ptrauth (ptr @returns_initially_incomplete, i32 0, i64 25106), ptr [[VAR]] - // PCH: [[VAR:%.*]] = alloca ptr, - // PCH-NEXT: store ptr ptrauth (ptr @returns_initially_incomplete, i32 0, i64 25106), ptr [[VAR]] - struct InitiallyIncomplete (*fnptr)(void) = &returns_initially_incomplete; -} -struct InitiallyIncomplete { int x; }; -// CHECK-LABEL: define void @use_while_complete() -void use_while_complete() { - // CHECK: [[VAR:%.*]] = alloca ptr, - // CHECK-NEXT: store ptr ptrauth (ptr @returns_initially_incomplete, i32 0, i64 25106), ptr [[VAR]] - // CHECK-NEXT: ret void - struct InitiallyIncomplete (*fnptr)(void) = &returns_initially_incomplete; -} - -// CHECK-LABEL: define void @test_memcpy_inline( -// CHECK-NOT: call{{.*}}memcpy - -extern inline __attribute__((__always_inline__)) -void *memcpy(void *d, const void *s, unsigned long) { - return 0; -} - -void test_memcpy_inline(char *d, char *s) { - memcpy(d, s, 4); -} From 227382d234f5a99bd4f995e5e07ba174e9d1ea9a Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Tue, 16 Jul 2024 18:51:05 -0700 Subject: [PATCH 7/7] Fix comment and run tests without -fptrauth-function-pointer-type-discrimination --- clang/lib/CodeGen/CGPointerAuth.cpp | 2 +- .../ptrauth-function-lvalue-cast-disc.c | 60 ++++++++++-------- ...ptrauth-function-type-discriminator-cast.c | 63 +++++++++++-------- 3 files changed, 70 insertions(+), 55 deletions(-) diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp b/clang/lib/CodeGen/CGPointerAuth.cpp index 1d668c4cce8b3..7fe62c0788742 100644 --- a/clang/lib/CodeGen/CGPointerAuth.cpp +++ b/clang/lib/CodeGen/CGPointerAuth.cpp @@ -232,7 +232,7 @@ llvm::Value *CodeGenFunction::emitPointerAuthResign( return Value; llvm::Value *Null = nullptr; - // If the Value is obviously null, we're done. + // If the value is obviously null, we're done. if (auto *PointerValue = dyn_cast(Value->getType())) { Null = CGM.getNullPointer(PointerValue, Type); } else { diff --git a/clang/test/CodeGen/ptrauth-function-lvalue-cast-disc.c b/clang/test/CodeGen/ptrauth-function-lvalue-cast-disc.c index 8e40f9d3a738a..7d76649e2e49c 100644 --- a/clang/test/CodeGen/ptrauth-function-lvalue-cast-disc.c +++ b/clang/test/CodeGen/ptrauth-function-lvalue-cast-disc.c @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 %s -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics -emit-llvm -o- -fptrauth-function-pointer-type-discrimination | FileCheck %s +// RUN: %clang_cc1 %s -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics -emit-llvm -o- -fptrauth-function-pointer-type-discrimination | FileCheck -check-prefixes CHECK,TYPE %s +// RUN: %clang_cc1 %s -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics -emit-llvm -o- | FileCheck -check-prefixes CHECK,ZERO %s typedef void (*fptr_t)(void); @@ -7,10 +8,11 @@ void (*fptr)(void); // CHECK-LABEL: define void @test1 void test1() { - // CHECK: [[LOAD:%.*]] = load ptr, ptr @cptr - // CHECK: [[TOINT:%.*]] = ptrtoint ptr [[LOAD]] to i64 - // CHECK: call i64 @llvm.ptrauth.resign(i64 [[TOINT]], i32 0, i64 0, i32 0, i64 18983) - // CHECK: call void {{.*}}() [ "ptrauth"(i32 0, i64 18983) ] + // TYPE: [[LOAD:%.*]] = load ptr, ptr @cptr + // TYPE: [[TOINT:%.*]] = ptrtoint ptr [[LOAD]] to i64 + // TYPE: call i64 @llvm.ptrauth.resign(i64 [[TOINT]], i32 0, i64 0, i32 0, i64 18983) + // TYPE: call void {{.*}}() [ "ptrauth"(i32 0, i64 18983) ] + // ZERO-NOT: @llvm.ptrauth.resign (*(fptr_t)cptr)(); } @@ -19,17 +21,18 @@ void test1() { char test2() { return *(char *)fptr; - // CHECK: [[LOAD:%.*]] = load ptr, ptr @fptr - // CHECK: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null - // CHECK-NEXT: br i1 [[CMP]], label %[[NONNULL:.*]], label %[[CONT:.*]] + // TYPE: [[LOAD:%.*]] = load ptr, ptr @fptr + // TYPE: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null + // TYPE-NEXT: br i1 [[CMP]], label %[[NONNULL:.*]], label %[[CONT:.*]] - // CHECK: [[NONNULL]]: - // CHECK: [[TOINT:%.*]] = ptrtoint ptr [[LOAD]] to i64 - // CHECK: [[CALL:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[TOINT]], i32 0, i64 18983, i32 0, i64 0) - // CHECK: [[TOPTR:%.*]] = inttoptr i64 [[CALL]] to ptr + // TYPE: [[NONNULL]]: + // TYPE: [[TOINT:%.*]] = ptrtoint ptr [[LOAD]] to i64 + // TYPE: [[CALL:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[TOINT]], i32 0, i64 18983, i32 0, i64 0) + // TYPE: [[TOPTR:%.*]] = inttoptr i64 [[CALL]] to ptr - // CHECK: [[CONT]]: - // CHECK: phi ptr [ null, {{.*}} ], [ [[TOPTR]], %[[NONNULL]] ] + // TYPE: [[CONT]]: + // TYPE: phi ptr [ null, {{.*}} ], [ [[TOPTR]], %[[NONNULL]] ] + // ZERO-NOT: @llvm.ptrauth.resign } // CHECK-LABEL: define void @test4 @@ -37,10 +40,12 @@ void test4() { (*((fptr_t)(&*((char *)(&*(fptr_t)cptr)))))(); // CHECK: [[LOAD:%.*]] = load ptr, ptr @cptr - // CHECK-NEXT: [[CAST4:%.*]] = ptrtoint ptr [[LOAD]] to i64 - // CHECK-NEXT: [[RESIGN:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[CAST4]], i32 0, i64 0, i32 0, i64 18983) - // CHECK-NEXT: [[CAST5:%.*]] = inttoptr i64 [[RESIGN]] to ptr - // CHECK-NEXT: call void [[CAST5]]() [ "ptrauth"(i32 0, i64 18983) ] + // TYPE-NEXT: [[CAST4:%.*]] = ptrtoint ptr [[LOAD]] to i64 + // TYPE-NEXT: [[RESIGN:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[CAST4]], i32 0, i64 0, i32 0, i64 18983) + // TYPE-NEXT: [[CAST5:%.*]] = inttoptr i64 [[RESIGN]] to ptr + // TYPE-NEXT: call void [[CAST5]]() [ "ptrauth"(i32 0, i64 18983) ] + // ZERO-NOT: @llvm.ptrauth.resign + // ZERO: call void [[LOAD]]() [ "ptrauth"(i32 0, i64 0) ] } void *vptr; @@ -48,15 +53,16 @@ void *vptr; void test5() { vptr = &*(char *)fptr; - // CHECK: [[LOAD:%.*]] = load ptr, ptr @fptr - // CHECK-NEXT: [[CMP]] = icmp ne ptr [[LOAD]], null - // CHECK-NEXT: br i1 [[CMP]], label %[[NONNULL:.*]], label %[[CONT:.*]] + // TYPE: [[LOAD:%.*]] = load ptr, ptr @fptr + // TYPE-NEXT: [[CMP]] = icmp ne ptr [[LOAD]], null + // TYPE-NEXT: br i1 [[CMP]], label %[[NONNULL:.*]], label %[[CONT:.*]] - // CHECK: [[NONNULL]]: - // CHECK: [[RESIGN:%.*]] = call i64 @llvm.ptrauth.resign(i64 {{.*}}, i32 0, i64 18983, i32 0, i64 0) - // CHECK: [[CAST:%.*]] = inttoptr i64 [[RESIGN]] to ptr + // TYPE: [[NONNULL]]: + // TYPE: [[RESIGN:%.*]] = call i64 @llvm.ptrauth.resign(i64 {{.*}}, i32 0, i64 18983, i32 0, i64 0) + // TYPE: [[CAST:%.*]] = inttoptr i64 [[RESIGN]] to ptr - // CHECK: [[CONT]]: - // CHECK: [[PHI:%.*]] = phi ptr [ null, {{.*}} ], [ [[CAST]], %[[NONNULL]] ] - // CHECK: store ptr [[PHI]], ptr @vptr + // TYPE: [[CONT]]: + // TYPE: [[PHI:%.*]] = phi ptr [ null, {{.*}} ], [ [[CAST]], %[[NONNULL]] ] + // TYPE: store ptr [[PHI]], ptr @vptr + // ZERO-NOT: @llvm.ptrauth.resign } diff --git a/clang/test/CodeGen/ptrauth-function-type-discriminator-cast.c b/clang/test/CodeGen/ptrauth-function-type-discriminator-cast.c index fa12e2c7ec19c..cdf9ee4907525 100644 --- a/clang/test/CodeGen/ptrauth-function-type-discriminator-cast.c +++ b/clang/test/CodeGen/ptrauth-function-type-discriminator-cast.c @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 %s -fptrauth-function-pointer-type-discrimination -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics -disable-llvm-passes -emit-llvm -o- | FileCheck %s -// RUN: %clang_cc1 -xc++ %s -fptrauth-function-pointer-type-discrimination -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics -disable-llvm-passes -emit-llvm -o- | FileCheck %s --check-prefixes=CHECK,CHECKCXX +// RUN: %clang_cc1 %s -fptrauth-function-pointer-type-discrimination -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics -disable-llvm-passes -emit-llvm -o- | FileCheck %s --check-prefixes=CHECK,TYPE +// RUN: %clang_cc1 %s -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics -disable-llvm-passes -emit-llvm -o- | FileCheck %s --check-prefixes=CHECK,ZERO +// RUN: %clang_cc1 -xc++ %s -fptrauth-function-pointer-type-discrimination -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics -disable-llvm-passes -emit-llvm -o- | FileCheck %s --check-prefixes=CHECK,CHECKCXX,TYPE,TYPECXX #ifdef __cplusplus extern "C" { @@ -19,7 +20,7 @@ ptr_member pm; void (*test_member)() = (void (*)())pm.fptr_; // CHECKCXX-LABEL: define internal void @__cxx_global_var_init -// CHECKCXX: call i64 @llvm.ptrauth.resign(i64 {{.*}}, i32 0, i64 2712, i32 0, i64 18983) +// TYPECXX: call i64 @llvm.ptrauth.resign(i64 {{.*}}, i32 0, i64 2712, i32 0, i64 18983) #endif @@ -27,56 +28,64 @@ void (*test_member)() = (void (*)())pm.fptr_; void test_cast_to_opaque() { opaque = (void *)f; - // CHECK: [[RESIGN_VAL:%.*]] = call i64 @llvm.ptrauth.resign(i64 ptrtoint (ptr ptrauth (ptr @f, i32 0, i64 18983) to i64), i32 0, i64 18983, i32 0, i64 0) - // CHECK: [[RESIGN_PTR:%.*]] = inttoptr i64 [[RESIGN_VAL]] to ptr + // TYPE: [[RESIGN_VAL:%.*]] = call i64 @llvm.ptrauth.resign(i64 ptrtoint (ptr ptrauth (ptr @f, i32 0, i64 18983) to i64), i32 0, i64 18983, i32 0, i64 0) + // TYPE: [[RESIGN_PTR:%.*]] = inttoptr i64 [[RESIGN_VAL]] to ptr + // ZERO-NOT: @llvm.ptrauth.resign } // CHECK-LABEL: define void @test_cast_from_opaque void test_cast_from_opaque() { fptr = (void (*)(void))opaque; - // CHECK: [[LOAD:%.*]] = load ptr, ptr @opaque - // CHECK: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null - // CHECK: br i1 [[CMP]], label %[[RESIGN_LAB:.*]], label + // TYPE: [[LOAD:%.*]] = load ptr, ptr @opaque + // TYPE: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null + // TYPE: br i1 [[CMP]], label %[[RESIGN_LAB:.*]], label - // CHECK: [[RESIGN_LAB]]: - // CHECK: [[INT:%.*]] = ptrtoint ptr [[LOAD]] to i64 - // CHECK: [[RESIGN_INT:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[INT]], i32 0, i64 0, i32 0, i64 18983) + // TYPE: [[RESIGN_LAB]]: + // TYPE: [[INT:%.*]] = ptrtoint ptr [[LOAD]] to i64 + // TYPE: [[RESIGN_INT:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[INT]], i32 0, i64 0, i32 0, i64 18983) + + // ZERO-NOT: @llvm.ptrauth.resign } // CHECK-LABEL: define void @test_cast_to_intptr void test_cast_to_intptr() { uintptr = (unsigned long)fptr; - // CHECK: [[ENTRY:.*]]: - // CHECK: [[LOAD:%.*]] = load ptr, ptr @fptr - // CHECK: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null - // CHECK: br i1 [[CMP]], label %[[RESIGN_LAB:.*]], label %[[RESIGN_CONT:.*]] + // TYPE: [[ENTRY:.*]]: + // TYPE: [[LOAD:%.*]] = load ptr, ptr @fptr + // TYPE: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null + // TYPE: br i1 [[CMP]], label %[[RESIGN_LAB:.*]], label %[[RESIGN_CONT:.*]] + + // TYPE: [[RESIGN_LAB]]: + // TYPE: [[INT:%.*]] = ptrtoint ptr [[LOAD]] to i64 + // TYPE: [[RESIGN_INT:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[INT]], i32 0, i64 18983, i32 0, i64 0) + // TYPE: [[RESIGN:%.*]] = inttoptr i64 [[RESIGN_INT]] to ptr + // TYPE: br label %[[RESIGN_CONT]] - // CHECK: [[RESIGN_LAB]]: - // CHECK: [[INT:%.*]] = ptrtoint ptr [[LOAD]] to i64 - // CHECK: [[RESIGN_INT:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[INT]], i32 0, i64 18983, i32 0, i64 0) - // CHECK: [[RESIGN:%.*]] = inttoptr i64 [[RESIGN_INT]] to ptr - // CHECK: br label %[[RESIGN_CONT]] + // TYPE: [[RESIGN_CONT]]: + // TYPE: phi ptr [ null, %[[ENTRY]] ], [ [[RESIGN]], %[[RESIGN_LAB]] ] - // CHECK: [[RESIGN_CONT]]: - // CHECK: phi ptr [ null, %[[ENTRY]] ], [ [[RESIGN]], %[[RESIGN_LAB]] ] + // ZERO-NOT: @llvm.ptrauth.resign } // CHECK-LABEL: define void @test_function_to_function_cast void test_function_to_function_cast() { void (*fptr2)(int) = (void (*)(int))fptr; - // CHECK: call i64 @llvm.ptrauth.resign(i64 {{.*}}, i32 0, i64 18983, i32 0, i64 2712) + // TYPE: call i64 @llvm.ptrauth.resign(i64 {{.*}}, i32 0, i64 18983, i32 0, i64 2712) + // ZERO-NOT: @llvm.ptrauth.resign } // CHECK-LABEL: define void @test_call_lvalue_cast void test_call_lvalue_cast() { (*(void (*)(int))f)(42); - // CHECK: entry: - // CHECK-NEXT: [[RESIGN:%.*]] = call i64 @llvm.ptrauth.resign(i64 ptrtoint (ptr ptrauth (ptr @f, i32 0, i64 18983) to i64), i32 0, i64 18983, i32 0, i64 2712) - // CHECK-NEXT: [[RESIGN_INT:%.*]] = inttoptr i64 [[RESIGN]] to ptr - // CHECK-NEXT: call void [[RESIGN_INT]](i32 noundef 42) [ "ptrauth"(i32 0, i64 2712) ] + // TYPE: entry: + // TYPE-NEXT: [[RESIGN:%.*]] = call i64 @llvm.ptrauth.resign(i64 ptrtoint (ptr ptrauth (ptr @f, i32 0, i64 18983) to i64), i32 0, i64 18983, i32 0, i64 2712) + // TYPE-NEXT: [[RESIGN_INT:%.*]] = inttoptr i64 [[RESIGN]] to ptr + // TYPE-NEXT: call void [[RESIGN_INT]](i32 noundef 42) [ "ptrauth"(i32 0, i64 2712) ] + // ZERO-NOT: @llvm.ptrauth.resign + // ZERO: call void ptrauth (ptr @f, i32 0)(i32 noundef 42) [ "ptrauth"(i32 0, i64 0) ] }