diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 16a19645d7f36792a4ef79e33e90bcefbbf423ce..ba83595cb11c71b55f871c422971c1fd2bb7a3a8 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -252,7 +252,7 @@ class ASTContext : public RefCountedBase { mutable llvm::FoldingSet BitIntTypes; mutable llvm::ContextualFoldingSet DependentBitIntTypes; - llvm::FoldingSet BTFTagAttributedTypes; + mutable llvm::FoldingSet BTFTagAttributedTypes; mutable llvm::FoldingSet CountAttributedTypes; @@ -1341,6 +1341,12 @@ public: /// calling T.withConst(). QualType getConstType(QualType T) const { return T.withConst(); } + /// Rebuild a type, preserving any existing type sugar. For function types, + /// you probably want to just use \c adjustFunctionResultType and friends + /// instead. + QualType adjustType(QualType OldType, + llvm::function_ref Adjust) const; + /// Change the ExtInfo on a function type. const FunctionType *adjustFunctionType(const FunctionType *Fn, FunctionType::ExtInfo EInfo); @@ -1616,6 +1622,18 @@ public: QualType adjustStringLiteralBaseType(QualType StrLTy) const; + bool hasNopacRec(const QualType &type) const; + QualType getNopacQualType(const QualType &type, bool &hasNopac) const; + QualType removeNopacQualType(QualType T) const; + + bool hasSameFunctionTypeIgnoringNopac(QualType T, QualType U) const; + QualType getFunctionTypeWithoutNopac(QualType T) const; + + static bool isPointerToFunction(QualType &type, int &level); + bool addNopacFunctionDecl(FunctionDecl *FD); + bool AddNopacTypedefNameDecl(TypedefNameDecl *D); + bool isFunctionDeclPtr2Fun(const FunctionDecl *FD); + private: /// Return a normal function type with a typed argument list. QualType getFunctionTypeInternal(QualType ResultTy, ArrayRef Args, @@ -1666,7 +1684,7 @@ public: QualType equivalentType) const; QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr, - QualType Wrapped); + QualType Wrapped) const; QualType getSubstTemplateTypeParmType(QualType Replacement, Decl *AssociatedDecl, diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 561a9d872acfb080868ab394b7b52a42aeffcc43..64fb3e10fa51e003796992e512afc09b8679513b 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -1109,6 +1109,8 @@ public: static VarDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID); + bool isNoPac() const; + SourceRange getSourceRange() const override LLVM_READONLY; /// Returns the storage class as written in the source. For the @@ -1985,6 +1987,8 @@ public: void setDeletedMessage(StringLiteral *Message); }; + bool isNoPac() const; + private: /// A new[]'d array of pointers to VarDecls for the formal /// parameters of this function. This is null if a prototype or if there are diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 0923736a95f97e2e437dd713a781803c62efac58..6f8acd67a58990358da3fc8acc5053d25a0b7872 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -568,6 +568,8 @@ public: return DD ? DD->Definition : nullptr; } + bool isNoPac() const; + bool hasDefinition() const { return DefinitionData || dataPtr(); } static CXXRecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 9a711030cff9ca24293ae4391959d8d4832b0f80..d1c6021fc2db0cbe1a163b8e8795bd160d09b3e3 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -410,9 +410,25 @@ public: L.removeAddressSpace(); R.removeAddressSpace(); } + + if (L.hasNopac() && R.hasNopac()) { + Q.addNopac(); + L.removeNopac(); + R.removeNopac(); + } return Q; } + bool hasNopac() const { return Mask & NopacMask; } + void addNopac() { Mask |= NopacMask; } + void removeNopac() { Mask &= ~NopacMask; } + + Qualifiers withNopac() const { + Qualifiers Qs = *this; + Qs.addNopac(); + return Qs; + } + static Qualifiers fromFastMask(unsigned Mask) { Qualifiers Qs; Qs.addFastQualifiers(Mask); @@ -637,10 +653,10 @@ public: void addQualifiers(Qualifiers Q) { // If the other set doesn't have any non-boolean qualifiers, just // bit-or it in. - if (!(Q.Mask & ~CVRMask)) + if (!(Q.Mask & ~(CVRMask | NopacMask))) Mask |= Q.Mask; else { - Mask |= (Q.Mask & CVRMask); + Mask |= (Q.Mask & (CVRMask | NopacMask)); if (Q.hasAddressSpace()) addAddressSpace(Q.getAddressSpace()); if (Q.hasObjCGCAttr()) @@ -656,10 +672,10 @@ public: void removeQualifiers(Qualifiers Q) { // If the other set doesn't have any non-boolean qualifiers, just // bit-and the inverse in. - if (!(Q.Mask & ~CVRMask)) + if (!(Q.Mask & ~(CVRMask | NopacMask))) Mask &= ~Q.Mask; else { - Mask &= ~(Q.Mask & CVRMask); + Mask &= ~(Q.Mask & (CVRMask | NopacMask)); if (getObjCGCAttr() == Q.getObjCGCAttr()) removeObjCGCAttr(); if (getObjCLifetime() == Q.getObjCLifetime()) @@ -809,8 +825,12 @@ public: void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Mask); } private: - // bits: |0 1 2|3|4 .. 5|6 .. 8|9 ... 31|32 ... 63| - // |C R V|U|GCAttr|Lifetime|AddressSpace| PtrAuth | + // obsolete // bits: |0 1 2|3|4 .. 5|6 .. 8|9 ... 31|32 ... 63| + // obsolete // |C R V|U|GCAttr|Lifetime|AddressSpace| PtrAuth | + + // bits: |0 1 2|3|4 .. 5|6 .. 8|9 |10 ... 31|32 ... 63| + // |C R V|U|GCAttr|Lifetime|Nopac|AddressSpace| PtrAuth | + uint64_t Mask = 0; static_assert(sizeof(PointerAuthQualifier) == sizeof(uint32_t), "PointerAuthQualifier must be 32 bits"); @@ -821,9 +841,18 @@ private: static constexpr uint64_t GCAttrShift = 4; static constexpr uint64_t LifetimeMask = 0x1C0; static constexpr uint64_t LifetimeShift = 6; + + // static constexpr uint64_t AddressSpaceMask = + // ~(CVRMask | UMask | GCAttrMask | LifetimeMask); + // static constexpr uint64_t AddressSpaceShift = 9; + + static const uint32_t NopacMask = 0x200; + static const uint32_t NopacShift = 9; + static constexpr uint64_t AddressSpaceMask = - ~(CVRMask | UMask | GCAttrMask | LifetimeMask); - static constexpr uint64_t AddressSpaceShift = 9; + ~(CVRMask | UMask | GCAttrMask | LifetimeMask | NopacMask); + static constexpr uint64_t AddressSpaceShift = 10; + static constexpr uint64_t PtrAuthShift = 32; static constexpr uint64_t PtrAuthMask = uint64_t(0xffffffff) << PtrAuthShift; }; @@ -1001,6 +1030,10 @@ public: return getTypePtr(); } + bool hasNopac() const { + return getQualifiers().hasNopac(); + } + bool isCanonical() const; bool isCanonicalAsParam() const; diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 46d0a66d59c3753bb8ea41fa494f9d99aabd9422..80116f79a81a0243d9c82844321d119c4969a384 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -4719,3 +4719,10 @@ def ClspvLibclcBuiltin: InheritableAttr { let Documentation = [ClspvLibclcBuiltinDoc]; let SimpleHandler = 1; } + +def Nopac : DeclOrTypeAttr { + let Spellings = [Clang<"nopac">]; + let Subjects = SubjectList<[Var, Function, CXXRecord, TypedefName, Record, Type, Field, FunctionLike]>; + let Documentation = [Undocumented]; + // let SimpleHandler = 1; +} \ No newline at end of file diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index dc71ef8f9869235e15f4c1a00c15981f29233bf9..1a1e856b24a710aadddc4965390335b117810e66 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -105,6 +105,10 @@ FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow)) FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo)) FEATURE(ptrauth_intrinsics, LangOpts.PointerAuthIntrinsics) FEATURE(ptrauth_calls, LangOpts.PointerAuthCalls) +FEATURE(ptrauth_icall, LangOpts.IndirectPointerAuthCallOnly) +FEATURE(ptrauth_vcall, LangOpts.VirtualFunctionPointerAuthCallOnly) +FEATURE(ptrauth_mfcall, LangOpts.MemberFunctionPointerAuthCallOnly) +FEATURE(ptrauth_vptr, LangOpts.VTablePointerAuthOnly) FEATURE(ptrauth_returns, LangOpts.PointerAuthReturns) FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtrAddressDiscrimination) FEATURE(ptrauth_vtable_pointer_type_discrimination, LangOpts.PointerAuthVTPtrTypeDiscrimination) @@ -113,6 +117,17 @@ FEATURE(ptrauth_member_function_pointer_type_discrimination, LangOpts.PointerAut FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini) FEATURE(ptrauth_function_pointer_type_discrimination, LangOpts.PointerAuthFunctionTypeDiscrimination) FEATURE(ptrauth_indirect_gotos, LangOpts.PointerAuthIndirectGotos) +FEATURE(ptrauth_cxx_function_pointer_zero_discrimination, LangOpts.PointerAuthCxxFunctionPointerZeroDiscrimination) +FEATURE(ptrauth_cxx_virtual_function_pointer_zero_discrimination, LangOpts.PointerAuthCxxVirtualFunctionPointerZeroDiscrimination) +FEATURE(ptrauth_init_fini_zero_discrimination, LangOpts.PointerAuthInitFiniZeroDiscrimination) + +FEATURE(ptrauth_mangle_class, LangOpts.PointerAuthMangleClass) +FEATURE(ptrauth_mangle_func, LangOpts.PointerAuthMangleFunc) +FEATURE(ptrauth_mangle_cxxabi, LangOpts.PointerAuthMangleCxxabi) + +FEATURE(ptrauth_nopac_atexit, LangOpts.PointerAuthNoPacAtexit) +FEATURE(ptrauth_nopac_throw, LangOpts.PointerAuthNoPacThrow) + EXTENSION(swiftcc, PP.getTargetInfo().checkCallingConvention(CC_Swift) == clang::TargetInfo::CCCR_OK) diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 834a6f6cd43e32054cd08de706c9b5eb1838bd7a..81806ea82994f65565c07445f6975fda261f5dbc 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -164,6 +164,10 @@ LANGOPT(ExperimentalLibrary, 1, 0, "enable unstable and experimental library fea LANGOPT(PointerAuthIntrinsics, 1, 0, "pointer authentication intrinsics") LANGOPT(PointerAuthCalls , 1, 0, "function pointer authentication") +LANGOPT(IndirectPointerAuthCallOnly, 1, 0, "indirect function pointer authentication only") +LANGOPT(VirtualFunctionPointerAuthCallOnly, 1, 0, "virtual function pointer authentication only") +LANGOPT(MemberFunctionPointerAuthCallOnly, 1, 0, "member function pointer authentication only") +LANGOPT(VTablePointerAuthOnly, 1, 0, "virtual table pointer authentication only") LANGOPT(PointerAuthReturns, 1, 0, "return pointer authentication") LANGOPT(PointerAuthIndirectGotos, 1, 0, "indirect gotos pointer authentication") LANGOPT(PointerAuthAuthTraps, 1, 0, "pointer authentication failure traps") @@ -173,6 +177,16 @@ LANGOPT(PointerAuthTypeInfoVTPtrDiscrimination, 1, 0, "incorporate type and addr LANGOPT(PointerAuthInitFini, 1, 0, "sign function pointers in init/fini arrays") BENIGN_LANGOPT(PointerAuthFunctionTypeDiscrimination, 1, 0, "Use type discrimination when signing function pointers") +LANGOPT(PointerAuthCxxFunctionPointerZeroDiscrimination, 1, 0, "Enable zero discrimination on CXX function pointers") +LANGOPT(PointerAuthCxxVirtualFunctionPointerZeroDiscrimination, 1, 0, "Enable zero discrimination on CXX virtual function pointers") +LANGOPT(PointerAuthInitFiniZeroDiscrimination, 1, 0, "Enable zero discrimination of function pointers in init/fini arrays") + +LANGOPT(PointerAuthMangleClass, 1, 0, "Add PAC_ prefix to class names compiled with pointer authentication") +LANGOPT(PointerAuthMangleFunc, 1, 0, "Add PAC_ prefix to functions and variables with types conaining pointer to functions when compiled with pointer authentication") +LANGOPT(PointerAuthMangleCxxabi, 1, 0, "Add PAC_ prefix to cxxabi classes. This is needed when libcxx is compiled with pointer authentication") + +LANGOPT(PointerAuthNoPacAtexit, 1, 0, "Enable NoPac for atexit function pointers") +LANGOPT(PointerAuthNoPacThrow, 1, 0, "Enable NoPac for function pointers to throw") LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes") LANGOPT(ExperimentalLateParseAttributes, 1, 0, "experimental late parsing of attributes") @@ -361,6 +375,7 @@ BENIGN_LANGOPT(CompatibilityQualifiedIdBlockParamTypeChecking, 1, 0, LANGOPT(ObjCDisableDirectMethodsForTesting, 1, 0, "Disable recognition of objc_direct methods") LANGOPT(CFProtectionBranch , 1, 0, "Control-Flow Branch Protection enabled") +LANGOPT(UseNopacAttribute , 1, 0, "Use nopac attribute") LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map") ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "OpenCL address space map mangling mode") LANGOPT(IncludeDefaultHeader, 1, 0, "Include default header file for OpenCL") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 15f9ee75492e3f95ccc03f995be6f7f91ba848e9..a34a9f59a6d49842f7c86a75be84cb81c724cb4b 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4243,9 +4243,19 @@ defm strict_return : BoolFOption<"strict-return", " of a non-void function as unreachable">, PosFlag>; +defm use_nopac_attribute : BoolFOption<"use-nopac-attribute", + LangOpts<"UseNopacAttribute">, DefaultTrue, + PosFlag, + NegFlag>; + let Flags = [TargetSpecific] in { defm ptrauth_intrinsics : OptInCC1FFlag<"ptrauth-intrinsics", "Enable pointer authentication intrinsics">; defm ptrauth_calls : OptInCC1FFlag<"ptrauth-calls", "Enable signing and authentication of all indirect calls">; +defm ptrauth_icall : OptInCC1FFlag<"ptrauth-icall", "Enable signing and authentication of indirect function calls only">; +defm ptrauth_vcall : OptInCC1FFlag<"ptrauth-vcall", "Enable signing and authentication of virtual function calls only">; +defm ptrauth_mfcall : OptInCC1FFlag<"ptrauth-mfcall", "Enable signing and authentication of member function calls only">; +defm ptrauth_vptr : OptInCC1FFlag<"ptrauth-vptr", "Enable signing and authentication of vtable pointer only">; defm ptrauth_returns : OptInCC1FFlag<"ptrauth-returns", "Enable signing and authentication of return addresses">; defm ptrauth_auth_traps : OptInCC1FFlag<"ptrauth-auth-traps", "Enable traps on authentication failures">; defm ptrauth_vtable_pointer_address_discrimination : @@ -4259,6 +4269,23 @@ defm ptrauth_function_pointer_type_discrimination : OptInCC1FFlag<"ptrauth-funct "Enable type discrimination on C function pointers">; defm ptrauth_indirect_gotos : OptInCC1FFlag<"ptrauth-indirect-gotos", "Enable signing and authentication of indirect goto targets">; +defm ptrauth_cxx_function_pointer_zero_discrimination : OptInCC1FFlag<"ptrauth-cxx-function-pointer-zero-discrimination", + "Enable zero discrimination on CXX function pointers">; +defm ptrauth_cxx_virtual_function_pointer_zero_discrimination : OptInCC1FFlag<"ptrauth-cxx-virtual-function-pointer-zero-discrimination", + "Enable zero discrimination on CXX virtual function pointers">; +defm ptrauth_init_fini_zero_discrimination : OptInCC1FFlag<"ptrauth-init-fini-zero-discrimination", + "Enable zero discrimination of function pointers in init/fini arrays">; + +defm ptrauth_mangle_class : OptInCC1FFlag<"ptrauth-mangle-class", + "Add PAC_ prefix to class names compiled with pointer authentication">; +defm ptrauth_mangle_func : OptInCC1FFlag<"ptrauth-mangle-func", + "Add PAC_ prefix to functions and variables with types conaining pointer to functions when compiled with pointer authentication">; +defm ptrauth_mangle_cxxabi : OptInCC1FFlag<"ptrauth-mangle-cxxabi", + "Add PAC_ prefix to cxxabi classes. This is needed when libcxx is compiled with pointer authentication.">; + + +defm ptrauth_nopac_atexit : OptInCC1FFlag<"ptrauth-nopac-atexit", "Enable NoPac for atexit function pointers">; +defm ptrauth_nopac_throw : OptInCC1FFlag<"ptrauth-nopac-throw", "Enable NoPac for destructor pointers on throw">; } def fenable_matrix : Flag<["-"], "fenable-matrix">, Group, diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 1064507f34616a5ba9e33588f7d0b184fd8bcde7..4ee1389f9e9445cbb8a4770067f71c7cf07f8886 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3028,6 +3028,214 @@ ASTContext::getASTObjCImplementationLayout( return getObjCLayout(D->getClassInterface(), D); } +bool ASTContext::isPointerToFunction(QualType &type, int &level) +{ + QualType t = type.getCanonicalType(); + for(level = 0; t->isPointerType(); level++, t = t->getPointeeType()); + return level > 0 && t->isFunctionType(); +} + +bool ASTContext::isFunctionDeclPtr2Fun(const FunctionDecl *FD) +{ + // llvm::outs() << " - function declaration \n"; + QualType t = FD->getType(); + bool hasNopac; + getNopacQualType(t, hasNopac); + return hasNopac; +} + +bool ASTContext::addNopacFunctionDecl(FunctionDecl *FD) +{ + // llvm::outs() << " - function declaration \n"; + QualType t = FD->getType(); + bool hasNopac; + auto rt = getNopacQualType(t, hasNopac); + + if(!hasNopac) + { + return false; + } + + FD->setType(rt); + + for(auto param : FD->parameters()) + { + auto t = param->getType(); + bool _hasNopac; + auto t2 = getNopacQualType(t, _hasNopac); + if(_hasNopac) + { + param->setType(t2); + } + } + return true; +} + +bool ASTContext::AddNopacTypedefNameDecl(TypedefNameDecl *D) +{ + // TypeAliasDecl + // TypedefDecl + // llvm::outs() << " - TypedefDecl or TypeAliasDecl: " << D->getName() << "\n"; + + bool hasNopac; + + auto oldType = D->getUnderlyingType(); + auto newType = getNopacQualType(oldType, hasNopac); + + if(hasNopac) + { + if (D->isModed()) { + // llvm::outs() << " - moded\n"; + D->setModedTypeSourceInfo(D->getTypeSourceInfo(), newType); + } + else { + // llvm::outs() << " - not moded\n"; + D->setTypeSourceInfo(CreateTypeSourceInfo(newType)); + } + } + + return hasNopac; +} + +QualType ASTContext::removeNopacQualType(QualType T) const { + if (T->isFunctionPointerType() || T->isMemberFunctionPointerType()) { + if (!T.hasNopac()) + return T; + QualifierCollector Quals; + const Type *TypeNode = Quals.strip(T); + Quals.removeNopac(); + + // Removal of the NoPac can mean there are no longer any + // non-fast qualifiers, so creating an ExtQualType isn't possible (asserts) + // or required. + if (Quals.hasNonFastQualifiers()) + return getExtQualType(TypeNode, Quals); + return QualType(TypeNode, Quals.getFastQualifiers()); + } else if (const PointerType *Ptr = T->getAs()) { + QualType Pointee = Ptr->getPointeeType(); + if (Pointee->isPointerType()) { + return getPointerType(removeNopacQualType(Pointee)); + } + } + return T; +} + +bool ASTContext::hasSameFunctionTypeIgnoringNopac(QualType T, QualType U) const { + return hasSameType(T, U) || + hasSameType(getFunctionTypeWithoutNopac(T), + getFunctionTypeWithoutNopac(U)); +} + +QualType ASTContext::getFunctionTypeWithoutNopac(QualType T) const { + if (const auto *Proto = T->getAs()) { + QualType RetTy = removeNopacQualType(Proto->getReturnType()); + SmallVector Args(Proto->param_types()); + for (unsigned i = 0, n = Args.size(); i != n; ++i) + Args[i] = removeNopacQualType(Args[i]); + return getFunctionType(RetTy, Args, Proto->getExtProtoInfo()); + } + + if (const FunctionNoProtoType *Proto = T->getAs()) { + QualType RetTy = removeNopacQualType(Proto->getReturnType()); + return getFunctionNoProtoType(RetTy, Proto->getExtInfo()); + } + + return T; +} + +bool ASTContext::hasNopacRec(const QualType &type) const +{ + if (type.isNull()) { + return false; + } + if (type.getQualifiers().hasNopac()) { + return true; + } + if (type->isFunctionNoProtoType()) { + const FunctionNoProtoType *F = type.getTypePtr()->castAs(); + if(hasNopacRec(F->getReturnType())) { + return true; + } + return false; + } else if (type->isFunctionProtoType()) { + const FunctionProtoType *FPT = type.getTypePtr()->castAs(); + if(hasNopacRec(FPT->getReturnType())) { + return true; + } + for(auto t : FPT->param_types()) { + if(hasNopacRec(t)) { + return true; + } + } + } else if(type->isPointerType() && type->isReferenceType()) { + auto t = type->getPointeeType(); + return hasNopacRec(t); + } + return false; +} + +QualType ASTContext::getNopacQualType(const QualType &type, bool &hasNopac) const +{ + hasNopac = false; + // return type; + + QualifierCollector Quals; + const Type *TypeNode = Quals.strip(type); + + if (type.isNull()) + { + return type; + } + + if(TypeNode->isFunctionNoProtoType()) + { + auto newtype = adjustType(type, [&](QualType orig) { + const FunctionNoProtoType *F = orig->castAs(); + QualType newReturnType = getNopacQualType(F->getReturnType(), hasNopac); + QualType rt = getFunctionNoProtoType(newReturnType, F->getExtInfo()); + return rt; + } ); + + return newtype; + } + else if (TypeNode->isFunctionProtoType()) + { + auto newtype = adjustType(type, [&](QualType orig) { + const FunctionProtoType *FPT = orig->castAs(); + QualType newReturnType = getNopacQualType(FPT->getReturnType(), hasNopac); + auto paramTypes = FPT->getParamTypes(); + std::vector types; + for(const QualType &pt : paramTypes) + { + bool _hasNopac; + types.push_back(getNopacQualType(pt, _hasNopac)); + hasNopac = hasNopac | _hasNopac; + } + ArrayRef newParamTypes = types; + QualType rt = getFunctionType(newReturnType, newParamTypes, FPT->getExtProtoInfo()); + return rt; + } ); + + return newtype; + } + else if(TypeNode->isPointerType()) { + //llvm::outs() << " - isPointerType \n"; + const PointerType *ptype = TypeNode->getAs(); + auto t = getNopacQualType(ptype->getPointeeType(), hasNopac); + if(ptype->isFunctionPointerType()) + { + //llvm::outs() << " - isFunctionPointerType \n"; + hasNopac = true; + Quals.addNopac(); + } + auto rt = getQualifiedType(getPointerType(t), Quals); + //llvm::outs() << " - isPointerType end\n"; + return rt; + } + + return type; +} + static auto getCanonicalTemplateArguments(const ASTContext &C, ArrayRef Args, bool &AnyNonCanonArgs) { @@ -3421,6 +3629,34 @@ uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) { encodeTypeForFunctionPointerAuth(*this, Out, T); } else { T = T.getUnqualifiedType(); + // Calls to member function pointers don't need to worry about + // language interop or the laxness of the C type compatibility rules. + // We just mangle the member pointer type directly, which is + // implicitly much stricter about type matching. However, we do + // strip any top-level exception specification before this mangling. + // C++23 requires calls to work when the function type is convertible + // to the pointer type by a function pointer conversion, which can + // change the exception specification. This does not technically + // require the exception specification to not affect representation, + // because the function pointer conversion is still always a direct + // value conversion and therefore an opportunity to resign the + // pointer. (This is in contrast to e.g. qualification conversions, + // which can be applied in nested pointer positions, effectively + // requiring qualified and unqualified representations to match.) + // However, it is pragmatic to ignore exception specifications + // because it allows a certain amount of `noexcept` mismatching + // to not become a visible ODR problem. This also leaves some + // room for the committee to add laxness to function pointer + // conversions in future standards. + if (auto *MPT = T->getAs()) + if (MPT->isMemberFunctionPointer()) { + QualType PointeeType = MPT->getPointeeType(); + if (PointeeType->castAs()->getExceptionSpecType() != + EST_None) { + QualType FT = getFunctionTypeWithExceptionSpec(PointeeType, EST_None); + T = getMemberPointerType(FT, MPT->getClass()); + } + } std::unique_ptr MC(createMangleContext()); MC->mangleCanonicalTypeName(T, Out); } @@ -3492,6 +3728,50 @@ QualType ASTContext::getCountAttributedType( return QualType(CATy, 0); } +QualType +ASTContext::adjustType(QualType Orig, + llvm::function_ref Adjust) const { + switch (Orig->getTypeClass()) { + case Type::Attributed: { + const auto *AT = cast(Orig); + return getAttributedType(AT->getAttrKind(), + adjustType(AT->getModifiedType(), Adjust), + adjustType(AT->getEquivalentType(), Adjust)); + } + + case Type::BTFTagAttributed: { + const auto *BTFT = dyn_cast(Orig); + return getBTFTagAttributedType(BTFT->getAttr(), + adjustType(BTFT->getWrappedType(), Adjust)); + } + + case Type::Elaborated: { + const auto *ET = cast(Orig); + return getElaboratedType(ET->getKeyword(), ET->getQualifier(), + adjustType(ET->getNamedType(), Adjust)); + } + + case Type::Paren: + return getParenType( + adjustType(cast(Orig)->getInnerType(), Adjust)); + + case Type::Adjusted: { + const auto *AT = cast(Orig); + return getAdjustedType(AT->getOriginalType(), + adjustType(AT->getAdjustedType(), Adjust)); + } + + case Type::MacroQualified: { + const auto *MQT = cast(Orig); + return getMacroQualifiedType(adjustType(MQT->getUnderlyingType(), Adjust), + MQT->getMacroIdentifier()); + } + + default: + return Adjust(Orig); + } +} + const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T, FunctionType::ExtInfo Info) { if (T->getExtInfo() == Info) @@ -5180,7 +5460,7 @@ QualType ASTContext::getAttributedType(attr::Kind attrKind, } QualType ASTContext::getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr, - QualType Wrapped) { + QualType Wrapped) const { llvm::FoldingSetNodeID ID; BTFTagAttributedType::Profile(ID, Wrapped, BTFAttr); @@ -11026,6 +11306,16 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, bool OfBlockPointer, // If the qualifiers are different, the types aren't compatible... mostly. Qualifiers LQuals = LHSCan.getLocalQualifiers(); Qualifiers RQuals = RHSCan.getLocalQualifiers(); + + if (LQuals.hasNopac() && !RQuals.hasNopac()) { + bool hasNopac; + return mergeTypes(LHS, getNopacQualType(RHS, hasNopac)); + } else if (!LQuals.hasNopac() && RQuals.hasNopac()) { + bool hasNopac; + return mergeTypes(getNopacQualType(LHS, hasNopac), RHS); + } + + if (LQuals != RQuals) { // If any of these qualifiers are different, we have a type // mismatch. @@ -14205,7 +14495,7 @@ bool ASTContext::useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl, auto *Method = cast(VirtualMethodDecl.getDecl()); assert(Method->isVirtual()); bool DefaultIncludesPointerAuth = - LangOpts.PointerAuthCalls || LangOpts.PointerAuthIntrinsics; + LangOpts.PointerAuthCalls || LangOpts.VirtualFunctionPointerAuthCallOnly || LangOpts.PointerAuthIntrinsics; if (!DefaultIncludesPointerAuth) return true; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index bc7cce0bcd7fc27afafd80f74feb5872b4595aed..7de480b52ed3e293c4477fc3b505baad8b9a8471 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2142,6 +2142,12 @@ VarDecl *VarDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { QualType(), nullptr, SC_None); } +bool VarDecl::isNoPac() const +{ + QualType Ty = getType(); + return hasAttr() || Ty.getQualifiers().hasNopac(); +} + void VarDecl::setStorageClass(StorageClass SC) { assert(isLegalForVariable(SC)); VarDeclBits.SClass = SC; @@ -5399,6 +5405,17 @@ FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, return New; } +bool FunctionDecl::isNoPac() const { + if (hasAttr()) return true; + + if (getReturnType().getQualifiers().hasNopac()) return true; + + for (auto *PD: parameters()) + if (PD->isNoPac()) return true; + + return false; +} + FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) { return new (C, ID) FunctionDecl( Function, C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 9a3ede426e91433407d826ac83276f96b676a87a..1fe58c4db89624b4cbbfca016885e49260ec486d 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -144,6 +144,17 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, return R; } +bool CXXRecordDecl::isNoPac() const { + if(hasAttr()) + return true; + if(const ClassTemplateSpecializationDecl *A = dyn_cast(this)) + { + ClassTemplateDecl *T = A->getSpecializedTemplate(); + return T && T->hasAttr(); + } + return false; +} + CXXRecordDecl * CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, TypeSourceInfo *Info, SourceLocation Loc, diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index d46d621d4c7d41e832a856956a509b2f63a409d0..e3f91d6624b91148f0de6f88ff4b26fea1173189 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -524,7 +524,7 @@ private: const AbiTagList *AdditionalAbiTags); void mangleUnscopedTemplateName(GlobalDecl GD, const DeclContext *DC, const AbiTagList *AdditionalAbiTags); - void mangleSourceName(const IdentifierInfo *II); + void mangleSourceName(const IdentifierInfo *II, bool isPac = false); void mangleRegCallName(const IdentifierInfo *II); void mangleDeviceStubName(const IdentifierInfo *II); void mangleSourceNameWithAbiTags( @@ -1481,6 +1481,38 @@ void CXXNameMangler::mangleUnqualifiedName( Out << 'F'; } + bool isPac = false; + + auto &ctx = GD.getDecl()->getASTContext(); + auto &langOptions = ctx.getLangOpts(); + + bool pauth_class = langOptions.PointerAuthCalls + || langOptions.VirtualFunctionPointerAuthCallOnly + || langOptions.MemberFunctionPointerAuthCallOnly + || langOptions.VTablePointerAuthOnly; + bool pauth_func = langOptions.PointerAuthCalls + || langOptions.IndirectPointerAuthCallOnly + || langOptions.VirtualFunctionPointerAuthCallOnly + || langOptions.MemberFunctionPointerAuthCallOnly; + + if (pauth_class) + { + if (const CXXRecordDecl *A = dyn_cast(GD.getDecl())) + { + // todo: if class info is signed, then we must mangle also the name of non polymorphic classes. + isPac = langOptions.PointerAuthMangleClass + && (!A->hasDefinition() || A->isPolymorphic()) && !A->isNoPac(); + } + } + if (pauth_func) + { + if (const FunctionDecl *A = dyn_cast(GD.getDecl())) + { + isPac = langOptions.PointerAuthMangleFunc + && ctx.isFunctionDeclPtr2Fun(A) && !A->isNoPac(); + } + } + unsigned Arity = KnownArity; switch (Name.getNameKind()) { case DeclarationName::Identifier: { @@ -1543,11 +1575,17 @@ void CXXNameMangler::mangleUnqualifiedName( FD && FD->hasAttr() && GD.getKernelReferenceKind() == KernelReferenceKind::Stub; if (IsDeviceStub) + { mangleDeviceStubName(II); + } else if (IsRegCall) + { mangleRegCallName(II); + } else - mangleSourceName(II); + { + mangleSourceName(II, isPac); + } writeAbiTags(ND, AdditionalAbiTags); break; @@ -1761,11 +1799,19 @@ void CXXNameMangler::mangleDeviceStubName(const IdentifierInfo *II) { << II->getName(); } -void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) { +void CXXNameMangler::mangleSourceName(const IdentifierInfo *II, bool isPac) { // ::= // ::= [n] // ::= - Out << II->getLength() << II->getName(); + + if(isPac) + { + Out << II->getLength() + 4 << "PAC_" << II->getName(); + } + else + { + Out << II->getLength() << II->getName(); + } } void CXXNameMangler::mangleNestedName(GlobalDecl GD, diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index ffec3ef9d22692c0189a7ab436a69e7b933907fa..ec02668f0574832afba2710bafe9135c883cf98a 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -2023,6 +2023,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T, case attr::ArmMveStrictPolymorphism: OS << "__clang_arm_mve_strict_polymorphism"; break; + case attr::Nopac: + OS << "nopac"; + break; // Nothing to print for this attribute. case attr::HLSLParamModifier: @@ -2432,6 +2435,9 @@ bool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const { if (getCVRQualifiers()) return false; + if (hasNopac()) + return false; + if (getAddressSpace() != LangAS::Default) return false; @@ -2507,6 +2513,12 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy, OS << "__unaligned"; addSpace = true; } + if(hasNopac()) { + if (addSpace) + OS << ' '; + addSpace = true; + OS << "__attribute__((nopac))"; + } auto ASStr = getAddrSpaceAsString(getAddressSpace()); if (!ASStr.empty()) { if (addSpace) diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 63fc15f916c5580a1df89fe8689bf0c32cfba5b6..10579a5008ccd5802cdb88427efc24cdb04b816d 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -1087,6 +1087,10 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector &Features, HasPAuthLR = true; HasPAuth = true; } + if (Feature == "+pauth-hint-only") { + HasPAuthHintOnly = true; + HasPAuth = true; + } } // Check features that are manually disabled by command line options. diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h index 526f7f30a386185b0567551cdb7620562c4f9cdc..9c883d40818769a3c8efb311682f1ab80c51ce9b 100644 --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -90,6 +90,7 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo { bool HasRCPC3 = false; bool HasSMEFA64 = false; bool HasPAuthLR = false; + bool HasPAuthHintOnly = false; const llvm::AArch64::ArchInfo *ArchInfo = &llvm::AArch64::ARMV8A; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 0416fa03d749a5667483d8b91f06867c08a72485..4062ae2b2d09d49fab290697436eb976595e0252 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -5008,6 +5008,10 @@ static unsigned getMaxVectorWidth(const llvm::Type *Ty) { return MaxVectorWidth; } +static bool isNoPacFunction(const FunctionDecl *FD) { + return FD->isNoPac(); +} + RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, @@ -5130,6 +5134,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, bool ArgHasMaybeUndefAttr = IsArgumentMaybeUndef(TargetDecl, CallInfo.getNumRequiredArgs(), ArgNo); + const FunctionDecl *FD = dyn_cast_or_null(TargetDecl); + bool nopac = FD && isNoPacFunction(FD); + switch (ArgInfo.getKind()) { case ABIArgInfo::InAlloca: { assert(NumIRArgs == 0); @@ -5324,6 +5331,13 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (ArgHasMaybeUndefAttr) V = Builder.CreateFreeze(V); + + if (nopac && I->Ty.getUnqualifiedType()->isSignableType()) { + auto NoPacAuthInfo = CGPointerAuthInfo(); + auto FuncPAI = CGM.getPointerAuthInfoForType(I->Ty.getUnqualifiedType()); + V = emitPointerAuthResign(V, I->Ty, FuncPAI, NoPacAuthInfo, false); + } + IRCallArgs[FirstIRArg] = V; break; } @@ -5926,6 +5940,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::Value *V = CI; if (V->getType() != RetIRTy) V = Builder.CreateBitCast(V, RetIRTy); + const FunctionDecl *FD = dyn_cast_or_null(TargetDecl); + if (FD && isNoPacFunction(FD) && RetTy.getUnqualifiedType()->isSignableType()) { + auto NoPacAuthInfo = CGPointerAuthInfo(); + auto FuncPAI = CGM.getPointerAuthInfoForType(RetTy.getUnqualifiedType()); + V = emitPointerAuthResign(V, RetTy, NoPacAuthInfo, FuncPAI, false); + } return RValue::get(V); } } diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 3d8a715b692de824421ace015fcb8cacce816e43..2a251dc92d112155f0a011e54543929931faa587 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -986,6 +986,7 @@ static void stripUnusedQualifiers(Qualifiers &Q) { Q.removeAddressSpace(); Q.removeObjCLifetime(); Q.removeUnaligned(); + Q.removeNopac(); } static llvm::dwarf::Tag getNextQualifier(Qualifiers &Q) { diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index c3251bb5ab5657978203191fa1989b0464cc383a..2a8861ae27b76f26e6cb911fb88cb2e36a1c95c6 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -2583,6 +2583,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, Arg.getAnyValue()->setName(D.getName()); QualType Ty = D.getType(); + bool isNopac = D.isNoPac(); // Use better IR generation for certain implicit parameters. if (auto IPD = dyn_cast(&D)) { @@ -2736,6 +2737,11 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, } } + if (isNopac && Ty.getUnqualifiedType()->isSignableType()) { + auto NoPacAuthInfo = CGPointerAuthInfo(); + auto FuncPAI = CGM.getPointerAuthInfoForType(Ty.getUnqualifiedType()); + ArgVal = emitPointerAuthResign(ArgVal, Ty, NoPacAuthInfo, FuncPAI, false); + } // Store the initial value into the alloca. if (DoStore) EmitStoreOfScalar(ArgVal, lv, /* isInitialization */ true); diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 2f56355cff90ec087b52149c83ac02fb9da48a28..3fadde7b8deba41074cae51139fa1271342160f7 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -267,9 +267,14 @@ llvm::Constant *CodeGenFunction::createAtExitStub(const VarDecl &VD, // Get a proper function pointer. FunctionProtoType::ExtProtoInfo EPI(getContext().getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/false)); - QualType fnType = getContext().getFunctionType(getContext().VoidTy, - {getContext().VoidPtrTy}, EPI); - return CGM.getFunctionPointer(fn, fnType); + + if (getLangOpts().PointerAuthNoPacAtexit) { + return fn; + } else { + QualType fnType = getContext().getFunctionType(getContext().VoidTy, + {getContext().VoidPtrTy}, EPI); + return CGM.getFunctionPointer(fn, fnType); + } } /// Create a stub function, suitable for being passed to __pt_atexit_np, diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 3ef22b17f7691d054874f1b89fd42df26411df60..28d3c360cd8427c5924431f75d27da4ddb307f97 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -2012,6 +2012,14 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile, llvm::MDNode::get(getLLVMContext(), std::nullopt)); } + if (Ty->isFunctionPointerType()) { + if (Ty.getQualifiers().hasNopac()) { + auto NoPacAuthInfo = CGPointerAuthInfo(); + auto FuncPAI = CGM.getPointerAuthInfoForType(Ty.getUnqualifiedType()); + return emitPointerAuthResign(EmitFromMemory(Load, Ty), Ty, NoPacAuthInfo, FuncPAI, false); + } + } + return EmitFromMemory(Load, Ty); } @@ -2034,6 +2042,13 @@ llvm::Value *CodeGenFunction::EmitToMemory(llvm::Value *Value, QualType Ty) { //

--> iP. Value = Builder.CreateBitCast(Value, StoreTy); } + if (Ty->isFunctionPointerType()) { + if (Ty.getQualifiers().hasNopac()) { + auto NoPacAuthInfo = CGPointerAuthInfo(); + auto FuncPAI = CGM.getPointerAuthInfoForType(Ty.getUnqualifiedType()); + Value = emitPointerAuthResign(Value, Ty, FuncPAI, NoPacAuthInfo, false); + } + } return Value; } diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 8eb6ab7381acbc871c342d28610e896dba2740bf..132c691348e83ddfe227a8717ca025feee1171b0 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -2277,7 +2277,8 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr, bool IsExact = !IsDynamicCastToVoid && CGM.getCodeGenOpts().OptimizationLevel > 0 && DestRecordTy->getAsCXXRecordDecl()->isEffectivelyFinal() && - CGM.getCXXABI().shouldEmitExactDynamicCast(DestRecordTy); + CGM.getCXXABI().shouldEmitExactDynamicCast(DestRecordTy) && + !CGM.getCodeGenOpts().PointerAuth.CXXVTablePointers; // C++ [expr.dynamic.cast]p4: // If the value of v is a null pointer value in the pointer case, the result diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp b/clang/lib/CodeGen/CGPointerAuth.cpp index 0c63b9d6bb7e75946977fb5a516d0d450ad4e1f0..e7e26cfea6a2081a7b5e05b17f48b9d7715aec1c 100644 --- a/clang/lib/CodeGen/CGPointerAuth.cpp +++ b/clang/lib/CodeGen/CGPointerAuth.cpp @@ -365,10 +365,10 @@ llvm::Constant *CodeGenModule::getFunctionPointer(GlobalDecl GD, return getFunctionPointer(getRawFunctionPointer(GD, Ty), FuncType); } -CGPointerAuthInfo CodeGenModule::getMemberFunctionPointerAuthInfo(QualType FT) { +CGPointerAuthInfo CodeGenModule::getMemberFunctionPointerAuthInfo(QualType FT, bool NoPac) { assert(FT->getAs() && "MemberPointerType expected"); const auto &Schema = getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers; - if (!Schema) + if (!Schema || NoPac) return CGPointerAuthInfo(); assert(!Schema.isAddressDiscriminated() && @@ -382,8 +382,9 @@ CGPointerAuthInfo CodeGenModule::getMemberFunctionPointerAuthInfo(QualType FT) { } llvm::Constant *CodeGenModule::getMemberFunctionPointer(llvm::Constant *Pointer, - QualType FT) { - if (CGPointerAuthInfo PointerAuth = getMemberFunctionPointerAuthInfo(FT)) + QualType FT, + bool NoPac) { + if (CGPointerAuthInfo PointerAuth = getMemberFunctionPointerAuthInfo(FT, NoPac)) return getConstantSignedPointer( Pointer, PointerAuth.getKey(), nullptr, cast_or_null(PointerAuth.getDiscriminator())); @@ -392,17 +393,18 @@ llvm::Constant *CodeGenModule::getMemberFunctionPointer(llvm::Constant *Pointer, } llvm::Constant *CodeGenModule::getMemberFunctionPointer(const FunctionDecl *FD, - llvm::Type *Ty) { + llvm::Type *Ty, + bool NoPac) { QualType FT = FD->getType(); FT = getContext().getMemberPointerType( FT, cast(FD)->getParent()->getTypeForDecl()); - return getMemberFunctionPointer(getRawFunctionPointer(FD, Ty), FT); + return getMemberFunctionPointer(getRawFunctionPointer(FD, Ty), FT, NoPac); } std::optional CodeGenModule::computeVTPointerAuthentication(const CXXRecordDecl *ThisClass) { auto DefaultAuthentication = getCodeGenOpts().PointerAuth.CXXVTablePointers; - if (!DefaultAuthentication) + if (!DefaultAuthentication || ThisClass->isNoPac()) return std::nullopt; const CXXRecordDecl *PrimaryBase = Context.baseForVTableAuthentication(ThisClass); @@ -485,6 +487,10 @@ std::optional CodeGenModule::getVTablePointerAuthInfo(CodeGenFunction *CGF, const CXXRecordDecl *Record, llvm::Value *StorageAddress) { + bool NoPac = Record->isNoPac(); + if (NoPac) + return std::nullopt; + auto Authentication = getVTablePointerAuthentication(Record); if (!Authentication) return std::nullopt; diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 2f466602d2f680d0aed0ac7bcd0704745d65185c..e7805114b0a66f506f06449b20d8332c4f76a6fb 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -1545,6 +1545,14 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { switch (getEvaluationKind(RV->getType())) { case TEK_Scalar: { llvm::Value *Ret = EmitScalarExpr(RV); + if (FnRetTy->isFunctionPointerType()) { + auto FN = dyn_cast(CurCodeDecl); + if(FnRetTy.getQualifiers().hasNopac() || (FN && FN->isNoPac())) { + auto NoPacAuthInfo = CGPointerAuthInfo(); + auto FuncPAI = CGM.getPointerAuthInfoForType(FnRetTy.getUnqualifiedType()); + Ret = emitPointerAuthResign(Ret, FnRetTy, FuncPAI, NoPacAuthInfo, false); + } + } if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect) EmitStoreOfScalar(Ret, MakeAddrLValue(ReturnValue, RV->getType()), /*isInit*/ true); diff --git a/clang/lib/CodeGen/CGVTT.cpp b/clang/lib/CodeGen/CGVTT.cpp index 20bd2c2fc2c6420357cfbdda6679d4547e5d1fd6..7dd216122589c6ae75b0aa91820ad6f01fae1b54 100644 --- a/clang/lib/CodeGen/CGVTT.cpp +++ b/clang/lib/CodeGen/CGVTT.cpp @@ -90,9 +90,10 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT, llvm::Constant *Init = llvm::ConstantExpr::getGetElementPtr( VTable->getValueType(), VTable, Idxs, /*InBounds=*/true, InRange); - if (const auto &Schema = - CGM.getCodeGenOpts().PointerAuth.CXXVTTVTablePointers) - Init = CGM.getConstantSignedPointer(Init, Schema, nullptr, GlobalDecl(), + if (!RD->isNoPac()) + if (const auto &Schema = + CGM.getCodeGenOpts().PointerAuth.CXXVTTVTablePointers) + Init = CGM.getConstantSignedPointer(Init, Schema, nullptr, GlobalDecl(), QualType()); VTTComponents.push_back(Init); diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 267bdf0982970033d3e33528530f3266af24e5c1..6ab063962fe4cf0ec561ca19d049cb6fc0aed025 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -737,6 +737,14 @@ static void AddRelativeLayoutOffset(const CodeGenModule &CGM, builder.add(llvm::ConstantInt::get(CGM.Int32Ty, offset.getQuantity())); } +static bool isInNoPacClass(GlobalDecl &GD) { + const CXXMethodDecl *MD = cast(GD.getDecl()); + if (!MD) + return false; + const CXXRecordDecl *RD = MD->getParent(); + return RD->isNoPac(); +} + void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder, const VTableLayout &layout, unsigned componentIndex, @@ -866,9 +874,10 @@ void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder, if (FnAS != GVAS) fnPtr = llvm::ConstantExpr::getAddrSpaceCast(fnPtr, CGM.GlobalsInt8PtrTy); - if (const auto &Schema = - CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers) - return builder.addSignedPointer(fnPtr, Schema, GD, QualType()); + if (!isInNoPacClass(GD)) + if (const auto &Schema = + CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers) + return builder.addSignedPointer(fnPtr, Schema, GD, QualType()); return builder.add(fnPtr); } } diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 2a5d5f9083ae6526355728f67e50ac7b064aa795..a0f24f268859661f5c6b642f981d4d552cc9ddca 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1210,7 +1210,9 @@ void CodeGenModule::Release() { uint64_t PAuthABIVersion = (LangOpts.PointerAuthIntrinsics << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INTRINSICS) | - (LangOpts.PointerAuthCalls + ((LangOpts.PointerAuthCalls | LangOpts.IndirectPointerAuthCallOnly | + LangOpts.VirtualFunctionPointerAuthCallOnly | LangOpts.MemberFunctionPointerAuthCallOnly | + LangOpts.VTablePointerAuthOnly) << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_CALLS) | (LangOpts.PointerAuthReturns << AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_RETURNS) | @@ -1225,6 +1227,7 @@ void CodeGenModule::Release() { static_assert(AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_INITFINI == AARCH64_PAUTH_PLATFORM_LLVM_LINUX_VERSION_LAST, "Update when new enum items are defined"); + //viorel todo: add PointerAuthCxxFunctionPointerZeroDiscrimination | PointerAuthCxxVirtualFunctionPointerZeroDiscrimination | PointerAuthInitFiniZeroDiscrimination if (PAuthABIVersion != 0) { getModule().addModuleFlag(llvm::Module::Error, "aarch64-elf-pauthabi-platform", @@ -1861,6 +1864,25 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD, GD.getKernelReferenceKind() == KernelReferenceKind::Stub) { Out << "__device_stub__" << II->getName(); } else { + + auto &ctx = GD.getDecl()->getASTContext(); + auto &langOptions = CGM.getLangOpts(); + bool isPac = langOptions.PointerAuthMangleFunc && FD && ctx.isFunctionDeclPtr2Fun(FD) && !FD->isNoPac(); + isPac = isPac + && II->getName().str() != "__cxa_throw" + && II->getName().str() != "__cxa_atexit" + && II->getName().str() != "dl_iterate_phdr" + && II->getName().str() != "pthread_key_create" + && II->getName().str() != "pthread_once" + && II->getName().str() != "__clone" + //&& II->getName().str() != "" + //&& II->getName().str() != "" + ; + + if(isPac) + { + Out << "PAC_"; + } Out << II->getName(); } } @@ -5480,7 +5502,12 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, Init = llvm::UndefValue::get(getTypes().ConvertType(T)); } } else { - Init = Initializer; + const auto *CPA = dyn_cast(Initializer); + if (CPA && D->isNoPac()) { + Init = CPA->getPointer(); + } else { + Init = Initializer; + } // We don't need an initializer, so remove the entry for the delayed // initializer position (just in case this entry was delayed) if we // also don't need to register a destructor. diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index c58bb88035ca8ab3ef781e9350424aa8bf89fca1..07dcb04f7fc1d90ba6f9aac5694edfe2ed02f854 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -975,14 +975,17 @@ public: QualType FunctionType); llvm::Constant *getMemberFunctionPointer(const FunctionDecl *FD, - llvm::Type *Ty = nullptr); + llvm::Type *Ty = nullptr, + bool NoPac = false); llvm::Constant *getMemberFunctionPointer(llvm::Constant *Pointer, - QualType FT); + QualType FT, + bool NoPac = false); CGPointerAuthInfo getFunctionPointerAuthInfo(QualType T); - CGPointerAuthInfo getMemberFunctionPointerAuthInfo(QualType FT); + CGPointerAuthInfo getMemberFunctionPointerAuthInfo(QualType FT, + bool NoPac = false); CGPointerAuthInfo getPointerAuthInfoForPointeeType(QualType type); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 0be92fb2e2757990a92bef9d6571f1871fd761c8..bedfaaaa1e8c4bc7ba60450151c0d5b005067cae 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -842,23 +842,25 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( CalleePtr->addIncoming(NonVirtualFn, FnNonVirtual); CGPointerAuthInfo PointerAuth; - - if (const auto &Schema = - CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers) { - llvm::PHINode *DiscriminatorPHI = Builder.CreatePHI(CGF.IntPtrTy, 2); - DiscriminatorPHI->addIncoming(llvm::ConstantInt::get(CGF.IntPtrTy, 0), - FnVirtual); - const auto &AuthInfo = - CGM.getMemberFunctionPointerAuthInfo(QualType(MPT, 0)); - assert(Schema.getKey() == AuthInfo.getKey() && - "Keys for virtual and non-virtual member functions must match"); - auto *NonVirtualDiscriminator = AuthInfo.getDiscriminator(); - DiscriminatorPHI->addIncoming(NonVirtualDiscriminator, FnNonVirtual); - PointerAuth = CGPointerAuthInfo( - Schema.getKey(), Schema.getAuthenticationMode(), Schema.isIsaPointer(), - Schema.authenticatesNullValues(), DiscriminatorPHI); + bool NoPac = MPT->getClass()->getAsCXXRecordDecl()->isNoPac(); + if (!NoPac) { + if (const auto &Schema = + CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers) { + llvm::PHINode *DiscriminatorPHI = Builder.CreatePHI(CGF.IntPtrTy, 2); + DiscriminatorPHI->addIncoming(llvm::ConstantInt::get(CGF.IntPtrTy, 0), + FnVirtual); + const bool NoPac = RD->isNoPac(); + const auto &AuthInfo = + CGM.getMemberFunctionPointerAuthInfo(QualType(MPT, 0), NoPac); + assert(Schema.getKey() == AuthInfo.getKey() && + "Keys for virtual and non-virtual member functions must match"); + auto *NonVirtualDiscriminator = AuthInfo.getDiscriminator(); + DiscriminatorPHI->addIncoming(NonVirtualDiscriminator, FnNonVirtual); + PointerAuth = CGPointerAuthInfo( + Schema.getKey(), Schema.getAuthenticationMode(), Schema.isIsaPointer(), + Schema.authenticatesNullValues(), DiscriminatorPHI); + } } - CGCallee Callee(FPT, CalleePtr, PointerAuth); return Callee; } @@ -934,12 +936,21 @@ ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, CGBuilderTy &Builder = CGF.Builder; QualType DstType = E->getType(); + + const MemberPointerType *destTy = + E->getType()->castAs(); + + assert(destTy != nullptr && "destTy is nullptr"); + auto *RD = destTy->getMostRecentCXXRecordDecl(); + assert(RD != nullptr && "RD is nullptr"); + const bool NoPac = RD->isNoPac(); + if (DstType->isMemberFunctionPointerType()) { if (const auto &NewAuthInfo = - CGM.getMemberFunctionPointerAuthInfo(DstType)) { + CGM.getMemberFunctionPointerAuthInfo(DstType, NoPac)) { QualType SrcType = E->getSubExpr()->getType(); assert(SrcType->isMemberFunctionPointerType()); - const auto &CurAuthInfo = CGM.getMemberFunctionPointerAuthInfo(SrcType); + const auto &CurAuthInfo = CGM.getMemberFunctionPointerAuthInfo(SrcType, NoPac); llvm::Value *MemFnPtr = Builder.CreateExtractValue(src, 0, "memptr.ptr"); llvm::Type *OrigTy = MemFnPtr->getType(); @@ -982,9 +993,6 @@ ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer); - const MemberPointerType *destTy = - E->getType()->castAs(); - // For member data pointers, this is just a matter of adding the // offset if the source is non-null. if (destTy->isMemberDataPointer()) { @@ -1019,7 +1027,8 @@ ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, static llvm::Constant * pointerAuthResignMemberFunctionPointer(llvm::Constant *Src, QualType DestType, - QualType SrcType, CodeGenModule &CGM) { + QualType SrcType, CodeGenModule &CGM, + bool DstNoPac, bool SrcNoPac) { assert(DestType->isMemberFunctionPointerType() && SrcType->isMemberFunctionPointerType() && "member function pointers expected"); @@ -1039,8 +1048,11 @@ pointerAuthResignMemberFunctionPointer(llvm::Constant *Src, QualType DestType, return Src; } - llvm::Constant *ConstPtr = pointerAuthResignConstant( - cast(MemFnPtr)->getOperand(0), CurAuthInfo, NewAuthInfo, CGM); + llvm::Constant *ConstPtr = DstNoPac + ? dyn_cast(cast(MemFnPtr)->getOperand(0)) + : pointerAuthResignConstant(cast(MemFnPtr)->getOperand(0), + CurAuthInfo, NewAuthInfo, CGM); + assert(ConstPtr != nullptr && "ConstPtr is nullptr"); ConstPtr = llvm::ConstantExpr::getPtrToInt(ConstPtr, MemFnPtr->getType()); return ConstantFoldInsertValueInstruction(Src, ConstPtr, 0); } @@ -1052,11 +1064,17 @@ ItaniumCXXABI::EmitMemberPointerConversion(const CastExpr *E, E->getCastKind() == CK_BaseToDerivedMemberPointer || E->getCastKind() == CK_ReinterpretMemberPointer); + const MemberPointerType *destTy = + E->getType()->castAs(); + assert(destTy != nullptr && "destTy is nullptr"); + auto *RD = destTy->getMostRecentCXXRecordDecl(); + assert(RD != nullptr && "RD is nullptr"); + const bool NoPac = RD->isNoPac(); QualType DstType = E->getType(); if (DstType->isMemberFunctionPointerType()) src = pointerAuthResignMemberFunctionPointer( - src, DstType, E->getSubExpr()->getType(), CGM); + src, DstType, E->getSubExpr()->getType(), CGM, NoPac, NoPac); // Under Itanium, reinterprets don't require any additional processing. if (E->getCastKind() == CK_ReinterpretMemberPointer) return src; @@ -1067,9 +1085,6 @@ ItaniumCXXABI::EmitMemberPointerConversion(const CastExpr *E, bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer); - const MemberPointerType *destTy = - E->getType()->castAs(); - // For member data pointers, this is just a matter of adding the // offset if the source is non-null. if (destTy->isMemberDataPointer()) { @@ -1172,7 +1187,10 @@ llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD, // be valid. const auto &Schema = CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers; - if (Schema) + const auto &vfuncSchema = CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers; + auto *RD = MD->getParent(); + bool NoPac = RD->isNoPac(); + if ((Schema || vfuncSchema) && !NoPac) MemPtr[0] = llvm::ConstantExpr::getPtrToInt( getSignedVirtualMemberFunctionPointer(MD), CGM.PtrDiffTy); else @@ -1180,7 +1198,7 @@ llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD, // Don't set the LSB of adj to 1 if pointer authentication for member // function pointers is enabled. MemPtr[1] = llvm::ConstantInt::get( - CGM.PtrDiffTy, 2 * ThisAdjustment.getQuantity() + !Schema); + CGM.PtrDiffTy, 2 * ThisAdjustment.getQuantity() + (!(Schema || vfuncSchema) || NoPac)); } else { // Itanium C++ ABI 2.3: // For a virtual function, [the pointer field] is 1 plus the @@ -1202,7 +1220,8 @@ llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD, // function type is incomplete. Ty = CGM.PtrDiffTy; } - llvm::Constant *addr = CGM.getMemberFunctionPointer(MD, Ty); + const bool NoPac = MD->getParent()->isNoPac(); + llvm::Constant *addr = CGM.getMemberFunctionPointer(MD, Ty, NoPac); MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy); MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy, @@ -1226,7 +1245,9 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP, llvm::Constant *Src = BuildMemberPointer(MD, ThisAdjustment); QualType SrcType = getContext().getMemberPointerType( MD->getType(), MD->getParent()->getTypeForDecl()); - return pointerAuthResignMemberFunctionPointer(Src, MPType, SrcType, CGM); + const bool NoPac = MD->getParent()->isNoPac(); + return pointerAuthResignMemberFunctionPointer(Src, MPType, SrcType, CGM, + NoPac, NoPac); } CharUnits FieldOffset = @@ -1470,13 +1491,15 @@ void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) { // __cxa_throw is declared to take its destructor as void (*)(void *). We // must match that if function pointers can be authenticated with a // discriminator based on their type. - const ASTContext &Ctx = getContext(); - QualType DtorTy = Ctx.getFunctionType(Ctx.VoidTy, {Ctx.VoidPtrTy}, - FunctionProtoType::ExtProtoInfo()); CXXDestructorDecl *DtorD = Record->getDestructor(); Dtor = CGM.getAddrOfCXXStructor(GlobalDecl(DtorD, Dtor_Complete)); - Dtor = CGM.getFunctionPointer(Dtor, DtorTy); + if (!CGM.getLangOpts().PointerAuthNoPacAtexit) { + const ASTContext &Ctx = getContext(); + QualType DtorTy = Ctx.getFunctionType(Ctx.VoidTy, {Ctx.VoidPtrTy}, + FunctionProtoType::ExtProtoInfo()); + Dtor = CGM.getFunctionPointer(Dtor, DtorTy); + } } } if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy); @@ -2128,6 +2151,12 @@ llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT( CGF.Builder.CreateAlignedLoad(CGF.GlobalsVoidPtrTy, VTT, CGF.getPointerAlign()); + bool NoPac = VTableClass->isNoPac(); + // Sanity check: Base classes should also be NoPac if the derived class is. + // NoPac |= Base.getBase()->hasAttr(); + if (NoPac) + return AP; + if (auto &Schema = CGF.CGM.getCodeGenOpts().PointerAuth.CXXVTTVTablePointers) { CGPointerAuthInfo PointerAuth = CGF.EmitPointerAuthInfo(Schema, VTT, GlobalDecl(), @@ -2189,7 +2218,11 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD); llvm::Value *VFunc, *VTableSlotPtr = nullptr; auto &Schema = CGM.getCodeGenOpts().PointerAuth.CXXVirtualFunctionPointers; - if (!Schema && CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) { + auto *RD = MethodDecl->getParent(); + + bool nopac = RD->isNoPac(); + + if ((!Schema || nopac) && CGF.ShouldEmitVTableTypeCheckedLoad(MethodDecl->getParent())) { VFunc = CGF.EmitVTableTypeCheckedLoad( MethodDecl->getParent(), VTable, PtrTy, VTableIndex * @@ -2229,7 +2262,7 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, } CGPointerAuthInfo PointerAuth; - if (Schema) { + if (Schema && !nopac) { assert(VTableSlotPtr && "virtual function pointer not set"); GD = CGM.getItaniumVTableContext().findOriginalMethod(GD.getCanonicalDecl()); PointerAuth = CGF.EmitPointerAuthInfo(Schema, VTableSlotPtr, GD, QualType()); @@ -2859,11 +2892,12 @@ static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF, const auto &Context = CGF.CGM.getContext(); FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/false)); - QualType fnType = - Context.getFunctionType(Context.VoidTy, {Context.VoidPtrTy}, EPI); llvm::Constant *dtorCallee = cast(dtor.getCallee()); - dtorCallee = CGF.CGM.getFunctionPointer(dtorCallee, fnType); - + if (!CGF.CGM.getLangOpts().PointerAuthNoPacAtexit) { + QualType fnType = + Context.getFunctionType(Context.VoidTy, {Context.VoidPtrTy}, EPI); + dtorCallee = CGF.CGM.getFunctionPointer(dtorCallee, fnType); + } if (!addr) // addr is null when we are trying to register a dtor annotated with // __attribute__((destructor)) in a constructor function. Using null here is @@ -3424,7 +3458,7 @@ class ItaniumRTTIBuilder { llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty); /// BuildVTablePointer - Build the vtable pointer for the given type. - void BuildVTablePointer(const Type *Ty); + void BuildVTablePointer(const Type *Ty, llvm::Constant *StorageAddress); /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single /// inheritance, according to the Itanium C++ ABI, 2.9.5p6b. @@ -3819,16 +3853,20 @@ static bool CanUseSingleInheritance(const CXXRecordDecl *RD) { return true; } -void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) { +void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty, + llvm::Constant *StorageAddress) { + bool mangleCxxabi = CGM.getContext().getLangOpts().PointerAuthMangleCxxabi; + // abi::__class_type_info. - static const char * const ClassTypeInfo = - "_ZTVN10__cxxabiv117__class_type_infoE"; + const char * ClassTypeInfo = + mangleCxxabi ? "_ZTVN10__cxxabiv121PAC___class_type_infoE" : "_ZTVN10__cxxabiv117__class_type_infoE"; // abi::__si_class_type_info. - static const char * const SIClassTypeInfo = - "_ZTVN10__cxxabiv120__si_class_type_infoE"; + const char * SIClassTypeInfo = + mangleCxxabi ? "_ZTVN10__cxxabiv124PAC___si_class_type_infoE" : "_ZTVN10__cxxabiv120__si_class_type_infoE"; // abi::__vmi_class_type_info. - static const char * const VMIClassTypeInfo = - "_ZTVN10__cxxabiv121__vmi_class_type_infoE"; + const char * VMIClassTypeInfo = + mangleCxxabi ? "_ZTVN10__cxxabiv125PAC___vmi_class_type_infoE" : "_ZTVN10__cxxabiv121__vmi_class_type_infoE"; + const char *VTableName = nullptr; @@ -3866,25 +3904,25 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) { // FIXME: GCC treats block pointers as fundamental types?! case Type::BlockPointer: // abi::__fundamental_type_info. - VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE"; + VTableName = mangleCxxabi ? "_ZTVN10__cxxabiv127PAC___fundamental_type_infoE" : "_ZTVN10__cxxabiv123__fundamental_type_infoE"; break; case Type::ConstantArray: case Type::IncompleteArray: case Type::VariableArray: // abi::__array_type_info. - VTableName = "_ZTVN10__cxxabiv117__array_type_infoE"; + VTableName = mangleCxxabi ? "_ZTVN10__cxxabiv121PAC___array_type_infoE" : "_ZTVN10__cxxabiv117__array_type_infoE"; break; case Type::FunctionNoProto: case Type::FunctionProto: // abi::__function_type_info. - VTableName = "_ZTVN10__cxxabiv120__function_type_infoE"; + VTableName = mangleCxxabi ? "_ZTVN10__cxxabiv124PAC___function_type_infoE": "_ZTVN10__cxxabiv120__function_type_infoE"; break; case Type::Enum: // abi::__enum_type_info. - VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE"; + VTableName = mangleCxxabi ? "_ZTVN10__cxxabiv120PAC___enum_type_infoE" : "_ZTVN10__cxxabiv116__enum_type_infoE"; break; case Type::Record: { @@ -3926,12 +3964,12 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) { case Type::ObjCObjectPointer: case Type::Pointer: // abi::__pointer_type_info. - VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE"; + VTableName = mangleCxxabi ? "_ZTVN10__cxxabiv123PAC___pointer_type_infoE" : "_ZTVN10__cxxabiv119__pointer_type_infoE"; break; case Type::MemberPointer: // abi::__pointer_to_member_type_info. - VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE"; + VTableName = mangleCxxabi ? "_ZTVN10__cxxabiv133PAC___pointer_to_member_type_infoE" : "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE"; break; } @@ -3963,9 +4001,12 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) { VTable, Two); } - if (auto &Schema = CGM.getCodeGenOpts().PointerAuth.CXXTypeInfoVTablePointer) - VTable = CGM.getConstantSignedPointer(VTable, Schema, nullptr, GlobalDecl(), - QualType(Ty, 0)); + if (const auto &Schema = + CGM.getCodeGenOpts().PointerAuth.CXXTypeInfoVTablePointer) + VTable = CGM.getConstantSignedPointer( + VTable, Schema, + Schema.isAddressDiscriminated() ? StorageAddress : nullptr, + GlobalDecl(), QualType(Ty, 0)); Fields.push_back(VTable); } @@ -4081,8 +4122,18 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( llvm::GlobalVariable::LinkageTypes Linkage, llvm::GlobalValue::VisibilityTypes Visibility, llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) { + SmallString<256> Name; + llvm::raw_svector_ostream Out(Name); + CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out); + llvm::Module &M = CGM.getModule(); + llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name); + // int8 is an arbitrary type to be replaced later with replaceInitializer. + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(M, CGM.Int8Ty, /*isConstant=*/true, Linkage, + /*Initializer=*/nullptr, Name); + // Add the vtable pointer. - BuildVTablePointer(cast(Ty)); + BuildVTablePointer(cast(Ty), GV); // And the name. llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage); @@ -4197,16 +4248,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( break; } - llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields); - - SmallString<256> Name; - llvm::raw_svector_ostream Out(Name); - CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out); - llvm::Module &M = CGM.getModule(); - llvm::GlobalVariable *OldGV = M.getNamedGlobal(Name); - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(M, Init->getType(), - /*isConstant=*/true, Linkage, Init, Name); + GV->replaceInitializer(llvm::ConstantStruct::getAnon(Fields)); // Export the typeinfo in the same circumstances as the vtable is exported. auto GVDLLStorageClass = DLLStorageClass; @@ -5105,7 +5147,8 @@ ItaniumCXXABI::getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD) { llvm::Constant *thunk = getOrCreateVirtualFunctionPointerThunk(origMD); QualType funcType = CGM.getContext().getMemberPointerType( MD->getType(), MD->getParent()->getTypeForDecl()); - return CGM.getMemberFunctionPointer(thunk, funcType); + const bool NoPac = MD->getParent()->isNoPac(); + return CGM.getMemberFunctionPointer(thunk, funcType, NoPac); } void WebAssemblyCXXABI::emitBeginCatch(CodeGenFunction &CGF, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 8858c318aba7a1ab4aa3bdda1fe4757afcf60710..d23eb5e28849589015ac27778f81765f7c27b114 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1498,6 +1498,22 @@ static void handlePAuthABI(const ArgList &DriverArgs, ArgStringList &CC1Args) { options::OPT_fno_ptrauth_calls)) CC1Args.push_back("-fptrauth-calls"); + if (!DriverArgs.hasArg(options::OPT_fptrauth_icall, + options::OPT_fno_ptrauth_icall)) + CC1Args.push_back("-fptrauth-icall"); + + if (!DriverArgs.hasArg(options::OPT_fptrauth_vcall, + options::OPT_fno_ptrauth_vcall)) + CC1Args.push_back("-fptrauth-vcall"); + + if (!DriverArgs.hasArg(options::OPT_fptrauth_mfcall, + options::OPT_fno_ptrauth_mfcall)) + CC1Args.push_back("-fptrauth-mfcall"); + + if (!DriverArgs.hasArg(options::OPT_fptrauth_vptr, + options::OPT_fno_ptrauth_vptr)) + CC1Args.push_back("-fptrauth-vptr"); + if (!DriverArgs.hasArg(options::OPT_fptrauth_returns, options::OPT_fno_ptrauth_returns)) CC1Args.push_back("-fptrauth-returns"); @@ -1523,6 +1539,36 @@ static void handlePAuthABI(const ArgList &DriverArgs, ArgStringList &CC1Args) { if (!DriverArgs.hasArg(options::OPT_fptrauth_init_fini, options::OPT_fno_ptrauth_init_fini)) CC1Args.push_back("-fptrauth-init-fini"); + if (!DriverArgs.hasArg(options::OPT_fptrauth_nopac_atexit, + options::OPT_fno_ptrauth_nopac_atexit)) + CC1Args.push_back("-fptrauth-nopac-atexit"); + if (!DriverArgs.hasArg(options::OPT_fptrauth_nopac_throw, + options::OPT_fno_ptrauth_nopac_throw)) + CC1Args.push_back("-fptrauth-nopac-throw"); + + if (!DriverArgs.hasArg(options::OPT_fptrauth_cxx_function_pointer_zero_discrimination, + options::OPT_fno_ptrauth_cxx_function_pointer_zero_discrimination)) + CC1Args.push_back("-fptrauth-cxx-function-pointer-zero-discrimination"); + + if (!DriverArgs.hasArg(options::OPT_fptrauth_cxx_virtual_function_pointer_zero_discrimination, + options::OPT_fno_ptrauth_cxx_virtual_function_pointer_zero_discrimination)) + CC1Args.push_back("-fptrauth-cxx-virtual-function-pointer-zero-discrimination"); + + if (!DriverArgs.hasArg(options::OPT_fptrauth_init_fini_zero_discrimination, + options::OPT_fno_ptrauth_init_fini_zero_discrimination)) + CC1Args.push_back("-fptrauth-init-fini-zero-discrimination"); + + if (!DriverArgs.hasArg(options::OPT_fptrauth_mangle_class, + options::OPT_fno_ptrauth_mangle_class)) + CC1Args.push_back("-fptrauth-mangle-class"); + + if (!DriverArgs.hasArg(options::OPT_fptrauth_mangle_func, + options::OPT_fno_ptrauth_mangle_func)) + CC1Args.push_back("-fptrauth-mangle-func"); + + if (!DriverArgs.hasArg(options::OPT_fptrauth_mangle_cxxabi, + options::OPT_fno_ptrauth_mangle_func)) + CC1Args.push_back("-fptrauth-mangle-cxxabi"); } static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, @@ -1837,6 +1883,14 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, options::OPT_fno_ptrauth_intrinsics); Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_calls, options::OPT_fno_ptrauth_calls); + Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_icall, + options::OPT_fno_ptrauth_icall); + Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_vcall, + options::OPT_fno_ptrauth_vcall); + Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_mfcall, + options::OPT_fno_ptrauth_mfcall); + Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_vptr, + options::OPT_fno_ptrauth_vptr); Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_returns, options::OPT_fno_ptrauth_returns); Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_auth_traps, @@ -1858,6 +1912,32 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_indirect_gotos, options::OPT_fno_ptrauth_indirect_gotos); + Args.addOptInFlag( + CmdArgs, options::OPT_fptrauth_cxx_function_pointer_zero_discrimination, + options::OPT_fno_ptrauth_cxx_function_pointer_zero_discrimination); + Args.addOptInFlag( + CmdArgs, options::OPT_fptrauth_cxx_virtual_function_pointer_zero_discrimination, + options::OPT_fno_ptrauth_cxx_virtual_function_pointer_zero_discrimination); + Args.addOptInFlag( + CmdArgs, options::OPT_fptrauth_init_fini_zero_discrimination, + options::OPT_fno_ptrauth_init_fini_zero_discrimination); + Args.addOptInFlag( + CmdArgs, options::OPT_fptrauth_mangle_class, + options::OPT_fno_ptrauth_mangle_class); + Args.addOptInFlag( + CmdArgs, options::OPT_fptrauth_mangle_func, + options::OPT_fno_ptrauth_mangle_func); + Args.addOptInFlag( + CmdArgs, options::OPT_fptrauth_mangle_cxxabi, + options::OPT_fno_ptrauth_mangle_cxxabi); + + + Args.addOptInFlag( + CmdArgs, options::OPT_fptrauth_nopac_atexit, + options::OPT_fno_ptrauth_nopac_atexit); + Args.addOptInFlag( + CmdArgs, options::OPT_fptrauth_nopac_throw, + options::OPT_fno_ptrauth_nopac_throw); } void Clang::AddLoongArchTargetArgs(const ArgList &Args, @@ -6603,6 +6683,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fraw_string_literals, options::OPT_fno_raw_string_literals); + Args.AddLastArg(CmdArgs, options::OPT_fuse_nopac_attribute, + options::OPT_fno_use_nopac_attribute); + if (Args.hasFlag(options::OPT_femulated_tls, options::OPT_fno_emulated_tls, Triple.hasDefaultEmulatedTLS())) CmdArgs.push_back("-femulated-tls"); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 028fdb2cc6b9dac7684fc16fab46d82b906f11f9..98f604467c414a92ef689e297fcf4a8b3dc9337e 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1475,15 +1475,17 @@ void CompilerInvocation::setDefaultPointerAuthOptions( PointerAuthOptions &Opts, const LangOptions &LangOpts, const llvm::Triple &Triple) { assert(Triple.getArch() == llvm::Triple::aarch64); - if (LangOpts.PointerAuthCalls) { - using Key = PointerAuthSchema::ARM8_3Key; - using Discrimination = PointerAuthSchema::Discrimination; - // If you change anything here, be sure to update . + using Key = PointerAuthSchema::ARM8_3Key; + using Discrimination = PointerAuthSchema::Discrimination; + // If you change anything here, be sure to update . + if (LangOpts.PointerAuthCalls || LangOpts.IndirectPointerAuthCallOnly) { Opts.FunctionPointers = PointerAuthSchema( Key::ASIA, false, LangOpts.PointerAuthFunctionTypeDiscrimination ? Discrimination::Type : Discrimination::None); + } + if (LangOpts.PointerAuthCalls || LangOpts.VTablePointerAuthOnly) { Opts.CXXVTablePointers = PointerAuthSchema( Key::ASDA, LangOpts.PointerAuthVTPtrAddressDiscrimination, LangOpts.PointerAuthVTPtrTypeDiscrimination ? Discrimination::Type @@ -1499,10 +1501,27 @@ void CompilerInvocation::setDefaultPointerAuthOptions( Opts.CXXVTTVTablePointers = PointerAuthSchema(Key::ASDA, false, Discrimination::None); - Opts.CXXVirtualFunctionPointers = Opts.CXXVirtualVariadicFunctionPointers = - PointerAuthSchema(Key::ASIA, true, Discrimination::Decl); - Opts.CXXMemberFunctionPointers = - PointerAuthSchema(Key::ASIA, false, Discrimination::Type); + } + + + if (LangOpts.PointerAuthCalls || LangOpts.VirtualFunctionPointerAuthCallOnly) { + if (LangOpts.PointerAuthCxxVirtualFunctionPointerZeroDiscrimination) { + Opts.CXXVirtualFunctionPointers = Opts.CXXVirtualVariadicFunctionPointers = + PointerAuthSchema(Key::ASIA, false, Discrimination::None); + } else { + Opts.CXXVirtualFunctionPointers = Opts.CXXVirtualVariadicFunctionPointers = + PointerAuthSchema(Key::ASIA, true, Discrimination::Decl); + } + } + + if (LangOpts.PointerAuthCalls || LangOpts.MemberFunctionPointerAuthCallOnly) { + if (LangOpts.PointerAuthCxxFunctionPointerZeroDiscrimination) { + Opts.CXXMemberFunctionPointers = + PointerAuthSchema(Key::ASIA, false, Discrimination::None); + } else { + Opts.CXXMemberFunctionPointers = + PointerAuthSchema(Key::ASIA, false, Discrimination::Type); + } } Opts.ReturnAddresses = LangOpts.PointerAuthReturns; Opts.AuthTraps = LangOpts.PointerAuthAuthTraps; @@ -1514,6 +1533,8 @@ static void parsePointerAuthOptions(PointerAuthOptions &Opts, const llvm::Triple &Triple, DiagnosticsEngine &Diags) { if (!LangOpts.PointerAuthCalls && !LangOpts.PointerAuthReturns && + !LangOpts.IndirectPointerAuthCallOnly && !LangOpts.VirtualFunctionPointerAuthCallOnly && + !LangOpts.MemberFunctionPointerAuthCallOnly && !LangOpts.VTablePointerAuthOnly && !LangOpts.PointerAuthAuthTraps && !LangOpts.PointerAuthIndirectGotos) return; @@ -3416,6 +3437,14 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts, GenerateArg(Consumer, OPT_fptrauth_intrinsics); if (Opts.PointerAuthCalls) GenerateArg(Consumer, OPT_fptrauth_calls); + if (Opts.IndirectPointerAuthCallOnly) + GenerateArg(Consumer, OPT_fptrauth_icall); + if (Opts.VirtualFunctionPointerAuthCallOnly) + GenerateArg(Consumer, OPT_fptrauth_vcall); + if (Opts.MemberFunctionPointerAuthCallOnly) + GenerateArg(Consumer, OPT_fptrauth_mfcall); + if (Opts.VTablePointerAuthOnly) + GenerateArg(Consumer, OPT_fptrauth_vptr); if (Opts.PointerAuthReturns) GenerateArg(Consumer, OPT_fptrauth_returns); if (Opts.PointerAuthIndirectGotos) @@ -3433,12 +3462,34 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts, GenerateArg(Consumer, OPT_fptrauth_init_fini); if (Opts.PointerAuthFunctionTypeDiscrimination) GenerateArg(Consumer, OPT_fptrauth_function_pointer_type_discrimination); + if (Opts.PointerAuthCxxFunctionPointerZeroDiscrimination) + GenerateArg(Consumer, OPT_fptrauth_cxx_function_pointer_zero_discrimination); + if (Opts.PointerAuthCxxVirtualFunctionPointerZeroDiscrimination) + GenerateArg(Consumer, OPT_fptrauth_cxx_virtual_function_pointer_zero_discrimination); + if (Opts.PointerAuthInitFiniZeroDiscrimination) + GenerateArg(Consumer, OPT_fptrauth_init_fini_zero_discrimination); + + if (Opts.PointerAuthMangleClass) + GenerateArg(Consumer, OPT_fptrauth_mangle_class); + if (Opts.PointerAuthMangleFunc) + GenerateArg(Consumer, OPT_fptrauth_mangle_func); + if (Opts.PointerAuthMangleCxxabi) + GenerateArg(Consumer, OPT_fptrauth_mangle_cxxabi); + + if (Opts.PointerAuthNoPacAtexit) + GenerateArg(Consumer, OPT_fptrauth_nopac_atexit); + if (Opts.PointerAuthNoPacThrow) + GenerateArg(Consumer, OPT_fptrauth_nopac_throw); } static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags) { Opts.PointerAuthIntrinsics = Args.hasArg(OPT_fptrauth_intrinsics); Opts.PointerAuthCalls = Args.hasArg(OPT_fptrauth_calls); + Opts.IndirectPointerAuthCallOnly = Args.hasArg(OPT_fptrauth_icall); + Opts.VirtualFunctionPointerAuthCallOnly = Args.hasArg(OPT_fptrauth_vcall); + Opts.MemberFunctionPointerAuthCallOnly = Args.hasArg(OPT_fptrauth_mfcall); + Opts.VTablePointerAuthOnly = Args.hasArg(OPT_fptrauth_vptr); Opts.PointerAuthReturns = Args.hasArg(OPT_fptrauth_returns); Opts.PointerAuthIndirectGotos = Args.hasArg(OPT_fptrauth_indirect_gotos); Opts.PointerAuthAuthTraps = Args.hasArg(OPT_fptrauth_auth_traps); @@ -3452,6 +3503,22 @@ static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args, Opts.PointerAuthInitFini = Args.hasArg(OPT_fptrauth_init_fini); Opts.PointerAuthFunctionTypeDiscrimination = Args.hasArg(OPT_fptrauth_function_pointer_type_discrimination); + Opts.PointerAuthCxxFunctionPointerZeroDiscrimination = + Args.hasArg(OPT_fptrauth_cxx_function_pointer_zero_discrimination); + Opts.PointerAuthCxxVirtualFunctionPointerZeroDiscrimination = + Args.hasArg(OPT_fptrauth_cxx_virtual_function_pointer_zero_discrimination); + Opts.PointerAuthInitFiniZeroDiscrimination = + Args.hasArg(OPT_fptrauth_init_fini_zero_discrimination); + + Opts.PointerAuthMangleClass = Args.hasArg(OPT_fptrauth_mangle_class); + Opts.PointerAuthMangleFunc = Args.hasArg(OPT_fptrauth_mangle_func); + Opts.PointerAuthMangleCxxabi = Args.hasArg(OPT_fptrauth_mangle_cxxabi); + + + Opts.PointerAuthNoPacAtexit = + Args.hasArg(OPT_fptrauth_nopac_atexit); + Opts.PointerAuthNoPacAtexit = + Args.hasArg(OPT_fptrauth_nopac_throw); } /// Check if input file kind and language standard are compatible. @@ -3968,6 +4035,9 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Diags.Report(diag::err_arc_unsupported_on_runtime); } + if (Args.hasArg(OPT_fno_use_nopac_attribute)) + Opts.UseNopacAttribute = 0; + // ObjCWeakRuntime tracks whether the runtime supports __weak, not // whether the feature is actually enabled. This is predominantly // determined by -fobjc-runtime, but we allow it to be overridden diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 717ddb8339584cf7c200164ad8ba60b7af50a2cb..26d9cc1d0392a8b4d88777960ddb39d27ce304de 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3325,6 +3325,25 @@ static bool EquivalentArrayTypes(QualType Old, QualType New, return Old == New; } +static bool isFuncPtr(QualType T) { + return (T->isFunctionPointerType() || T->isMemberFunctionPointerType()); +} + +// viorel todo: check references also. +static bool areMergeableNoPac(QualType OldType, QualType NewType) { + if(!OldType->isPointerType() || !NewType->isPointerType()) { + return false; + } + if (isFuncPtr(OldType) && isFuncPtr(NewType)) { + return (OldType.getQualifiers().hasNopac() || NewType.getQualifiers().hasNopac()); + } + + QualType OldTypePointee = OldType->getPointeeType(); + QualType NewTypePointee = NewType->getPointeeType(); + + return areMergeableNoPac(OldTypePointee, NewTypePointee); +} + static void mergeParamDeclTypes(ParmVarDecl *NewParam, const ParmVarDecl *OldParam, Sema &S) { @@ -3350,6 +3369,10 @@ static void mergeParamDeclTypes(ParmVarDecl *NewParam, NewParam->setType(NewT); } } + if (areMergeableNoPac(OldParam->getType(), NewParam->getType())) { + bool hasNopac; + NewParam->setType(S.Context.getNopacQualType(NewParam->getType(), hasNopac)); + } const auto *OldParamDT = dyn_cast(OldParam->getType()); const auto *NewParamDT = dyn_cast(NewParam->getType()); if (OldParamDT && NewParamDT && @@ -3869,6 +3892,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S, // use that placeholder, not a deduced type. QualType OldDeclaredReturnType = Old->getDeclaredReturnType(); QualType NewDeclaredReturnType = New->getDeclaredReturnType(); + + OldDeclaredReturnType = Context.removeNopacQualType(OldDeclaredReturnType); + NewDeclaredReturnType = Context.removeNopacQualType(NewDeclaredReturnType); if (!Context.hasSameType(OldDeclaredReturnType, NewDeclaredReturnType) && canFullyTypeCheckRedeclaration(New, Old, NewDeclaredReturnType, OldDeclaredReturnType)) { @@ -4049,12 +4075,15 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S, } } + OldQTypeForComparison = Context.removeNopacQualType(OldQTypeForComparison); + // If the function types are compatible, merge the declarations. Ignore the // exception specifier because it was already checked above in // CheckEquivalentExceptionSpec, and we don't want follow-on diagnostics // about incompatible types under -fms-compatibility. if (Context.hasSameFunctionTypeIgnoringExceptionSpec(OldQTypeForComparison, - NewQType)) + NewQType) || + Context.hasSameFunctionTypeIgnoringNopac(OldQTypeForComparison, NewQType)) return MergeCompatibleFunctionDecls(New, Old, S, MergeTypeWithOld); // If the types are imprecise (due to dependent constructs in friends or diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index e2eada24f9fccbfa1e67bc52d617b4bf85c38248..39d0e8ab766345e150959ba8c9c4c153149142ba 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1656,10 +1656,28 @@ static void handleIFuncAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } static void handleAliasAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + StringRef Str; if (!S.checkStringLiteralArgumentAttr(AL, 0, Str)) return; + auto FD = dyn_cast(D); + // todo: unify this with the test from getMangledNameImpl + bool isPac = S.getLangOpts().PointerAuthMangleFunc && FD && S.Context.isFunctionDeclPtr2Fun(FD) && !FD->isNoPac(); + isPac = isPac + && Str.str() != "__cxa_throw" + && Str.str() != "__cxa_atexit" + && Str.str() != "dl_iterate_phdr" + && Str.str() != "pthread_key_create" + && Str.str() != "pthread_once" + && Str.str() != "__clone" + ; + if(isPac) + { + auto s = new std::string("PAC_" + Str.str()); + Str = s->c_str(); + } + if (S.Context.getTargetInfo().getTriple().isOSDarwin()) { S.Diag(AL.getLoc(), diag::err_alias_not_supported_on_darwin); return; @@ -6131,7 +6149,7 @@ static void handleVTablePointerAuthentication(Sema &S, Decl *D, AL.setInvalid(); } if (KeyType == VTablePointerAuthenticationAttr::DefaultKey && - !S.getLangOpts().PointerAuthCalls) { + !S.getLangOpts().PointerAuthCalls && !S.getLangOpts().VTablePointerAuthOnly) { S.Diag(AL.getLoc(), diag::err_no_default_vtable_pointer_auth) << 0; AL.setInvalid(); } @@ -6154,7 +6172,7 @@ static void handleVTablePointerAuthentication(Sema &S, Decl *D, } if (AddressDiversityMode == VTablePointerAuthenticationAttr::DefaultAddressDiscrimination && - !S.getLangOpts().PointerAuthCalls) { + !S.getLangOpts().PointerAuthCalls && !S.getLangOpts().VTablePointerAuthOnly) { S.Diag(IL->Loc, diag::err_no_default_vtable_pointer_auth) << 1; AL.setInvalid(); } @@ -6175,7 +6193,7 @@ static void handleVTablePointerAuthentication(Sema &S, Decl *D, AL.setInvalid(); } if (ED == VTablePointerAuthenticationAttr::DefaultExtraDiscrimination && - !S.getLangOpts().PointerAuthCalls) { + !S.getLangOpts().PointerAuthCalls && !S.getLangOpts().VTablePointerAuthOnly) { S.Diag(AL.getLoc(), diag::err_no_default_vtable_pointer_auth) << 2; AL.setInvalid(); } @@ -7100,6 +7118,43 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_VTablePointerAuthentication: handleVTablePointerAuthentication(S, D, AL); break; + + case ParsedAttr::AT_Nopac: + if(!S.getLangOpts().UseNopacAttribute) + { + break; + } + handleSimpleAttribute(S, D, AL); + { + bool hasNopac; + if(FunctionDecl *FD = D->getAsFunction()) + { + S.Context.addNopacFunctionDecl(FD); + } + else if(TypedefNameDecl *TND = dyn_cast (D)) + { + S.Context.AddNopacTypedefNameDecl(TND); + } + else if(VarDecl *VD = dyn_cast (D)) + { + auto t = VD->getType(); + auto t2 = S.Context.getNopacQualType(t, hasNopac); + if(hasNopac) + { + VD->setType(t2); + } + } + else if(FieldDecl *FD = dyn_cast (D)) + { + auto t = FD->getType(); + auto t2 = S.Context.getNopacQualType(t, hasNopac); + if(hasNopac) + { + FD->setType(t2); + } + } + } + break; } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 687b1be9459219f340669eb39f7914a8bda7f598..9d26aeb53b1f0ac096a88c8384bcdec870c09ad8 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -14084,7 +14084,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { QualType MPTy = Context.getMemberPointerType( op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr()); - if (getLangOpts().PointerAuthCalls && MD->isVirtual() && + if ((getLangOpts().PointerAuthCalls || getLangOpts().MemberFunctionPointerAuthCallOnly || + getLangOpts().VirtualFunctionPointerAuthCallOnly) && MD->isVirtual() && !isUnevaluatedContext() && !MPTy->isDependentType()) { // When pointer authentication is enabled, argument and return types of // vitual member functions must be complete. This is because vitrual diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 6fa39cdccef2b9c3c7ccc9a19e9d299fccc5967f..1c3b167c1ed043c9b861bebcaae21edfe8f1e434 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -8492,6 +8492,47 @@ static void HandleHLSLParamModifierAttr(QualType &CurType, CurType = S.getASTContext().getLValueReferenceType(CurType); } +static void HandleNopacTypeAttribute(QualType &type, ParsedAttr &attr, + TypeProcessingState &state) { + /* + auto funproto = type->getAs(); + + if (!type->isFunctionPointerType() && !(funproto && funproto->isVariadic()) && + !type->isMemberFunctionPointerType() && + !type->isInstantiationDependentType()) { + //S.Diag(attr.getLoc(), diag::err_attribute_function_pointers_only) << attr; + attr.setInvalid(); + return; + } + + if (attr.getNumArgs() > 0) { + S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) + << attr << 0; + attr.setInvalid(); + return; + } + */ + + // llvm::outs() << " - HandleNopacTypeAttribute: " << type << "\n"; + + Sema &S = state.getSema(); + int level; + if(!S.Context.isPointerToFunction(type, level)) + { + return; + } + + bool hasNopac; + auto type2 = S.Context.getNopacQualType(type, hasNopac); + if(hasNopac) + { + type = type2; + } + + // llvm::outs() << " - HandleNopacTypeAttribute end\n"; + +} + static void processTypeAttrs(TypeProcessingState &state, QualType &type, TypeAttrLocation TAL, const ParsedAttributesView &attrs, @@ -8558,6 +8599,14 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, attr.setUsedAsTypeAttr(); } break; + case ParsedAttr::AT_Nopac: + if(!state.getSema().getLangOpts().UseNopacAttribute) + { + break; + } + HandleNopacTypeAttribute(type, attr, state); + attr.setUsedAsTypeAttr(); + break; case ParsedAttr::UnknownAttribute: if (attr.isStandardAttributeSyntax()) { diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/child-inheritted-from-parent-in-comdat.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/child-inheritted-from-parent-in-comdat.cpp index 62b09c85ce40a95efff8eb5ac3e3fe3410e8e885..180eb7daf11f17bcad77a3ecde9d2deabcf59ca6 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/child-inheritted-from-parent-in-comdat.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/child-inheritted-from-parent-in-comdat.cpp @@ -4,8 +4,8 @@ // RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -o - -emit-llvm -fhalf-no-semantic-interposition | FileCheck %s // The inline function is emitted in each module with the same comdat -// CHECK: $_ZTS1A = comdat any // CHECK: $_ZTI1A = comdat any +// CHECK: $_ZTS1A = comdat any // CHECK: $_ZTI1B.rtti_proxy = comdat any // The VTable is emitted everywhere used diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/inlined-key-function.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/inlined-key-function.cpp index d5d9a85d4e22f4221f03ee52236a5dd719e52752..70f8289e9df37afa698d3a07953306c2bfcdf196 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/inlined-key-function.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/inlined-key-function.cpp @@ -4,8 +4,8 @@ // RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -o - -emit-llvm | FileCheck %s // CHECK: $_ZTV1A = comdat any -// CHECK: $_ZTS1A = comdat any // CHECK: $_ZTI1A = comdat any +// CHECK: $_ZTS1A = comdat any // CHECK: $_ZTI1A.rtti_proxy = comdat any // The VTable is linkonce_odr and in a comdat here bc it’s key function is inline defined. diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/parent-and-child-in-comdats.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/parent-and-child-in-comdats.cpp index a033ac41868f566d32a2f90f40938b10a528a87b..c1b9a9398219a82e76603242f9201be3c1331933 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/parent-and-child-in-comdats.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/parent-and-child-in-comdats.cpp @@ -8,12 +8,12 @@ // CHECK: $_ZN1A3fooEv = comdat any // CHECK: $_ZN1B3fooEv = comdat any // CHECK: $_ZTV1A = comdat any -// CHECK: $_ZTS1A = comdat any // CHECK: $_ZTI1A = comdat any +// CHECK: $_ZTS1A = comdat any // CHECK: $_ZTI1A.rtti_proxy = comdat any // CHECK: $_ZTV1B = comdat any -// CHECK: $_ZTS1B = comdat any // CHECK: $_ZTI1B = comdat any +// CHECK: $_ZTS1B = comdat any // CHECK: $_ZTI1B.rtti_proxy = comdat any // Both the vtables for A and B are emitted and in their own comdats. diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/parent-vtable-in-comdat.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/parent-vtable-in-comdat.cpp index 341c53146d476d1a7a35e41a5e6b97592cf403ef..d6eda793cc5b4b5647eebee8d25cbdf86839f0f7 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/parent-vtable-in-comdat.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/parent-vtable-in-comdat.cpp @@ -7,17 +7,17 @@ // A::foo() has a comdat since it is an inline function // CHECK: $_ZN1A3fooEv = comdat any // CHECK: $_ZTV1A = comdat any +// CHECK: $_ZTI1A = comdat any // CHECK: $_ZTS1A = comdat any // The VTable for A has its own comdat section bc it has no key function -// CHECK: $_ZTI1A = comdat any // CHECK: $_ZTI1A.rtti_proxy = comdat any // The VTable for A is emitted here and in a comdat section since it has no key function, and is used in this module when creating an instance of A. // CHECK: @_ZTV1A.local = linkonce_odr hidden unnamed_addr constant { [3 x i32] } { [3 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1A.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [3 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [3 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32)] }, comdat($_ZTV1A), align 4 +// CHECK: @_ZTI1A = linkonce_odr constant { ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 8), ptr @_ZTS1A }, comdat, align 8 // CHECK: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr] // CHECK: @_ZTS1A = linkonce_odr constant [3 x i8] c"1A\00", comdat, align 1 -// CHECK: @_ZTI1A = linkonce_odr constant { ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 8), ptr @_ZTS1A }, comdat, align 8 // CHECK: @_ZTI1A.rtti_proxy = linkonce_odr hidden unnamed_addr constant ptr @_ZTI1A, comdat // CHECK: @_ZTV1A = linkonce_odr unnamed_addr alias { [3 x i32] }, ptr @_ZTV1A.local diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/simple-vtable-definition.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/simple-vtable-definition.cpp index 0e88015ab6f3d2c3da01751d034d51d5b1dd26b4..60bbf78991269da7818b1e6f0d204f7c34f03079 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/simple-vtable-definition.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/simple-vtable-definition.cpp @@ -9,9 +9,9 @@ // The vtable definition itself is private so we can take relative references to // it. The vtable symbol will be exposed through a public alias. // CHECK: @_ZTV1A.local = private unnamed_addr constant { [3 x i32] } { [3 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @_ZTI1A.rtti_proxy to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [3 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A3fooEv to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [3 x i32] }, ptr @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32)] }, align 4 +// CHECK: @_ZTI1A ={{.*}} constant { ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 8), ptr @_ZTS1A }, align 8 // CHECK: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr] // CHECK: @_ZTS1A ={{.*}} constant [3 x i8] c"1A\00", align 1 -// CHECK: @_ZTI1A ={{.*}} constant { ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 8), ptr @_ZTS1A }, align 8 // The rtti should be in a comdat // CHECK: @_ZTI1A.rtti_proxy = {{.*}}comdat diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/type-info.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/type-info.cpp index c6ccae587bbff05b8f68903e5c116c697ff008ae..5f1e32122d08825896ee4be46205a1fb5f1bb7b9 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/type-info.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/type-info.cpp @@ -5,12 +5,12 @@ // CHECK: $_ZTI1A.rtti_proxy = comdat any // CHECK: $_ZTI1B.rtti_proxy = comdat any +// CHECK: @_ZTI1A ={{.*}} constant { ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 8), ptr @_ZTS1A }, align 8 // CHECK: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr] // CHECK: @_ZTS1A ={{.*}} constant [3 x i8] c"1A\00", align 1 -// CHECK: @_ZTI1A ={{.*}} constant { ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 8), ptr @_ZTS1A }, align 8 +// CHECK: @_ZTI1B ={{.*}} constant { ptr, ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i32 8), ptr @_ZTS1B, ptr @_ZTI1A }, align 8 // CHECK: @_ZTVN10__cxxabiv120__si_class_type_infoE = external global [0 x ptr] // CHECK: @_ZTS1B ={{.*}} constant [3 x i8] c"1B\00", align 1 -// CHECK: @_ZTI1B ={{.*}} constant { ptr, ptr, ptr } { ptr getelementptr inbounds (i8, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i32 8), ptr @_ZTS1B, ptr @_ZTI1A }, align 8 // CHECK: @_ZTI1A.rtti_proxy = linkonce_odr hidden unnamed_addr constant ptr @_ZTI1A, comdat // CHECK: @_ZTI1B.rtti_proxy = linkonce_odr hidden unnamed_addr constant ptr @_ZTI1B, comdat diff --git a/clang/test/CodeGenCXX/armv7k.cpp b/clang/test/CodeGenCXX/armv7k.cpp index a4a243c162ea3f3bd6967b34ad43994e09fc7dd0..7aa9fd7944cfdff3157bedc7ce24254fced6af6d 100644 --- a/clang/test/CodeGenCXX/armv7k.cpp +++ b/clang/test/CodeGenCXX/armv7k.cpp @@ -50,17 +50,17 @@ namespace test2 { struct __attribute__((visibility("hidden"))) B {}; const std::type_info &b0 = typeid(B); - // CHECK-GLOBALS: @_ZTSN5test21BE = linkonce_odr hidden constant // CHECK-GLOBALS: @_ZTIN5test21BE = linkonce_odr hidden constant { {{.*}}, ptr @_ZTSN5test21BE } + // CHECK-GLOBALS: @_ZTSN5test21BE = linkonce_odr hidden constant const std::type_info &b1 = typeid(B*); - // CHECK-GLOBALS: @_ZTSPN5test21BE = linkonce_odr hidden constant // CHECK-GLOBALS: @_ZTIPN5test21BE = linkonce_odr hidden constant { {{.*}}, ptr @_ZTSPN5test21BE, i32 0, ptr @_ZTIN5test21BE + // CHECK-GLOBALS: @_ZTSPN5test21BE = linkonce_odr hidden constant struct C {}; const std::type_info &c0 = typeid(C); - // CHECK-GLOBALS: @_ZTSN5test21CE = linkonce_odr constant [11 x i8] c"N5test21CE\00" // CHECK-GLOBALS: @_ZTIN5test21CE = linkonce_odr constant { {{.*}}, ptr @_ZTSN5test21CE } + // CHECK-GLOBALS: @_ZTSN5test21CE = linkonce_odr constant [11 x i8] c"N5test21CE\00" } // va_list should be based on "char *" rather than "ptr". diff --git a/clang/test/CodeGenCXX/dynamic-cast-address-space.cpp b/clang/test/CodeGenCXX/dynamic-cast-address-space.cpp index 3d5e32516c7af2fe5075b790fd68115e76cd873c..96a06adb2aac66274f4ed8ab44c959a7e3dc5943 100644 --- a/clang/test/CodeGenCXX/dynamic-cast-address-space.cpp +++ b/clang/test/CodeGenCXX/dynamic-cast-address-space.cpp @@ -10,17 +10,17 @@ B fail; // CHECK: @_ZTV1B = linkonce_odr unnamed_addr addrspace(1) constant { [3 x ptr addrspace(1)] } { [3 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) @_ZTI1B, ptr addrspace(1) addrspacecast (ptr @_ZN1A1fEv to ptr addrspace(1))] }, comdat, align 8 // CHECK: @fail = addrspace(1) global { ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, i32 0, i32 2) }, align 8 // CHECK: @_ZTI1A = external addrspace(1) constant ptr addrspace(1) +// CHECK: @_ZTI1B = linkonce_odr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1B, ptr addrspace(1) @_ZTI1A }, comdat, align 8 // CHECK: @_ZTVN10__cxxabiv120__si_class_type_infoE = external addrspace(1) global [0 x ptr addrspace(1)] // CHECK: @_ZTS1B = linkonce_odr addrspace(1) constant [3 x i8] c"1B\00", comdat, align 1 -// CHECK: @_ZTI1B = linkonce_odr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1B, ptr addrspace(1) @_ZTI1A }, comdat, align 8 // CHECK: @__oclc_ABI_version = weak_odr hidden local_unnamed_addr addrspace(4) constant i32 500 //. // WITH-NONZERO-DEFAULT-AS: @_ZTV1B = linkonce_odr unnamed_addr addrspace(1) constant { [3 x ptr addrspace(1)] } { [3 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) @_ZTI1B, ptr addrspace(1) addrspacecast (ptr @_ZN1A1fEv to ptr addrspace(1))] }, comdat, align 8 // WITH-NONZERO-DEFAULT-AS: @fail = addrspace(1) global { ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds inrange(-16, 8) ({ [3 x ptr addrspace(1)] }, ptr addrspace(1) @_ZTV1B, i32 0, i32 0, i32 2) }, align 8 // WITH-NONZERO-DEFAULT-AS: @_ZTI1A = external addrspace(1) constant ptr addrspace(1) +// WITH-NONZERO-DEFAULT-AS: @_ZTI1B = linkonce_odr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1B, ptr addrspace(1) @_ZTI1A }, comdat, align 8 // WITH-NONZERO-DEFAULT-AS: @_ZTVN10__cxxabiv120__si_class_type_infoE = external addrspace(1) global [0 x ptr addrspace(1)] // WITH-NONZERO-DEFAULT-AS: @_ZTS1B = linkonce_odr addrspace(1) constant [3 x i8] c"1B\00", comdat, align 1 -// WITH-NONZERO-DEFAULT-AS: @_ZTI1B = linkonce_odr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1B, ptr addrspace(1) @_ZTI1A }, comdat, align 8 //. // CHECK-LABEL: define dso_local noundef nonnull align 8 dereferenceable(8) ptr @_Z1fP1A( // CHECK-SAME: ptr noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] personality ptr @__gxx_personality_v0 { diff --git a/clang/test/CodeGenCXX/exceptions-no-rtti.cpp b/clang/test/CodeGenCXX/exceptions-no-rtti.cpp index 7c73285b948f16132df14867a800072d6ddc60ba..a3d969665bdc71fe9a2fa43e0610fd8597b91418 100644 --- a/clang/test/CodeGenCXX/exceptions-no-rtti.cpp +++ b/clang/test/CodeGenCXX/exceptions-no-rtti.cpp @@ -3,8 +3,8 @@ // CHECK: @_ZTIN5test11AE = linkonce_odr constant // CHECK: @_ZTIN5test11BE = linkonce_odr constant // CHECK: @_ZTIN5test11CE = linkonce_odr constant -// CHECK: @_ZTIN5test11DE = linkonce_odr constant // CHECK: @_ZTIPN5test11DE = linkonce_odr constant {{.*}} @_ZTIN5test11DE +// CHECK: @_ZTIN5test11DE = linkonce_odr constant // PR6974: this shouldn't crash namespace test0 { diff --git a/clang/test/CodeGenCXX/implicit-record-visibility.cpp b/clang/test/CodeGenCXX/implicit-record-visibility.cpp index ef388c7b8316a088c7d2cb99b542aae05ec6d494..84ad822702d39bee5c1b41ae55434fb2cb9d7b4f 100644 --- a/clang/test/CodeGenCXX/implicit-record-visibility.cpp +++ b/clang/test/CodeGenCXX/implicit-record-visibility.cpp @@ -7,6 +7,6 @@ // under -fvisibility=hidden the type of function f, due to its va_list (aka // __builtin_va_list, aka __va_list_tag (*)[1]) parameter would be hidden: -// CHECK: @_ZTSFvP13__va_list_tagE = linkonce_odr constant // CHECK: @_ZTIFvP13__va_list_tagE = linkonce_odr constant +// CHECK: @_ZTSFvP13__va_list_tagE = linkonce_odr constant void f(va_list) { (void)typeid(f); } diff --git a/clang/test/CodeGenCXX/mdefault-visibility-export-mapping-rtti.cpp b/clang/test/CodeGenCXX/mdefault-visibility-export-mapping-rtti.cpp index 1af105e915e6363b87c62a86fe9c8482667f8819..2fc0a6a4ee608e19f0d933ae1b433adc6d52704c 100644 --- a/clang/test/CodeGenCXX/mdefault-visibility-export-mapping-rtti.cpp +++ b/clang/test/CodeGenCXX/mdefault-visibility-export-mapping-rtti.cpp @@ -16,20 +16,20 @@ // C is an incomplete class type, so any direct or indirect pointer types should have // internal linkage, as should the type info for C itself. struct C; +// CHECK: @_ZTIP1C = internal constant // CHECK: @_ZTSP1C = internal constant -// CHECK: @_ZTS1C = internal constant // CHECK: @_ZTI1C = internal constant -// CHECK: @_ZTIP1C = internal constant -// CHECK: @_ZTSPP1C = internal constant +// CHECK: @_ZTS1C = internal constant // CHECK: @_ZTIPP1C = internal constant +// CHECK: @_ZTSPP1C = internal constant struct __attribute__((type_visibility("default"))) D; +// CHECK: @_ZTIP1D = internal constant // CHECK: @_ZTSP1D = internal constant -// CHECK: @_ZTS1D = internal constant // CHECK: @_ZTI1D = internal constant -// CHECK: @_ZTIP1D = internal constant -// CHECK: @_ZTSPP1D = internal constant +// CHECK: @_ZTS1D = internal constant // CHECK: @_ZTIPP1D = internal constant +// CHECK: @_ZTSPP1D = internal constant void __attribute__((visibility("default"))) tfunc() { (void)typeid(C *); @@ -46,12 +46,12 @@ void s::foo() {} // UNSPECIFIED-DEF: @_ZTV1s = unnamed_addr constant // UNSPECIFIED-HID: @_ZTV1s = hidden unnamed_addr constant // UNSPECIFIED-EXP: @_ZTV1s = dllexport unnamed_addr constant -// UNSPECIFIED-DEF: @_ZTS1s = constant -// UNSPECIFIED-HID: @_ZTS1s = hidden constant -// UNSPECIFIED-EXP: @_ZTS1s = dllexport constant // UNSPECIFIED-DEF: @_ZTI1s = constant // UNSPECIFIED-HID: @_ZTI1s = hidden constant // UNSPECIFIED-EXP: @_ZTI1s = dllexport constant +// UNSPECIFIED-DEF: @_ZTS1s = constant +// UNSPECIFIED-HID: @_ZTS1s = hidden constant +// UNSPECIFIED-EXP: @_ZTS1s = dllexport constant // explicit default visibility RTTI & vtable struct __attribute__((type_visibility("default"))) t { @@ -61,12 +61,12 @@ void t::foo() {} // EXPLICIT-DEF: @_ZTV1t = unnamed_addr constant // EXPLICIT-HID: @_ZTV1t = hidden unnamed_addr constant // EXPLICIT-EXP: @_ZTV1t = dllexport unnamed_addr constant -// EXPLICIT-DEF: @_ZTS1t = constant -// EXPLICIT-HID: @_ZTS1t = hidden constant -// EXPLICIT-EXP: @_ZTS1t = dllexport constant // EXPLICIT-DEF: @_ZTI1t = constant // EXPLICIT-HID: @_ZTI1t = hidden constant // EXPLICIT-EXP: @_ZTI1t = dllexport constant +// EXPLICIT-DEF: @_ZTS1t = constant +// EXPLICIT-HID: @_ZTS1t = hidden constant +// EXPLICIT-EXP: @_ZTS1t = dllexport constant #ifdef FUNDAMENTAL_IS_EXPLICIT #define TYPE_VIS __attribute__((type_visibility("default"))) @@ -86,511 +86,511 @@ __fundamental_type_info::~__fundamental_type_info() {} // __cxxabiv1::__fundamental_type_info // FUND-DEF: @_ZTVN10__cxxabiv123__fundamental_type_infoE = unnamed_addr constant -// FUND-DEF: @_ZTSN10__cxxabiv123__fundamental_type_infoE = constant // FUND-DEF: @_ZTIN10__cxxabiv123__fundamental_type_infoE = constant +// FUND-DEF: @_ZTSN10__cxxabiv123__fundamental_type_infoE = constant // FUND-HID: @_ZTVN10__cxxabiv123__fundamental_type_infoE = hidden unnamed_addr constant -// FUND-HID: @_ZTSN10__cxxabiv123__fundamental_type_infoE = hidden constant // FUND-HID: @_ZTIN10__cxxabiv123__fundamental_type_infoE = hidden constant +// FUND-HID: @_ZTSN10__cxxabiv123__fundamental_type_infoE = hidden constant // FUND-EXP: @_ZTVN10__cxxabiv123__fundamental_type_infoE = dllexport unnamed_addr constant -// FUND-EXP: @_ZTSN10__cxxabiv123__fundamental_type_infoE = dllexport constant // FUND-EXP: @_ZTIN10__cxxabiv123__fundamental_type_infoE = dllexport constant +// FUND-EXP: @_ZTSN10__cxxabiv123__fundamental_type_infoE = dllexport constant // void -// FUND-DEF: @_ZTSv = constant // FUND-DEF: @_ZTIv = constant -// FUND-DEF: @_ZTSPv = constant +// FUND-DEF: @_ZTSv = constant // FUND-DEF: @_ZTIPv = constant -// FUND-DEF: @_ZTSPKv = constant +// FUND-DEF: @_ZTSPv = constant // FUND-DEF: @_ZTIPKv = constant -// FUND-HID: @_ZTSv = hidden constant +// FUND-DEF: @_ZTSPKv = constant // FUND-HID: @_ZTIv = hidden constant -// FUND-HID: @_ZTSPv = hidden constant +// FUND-HID: @_ZTSv = hidden constant // FUND-HID: @_ZTIPv = hidden constant -// FUND-HID: @_ZTSPKv = hidden constant +// FUND-HID: @_ZTSPv = hidden constant // FUND-HID: @_ZTIPKv = hidden constant -// FUND-EXP: @_ZTSv = dllexport constant +// FUND-HID: @_ZTSPKv = hidden constant // FUND-EXP: @_ZTIv = dllexport constant -// FUND-EXP: @_ZTSPv = dllexport constant +// FUND-EXP: @_ZTSv = dllexport constant // FUND-EXP: @_ZTIPv = dllexport constant -// FUND-EXP: @_ZTSPKv = dllexport constant +// FUND-EXP: @_ZTSPv = dllexport constant // FUND-EXP: @_ZTIPKv = dllexport constant +// FUND-EXP: @_ZTSPKv = dllexport constant // std::nullptr_t -// FUND-DEF: @_ZTSDn = constant // FUND-DEF: @_ZTIDn = constant -// FUND-DEF: @_ZTSPDn = constant +// FUND-DEF: @_ZTSDn = constant // FUND-DEF: @_ZTIPDn = constant -// FUND-DEF: @_ZTSPKDn = constant +// FUND-DEF: @_ZTSPDn = constant // FUND-DEF: @_ZTIPKDn = constant -// FUND-HID: @_ZTSDn = hidden constant +// FUND-DEF: @_ZTSPKDn = constant // FUND-HID: @_ZTIDn = hidden constant -// FUND-HID: @_ZTSPDn = hidden constant +// FUND-HID: @_ZTSDn = hidden constant // FUND-HID: @_ZTIPDn = hidden constant -// FUND-HID: @_ZTSPKDn = hidden constant +// FUND-HID: @_ZTSPDn = hidden constant // FUND-HID: @_ZTIPKDn = hidden constant -// FUND-EXP: @_ZTSDn = dllexport constant +// FUND-HID: @_ZTSPKDn = hidden constant // FUND-EXP: @_ZTIDn = dllexport constant -// FUND-EXP: @_ZTSPDn = dllexport constant +// FUND-EXP: @_ZTSDn = dllexport constant // FUND-EXP: @_ZTIPDn = dllexport constant -// FUND-EXP: @_ZTSPKDn = dllexport constant +// FUND-EXP: @_ZTSPDn = dllexport constant // FUND-EXP: @_ZTIPKDn = dllexport constant +// FUND-EXP: @_ZTSPKDn = dllexport constant // bool -// FUND-DEF: @_ZTSb = constant // FUND-DEF: @_ZTIb = constant -// FUND-DEF: @_ZTSPb = constant +// FUND-DEF: @_ZTSb = constant // FUND-DEF: @_ZTIPb = constant -// FUND-DEF: @_ZTSPKb = constant +// FUND-DEF: @_ZTSPb = constant // FUND-DEF: @_ZTIPKb = constant -// FUND-HID: @_ZTSb = hidden constant +// FUND-DEF: @_ZTSPKb = constant // FUND-HID: @_ZTIb = hidden constant -// FUND-HID: @_ZTSPb = hidden constant +// FUND-HID: @_ZTSb = hidden constant // FUND-HID: @_ZTIPb = hidden constant -// FUND-HID: @_ZTSPKb = hidden constant +// FUND-HID: @_ZTSPb = hidden constant // FUND-HID: @_ZTIPKb = hidden constant -// FUND-EXP: @_ZTSb = dllexport constant +// FUND-HID: @_ZTSPKb = hidden constant // FUND-EXP: @_ZTIb = dllexport constant -// FUND-EXP: @_ZTSPb = dllexport constant +// FUND-EXP: @_ZTSb = dllexport constant // FUND-EXP: @_ZTIPb = dllexport constant -// FUND-EXP: @_ZTSPKb = dllexport constant +// FUND-EXP: @_ZTSPb = dllexport constant // FUND-EXP: @_ZTIPKb = dllexport constant +// FUND-EXP: @_ZTSPKb = dllexport constant // wchar_t -// FUND-DEF: @_ZTSw = constant // FUND-DEF: @_ZTIw = constant -// FUND-DEF: @_ZTSPw = constant +// FUND-DEF: @_ZTSw = constant // FUND-DEF: @_ZTIPw = constant -// FUND-DEF: @_ZTSPKw = constant +// FUND-DEF: @_ZTSPw = constant // FUND-DEF: @_ZTIPKw = constant -// FUND-HID: @_ZTSw = hidden constant +// FUND-DEF: @_ZTSPKw = constant // FUND-HID: @_ZTIw = hidden constant -// FUND-HID: @_ZTSPw = hidden constant +// FUND-HID: @_ZTSw = hidden constant // FUND-HID: @_ZTIPw = hidden constant -// FUND-HID: @_ZTSPKw = hidden constant +// FUND-HID: @_ZTSPw = hidden constant // FUND-HID: @_ZTIPKw = hidden constant -// FUND-EXP: @_ZTSw = dllexport constant +// FUND-HID: @_ZTSPKw = hidden constant // FUND-EXP: @_ZTIw = dllexport constant -// FUND-EXP: @_ZTSPw = dllexport constant +// FUND-EXP: @_ZTSw = dllexport constant // FUND-EXP: @_ZTIPw = dllexport constant -// FUND-EXP: @_ZTSPKw = dllexport constant +// FUND-EXP: @_ZTSPw = dllexport constant // FUND-EXP: @_ZTIPKw = dllexport constant +// FUND-EXP: @_ZTSPKw = dllexport constant // char -// FUND-DEF: @_ZTSc = constant // FUND-DEF: @_ZTIc = constant -// FUND-DEF: @_ZTSPc = constant +// FUND-DEF: @_ZTSc = constant // FUND-DEF: @_ZTIPc = constant -// FUND-DEF: @_ZTSPKc = constant +// FUND-DEF: @_ZTSPc = constant // FUND-DEF: @_ZTIPKc = constant -// FUND-HID: @_ZTSc = hidden constant +// FUND-DEF: @_ZTSPKc = constant // FUND-HID: @_ZTIc = hidden constant -// FUND-HID: @_ZTSPc = hidden constant +// FUND-HID: @_ZTSc = hidden constant // FUND-HID: @_ZTIPc = hidden constant -// FUND-HID: @_ZTSPKc = hidden constant +// FUND-HID: @_ZTSPc = hidden constant // FUND-HID: @_ZTIPKc = hidden constant -// FUND-EXP: @_ZTSc = dllexport constant +// FUND-HID: @_ZTSPKc = hidden constant // FUND-EXP: @_ZTIc = dllexport constant -// FUND-EXP: @_ZTSPc = dllexport constant +// FUND-EXP: @_ZTSc = dllexport constant // FUND-EXP: @_ZTIPc = dllexport constant -// FUND-EXP: @_ZTSPKc = dllexport constant +// FUND-EXP: @_ZTSPc = dllexport constant // FUND-EXP: @_ZTIPKc = dllexport constant +// FUND-EXP: @_ZTSPKc = dllexport constant // unsigned char -// FUND-DEF: @_ZTSh = constant // FUND-DEF: @_ZTIh = constant -// FUND-DEF: @_ZTSPh = constant +// FUND-DEF: @_ZTSh = constant // FUND-DEF: @_ZTIPh = constant -// FUND-DEF: @_ZTSPKh = constant +// FUND-DEF: @_ZTSPh = constant // FUND-DEF: @_ZTIPKh = constant -// FUND-HID: @_ZTSh = hidden constant +// FUND-DEF: @_ZTSPKh = constant // FUND-HID: @_ZTIh = hidden constant -// FUND-HID: @_ZTSPh = hidden constant +// FUND-HID: @_ZTSh = hidden constant // FUND-HID: @_ZTIPh = hidden constant -// FUND-HID: @_ZTSPKh = hidden constant +// FUND-HID: @_ZTSPh = hidden constant // FUND-HID: @_ZTIPKh = hidden constant -// FUND-EXP: @_ZTSh = dllexport constant +// FUND-HID: @_ZTSPKh = hidden constant // FUND-EXP: @_ZTIh = dllexport constant -// FUND-EXP: @_ZTSPh = dllexport constant +// FUND-EXP: @_ZTSh = dllexport constant // FUND-EXP: @_ZTIPh = dllexport constant -// FUND-EXP: @_ZTSPKh = dllexport constant +// FUND-EXP: @_ZTSPh = dllexport constant // FUND-EXP: @_ZTIPKh = dllexport constant +// FUND-EXP: @_ZTSPKh = dllexport constant // signed char -// FUND-DEF: @_ZTSa = constant // FUND-DEF: @_ZTIa = constant -// FUND-DEF: @_ZTSPa = constant +// FUND-DEF: @_ZTSa = constant // FUND-DEF: @_ZTIPa = constant -// FUND-DEF: @_ZTSPKa = constant +// FUND-DEF: @_ZTSPa = constant // FUND-DEF: @_ZTIPKa = constant -// FUND-HID: @_ZTSa = hidden constant +// FUND-DEF: @_ZTSPKa = constant // FUND-HID: @_ZTIa = hidden constant -// FUND-HID: @_ZTSPa = hidden constant +// FUND-HID: @_ZTSa = hidden constant // FUND-HID: @_ZTIPa = hidden constant -// FUND-HID: @_ZTSPKa = hidden constant +// FUND-HID: @_ZTSPa = hidden constant // FUND-HID: @_ZTIPKa = hidden constant -// FUND-EXP: @_ZTSa = dllexport constant +// FUND-HID: @_ZTSPKa = hidden constant // FUND-EXP: @_ZTIa = dllexport constant -// FUND-EXP: @_ZTSPa = dllexport constant +// FUND-EXP: @_ZTSa = dllexport constant // FUND-EXP: @_ZTIPa = dllexport constant -// FUND-EXP: @_ZTSPKa = dllexport constant +// FUND-EXP: @_ZTSPa = dllexport constant // FUND-EXP: @_ZTIPKa = dllexport constant +// FUND-EXP: @_ZTSPKa = dllexport constant // short -// FUND-DEF: @_ZTSs = constant // FUND-DEF: @_ZTIs = constant -// FUND-DEF: @_ZTSPs = constant +// FUND-DEF: @_ZTSs = constant // FUND-DEF: @_ZTIPs = constant -// FUND-DEF: @_ZTSPKs = constant +// FUND-DEF: @_ZTSPs = constant // FUND-DEF: @_ZTIPKs = constant -// FUND-HID: @_ZTSs = hidden constant +// FUND-DEF: @_ZTSPKs = constant // FUND-HID: @_ZTIs = hidden constant -// FUND-HID: @_ZTSPs = hidden constant +// FUND-HID: @_ZTSs = hidden constant // FUND-HID: @_ZTIPs = hidden constant -// FUND-HID: @_ZTSPKs = hidden constant +// FUND-HID: @_ZTSPs = hidden constant // FUND-HID: @_ZTIPKs = hidden constant -// FUND-EXP: @_ZTSs = dllexport constant +// FUND-HID: @_ZTSPKs = hidden constant // FUND-EXP: @_ZTIs = dllexport constant -// FUND-EXP: @_ZTSPs = dllexport constant +// FUND-EXP: @_ZTSs = dllexport constant // FUND-EXP: @_ZTIPs = dllexport constant -// FUND-EXP: @_ZTSPKs = dllexport constant +// FUND-EXP: @_ZTSPs = dllexport constant // FUND-EXP: @_ZTIPKs = dllexport constant +// FUND-EXP: @_ZTSPKs = dllexport constant // unsigned short -// FUND-DEF: @_ZTSt = constant // FUND-DEF: @_ZTIt = constant -// FUND-DEF: @_ZTSPt = constant +// FUND-DEF: @_ZTSt = constant // FUND-DEF: @_ZTIPt = constant -// FUND-DEF: @_ZTSPKt = constant +// FUND-DEF: @_ZTSPt = constant // FUND-DEF: @_ZTIPKt = constant -// FUND-HID: @_ZTSt = hidden constant +// FUND-DEF: @_ZTSPKt = constant // FUND-HID: @_ZTIt = hidden constant -// FUND-HID: @_ZTSPt = hidden constant +// FUND-HID: @_ZTSt = hidden constant // FUND-HID: @_ZTIPt = hidden constant -// FUND-HID: @_ZTSPKt = hidden constant +// FUND-HID: @_ZTSPt = hidden constant // FUND-HID: @_ZTIPKt = hidden constant -// FUND-EXP: @_ZTSt = dllexport constant +// FUND-HID: @_ZTSPKt = hidden constant // FUND-EXP: @_ZTIt = dllexport constant -// FUND-EXP: @_ZTSPt = dllexport constant +// FUND-EXP: @_ZTSt = dllexport constant // FUND-EXP: @_ZTIPt = dllexport constant -// FUND-EXP: @_ZTSPKt = dllexport constant +// FUND-EXP: @_ZTSPt = dllexport constant // FUND-EXP: @_ZTIPKt = dllexport constant +// FUND-EXP: @_ZTSPKt = dllexport constant // int -// FUND-DEF: @_ZTSi = constant // FUND-DEF: @_ZTIi = constant -// FUND-DEF: @_ZTSPi = constant +// FUND-DEF: @_ZTSi = constant // FUND-DEF: @_ZTIPi = constant -// FUND-DEF: @_ZTSPKi = constant +// FUND-DEF: @_ZTSPi = constant // FUND-DEF: @_ZTIPKi = constant -// FUND-HID: @_ZTSi = hidden constant +// FUND-DEF: @_ZTSPKi = constant // FUND-HID: @_ZTIi = hidden constant -// FUND-HID: @_ZTSPi = hidden constant +// FUND-HID: @_ZTSi = hidden constant // FUND-HID: @_ZTIPi = hidden constant -// FUND-HID: @_ZTSPKi = hidden constant +// FUND-HID: @_ZTSPi = hidden constant // FUND-HID: @_ZTIPKi = hidden constant -// FUND-EXP: @_ZTSi = dllexport constant +// FUND-HID: @_ZTSPKi = hidden constant // FUND-EXP: @_ZTIi = dllexport constant -// FUND-EXP: @_ZTSPi = dllexport constant +// FUND-EXP: @_ZTSi = dllexport constant // FUND-EXP: @_ZTIPi = dllexport constant -// FUND-EXP: @_ZTSPKi = dllexport constant +// FUND-EXP: @_ZTSPi = dllexport constant // FUND-EXP: @_ZTIPKi = dllexport constant +// FUND-EXP: @_ZTSPKi = dllexport constant // unsigned int -// FUND-DEF: @_ZTSj = constant // FUND-DEF: @_ZTIj = constant -// FUND-DEF: @_ZTSPj = constant +// FUND-DEF: @_ZTSj = constant // FUND-DEF: @_ZTIPj = constant -// FUND-DEF: @_ZTSPKj = constant +// FUND-DEF: @_ZTSPj = constant // FUND-DEF: @_ZTIPKj = constant -// FUND-HID: @_ZTSj = hidden constant +// FUND-DEF: @_ZTSPKj = constant // FUND-HID: @_ZTIj = hidden constant -// FUND-HID: @_ZTSPj = hidden constant +// FUND-HID: @_ZTSj = hidden constant // FUND-HID: @_ZTIPj = hidden constant -// FUND-HID: @_ZTSPKj = hidden constant +// FUND-HID: @_ZTSPj = hidden constant // FUND-HID: @_ZTIPKj = hidden constant -// FUND-EXP: @_ZTSj = dllexport constant +// FUND-HID: @_ZTSPKj = hidden constant // FUND-EXP: @_ZTIj = dllexport constant -// FUND-EXP: @_ZTSPj = dllexport constant +// FUND-EXP: @_ZTSj = dllexport constant // FUND-EXP: @_ZTIPj = dllexport constant -// FUND-EXP: @_ZTSPKj = dllexport constant +// FUND-EXP: @_ZTSPj = dllexport constant // FUND-EXP: @_ZTIPKj = dllexport constant +// FUND-EXP: @_ZTSPKj = dllexport constant // long -// FUND-DEF: @_ZTSl = constant // FUND-DEF: @_ZTIl = constant -// FUND-DEF: @_ZTSPl = constant +// FUND-DEF: @_ZTSl = constant // FUND-DEF: @_ZTIPl = constant -// FUND-DEF: @_ZTSPKl = constant +// FUND-DEF: @_ZTSPl = constant // FUND-DEF: @_ZTIPKl = constant -// FUND-HID: @_ZTSl = hidden constant +// FUND-DEF: @_ZTSPKl = constant // FUND-HID: @_ZTIl = hidden constant -// FUND-HID: @_ZTSPl = hidden constant +// FUND-HID: @_ZTSl = hidden constant // FUND-HID: @_ZTIPl = hidden constant -// FUND-HID: @_ZTSPKl = hidden constant +// FUND-HID: @_ZTSPl = hidden constant // FUND-HID: @_ZTIPKl = hidden constant -// FUND-EXP: @_ZTSl = dllexport constant +// FUND-HID: @_ZTSPKl = hidden constant // FUND-EXP: @_ZTIl = dllexport constant -// FUND-EXP: @_ZTSPl = dllexport constant +// FUND-EXP: @_ZTSl = dllexport constant // FUND-EXP: @_ZTIPl = dllexport constant -// FUND-EXP: @_ZTSPKl = dllexport constant +// FUND-EXP: @_ZTSPl = dllexport constant // FUND-EXP: @_ZTIPKl = dllexport constant +// FUND-EXP: @_ZTSPKl = dllexport constant // unsigned long -// FUND-DEF: @_ZTSm = constant // FUND-DEF: @_ZTIm = constant -// FUND-DEF: @_ZTSPm = constant +// FUND-DEF: @_ZTSm = constant // FUND-DEF: @_ZTIPm = constant -// FUND-DEF: @_ZTSPKm = constant +// FUND-DEF: @_ZTSPm = constant // FUND-DEF: @_ZTIPKm = constant -// FUND-HID: @_ZTSm = hidden constant +// FUND-DEF: @_ZTSPKm = constant // FUND-HID: @_ZTIm = hidden constant -// FUND-HID: @_ZTSPm = hidden constant +// FUND-HID: @_ZTSm = hidden constant // FUND-HID: @_ZTIPm = hidden constant -// FUND-HID: @_ZTSPKm = hidden constant +// FUND-HID: @_ZTSPm = hidden constant // FUND-HID: @_ZTIPKm = hidden constant -// FUND-EXP: @_ZTSm = dllexport constant +// FUND-HID: @_ZTSPKm = hidden constant // FUND-EXP: @_ZTIm = dllexport constant -// FUND-EXP: @_ZTSPm = dllexport constant +// FUND-EXP: @_ZTSm = dllexport constant // FUND-EXP: @_ZTIPm = dllexport constant -// FUND-EXP: @_ZTSPKm = dllexport constant +// FUND-EXP: @_ZTSPm = dllexport constant // FUND-EXP: @_ZTIPKm = dllexport constant +// FUND-EXP: @_ZTSPKm = dllexport constant // long long -// FUND-DEF: @_ZTSx = constant // FUND-DEF: @_ZTIx = constant -// FUND-DEF: @_ZTSPx = constant +// FUND-DEF: @_ZTSx = constant // FUND-DEF: @_ZTIPx = constant -// FUND-DEF: @_ZTSPKx = constant +// FUND-DEF: @_ZTSPx = constant // FUND-DEF: @_ZTIPKx = constant -// FUND-HID: @_ZTSx = hidden constant +// FUND-DEF: @_ZTSPKx = constant // FUND-HID: @_ZTIx = hidden constant -// FUND-HID: @_ZTSPx = hidden constant +// FUND-HID: @_ZTSx = hidden constant // FUND-HID: @_ZTIPx = hidden constant -// FUND-HID: @_ZTSPKx = hidden constant +// FUND-HID: @_ZTSPx = hidden constant // FUND-HID: @_ZTIPKx = hidden constant -// FUND-EXP: @_ZTSx = dllexport constant +// FUND-HID: @_ZTSPKx = hidden constant // FUND-EXP: @_ZTIx = dllexport constant -// FUND-EXP: @_ZTSPx = dllexport constant +// FUND-EXP: @_ZTSx = dllexport constant // FUND-EXP: @_ZTIPx = dllexport constant -// FUND-EXP: @_ZTSPKx = dllexport constant +// FUND-EXP: @_ZTSPx = dllexport constant // FUND-EXP: @_ZTIPKx = dllexport constant +// FUND-EXP: @_ZTSPKx = dllexport constant // unsigned long long -// FUND-DEF: @_ZTSy = constant // FUND-DEF: @_ZTIy = constant -// FUND-DEF: @_ZTSPy = constant +// FUND-DEF: @_ZTSy = constant // FUND-DEF: @_ZTIPy = constant -// FUND-DEF: @_ZTSPKy = constant +// FUND-DEF: @_ZTSPy = constant // FUND-DEF: @_ZTIPKy = constant -// FUND-HID: @_ZTSy = hidden constant +// FUND-DEF: @_ZTSPKy = constant // FUND-HID: @_ZTIy = hidden constant -// FUND-HID: @_ZTSPy = hidden constant +// FUND-HID: @_ZTSy = hidden constant // FUND-HID: @_ZTIPy = hidden constant -// FUND-HID: @_ZTSPKy = hidden constant +// FUND-HID: @_ZTSPy = hidden constant // FUND-HID: @_ZTIPKy = hidden constant -// FUND-EXP: @_ZTSy = dllexport constant +// FUND-HID: @_ZTSPKy = hidden constant // FUND-EXP: @_ZTIy = dllexport constant -// FUND-EXP: @_ZTSPy = dllexport constant +// FUND-EXP: @_ZTSy = dllexport constant // FUND-EXP: @_ZTIPy = dllexport constant -// FUND-EXP: @_ZTSPKy = dllexport constant +// FUND-EXP: @_ZTSPy = dllexport constant // FUND-EXP: @_ZTIPKy = dllexport constant +// FUND-EXP: @_ZTSPKy = dllexport constant // __int128 -// FUND-DEF: @_ZTSn = constant // FUND-DEF: @_ZTIn = constant -// FUND-DEF: @_ZTSPn = constant +// FUND-DEF: @_ZTSn = constant // FUND-DEF: @_ZTIPn = constant -// FUND-DEF: @_ZTSPKn = constant +// FUND-DEF: @_ZTSPn = constant // FUND-DEF: @_ZTIPKn = constant -// FUND-HID: @_ZTSn = hidden constant +// FUND-DEF: @_ZTSPKn = constant // FUND-HID: @_ZTIn = hidden constant -// FUND-HID: @_ZTSPn = hidden constant +// FUND-HID: @_ZTSn = hidden constant // FUND-HID: @_ZTIPn = hidden constant -// FUND-HID: @_ZTSPKn = hidden constant +// FUND-HID: @_ZTSPn = hidden constant // FUND-HID: @_ZTIPKn = hidden constant -// FUND-EXP: @_ZTSn = dllexport constant +// FUND-HID: @_ZTSPKn = hidden constant // FUND-EXP: @_ZTIn = dllexport constant -// FUND-EXP: @_ZTSPn = dllexport constant +// FUND-EXP: @_ZTSn = dllexport constant // FUND-EXP: @_ZTIPn = dllexport constant -// FUND-EXP: @_ZTSPKn = dllexport constant +// FUND-EXP: @_ZTSPn = dllexport constant // FUND-EXP: @_ZTIPKn = dllexport constant +// FUND-EXP: @_ZTSPKn = dllexport constant // unsigned __int128 -// FUND-DEF: @_ZTSo = constant // FUND-DEF: @_ZTIo = constant -// FUND-DEF: @_ZTSPo = constant +// FUND-DEF: @_ZTSo = constant // FUND-DEF: @_ZTIPo = constant -// FUND-DEF: @_ZTSPKo = constant +// FUND-DEF: @_ZTSPo = constant // FUND-DEF: @_ZTIPKo = constant -// FUND-HID: @_ZTSo = hidden constant +// FUND-DEF: @_ZTSPKo = constant // FUND-HID: @_ZTIo = hidden constant -// FUND-HID: @_ZTSPo = hidden constant +// FUND-HID: @_ZTSo = hidden constant // FUND-HID: @_ZTIPo = hidden constant -// FUND-HID: @_ZTSPKo = hidden constant +// FUND-HID: @_ZTSPo = hidden constant // FUND-HID: @_ZTIPKo = hidden constant -// FUND-EXP: @_ZTSo = dllexport constant +// FUND-HID: @_ZTSPKo = hidden constant // FUND-EXP: @_ZTIo = dllexport constant -// FUND-EXP: @_ZTSPo = dllexport constant +// FUND-EXP: @_ZTSo = dllexport constant // FUND-EXP: @_ZTIPo = dllexport constant -// FUND-EXP: @_ZTSPKo = dllexport constant +// FUND-EXP: @_ZTSPo = dllexport constant // FUND-EXP: @_ZTIPKo = dllexport constant +// FUND-EXP: @_ZTSPKo = dllexport constant // half -// FUND-DEF: @_ZTSDh = constant // FUND-DEF: @_ZTIDh = constant -// FUND-DEF: @_ZTSPDh = constant +// FUND-DEF: @_ZTSDh = constant // FUND-DEF: @_ZTIPDh = constant -// FUND-DEF: @_ZTSPKDh = constant +// FUND-DEF: @_ZTSPDh = constant // FUND-DEF: @_ZTIPKDh = constant -// FUND-HID: @_ZTSDh = hidden constant +// FUND-DEF: @_ZTSPKDh = constant // FUND-HID: @_ZTIDh = hidden constant -// FUND-HID: @_ZTSPDh = hidden constant +// FUND-HID: @_ZTSDh = hidden constant // FUND-HID: @_ZTIPDh = hidden constant -// FUND-HID: @_ZTSPKDh = hidden constant +// FUND-HID: @_ZTSPDh = hidden constant // FUND-HID: @_ZTIPKDh = hidden constant -// FUND-EXP: @_ZTSDh = dllexport constant +// FUND-HID: @_ZTSPKDh = hidden constant // FUND-EXP: @_ZTIDh = dllexport constant -// FUND-EXP: @_ZTSPDh = dllexport constant +// FUND-EXP: @_ZTSDh = dllexport constant // FUND-EXP: @_ZTIPDh = dllexport constant -// FUND-EXP: @_ZTSPKDh = dllexport constant +// FUND-EXP: @_ZTSPDh = dllexport constant // FUND-EXP: @_ZTIPKDh = dllexport constant +// FUND-EXP: @_ZTSPKDh = dllexport constant // float -// FUND-DEF: @_ZTSf = constant // FUND-DEF: @_ZTIf = constant -// FUND-DEF: @_ZTSPf = constant +// FUND-DEF: @_ZTSf = constant // FUND-DEF: @_ZTIPf = constant -// FUND-DEF: @_ZTSPKf = constant +// FUND-DEF: @_ZTSPf = constant // FUND-DEF: @_ZTIPKf = constant -// FUND-HID: @_ZTSf = hidden constant +// FUND-DEF: @_ZTSPKf = constant // FUND-HID: @_ZTIf = hidden constant -// FUND-HID: @_ZTSPf = hidden constant +// FUND-HID: @_ZTSf = hidden constant // FUND-HID: @_ZTIPf = hidden constant -// FUND-HID: @_ZTSPKf = hidden constant +// FUND-HID: @_ZTSPf = hidden constant // FUND-HID: @_ZTIPKf = hidden constant -// FUND-EXP: @_ZTSf = dllexport constant +// FUND-HID: @_ZTSPKf = hidden constant // FUND-EXP: @_ZTIf = dllexport constant -// FUND-EXP: @_ZTSPf = dllexport constant +// FUND-EXP: @_ZTSf = dllexport constant // FUND-EXP: @_ZTIPf = dllexport constant -// FUND-EXP: @_ZTSPKf = dllexport constant +// FUND-EXP: @_ZTSPf = dllexport constant // FUND-EXP: @_ZTIPKf = dllexport constant +// FUND-EXP: @_ZTSPKf = dllexport constant // double -// FUND-DEF: @_ZTSd = constant // FUND-DEF: @_ZTId = constant -// FUND-DEF: @_ZTSPd = constant +// FUND-DEF: @_ZTSd = constant // FUND-DEF: @_ZTIPd = constant -// FUND-DEF: @_ZTSPKd = constant +// FUND-DEF: @_ZTSPd = constant // FUND-DEF: @_ZTIPKd = constant -// FUND-HID: @_ZTSd = hidden constant +// FUND-DEF: @_ZTSPKd = constant // FUND-HID: @_ZTId = hidden constant -// FUND-HID: @_ZTSPd = hidden constant +// FUND-HID: @_ZTSd = hidden constant // FUND-HID: @_ZTIPd = hidden constant -// FUND-HID: @_ZTSPKd = hidden constant +// FUND-HID: @_ZTSPd = hidden constant // FUND-HID: @_ZTIPKd = hidden constant -// FUND-EXP: @_ZTSd = dllexport constant +// FUND-HID: @_ZTSPKd = hidden constant // FUND-EXP: @_ZTId = dllexport constant -// FUND-EXP: @_ZTSPd = dllexport constant +// FUND-EXP: @_ZTSd = dllexport constant // FUND-EXP: @_ZTIPd = dllexport constant -// FUND-EXP: @_ZTSPKd = dllexport constant +// FUND-EXP: @_ZTSPd = dllexport constant // FUND-EXP: @_ZTIPKd = dllexport constant +// FUND-EXP: @_ZTSPKd = dllexport constant // long double -// FUND-DEF: @_ZTSe = constant // FUND-DEF: @_ZTIe = constant -// FUND-DEF: @_ZTSPe = constant +// FUND-DEF: @_ZTSe = constant // FUND-DEF: @_ZTIPe = constant -// FUND-DEF: @_ZTSPKe = constant +// FUND-DEF: @_ZTSPe = constant // FUND-DEF: @_ZTIPKe = constant -// FUND-HID: @_ZTSe = hidden constant +// FUND-DEF: @_ZTSPKe = constant // FUND-HID: @_ZTIe = hidden constant -// FUND-HID: @_ZTSPe = hidden constant +// FUND-HID: @_ZTSe = hidden constant // FUND-HID: @_ZTIPe = hidden constant -// FUND-HID: @_ZTSPKe = hidden constant +// FUND-HID: @_ZTSPe = hidden constant // FUND-HID: @_ZTIPKe = hidden constant -// FUND-EXP: @_ZTSe = dllexport constant +// FUND-HID: @_ZTSPKe = hidden constant // FUND-EXP: @_ZTIe = dllexport constant -// FUND-EXP: @_ZTSPe = dllexport constant +// FUND-EXP: @_ZTSe = dllexport constant // FUND-EXP: @_ZTIPe = dllexport constant -// FUND-EXP: @_ZTSPKe = dllexport constant +// FUND-EXP: @_ZTSPe = dllexport constant // FUND-EXP: @_ZTIPKe = dllexport constant +// FUND-EXP: @_ZTSPKe = dllexport constant // __ieee128 -// FUND-DEF: @_ZTSu9__ieee128 = constant // FUND-DEF: @_ZTIu9__ieee128 = constant -// FUND-DEF: @_ZTSPu9__ieee128 = constant +// FUND-DEF: @_ZTSu9__ieee128 = constant // FUND-DEF: @_ZTIPu9__ieee128 = constant -// FUND-DEF: @_ZTSPKu9__ieee128 = constant +// FUND-DEF: @_ZTSPu9__ieee128 = constant // FUND-DEF: @_ZTIPKu9__ieee128 = constant -// FUND-HID: @_ZTSu9__ieee128 = hidden constant +// FUND-DEF: @_ZTSPKu9__ieee128 = constant // FUND-HID: @_ZTIu9__ieee128 = hidden constant -// FUND-HID: @_ZTSPu9__ieee128 = hidden constant +// FUND-HID: @_ZTSu9__ieee128 = hidden constant // FUND-HID: @_ZTIPu9__ieee128 = hidden constant -// FUND-HID: @_ZTSPKu9__ieee128 = hidden constant +// FUND-HID: @_ZTSPu9__ieee128 = hidden constant // FUND-HID: @_ZTIPKu9__ieee128 = hidden constant -// FUND-EXP: @_ZTSu9__ieee128 = dllexport constant +// FUND-HID: @_ZTSPKu9__ieee128 = hidden constant // FUND-EXP: @_ZTIu9__ieee128 = dllexport constant -// FUND-EXP: @_ZTSPu9__ieee128 = dllexport constant +// FUND-EXP: @_ZTSu9__ieee128 = dllexport constant // FUND-EXP: @_ZTIPu9__ieee128 = dllexport constant -// FUND-EXP: @_ZTSPKu9__ieee128 = dllexport constant +// FUND-EXP: @_ZTSPu9__ieee128 = dllexport constant // FUND-EXP: @_ZTIPKu9__ieee128 = dllexport constant +// FUND-EXP: @_ZTSPKu9__ieee128 = dllexport constant // char8_t -// FUND-DEF: @_ZTSDu = constant // FUND-DEF: @_ZTIDu = constant -// FUND-DEF: @_ZTSPDu = constant +// FUND-DEF: @_ZTSDu = constant // FUND-DEF: @_ZTIPDu = constant -// FUND-DEF: @_ZTSPKDu = constant +// FUND-DEF: @_ZTSPDu = constant // FUND-DEF: @_ZTIPKDu = constant -// FUND-HID: @_ZTSDu = hidden constant +// FUND-DEF: @_ZTSPKDu = constant // FUND-HID: @_ZTIDu = hidden constant -// FUND-HID: @_ZTSPDu = hidden constant +// FUND-HID: @_ZTSDu = hidden constant // FUND-HID: @_ZTIPDu = hidden constant -// FUND-HID: @_ZTSPKDu = hidden constant +// FUND-HID: @_ZTSPDu = hidden constant // FUND-HID: @_ZTIPKDu = hidden constant -// FUND-EXP: @_ZTSDu = dllexport constant +// FUND-HID: @_ZTSPKDu = hidden constant // FUND-EXP: @_ZTIDu = dllexport constant -// FUND-EXP: @_ZTSPDu = dllexport constant +// FUND-EXP: @_ZTSDu = dllexport constant // FUND-EXP: @_ZTIPDu = dllexport constant -// FUND-EXP: @_ZTSPKDu = dllexport constant +// FUND-EXP: @_ZTSPDu = dllexport constant // FUND-EXP: @_ZTIPKDu = dllexport constant +// FUND-EXP: @_ZTSPKDu = dllexport constant // char16_t -// FUND-DEF: @_ZTSDs = constant // FUND-DEF: @_ZTIDs = constant -// FUND-DEF: @_ZTSPDs = constant +// FUND-DEF: @_ZTSDs = constant // FUND-DEF: @_ZTIPDs = constant -// FUND-DEF: @_ZTSPKDs = constant +// FUND-DEF: @_ZTSPDs = constant // FUND-DEF: @_ZTIPKDs = constant -// FUND-HID: @_ZTSDs = hidden constant +// FUND-DEF: @_ZTSPKDs = constant // FUND-HID: @_ZTIDs = hidden constant -// FUND-HID: @_ZTSPDs = hidden constant +// FUND-HID: @_ZTSDs = hidden constant // FUND-HID: @_ZTIPDs = hidden constant -// FUND-HID: @_ZTSPKDs = hidden constant +// FUND-HID: @_ZTSPDs = hidden constant // FUND-HID: @_ZTIPKDs = hidden constant -// FUND-EXP: @_ZTSDs = dllexport constant +// FUND-HID: @_ZTSPKDs = hidden constant // FUND-EXP: @_ZTIDs = dllexport constant -// FUND-EXP: @_ZTSPDs = dllexport constant +// FUND-EXP: @_ZTSDs = dllexport constant // FUND-EXP: @_ZTIPDs = dllexport constant -// FUND-EXP: @_ZTSPKDs = dllexport constant +// FUND-EXP: @_ZTSPDs = dllexport constant // FUND-EXP: @_ZTIPKDs = dllexport constant +// FUND-EXP: @_ZTSPKDs = dllexport constant // char32_t -// FUND-DEF: @_ZTSDi = constant // FUND-DEF: @_ZTIDi = constant -// FUND-DEF: @_ZTSPDi = constant +// FUND-DEF: @_ZTSDi = constant // FUND-DEF: @_ZTIPDi = constant -// FUND-DEF: @_ZTSPKDi = constant +// FUND-DEF: @_ZTSPDi = constant // FUND-DEF: @_ZTIPKDi = constant -// FUND-HID: @_ZTSDi = hidden constant +// FUND-DEF: @_ZTSPKDi = constant // FUND-HID: @_ZTIDi = hidden constant -// FUND-HID: @_ZTSPDi = hidden constant +// FUND-HID: @_ZTSDi = hidden constant // FUND-HID: @_ZTIPDi = hidden constant -// FUND-HID: @_ZTSPKDi = hidden constant +// FUND-HID: @_ZTSPDi = hidden constant // FUND-HID: @_ZTIPKDi = hidden constant -// FUND-EXP: @_ZTSDi = dllexport constant +// FUND-HID: @_ZTSPKDi = hidden constant // FUND-EXP: @_ZTIDi = dllexport constant -// FUND-EXP: @_ZTSPDi = dllexport constant +// FUND-EXP: @_ZTSDi = dllexport constant // FUND-EXP: @_ZTIPDi = dllexport constant -// FUND-EXP: @_ZTSPKDi = dllexport constant +// FUND-EXP: @_ZTSPDi = dllexport constant // FUND-EXP: @_ZTIPKDi = dllexport constant +// FUND-EXP: @_ZTSPKDi = dllexport constant diff --git a/clang/test/CodeGenCXX/modules-vtable.cppm b/clang/test/CodeGenCXX/modules-vtable.cppm index 5cc3504d72628f216d774dc3d021f86a7a4930d1..6589b9f3c5d6491a5e8bc4cfb7d257daa7554354 100644 --- a/clang/test/CodeGenCXX/modules-vtable.cppm +++ b/clang/test/CodeGenCXX/modules-vtable.cppm @@ -40,13 +40,13 @@ inline Base::~Base() {} // CHECK: @_ZTVW3Mod4Base = unnamed_addr constant -// CHECK: @_ZTSW3Mod4Base = constant // CHECK: @_ZTIW3Mod4Base = constant +// CHECK: @_ZTSW3Mod4Base = constant // With the new Itanium C++ ABI, the linkage of vtables in modules don't need to be linkonce ODR. // CHECK-INLINE: @_ZTVW3Mod4Base = {{.*}}unnamed_addr constant -// CHECK-INLINE: @_ZTSW3Mod4Base = {{.*}}constant // CHECK-INLINE: @_ZTIW3Mod4Base = {{.*}}constant +// CHECK-INLINE: @_ZTSW3Mod4Base = {{.*}}constant module :private; int private_use() { @@ -61,12 +61,12 @@ int use() { return 43; } -// CHECK-NOT: @_ZTSW3Mod4Base // CHECK-NOT: @_ZTIW3Mod4Base +// CHECK-NOT: @_ZTSW3Mod4Base // CHECK: @_ZTVW3Mod4Base = external -// CHECK-INLINE-NOT: @_ZTSW3Mod4Base // CHECK-INLINE-NOT: @_ZTIW3Mod4Base +// CHECK-INLINE-NOT: @_ZTSW3Mod4Base // CHECK-INLINE: @_ZTVW3Mod4Base = external // Check the case that the declaration of the key function comes from another @@ -86,8 +86,8 @@ int a_use() { } // CHECK: @_ZTVW1M1C = unnamed_addr constant -// CHECK: @_ZTSW1M1C = constant // CHECK: @_ZTIW1M1C = constant +// CHECK: @_ZTSW1M1C = constant //--- M-B.cppm export module M:B; @@ -101,5 +101,5 @@ int b_use() { } // CHECK: @_ZTVW1M1C = external -// CHECK-NOT: @_ZTSW1M1C // CHECK-NOT: @_ZTIW1M1C +// CHECK-NOT: @_ZTSW1M1C diff --git a/clang/test/CodeGenCXX/nopac-explicit-vtable-pointer-control.cpp b/clang/test/CodeGenCXX/nopac-explicit-vtable-pointer-control.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f8e63f34d7c011dd98102be32eb8abb0b7e20591 --- /dev/null +++ b/clang/test/CodeGenCXX/nopac-explicit-vtable-pointer-control.cpp @@ -0,0 +1,295 @@ +// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ +// RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,NODISC %s + +// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ +// RUN: -fptrauth-vtable-pointer-type-discrimination \ +// RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,TYPE %s + +// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ +// RUN: -fptrauth-vtable-pointer-address-discrimination \ +// RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,ADDR %s + +// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ +// RUN: -fptrauth-vtable-pointer-type-discrimination \ +// RUN: -fptrauth-vtable-pointer-address-discrimination \ +// RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,BOTH %s + +// XFAIL: * + +/* + * NOTE: Disabled since NoPac cannot be combined with explciit ptrauth configuration. +*/ + +#include + +namespace test1 { + +#define authenticated(a...) ptrauth_cxx_vtable_pointer(a) + +struct __attribute__((nopac)) NoExplicitAuth { + virtual ~NoExplicitAuth(); + virtual void f(); + virtual void g(); +}; + +struct __attribute__((nopac)) authenticated(no_authentication, no_address_discrimination, no_extra_discrimination) ExplicitlyDisableAuth { + virtual ~ExplicitlyDisableAuth(); + virtual void f(); + virtual void g(); +}; + +struct __attribute__((nopac)) authenticated(default_key, address_discrimination, default_extra_discrimination) ExplicitAddressDiscrimination { + virtual ~ExplicitAddressDiscrimination(); + virtual void f(); + virtual void g(); +}; + +struct __attribute__((nopac)) authenticated(default_key, no_address_discrimination, default_extra_discrimination) ExplicitNoAddressDiscrimination { + virtual ~ExplicitNoAddressDiscrimination(); + virtual void f(); + virtual void g(); +}; + +struct __attribute__((nopac)) authenticated(default_key, default_address_discrimination, no_extra_discrimination) ExplicitNoExtraDiscrimination { + virtual ~ExplicitNoExtraDiscrimination(); + virtual void f(); + virtual void g(); +}; + +struct __attribute__((nopac)) authenticated(default_key, default_address_discrimination, type_discrimination) ExplicitTypeDiscrimination { + virtual ~ExplicitTypeDiscrimination(); + virtual void f(); + virtual void g(); +}; + +struct __attribute__((nopac)) authenticated(default_key, default_address_discrimination, custom_discrimination, 42424) ExplicitCustomDiscrimination { + virtual ~ExplicitCustomDiscrimination(); + virtual void f(); + virtual void g(); +}; + +template +struct __attribute__((nopac)) SubClass : T { + virtual void g(); + virtual T *h(); +}; + +template +SubClass *make_subclass(T *); + +struct __attribute__((nopac)) authenticated(default_key, address_discrimination, type_discrimination) BasicStruct { + virtual ~BasicStruct(); +}; + +template +struct __attribute__((nopac)) PrimaryBasicStruct : BasicStruct, T {}; +template +struct __attribute__((nopac)) PrimaryBasicStruct *make_multiple_primary(T *); + +template +struct __attribute__((nopac)) VirtualSubClass : virtual T { + virtual void g(); + virtual T *h(); +}; +template +struct __attribute__((nopac)) VirtualPrimaryStruct : virtual T, VirtualSubClass {}; +template +struct __attribute__((nopac)) VirtualPrimaryStruct *make_virtual_primary(T *); + +extern "C" { + +// CHECK: @TVDisc_NoExplicitAuth = global i32 [[DISC_DEFAULT:49565]], align 4 +int TVDisc_NoExplicitAuth = ptrauth_string_discriminator("_ZTVN5test114NoExplicitAuthE"); + +// CHECK: @TVDisc_ExplicitlyDisableAuth = global i32 [[DISC_DISABLED:24369]], align 4 +int TVDisc_ExplicitlyDisableAuth = ptrauth_string_discriminator("_ZTVN5test121ExplicitlyDisableAuthE"); + +// CHECK: @TVDisc_ExplicitAddressDiscrimination = global i32 [[DISC_ADDR:56943]], align 4 +int TVDisc_ExplicitAddressDiscrimination = ptrauth_string_discriminator("_ZTVN5test129ExplicitAddressDiscriminationE"); + +// CHECK: @TVDisc_ExplicitNoAddressDiscrimination = global i32 [[DISC_NO_ADDR:6022]], align 4 +int TVDisc_ExplicitNoAddressDiscrimination = ptrauth_string_discriminator("_ZTVN5test131ExplicitNoAddressDiscriminationE"); + +// CHECK: @TVDisc_ExplicitNoExtraDiscrimination = global i32 [[DISC_NO_EXTRA:9072]], align 4 +int TVDisc_ExplicitNoExtraDiscrimination = ptrauth_string_discriminator("_ZTVN5test129ExplicitNoExtraDiscriminationE"); + +// CHECK: @TVDisc_ExplicitTypeDiscrimination = global i32 [[DISC_TYPE:6177]], align 4 +int TVDisc_ExplicitTypeDiscrimination = ptrauth_string_discriminator("_ZTVN5test126ExplicitTypeDiscriminationE"); + + +// CHECK-LABEL: define{{.*}} void @test_default(ptr noundef {{%.*}}) {{#.*}} { +// CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 +// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_default(NoExplicitAuth *a) { + a->f(); +} + +// CHECK-LABEL: define{{.*}} void @test_disabled(ptr noundef {{%.*}}) {{#.*}} { +// CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 +// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_disabled(ExplicitlyDisableAuth *a) { + a->f(); +} + +// CHECK-LABEL: define{{.*}} void @test_addr_disc(ptr noundef {{%.*}}) {{#.*}} { +// CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 +// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_addr_disc(ExplicitAddressDiscrimination *a) { + a->f(); +} + +// CHECK-LABEL: define{{.*}} void @test_no_addr_disc(ptr noundef {{%.*}}) {{#.*}} { +// CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 +// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_no_addr_disc(ExplicitNoAddressDiscrimination *a) { + a->f(); +} + +// CHECK-LABEL: define{{.*}} void @test_no_extra_disc(ptr noundef {{%.*}}) {{#.*}} { +// CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 +// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_no_extra_disc(ExplicitNoExtraDiscrimination *a) { + a->f(); +} + +// CHECK-LABEL: define{{.*}} void @test_type_disc(ptr noundef {{%.*}}) {{#.*}} { +// CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 +// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_type_disc(ExplicitTypeDiscrimination *a) { + a->f(); +} + +// CHECK-LABEL: define{{.*}} void @test_custom_disc(ptr noundef {{%.*}}) {{#.*}} { +// CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 +// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_custom_disc(ExplicitCustomDiscrimination *a) { + a->f(); +} + +// +// Test some simple single inheritance cases. +// Codegen should be the same as the simple cases above once we have a vtable. +// + +// CHECK-LABEL: define{{.*}} void @test_subclass_default(ptr noundef {{%.*}}) {{#.*}} { +// CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass +// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_subclass_default(NoExplicitAuth *a) { + make_subclass(a)->f(); +} + +// CHECK-LABEL: define{{.*}} void @test_subclass_disabled(ptr noundef {{%.*}}) {{#.*}} { +// CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass +// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_subclass_disabled(ExplicitlyDisableAuth *a) { + make_subclass(a)->f(); +} + +// CHECK-LABEL: define{{.*}} void @test_subclass_addr_disc(ptr noundef {{%.*}}) {{#.*}} { +// CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass +// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_subclass_addr_disc(ExplicitAddressDiscrimination *a) { + make_subclass(a)->f(); +} + +// CHECK-LABEL: define{{.*}} void @test_subclass_no_addr_disc(ptr noundef {{%.*}}) {{#.*}} { +// CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass +// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_subclass_no_addr_disc(ExplicitNoAddressDiscrimination *a) { + make_subclass(a)->f(); +} + +// CHECK-LABEL: define{{.*}} void @test_subclass_no_extra_disc(ptr noundef {{%.*}}) {{#.*}} { +// CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass +// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_subclass_no_extra_disc(ExplicitNoExtraDiscrimination *a) { + make_subclass(a)->f(); +} + +// CHECK-LABEL: define{{.*}} void @test_subclass_type_disc(ptr noundef {{%.*}}) {{#.*}} { +// CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass +// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_subclass_type_disc(ExplicitTypeDiscrimination *a) { + make_subclass(a)->f(); +} + +// CHECK-LABEL: define{{.*}} void @test_subclass_custom_disc(ptr noundef {{%.*}}) {{#.*}} { +// CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass +// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_subclass_custom_disc(ExplicitCustomDiscrimination *a) { + make_subclass(a)->f(); +} + + +// +// Test some simple multiple inheritance cases. +// Codegen should be the same as the simple cases above once we have a vtable. +// + +// CHECK-LABEL: define{{.*}} void @test_multiple_default(ptr noundef {{%.*}}) {{#.*}} { +// CHECK: [[CALL:%.*]] = call noundef ptr @_ZN5test121make_multiple_primary +// CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 8 +// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_multiple_default(NoExplicitAuth *a) { + make_multiple_primary(a)->f(); +} + +// CHECK-LABEL: define{{.*}} void @test_multiple_disabled(ptr noundef {{%.*}}) {{#.*}} { +// CHECK: [[CALL:%.*]] = call noundef ptr @_ZN5test121make_multiple_primary +// CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 8 +// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_multiple_disabled(ExplicitlyDisableAuth *a) { + make_multiple_primary(a)->f(); +} + +// CHECK-LABEL: define{{.*}} void @test_multiple_custom_disc(ptr noundef {{%.*}}) {{#.*}} { +// CHECK: [[CALL:%.*]] = call noundef ptr @_ZN5test121make_multiple_primary +// CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 8 +// CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_multiple_custom_disc(ExplicitCustomDiscrimination *a) { + make_multiple_primary(a)->f(); +} + +// +// Test some virtual inheritance cases. +// Codegen should be the same as the simple cases above once we have a vtable, +// but twice for vtt/vtable. The names in the vtt version have "VTT" prefixes. +// + +// CHECK-LABEL: define{{.*}} void @test_virtual_default(ptr noundef {{%.*}}) {{#.*}} { +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_virtual_default(NoExplicitAuth *a) { + make_virtual_primary(a)->f(); +} + +// CHECK-LABEL: define{{.*}} void @test_virtual_disabled(ptr noundef {{%.*}}) {{#.*}} { +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_virtual_disabled(ExplicitlyDisableAuth *a) { + make_virtual_primary(a)->f(); +} + +// CHECK-LABEL: define{{.*}} void @test_virtual_custom_disc(ptr noundef {{%.*}}) {{#.*}} { +// CHECK-NOT: call i64 @llvm.ptrauth.auth +void test_virtual_custom_disc(ExplicitCustomDiscrimination *a) { + make_virtual_primary(a)->f(); +} + +} // extern "C" +} // namespace test1 diff --git a/clang/test/CodeGenCXX/nopac-global-constant-initializers.cpp b/clang/test/CodeGenCXX/nopac-global-constant-initializers.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f340e36790c9cd54a4f13389f65702d9c37945d4 --- /dev/null +++ b/clang/test/CodeGenCXX/nopac-global-constant-initializers.cpp @@ -0,0 +1,238 @@ +// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fno-rtti -fptrauth-vtable-pointer-type-discrimination \ +// RUN: -fptrauth-vtable-pointer-address-discrimination -emit-llvm -o - %s | FileCheck %s --check-prefixes=CHECK,ELF + +// CHECK: %struct.Base1 = type { ptr } +// CHECK: %struct.Base2 = type { ptr } +// CHECK: %struct.Derived1 = type { %struct.Base1, %struct.Base2 } +// CHECK: %struct.Derived2 = type { %struct.Base2, %struct.Base1 } +// CHECK: %struct.Derived3 = type { %struct.Base1, %struct.Base2 } +// CHECK: @_ZTV5Base1 = linkonce_odr unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @_ZN5Base11aEv] } +// CHECK: @g_b1 = global %struct.Base1 { ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV5Base1, i32 0, i32 0, i32 2) } +// CHECK: @_ZTV5Base2 = linkonce_odr unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr @_ZN5Base21bEv] } +// CHECK: @g_b2 = global %struct.Base2 { ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV5Base2, i32 0, i32 0, i32 2) } +// CHECK: @_ZTV8Derived1 = linkonce_odr unnamed_addr constant { [5 x ptr], [3 x ptr] } { [5 x ptr] [ptr null, ptr null, ptr @_ZN5Base11aEv, ptr @_ZN8Derived11cEv, ptr @_ZN8Derived11dEv], [3 x ptr] [ptr inttoptr (i64 -8 to ptr), ptr null, ptr @_ZN5Base21bEv] } +// CHECK: @g_d1 = global { ptr, ptr } { ptr getelementptr inbounds inrange(-16, 24) ({ [5 x ptr], [3 x ptr] }, ptr @_ZTV8Derived1, i32 0, i32 0, i32 2), ptr getelementptr inbounds inrange(-16, 8) ({ [5 x ptr], [3 x ptr] }, ptr @_ZTV8Derived1, i32 0, i32 1, i32 2) } +// CHECK: @_ZTV8Derived2 = linkonce_odr unnamed_addr constant { [5 x ptr], [3 x ptr] } { [5 x ptr] [ptr null, ptr null, ptr @_ZN5Base21bEv, ptr @_ZN8Derived21cEv, ptr @_ZN8Derived21eEv], [3 x ptr] [ptr inttoptr (i64 -8 to ptr), ptr null, ptr @_ZN5Base11aEv] } +// CHECK: @g_d2 = global { ptr, ptr } { ptr getelementptr inbounds inrange(-16, 24) ({ [5 x ptr], [3 x ptr] }, ptr @_ZTV8Derived2, i32 0, i32 0, i32 2), ptr getelementptr inbounds inrange(-16, 8) ({ [5 x ptr], [3 x ptr] }, ptr @_ZTV8Derived2, i32 0, i32 1, i32 2) } +// CHECK: @_ZTV8Derived3 = linkonce_odr unnamed_addr constant { [4 x ptr], [3 x ptr] } { [4 x ptr] [ptr null, ptr null, ptr @_ZN5Base11aEv, ptr @_ZN8Derived31iEv], [3 x ptr] [ptr inttoptr (i64 -8 to ptr), ptr null, ptr @_ZN5Base21bEv] } +// CHECK: @g_d3 = global { ptr, ptr } { ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [3 x ptr] }, ptr @_ZTV8Derived3, i32 0, i32 0, i32 2), ptr getelementptr inbounds inrange(-16, 8) ({ [4 x ptr], [3 x ptr] }, ptr @_ZTV8Derived3, i32 0, i32 1, i32 2) } +// CHECK: @g_vb1 = global %struct.VirtualBase1 zeroinitializer,{{.*}} align 8 +// CHECK: @g_vb2 = global %struct.VirtualBase2 zeroinitializer,{{.*}} align 8 +// CHECK: @g_d4 = global %struct.Derived4 zeroinitializer,{{.*}} align 8 +// CHECK: @_ZTV12VirtualBase1 = linkonce_odr unnamed_addr constant { [6 x ptr] } { [6 x ptr] [ptr null, ptr null, ptr null, ptr null, ptr @_ZN5Base11aEv, ptr @_ZN12VirtualBase11fEv] } +// CHECK: @_ZTT12VirtualBase1 = linkonce_odr unnamed_addr constant [2 x ptr] [ptr getelementptr inbounds inrange(-32, 16) ({ [6 x ptr] }, ptr @_ZTV12VirtualBase1, i32 0, i32 0, i32 4), ptr getelementptr inbounds inrange(-32, 16) ({ [6 x ptr] }, ptr @_ZTV12VirtualBase1, i32 0, i32 0, i32 4)] +// CHECK: @_ZTV12VirtualBase2 = linkonce_odr unnamed_addr constant { [5 x ptr], [4 x ptr] } { [5 x ptr] [ptr inttoptr (i64 8 to ptr), ptr null, ptr null, ptr @_ZN5Base21bEv, ptr @_ZN12VirtualBase21gEv], [4 x ptr] [ptr null, ptr inttoptr (i64 -8 to ptr), ptr null, ptr @_ZN5Base11aEv] } +// CHECK: @_ZTT12VirtualBase2 = linkonce_odr unnamed_addr constant [2 x ptr] [ptr getelementptr inbounds inrange(-24, 16) ({ [5 x ptr], [4 x ptr] }, ptr @_ZTV12VirtualBase2, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [5 x ptr], [4 x ptr] }, ptr @_ZTV12VirtualBase2, i32 0, i32 1, i32 3)] +// CHECK: @_ZTV8Derived4 = linkonce_odr unnamed_addr constant { [7 x ptr], [5 x ptr] } { [7 x ptr] [ptr null, ptr null, ptr null, ptr null, ptr @_ZN5Base11aEv, ptr @_ZN12VirtualBase11fEv, ptr @_ZN8Derived41hEv], [5 x ptr] [ptr inttoptr (i64 -8 to ptr), ptr inttoptr (i64 -8 to ptr), ptr null, ptr @_ZN5Base21bEv, ptr @_ZN12VirtualBase21gEv] } +// CHECK: @_ZTT8Derived4 = linkonce_odr unnamed_addr constant [7 x ptr] [ptr getelementptr inbounds inrange(-32, 24) ({ [7 x ptr], [5 x ptr] }, ptr @_ZTV8Derived4, i32 0, i32 0, i32 4), ptr getelementptr inbounds inrange(-32, 16) ({ [6 x ptr] }, ptr @_ZTC8Derived40_12VirtualBase1, i32 0, i32 0, i32 4), ptr getelementptr inbounds inrange(-32, 16) ({ [6 x ptr] }, ptr @_ZTC8Derived40_12VirtualBase1, i32 0, i32 0, i32 4), ptr getelementptr inbounds inrange(-24, 16) ({ [5 x ptr], [4 x ptr] }, ptr @_ZTC8Derived48_12VirtualBase2, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [5 x ptr], [4 x ptr] }, ptr @_ZTC8Derived48_12VirtualBase2, i32 0, i32 1, i32 3), ptr getelementptr inbounds inrange(-32, 24) ({ [7 x ptr], [5 x ptr] }, ptr @_ZTV8Derived4, i32 0, i32 0, i32 4), ptr getelementptr inbounds inrange(-24, 16) ({ [7 x ptr], [5 x ptr] }, ptr @_ZTV8Derived4, i32 0, i32 1, i32 3)] +// CHECK: @_ZTC8Derived40_12VirtualBase1 = linkonce_odr unnamed_addr constant { [6 x ptr] } { [6 x ptr] [ptr null, ptr null, ptr null, ptr null, ptr @_ZN5Base11aEv, ptr @_ZN12VirtualBase11fEv] } +// CHECK: @_ZTC8Derived48_12VirtualBase2 = linkonce_odr unnamed_addr constant { [5 x ptr], [4 x ptr] } { [5 x ptr] [ptr inttoptr (i64 -8 to ptr), ptr null, ptr null, ptr @_ZN5Base21bEv, ptr @_ZN12VirtualBase21gEv], [4 x ptr] [ptr null, ptr inttoptr (i64 8 to ptr), ptr null, ptr @_ZN5Base11aEv] } +// CHECK: @_ZTV8Derived5 = linkonce_odr unnamed_addr constant { [6 x ptr], [6 x ptr] } { [6 x ptr] [ptr inttoptr (i64 8 to ptr), ptr null, ptr null, ptr @_ZN5Base21bEv, ptr @_ZN12VirtualBase21gEv, ptr @_ZN8Derived51hEv], [6 x ptr] [ptr null, ptr null, ptr inttoptr (i64 -8 to ptr), ptr null, ptr @_ZN5Base11aEv, ptr @_ZN12VirtualBase11fEv] } +// CHECK: @_ZTT8Derived5 = linkonce_odr unnamed_addr constant [7 x ptr] [ptr getelementptr inbounds inrange(-24, 24) ({ [6 x ptr], [6 x ptr] }, ptr @_ZTV8Derived5, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-24, 16) ({ [5 x ptr], [4 x ptr] }, ptr @_ZTC8Derived50_12VirtualBase2, i32 0, i32 0, i32 3), ptr getelementptr inbounds inrange(-24, 8) ({ [5 x ptr], [4 x ptr] }, ptr @_ZTC8Derived50_12VirtualBase2, i32 0, i32 1, i32 3), ptr getelementptr inbounds inrange(-32, 16) ({ [6 x ptr] }, ptr @_ZTC8Derived58_12VirtualBase1, i32 0, i32 0, i32 4), ptr getelementptr inbounds inrange(-32, 16) ({ [6 x ptr] }, ptr @_ZTC8Derived58_12VirtualBase1, i32 0, i32 0, i32 4), ptr getelementptr inbounds inrange(-32, 16) ({ [6 x ptr], [6 x ptr] }, ptr @_ZTV8Derived5, i32 0, i32 1, i32 4), ptr getelementptr inbounds inrange(-32, 16) ({ [6 x ptr], [6 x ptr] }, ptr @_ZTV8Derived5, i32 0, i32 1, i32 4)] +// CHECK: @_ZTC8Derived50_12VirtualBase2 = linkonce_odr unnamed_addr constant { [5 x ptr], [4 x ptr] } { [5 x ptr] [ptr inttoptr (i64 8 to ptr), ptr null, ptr null, ptr @_ZN5Base21bEv, ptr @_ZN12VirtualBase21gEv], [4 x ptr] [ptr null, ptr inttoptr (i64 -8 to ptr), ptr null, ptr @_ZN5Base11aEv] } +// CHECK: @_ZTC8Derived58_12VirtualBase1 = linkonce_odr unnamed_addr constant { [6 x ptr] } { [6 x ptr] [ptr null, ptr null, ptr null, ptr null, ptr @_ZN5Base11aEv, ptr @_ZN12VirtualBase11fEv] } +// CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I_nopac_global_constant_initializers.cpp, ptr null }] + +struct __attribute__((nopac)) Base1 { virtual void a() {} }; +struct __attribute__((nopac)) Base2 { virtual void b() {} }; +struct __attribute__((nopac)) Derived1 : public Base1, public Base2 { + virtual void c() {} + virtual void d() {} +}; +struct __attribute__((nopac)) Derived2 : public Base2, public Base1 { + virtual void c() {} + virtual void e() {} +}; + +struct __attribute__((nopac)) Derived3 : public Base1, public Base2 { + constexpr Derived3(){} + virtual void i() {} +}; + +Base1 g_b1; +Base2 g_b2; +Derived1 g_d1; +Derived2 g_d2; +Derived3 g_d3; + +extern "C" void test_basic_inheritance() { + Base1 g_b1; + Base2 g_b2; + Derived1 g_d1; + Derived2 g_d2; + Derived3 g_d3; +} + +struct __attribute__((nopac)) VirtualBase1 : virtual Base1 { + VirtualBase1(){} + virtual void f() {} +}; +struct __attribute__((nopac)) VirtualBase2 : virtual Base1, Base2 { + VirtualBase2(){} + virtual void g() {} +}; +struct __attribute__((nopac)) Derived4 : VirtualBase1, VirtualBase2 { + virtual void h() {} +}; +struct __attribute__((nopac)) Derived5 : VirtualBase2, VirtualBase1 { + virtual void h() {} +}; + +// ELF-LABEL: define {{.*}} void @_ZN12VirtualBase1C1Ev +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 + +// ELF-LABEL: define {{.*}} void @_ZN12VirtualBase2C1Ev +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 + +// ELF-LABEL: define {{.*}} void @_ZN8Derived4C1Ev +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 + +// ELF-LABEL: define {{.*}} void @_ZN8Derived5C1Ev +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 + + +VirtualBase1 g_vb1; +VirtualBase2 g_vb2; +Derived4 g_d4; +Derived5 g_d5; + + +extern "C" void cross_check_vtables(Base1 *__attribute__((nopac)) b1, + Base2 *__attribute__((nopac)) b2, + Derived1 *__attribute__((nopac)) d1, + Derived2 *__attribute__((nopac)) d2, + Derived3 *__attribute__((nopac)) d3, + VirtualBase1 *__attribute__((nopac)) vb1, + VirtualBase2 *__attribute__((nopac)) vb2, + Derived4 *__attribute__((nopac)) d4, + Derived4 *__attribute__((nopac)) d5) { + asm("; b1->a()" ::: "memory"); + b1->a(); + asm("; b2->b()" ::: "memory"); + b2->b(); + asm("; d1->a()" ::: "memory"); + d1->a(); + asm("; d1->c()" ::: "memory"); + d1->c(); + asm("; d2->a()" ::: "memory"); + d2->a(); + asm("; d2->c()" ::: "memory"); + d2->c(); + asm("; d3->a()" ::: "memory"); + d3->a(); + asm("; d3->b()" ::: "memory"); + d3->b(); + asm("; d3->i()" ::: "memory"); + d3->i(); + asm("; vb1->a()" ::: "memory"); + vb1->a(); + asm("; vb1->f()" ::: "memory"); + vb1->f(); + asm("; vb2->a()" ::: "memory"); + vb2->a(); + asm("; vb2->g()" ::: "memory"); + vb2->g(); + asm("; d4->a()" ::: "memory"); + d4->a(); + asm("; d4->b()" ::: "memory"); + d4->b(); + asm("; d4->f()" ::: "memory"); + d4->f(); + asm("; d4->g()" ::: "memory"); + d4->g(); + asm("; d4->h()" ::: "memory"); + d4->h(); + asm("; d5->a()" ::: "memory"); + d5->a(); + asm("; d5->b()" ::: "memory"); + d5->b(); + asm("; d5->f()" ::: "memory"); + d5->f(); + asm("; d5->g()" ::: "memory"); + d5->g(); + asm("; d5->h()" ::: "memory"); + d5->h(); +} + +// CHECK-LABEL: define{{.*}} void @cross_check_vtables( +// CHECK: "; b1->a()", +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK: "; b2->b()" +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK: "; d1->a()" +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK: "; d1->c()" +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK: "; d2->a()" +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK: "; d2->c()" +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK: "; d3->a()" +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK: "; d3->b()" +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK: "; d3->i()" +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK: "; vb1->a()" +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK: "; vb1->f()" +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK: "; vb2->a()" +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK: "; vb2->g()" +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK: "; d4->a()" +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK: "; d4->b()" +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK: "; d4->f()" +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK: "; d4->g()" +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK: "; d4->h()" +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 + +// ELF-LABEL: define {{.*}} void @_ZN5Base1C2Ev +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 + +// ELF-LABEL: define {{.*}} void @_ZN5Base2C2Ev +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 + +// ELF-LABEL: define {{.*}} void @_ZN8Derived1C2Ev +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 + +// ELF-LABEL: define {{.*}} void @_ZN8Derived2C2Ev +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 + +// ELF-LABEL: define {{.*}} void @_ZN8Derived3C2Ev +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 +// CHECK-NOT: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 diff --git a/clang/test/CodeGenCXX/nopac-member-function-pointer.cpp b/clang/test/CodeGenCXX/nopac-member-function-pointer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..45537f9de2493c1fb9712184180a9aa43f1cb4c2 --- /dev/null +++ b/clang/test/CodeGenCXX/nopac-member-function-pointer.cpp @@ -0,0 +1,374 @@ +// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -o - %s | FileCheck -check-prefixes=CHECK,ELF %s +// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++17 -O1 -disable-llvm-passes -o - %s | FileCheck -check-prefixes=CHECK,ELF,CXX17 %s +// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -debug-info-kind=limited -o - %s | FileCheck -check-prefixes=CHECK,ELF %s + +// CHECK: @gmethod0 = global { i64, i64 } { i64 ptrtoint (ptr @_ZN5Base011nonvirtual0Ev to i64), i64 0 }, align 8 +// CHECK: @gmethod1 = global { i64, i64 } { i64 ptrtoint (ptr @_ZN8Derived011nonvirtual5Ev to i64), i64 0 }, align 8 +// CHECK: @gmethod2 = global { i64, i64 } { i64 0, i64 1 }, align 8 + +// CHECK: @__const._Z13testArrayInitv.p0 = private unnamed_addr constant [1 x { i64, i64 }] [{ i64, i64 } { i64 ptrtoint (ptr @_ZN5Base011nonvirtual0Ev to i64), i64 0 }], align 8 +// CHECK: @__const._Z13testArrayInitv.p1 = private unnamed_addr constant [1 x { i64, i64 }] [{ i64, i64 } { i64 0, i64 1 }], align 8 +// CHECK: @__const._Z13testArrayInitv.c0 = private unnamed_addr constant %struct.Class0 { { i64, i64 } { i64 ptrtoint (ptr @_ZN5Base011nonvirtual0Ev to i64), i64 0 } }, align 8 +// CHECK: @__const._Z13testArrayInitv.c1 = private unnamed_addr constant %struct.Class0 { { i64, i64 } { i64 0, i64 1 } }, align 8 + +// CHECK: @_ZN22testNoexceptConversion6mfptr1E = global { i64, i64 } { i64 ptrtoint (ptr @_ZN22testNoexceptConversion1S19nonvirtual_noexceptEv to i64), i64 0 }, align 8 +// CHECK: @_ZN22testNoexceptConversion6mfptr2E = global { i64, i64 } { i64 0, i64 1 }, align 8 +// CHECK: @_ZN22testNoexceptConversion15mfptr3_noexceptE = global { i64, i64 } { i64 ptrtoint (ptr @_ZN22testNoexceptConversion1S19nonvirtual_noexceptEv to i64), i64 0 }, align 8 + +// CHECK: @_ZTV5Base0 = unnamed_addr constant { [5 x ptr] } { [5 x ptr] [ptr null, ptr @_ZTI5Base0, +// CHECK-SAME: ptr @_ZN5Base08virtual1Ev, +// CHECK-SAME: ptr @_ZN5Base08virtual3Ev, +// CHECK-SAME: ptr @_ZN5Base016virtual_variadicEiz] }, align 8 + +typedef __SIZE_TYPE__ size_t; + +namespace std { +template +class __attribute__((nopac)) initializer_list { + const _Ep *__begin_; + size_t __size_; + + initializer_list(const _Ep *__b, size_t __s); +}; +} // namespace std + +struct __attribute__((nopac)) Base0 { + void nonvirtual0(); + virtual void virtual1(); + virtual void virtual3(); + virtual void virtual_variadic(int, ...); +}; + +struct __attribute__((nopac)) A0 { + int d[4]; +}; + +struct __attribute__((nopac)) A1 { + int d[8]; +}; + +struct __attribute__((nopac)) __attribute__((trivial_abi)) TrivialS { + TrivialS(const TrivialS &); + ~TrivialS(); + int p[4]; +}; + +struct __attribute__((nopac)) Derived0 : Base0 { + void virtual1() override; + void nonvirtual5(); + virtual void virtual6(); + virtual A0 return_agg(); + virtual A1 sret(); + virtual void trivial_abi(TrivialS); +}; + +struct __attribute__((nopac)) Base1 { + virtual void virtual7(); +}; + +struct __attribute__((nopac)) Derived1 : Base0, Base1 { + void virtual1() override; + void virtual7() override; +}; + +typedef void (Base0::*__attribute__((nopac)) MethodTy0)(); +#if __cplusplus >= 201703L +typedef void (Base0::*__attribute__((nopac)) NoExceptMethodTy0)() noexcept; +#endif +typedef void (Base0::*__attribute__((nopac)) VariadicMethodTy0)(int, ...); +typedef void (Derived0::*__attribute__((nopac)) MethodTy1)(); + +struct __attribute__((nopac)) Class0 { + MethodTy1 m0; +}; + +// CHECK: define{{.*}} void @_ZN5Base08virtual1Ev( + +// CHECK: define{{.*}} void @_Z5test0v() +// CHECK: %[[METHOD0:.*]] = alloca { i64, i64 }, align 8 +// CHECK-NEXT: %[[VARMETHOD1:.*]] = alloca { i64, i64 }, align 8 +// CHECK-NEXT: %[[METHOD2:.*]] = alloca { i64, i64 }, align 8 +// CHECK-NEXT: %[[METHOD3:.*]] = alloca { i64, i64 }, align 8 +// CHECK-NEXT: %[[METHOD4:.*]] = alloca { i64, i64 }, align 8 +// CHECK-NEXT: %[[METHOD5:.*]] = alloca { i64, i64 }, align 8 +// CHECK-NEXT: %[[METHOD6:.*]] = alloca { i64, i64 }, align 8 +// CHECK-NEXT: %[[METHOD7:.*]] = alloca { i64, i64 }, align 8 +// CHECK: store { i64, i64 } { i64 ptrtoint (ptr @_ZN5Base011nonvirtual0Ev to i64), i64 0 }, ptr %[[METHOD0]], align 8 +// CHECK-NEXT: store { i64, i64 } { i64 0, i64 1 }, ptr %[[METHOD0]], align 8 +// CHECK-NEXT: store { i64, i64 } { i64 8, i64 1 }, ptr %[[METHOD0]], align 8 +// CHECK: store { i64, i64 } { i64 16, i64 1 }, ptr %[[VARMETHOD1]], align 8 +// CHECK: store { i64, i64 } { i64 ptrtoint (ptr @_ZN5Base011nonvirtual0Ev to i64), i64 0 }, ptr %[[METHOD2]], align 8 +// CHECK-NEXT: store { i64, i64 } { i64 0, i64 1 }, ptr %[[METHOD2]], align 8 +// CHECK-NEXT: store { i64, i64 } { i64 8, i64 1 }, ptr %[[METHOD2]], align 8 +// CHECK: store { i64, i64 } { i64 ptrtoint (ptr @_ZN8Derived011nonvirtual5Ev to i64), i64 0 }, ptr %[[METHOD2]], align 8 +// CHECK: store { i64, i64 } { i64 24, i64 1 }, ptr %[[METHOD2]], align 8 +// CHECK: store { i64, i64 } { i64 32, i64 1 }, ptr %[[METHOD3]], align 8 +// CHECK: store { i64, i64 } { i64 40, i64 1 }, ptr %[[METHOD4]], align 8 +// CHECK: store { i64, i64 } { i64 48, i64 1 }, ptr %[[METHOD5]], align 8 +// CHECK: store { i64, i64 } { i64 0, i64 1 }, ptr %[[METHOD6]], align 8 +// CHECK: store { i64, i64 } { i64 24, i64 1 }, ptr %[[METHOD7]], align 8 +// CHECK: store { i64, i64 } { i64 0, i64 1 }, ptr %[[METHOD7]], align 8 +// CHECK: ret void + +// These are pure virtual function, so with nopac, there is nothing to define here. + +// CHECK-NOT: define linkonce_odr hidden void @_ZN8Derived08virtual6Ev_vfpthunk_(ptr noundef %[[THIS:.*]]) + +// CHECK-NOT: define linkonce_odr hidden [2 x i64] @_ZN8Derived010return_aggEv_vfpthunk_(ptr noundef %{{.*}}) + +// CHECK-NOT: define linkonce_odr hidden void @_ZN8Derived04sretEv_vfpthunk_(ptr dead_on_unwind noalias writable sret(%struct.A1) align 4 %[[AGG_RESULT:.*]], ptr noundef %{{.*}}) + +// CHECK-NOT: define linkonce_odr hidden void @_ZN8Derived011trivial_abiE8TrivialS_vfpthunk_(ptr noundef %{{.*}}, [2 x i64] %{{.*}}) + +// CHECK-NOT: define linkonce_odr hidden void @_ZN5Base18virtual7Ev_vfpthunk_(ptr noundef %[[THIS:.*]]) + +// CHECK-NOT: define linkonce_odr hidden void @_ZN8Derived18virtual7Ev_vfpthunk_(ptr noundef %[[THIS:.*]]) + +void Base0::virtual1() {} + +void test0() { + MethodTy0 method0; + method0 = &Base0::nonvirtual0; + method0 = &Base0::virtual1; + method0 = &Base0::virtual3; + + VariadicMethodTy0 varmethod1; + varmethod1 = &Base0::virtual_variadic; + + MethodTy1 method2; + method2 = &Derived0::nonvirtual0; + method2 = &Derived0::virtual1; + method2 = &Derived0::virtual3; + method2 = &Derived0::nonvirtual5; + method2 = &Derived0::virtual6; + + A0 (Derived0::*method3)(); + method3 = &Derived0::return_agg; + + A1 (Derived0::*method4)(); + method4 = &Derived0::sret; + + void (Derived0::*method5)(TrivialS); + method5 = &Derived0::trivial_abi; + + void (Base1::*method6)(); + method6 = &Base1::virtual7; + + void (Derived1::*method7)(); + method7 = &Derived1::virtual7; + method7 = &Derived1::virtual1; +} + +// CHECK: define{{.*}} void @_Z5test1P5Base0MS_FvvE(ptr noundef %[[A0:.*]], [2 x i64] %[[A1_COERCE:.*]]) +// CHECK: %[[A1:.*]] = alloca { i64, i64 }, align 8 +// CHECK: %[[A0_ADDR:.*]] = alloca ptr, align 8 +// CHECK: %[[A1_ADDR:.*]] = alloca { i64, i64 }, align 8 +// CHECK: store [2 x i64] %[[A1_COERCE]], ptr %[[A1]], align 8 +// CHECK: %[[A11:.*]] = load { i64, i64 }, ptr %[[A1]], align 8 +// CHECK: store ptr %[[A0]], ptr %[[A0_ADDR]], align 8 +// CHECK: store { i64, i64 } %[[A11]], ptr %[[A1_ADDR]], align 8 +// CHECK: %[[V1:.*]] = load ptr, ptr %[[A0_ADDR]], align 8 +// CHECK: %[[V2:.*]] = load { i64, i64 }, ptr %[[A1_ADDR]], align 8 +// CHECK: %[[MEMPTR_ADJ:.*]] = extractvalue { i64, i64 } %[[V2]], 1 +// CHECK: %[[MEMPTR_ADJ_SHIFTED:.*]] = ashr i64 %[[MEMPTR_ADJ]], 1 +// CHECK: %[[V4:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 %[[MEMPTR_ADJ_SHIFTED]] +// CHECK: %[[MEMPTR_PTR:.*]] = extractvalue { i64, i64 } %[[V2]], 0 +// CHECK: %[[V5:.*]] = and i64 %[[MEMPTR_ADJ]], 1 +// CHECK: %[[MEMPTR_ISVIRTUAL:.*]] = icmp ne i64 %[[V5]], 0 +// CHECK: br i1 %[[MEMPTR_ISVIRTUAL]] + +// CHECK: %[[VTABLE:.*]] = load ptr, ptr %[[V4]], align 8 +// ELF: %[[V12:.*]] = getelementptr i8, ptr %[[VTABLE]], i64 %[[MEMPTR_PTR]] +// CHECK: %[[MEMPTR_VIRTUALFN:.*]] = load ptr, ptr %[[V12]], align 8 +// CHECK: br + +// CHECK: %[[MEMPTR_NONVIRTUALFN:.*]] = inttoptr i64 %[[MEMPTR_PTR]] to ptr +// CHECK: br + +// CHECK: %[[V14:.*]] = phi ptr [ %[[MEMPTR_VIRTUALFN]], {{.*}} ], [ %[[MEMPTR_NONVIRTUALFN]], {{.*}} ] +// CHECK: call void %[[V14]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %[[V4]]) +// CHECK: ret void + +void test1(Base0 *a0, MethodTy0 a1) { + (a0->*a1)(); +} + +// CXX17: define{{.*}} void @_Z14test1_noexceptP5Base0MS_DoFvvE( +// CXX17: %[[V14:.*]] = phi ptr [ %{{.*}}, {{.*}} ], [ %{{.*}}, {{.*}} ] +// CXX17: call void %[[V14]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %{{.*}}) {{.*}} +#if __cplusplus >= 201703L +void test1_noexcept(Base0 *a0, NoExceptMethodTy0 a1) { + (a0->*a1)(); +} +#endif + +// CHECK: define{{.*}} void @_Z15testConversion0M5Base0FvvEM8Derived0FvvE([2 x i64] %[[METHOD0_COERCE:.*]], [2 x i64] %[[METHOD1_COERCE:.*]]) +// CHECK: %[[METHOD0:.*]] = alloca { i64, i64 }, align 8 +// CHECK: %[[METHOD1:.*]] = alloca { i64, i64 }, align 8 +// CHECK: %[[METHOD0_ADDR:.*]] = alloca { i64, i64 }, align 8 +// CHECK: %[[METHOD1_ADDR:.*]] = alloca { i64, i64 }, align 8 +// CHECK: store [2 x i64] %[[METHOD0_COERCE]], ptr %[[METHOD0]], align 8 +// CHECK: %[[METHOD01:.*]] = load { i64, i64 }, ptr %[[METHOD0]], align 8 +// CHECK: store [2 x i64] %[[METHOD1_COERCE]], ptr %[[METHOD1]], align 8 +// CHECK: %[[METHOD12:.*]] = load { i64, i64 }, ptr %[[METHOD1]], align 8 +// CHECK: store { i64, i64 } %[[METHOD01]], ptr %[[METHOD0_ADDR]], align 8 +// CHECK: store { i64, i64 } %[[METHOD12]], ptr %[[METHOD1_ADDR]], align 8 +// CHECK: %[[V2:.*]] = load { i64, i64 }, ptr %[[METHOD0_ADDR]], align 8 +// CHECK: store { i64, i64 } %[[V2]], ptr %[[METHOD1_ADDR]], align 8 +// CHECK: ret void + +void testConversion0(MethodTy0 method0, MethodTy1 method1) { + method1 = method0; +} + +// CHECK: define{{.*}} void @_Z15testConversion1M5Base0FvvE( +// CHECK-NOT: call i64 @llvm.ptrauth.resign + +void testConversion1(MethodTy0 method0) { + MethodTy1 method1 = reinterpret_cast(method0); +} + +// CHECK: define{{.*}} void @_Z15testConversion2M8Derived0FvvE( +// CHECK-NOT: call i64 @llvm.ptrauth.resign + +void testConversion2(MethodTy1 method1) { + MethodTy0 method0 = static_cast(method1); +} + +// CHECK: define{{.*}} void @_Z15testConversion3M8Derived0FvvE( +// CHECK-NOT: call i64 @llvm.ptrauth.resign + +void testConversion3(MethodTy1 method1) { + MethodTy0 method0 = reinterpret_cast(method1); +} + +// No need to call @llvm.ptrauth.resign if the source member function +// pointer is a constant. + +// CHECK: define{{.*}} void @_Z15testConversion4v( +// CHECK: %[[METHOD0:.*]] = alloca { i64, i64 }, align 8 +// CHECK: store { i64, i64 } { i64 0, i64 1 }, ptr %[[METHOD0]] +// CHECK: ret void + +void testConversion4() { + MethodTy0 method0 = reinterpret_cast(&Derived0::virtual1); +} + +// This code used to crash. +namespace testNonVirtualThunk { + struct __attribute__((nopac)) R {}; + + struct __attribute__((nopac)) B0 { + virtual void bar(); + }; + + struct __attribute__((nopac)) B1 { + virtual R foo(); + }; + + struct __attribute__((nopac)) D : B0, B1 { + virtual R foo(); + }; + + D d; +} + +namespace TestAnonymousNamespace { +namespace { +struct __attribute__((nopac)) S { + virtual void foo(){}; +}; +} // namespace + +void test() { + auto t = &S::foo; +} +} // namespace TestAnonymousNamespace + +MethodTy1 gmethod0 = reinterpret_cast(&Base0::nonvirtual0); +MethodTy0 gmethod1 = reinterpret_cast(&Derived0::nonvirtual5); +MethodTy0 gmethod2 = reinterpret_cast(&Derived0::virtual1); + +// CHECK-LABEL: define{{.*}} void @_Z13testArrayInitv() +// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %p0, ptr align 8 @__const._Z13testArrayInitv.p0, i64 16, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %p1, ptr align 8 @__const._Z13testArrayInitv.p1, i64 16, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %c0, ptr align 8 @__const._Z13testArrayInitv.c0, i64 16, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %c1, ptr align 8 @__const._Z13testArrayInitv.c1, i64 16, i1 false) +// CHECK-NOT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev +// CHECK-NOT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_ + +void initList(std::initializer_list); + +void testArrayInit() { + MethodTy1 p0[] = {&Base0::nonvirtual0}; + MethodTy1 p1[] = {&Base0::virtual1}; + Class0 c0{&Base0::nonvirtual0}; + Class0 c1{&Base0::virtual1}; + initList({&Base0::nonvirtual0}); + initList({&Base0::virtual1}); +} + + + +// STACK-PROT: define {{.*}}_vfpthunk{{.*}}[[ATTRS:#[0-9]+]] +// STACK-PROT: attributes [[ATTRS]] = +// STACK-PROT-NOT: ssp +// STACK-PROT-NOT: sspstrong +// STACK-PROT-NOT: sspreq +// STACK-PROT-NEXT: attributes + +// CHECK: define{{.*}} void @_Z15testConvertNullv( +// CHECK: %[[T:.*]] = alloca { i64, i64 }, +// store { i64, i64 } zeroinitializer, { i64, i64 }* %[[T]], + +void testConvertNull() { + VariadicMethodTy0 t = (VariadicMethodTy0)(MethodTy0{}); +} + +namespace testNoexceptConversion { + +// CHECK-LABEL: define internal void @__cxx_global_var_init() +// CHECK: %[[V0:.*]] = load { i64, i64 }, ptr @_ZN22testNoexceptConversion15mfptr0_noexceptE, align 8 +// CHECK: store { i64, i64 } %[[V0]], ptr @_ZN22testNoexceptConversion6mfptr4E, align 8 + +// CHECK: define {{.*}}void @_ZN22testNoexceptConversion5test0Ev() +// CHECK: %[[P0:.*]] = alloca { i64, i64 }, align 8 +// CHECK: store { i64, i64 } { i64 ptrtoint (ptr @_ZN22testNoexceptConversion1S19nonvirtual_noexceptEv to i64), i64 0 }, ptr %[[P0]], align 8, + +// CHECK: define {{.*}}void @_ZN22testNoexceptConversion5test1Ev() +// CHECK: %[[P0:.*]] = alloca { i64, i64 }, align 8 +// CHECK: store { i64, i64 } { i64 0, i64 1 }, ptr %[[P0]], align 8 + +// CHECK: define {{.*}}void @_ZN22testNoexceptConversion5test2Ev() +// CHECK: %[[P0:.*]] = alloca { i64, i64 }, align 8 +// CHECK: %[[V0:.*]] = load { i64, i64 }, ptr @_ZN22testNoexceptConversion15mfptr0_noexceptE, align 8 +// CHECK: store { i64, i64 } %[[V0]], ptr %[[P0]], align 8, + +struct __attribute__((nopac)) S { + void nonvirtual_noexcept() noexcept; + virtual void virtual_noexcept() noexcept; +}; + +void (S::*mfptr0_noexcept)() noexcept; +void (S::*mfptr1)() = &S::nonvirtual_noexcept; +void (S::*mfptr2)() = &S::virtual_noexcept; +void (S::*mfptr3_noexcept)() noexcept = &S::nonvirtual_noexcept; +void (S::*mfptr4)() = mfptr0_noexcept; + +void test0() { + void (S::*p0)() = &S::nonvirtual_noexcept; +} + +void test1() { + void (S::*p0)() = &S::virtual_noexcept; +} + +void test2() { + void (S::*p0)() = mfptr0_noexcept; +} + +} + +// CHECK: declare void @_ZN5Base08virtual3Ev(ptr noundef nonnull align 8 dereferenceable(8)) + +// CHECK: declare void @_ZN5Base016virtual_variadicEiz(ptr noundef nonnull align 8 dereferenceable(8), i32 noundef, ...) \ No newline at end of file diff --git a/clang/test/CodeGenCXX/nopac-rtti-layout.cpp b/clang/test/CodeGenCXX/nopac-rtti-layout.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7ab3a4c1ac1603fc35c5d4cc0515defb3b0e4713 --- /dev/null +++ b/clang/test/CodeGenCXX/nopac-rtti-layout.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 %s -I%S -triple=aarch64-linux-gnu -fptrauth-calls -std=c++11 -emit-llvm -o - | FileCheck --check-prefix=ELF %s + +// XFAIL: * +/* + * NOTE: This is currently not supported. + */ + +#include + +struct __attribute__((nopac)) A { int a; }; + +// ELF: @_ZTI1A = linkonce_odr constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr @_ZTS1A } +// ELF: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr] +// ELF: @_ZTS1A = linkonce_odr constant [3 x i8] c"1A\00" + +auto ATI = typeid(A); diff --git a/clang/test/CodeGenCXX/nopac-static-destructors.cpp b/clang/test/CodeGenCXX/nopac-static-destructors.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c2b819387960230f3a35c66b464a537be6d45720 --- /dev/null +++ b/clang/test/CodeGenCXX/nopac-static-destructors.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -emit-llvm -std=c++11 %s -o - \ +// RUN: | FileCheck %s --check-prefix=CXAATEXIT + +// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -emit-llvm -std=c++11 %s -o - \ +// RUN: -fno-use-cxa-atexit | FileCheck %s --check-prefixes=ATEXIT,ATEXIT_ELF + +// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -emit-llvm -std=c++11 %s \ +// RUN: -fptrauth-function-pointer-type-discrimination -o - | FileCheck %s --check-prefix=CXAATEXIT_DISC + +// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -emit-llvm -std=c++11 %s -o - \ +// RUN: -fptrauth-function-pointer-type-discrimination -fno-use-cxa-atexit \ +// RUN: | FileCheck %s --check-prefixes=ATEXIT_DISC,ATEXIT_DISC_ELF + +class __attribute__((nopac)) Foo { + public: + ~Foo() { + } +}; + +Foo global; + +// CXAATEXIT: define internal void @__cxx_global_var_init() +// CXAATEXIT: call i32 @__cxa_atexit(ptr ptrauth (ptr @_ZN3FooD1Ev, i32 0), ptr @global, ptr @__dso_handle) + +// CXAATEXIT_DISC: define internal void @__cxx_global_var_init() +// CXAATEXIT_DISC: call i32 @__cxa_atexit(ptr ptrauth (ptr @_ZN3FooD1Ev, i32 0, i64 10942), ptr @global, ptr @__dso_handle) + +// ATEXIT: define internal void @__cxx_global_var_init() +// ATEXIT: %{{.*}} = call i32 @atexit(ptr ptrauth (ptr @__dtor_global, i32 0)) + +// ATEXIT_DARWIN: define internal void @__dtor_global() {{.*}} section "__TEXT,__StaticInit,regular,pure_instructions" { +// ATEXIT_ELF: define internal void @__dtor_global() {{.*}} section ".text.startup" { +// ATEXIT_DARWIN: %{{.*}} = call ptr @_ZN3FooD1Ev(ptr @global) +// ATEXIT_ELF: call void @_ZN3FooD1Ev(ptr @global) + +// ATEXIT_DISC: define internal void @__cxx_global_var_init() +// ATEXIT_DISC: %{{.*}} = call i32 @atexit(ptr ptrauth (ptr @__dtor_global, i32 0, i64 10942)) + + +// ATEXIT_DISC_DARWIN: define internal void @__dtor_global() {{.*}} section "__TEXT,__StaticInit,regular,pure_instructions" { +// ATEXIT_DISC_ELF: define internal void @__dtor_global() {{.*}} section ".text.startup" { +// ATEXIT_DISC_DARWIN: %{{.*}} = call ptr @_ZN3FooD1Ev(ptr @global) +// ATEXIT_DISC_ELF: call void @_ZN3FooD1Ev(ptr @global) diff --git a/clang/test/CodeGenCXX/nopac-throw.cpp b/clang/test/CodeGenCXX/nopac-throw.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4063e5a97f059cefbb631debfdaaadbdd0f31b7f --- /dev/null +++ b/clang/test/CodeGenCXX/nopac-throw.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fcxx-exceptions -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK +// RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple aarch64-linux-gnu -fptrauth-calls -fcxx-exceptions -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECKDISC + +class __attribute__((nopac)) Foo { + public: + ~Foo() { + } +}; + +// CHECK-LABEL: define{{.*}} void @_Z1fv() +// CHECK: call void @__cxa_throw(ptr %{{.*}}, ptr @_ZTI3Foo, ptr ptrauth (ptr @_ZN3FooD1Ev, i32 0)) + +// CHECKDISC-LABEL: define{{.*}} void @_Z1fv() +// CHECKDISC: call void @__cxa_throw(ptr %{{.*}}, ptr @_ZTI3Foo, ptr ptrauth (ptr @_ZN3FooD1Ev, i32 0, i64 10942)) + +void f() { + throw Foo(); +} + + +// __cxa_throw is defined to take its destructor as "void (*)(void *)" in the ABI. +// CHECK-LABEL: define{{.*}} void @__cxa_throw({{.*}}) +// CHECK: call void {{%.*}}(ptr noundef {{%.*}}) [ "ptrauth"(i32 0, i64 0) ] + +// CHECKDISC-LABEL: define{{.*}} void @__cxa_throw({{.*}}) +// CHECKDISC: call void {{%.*}}(ptr noundef {{%.*}}) [ "ptrauth"(i32 0, i64 10942) ] + +extern "C" void __cxa_throw(void *exception, void *, void (*dtor)(void *)) { + dtor(exception); +} diff --git a/clang/test/CodeGenCXX/nopac-thunks.cpp b/clang/test/CodeGenCXX/nopac-thunks.cpp new file mode 100644 index 0000000000000000000000000000000000000000..594ac56a08d564c9f50ae70673fefbcbf5414007 --- /dev/null +++ b/clang/test/CodeGenCXX/nopac-thunks.cpp @@ -0,0 +1,44 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -emit-llvm -std=c++11 %s -o - | FileCheck %s + +namespace Test1 { + struct __attribute__((nopac)) B1 { + virtual void* foo1() { + return 0; + } + }; + struct __attribute__((nopac)) Pad1 { + virtual ~Pad1() {} + }; + struct __attribute__((nopac)) Proxy1 : Pad1, B1 { + virtual ~Proxy1() {} + }; + struct __attribute__((nopac)) D : virtual Proxy1 { + virtual ~D() {} + virtual void* foo1(); + }; + void* D::foo1() { + return (void*)this; + } +} + +// CHECK-LABEL: define dso_local noundef ptr @_ZN5Test11D4foo1Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret ptr [[THIS1]] +// + +// CHECK-LABEL: define linkonce_odr void @_ZN5Test11DD1Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) unnamed_addr #[[ATTR0]] comdat { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: call void @_ZN5Test11DD2Ev(ptr noundef nonnull align 8 dereferenceable(8) [[THIS1]], ptr noundef @_ZTTN5Test11DE) #[[ATTR3:[0-9]+]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[THIS1]], i64 8 +// CHECK-NEXT: call void @_ZN5Test16Proxy1D2Ev(ptr noundef nonnull align 8 dereferenceable(16) [[TMP0]]) #[[ATTR3]] +// CHECK-NEXT: ret void +// \ No newline at end of file diff --git a/clang/test/CodeGenCXX/nopac-type-info-vtable.cpp b/clang/test/CodeGenCXX/nopac-type-info-vtable.cpp new file mode 100644 index 0000000000000000000000000000000000000000..76587ed2361c1464658aca0c9f4ff08ae04878ba --- /dev/null +++ b/clang/test/CodeGenCXX/nopac-type-info-vtable.cpp @@ -0,0 +1,90 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -DENABLE_TID=0 -I%S -std=c++11 -triple=aarch64-linux-gnu \ +// RUN: -fptrauth-calls -fptrauth-intrinsics \ +// RUN: -fptrauth-vtable-pointer-type-discrimination \ +// RUN: -fptrauth-vtable-pointer-address-discrimination \ +// RUN: %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,NODISC + +// RUN: %clang_cc1 -DENABLE_TID=1 -I%S -std=c++11 -triple=aarch64-linux-gnu \ +// RUN: -fptrauth-calls -fptrauth-intrinsics \ +// RUN: -fptrauth-vtable-pointer-type-discrimination \ +// RUN: -fptrauth-vtable-pointer-address-discrimination \ +// RUN: -fptrauth-type-info-vtable-pointer-discrimination \ +// RUN: %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,DISC + +// copied from typeinfo_nopac +namespace std { + +#if __has_cpp_attribute(clang::ptrauth_vtable_pointer) +# if __has_feature(ptrauth_type_info_vtable_pointer_discrimination) +# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH \ + [[clang::ptrauth_vtable_pointer(process_independent, address_discrimination, type_discrimination)]] +# else +# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH \ + [[clang::ptrauth_vtable_pointer(process_independent, no_address_discrimination, no_extra_discrimination)]] +# endif +#else +# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH +#endif + + class __attribute__((nopac)) _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH type_info + { + type_info& operator=(const type_info&); + type_info(const type_info&); + + protected: + explicit type_info(const char* __n); + + public: + virtual ~type_info(); + + virtual void test_method(); + }; +} // namespace std + +struct __attribute__((nopac)) TestStruct { + virtual ~TestStruct(); + int a; +}; + +// CHECK-LABEL: define dso_local void @_ZN10TestStructD1Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(12) [[THIS:%.*]]) unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: call void @_ZN10TestStructD2Ev(ptr noundef nonnull align 8 dereferenceable(12) [[THIS1]]) #[[ATTR3:[0-9]+]] +// CHECK-NEXT: ret void +// +TestStruct::~TestStruct(){} + +// CHECK-LABEL: define dso_local void @test_vtable( +// CHECK-SAME: ptr noundef [[T:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[T_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[T]], ptr [[T_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[T_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 2 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: call void [[TMP1]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP0]]) +// CHECK-NEXT: ret void +// +extern "C" void test_vtable(std::type_info* t) { + t->test_method(); +} + + +// CHECK-LABEL: define dso_local ptr @ensure_typeinfo( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[CALL:%.*]] = call noalias noundef nonnull ptr @_Znwm(i64 noundef 16) #[[ATTR5:[0-9]+]] +// CHECK-NEXT: call void @_ZN10TestStructC1Ev(ptr noundef nonnull align 8 dereferenceable(12) [[CALL]]) #[[ATTR3]] +// CHECK-NEXT: ret ptr [[CALL]] +// +extern "C" const void *ensure_typeinfo() { + return new TestStruct; +} +//// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +// DISC: {{.*}} +// NODISC: {{.*}} diff --git a/clang/test/CodeGenCXX/nopac-virtual-function.cpp b/clang/test/CodeGenCXX/nopac-virtual-function.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f84f14b0bdcfc0076a044956f06863f14adaa53 --- /dev/null +++ b/clang/test/CodeGenCXX/nopac-virtual-function.cpp @@ -0,0 +1,563 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -emit-llvm -std=c++11 %s -o - | FileCheck --check-prefixes=CHECK,ELF %s + +struct __attribute__((nopac)) S0 { + int f; +}; + +struct __attribute__((nopac)) S1 { + int f; +}; + +struct __attribute__((nopac)) S2 : S0, S1 { + int f; +}; + +class __attribute__((nopac)) B0 { +public: + virtual void m0(); + virtual S1 *m1(); + virtual void m2(); + virtual ~B0(); + int f; +}; + +class __attribute__((nopac)) B1 { +public: + virtual void m0(); +}; + +class __attribute__((nopac)) D0 : public B0 { +public: + void m0() override; + S2 *m1() override; + virtual void m3(); + int f; +}; + +class __attribute__((nopac)) D1 : public B0 { +public: + void m0() override; + S2 *m1() override; + int f; +}; + +class __attribute__((nopac)) D2 : public D0, public D1 { +public: + void m0() override; + S2 *m1() override; + void m3() override; + int f; +}; + +class __attribute__((nopac)) V0 : public virtual B0 { +public: + void m0() override; + S2 *m1() override; + int f; +}; + +class __attribute__((nopac)) V1 : public virtual B0 { +public: + void m0() override; + S2 *m1() override; + ~V1(); + int f; +}; + +class __attribute__((nopac)) D3 : public V0, public V1 { +public: + void m0() override; + S2 *m1() override; + int f; +}; + +B1 g_B1; + +// CHECK-LABEL: define dso_local void @_ZN2B02m0Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(12) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret void +// +void B0::m0() {} + +// CHECK-LABEL: define dso_local void @_ZN2B12m0Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret void +// +void B1::m0() {} + +// CHECK-LABEL: define dso_local void @_ZN2D02m0Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(16) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret void +// +void D0::m0() {} + +// CHECK-LABEL: define dso_local void @_ZN2D12m0Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(16) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret void +// +void D1::m0() {} + +// CHECK-LABEL: define dso_local void @_ZN2D22m0Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(36) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret void +// +void D2::m0() {} + +// CHECK-LABEL: define dso_local void @_ZN2D32m0Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret void +// +void D3::m0() {} + +// CHECK-LABEL: define dso_local void @_ZN2V1D1Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(12) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: call void @_ZN2V1D2Ev(ptr noundef nonnull align 8 dereferenceable(12) [[THIS1]], ptr noundef @_ZTT2V1) #[[ATTR5:[0-9]+]] +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[THIS1]], i64 16 +// CHECK-NEXT: call void @_ZN2B0D2Ev(ptr noundef nonnull align 8 dereferenceable(12) [[TMP0]]) #[[ATTR5]] +// CHECK-NEXT: ret void +// +V1::~V1() { + m1(); +} + + +// CHECK-LABEL: define dso_local void @_Z8testB0m0P2B0( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 0 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: call void [[TMP1]](ptr noundef nonnull align 8 dereferenceable(12) [[TMP0]]) +// CHECK-NEXT: ret void +// +void testB0m0(B0 *a) { + a->m0(); +} + + +// CHECK-LABEL: define dso_local void @_Z8testB0m1P2B0( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 1 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: [[CALL:%.*]] = call noundef ptr [[TMP1]](ptr noundef nonnull align 8 dereferenceable(12) [[TMP0]]) +// CHECK-NEXT: ret void +// +void testB0m1(B0 *a) { + a->m1(); +} + + +// CHECK-LABEL: define dso_local void @_Z8testB0m2P2B0( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 2 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: call void [[TMP1]](ptr noundef nonnull align 8 dereferenceable(12) [[TMP0]]) +// CHECK-NEXT: ret void +// +void testB0m2(B0 *a) { + a->m2(); +} + + +// CHECK-LABEL: define dso_local void @_Z8testD0m0P2D0( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 0 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: call void [[TMP1]](ptr noundef nonnull align 8 dereferenceable(16) [[TMP0]]) +// CHECK-NEXT: ret void +// +void testD0m0(D0 *a) { + a->m0(); +} + + +// CHECK-LABEL: define dso_local void @_Z8testD0m1P2D0( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 5 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: [[CALL:%.*]] = call noundef ptr [[TMP1]](ptr noundef nonnull align 8 dereferenceable(16) [[TMP0]]) +// CHECK-NEXT: ret void +// +void testD0m1(D0 *a) { + a->m1(); +} + + +// CHECK-LABEL: define dso_local void @_Z8testD0m2P2D0( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 2 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: call void [[TMP1]](ptr noundef nonnull align 8 dereferenceable(12) [[TMP0]]) +// CHECK-NEXT: ret void +// +void testD0m2(D0 *a) { + a->m2(); +} + + +// CHECK-LABEL: define dso_local void @_Z8testD0m3P2D0( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 6 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: call void [[TMP1]](ptr noundef nonnull align 8 dereferenceable(16) [[TMP0]]) +// CHECK-NEXT: ret void +// +void testD0m3(D0 *a) { + a->m3(); +} + + + +// CHECK-LABEL: define dso_local void @_Z8testD1m0P2D1( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 0 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: call void [[TMP1]](ptr noundef nonnull align 8 dereferenceable(16) [[TMP0]]) +// CHECK-NEXT: ret void +// +void testD1m0(D1 *a) { + a->m0(); +} + + +// CHECK-LABEL: define dso_local void @_Z8testD1m1P2D1( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 5 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: [[CALL:%.*]] = call noundef ptr [[TMP1]](ptr noundef nonnull align 8 dereferenceable(16) [[TMP0]]) +// CHECK-NEXT: ret void +// +void testD1m1(D1 *a) { + a->m1(); +} + + +// CHECK-LABEL: define dso_local void @_Z8testD1m2P2D1( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 2 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: call void [[TMP1]](ptr noundef nonnull align 8 dereferenceable(12) [[TMP0]]) +// CHECK-NEXT: ret void +// +void testD1m2(D1 *a) { + a->m2(); +} + + + +// CHECK-LABEL: define dso_local void @_Z8testD2m0P2D2( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 0 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: call void [[TMP1]](ptr noundef nonnull align 8 dereferenceable(36) [[TMP0]]) +// CHECK-NEXT: ret void +// +void testD2m0(D2 *a) { + a->m0(); +} + + +// CHECK-LABEL: define dso_local void @_Z8testD2m1P2D2( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 5 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: [[CALL:%.*]] = call noundef ptr [[TMP1]](ptr noundef nonnull align 8 dereferenceable(36) [[TMP0]]) +// CHECK-NEXT: ret void +// +void testD2m1(D2 *a) { + a->m1(); +} + + +// CHECK-LABEL: define dso_local void @_Z10testD2m2D0P2D2( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: call void @_ZN2B02m2Ev(ptr noundef nonnull align 8 dereferenceable(12) [[TMP0]]) +// CHECK-NEXT: ret void +// +void testD2m2D0(D2 *a) { + a->D0::m2(); +} + + +// CHECK-LABEL: define dso_local void @_Z10testD2m2D1P2D2( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 16 +// CHECK-NEXT: call void @_ZN2B02m2Ev(ptr noundef nonnull align 8 dereferenceable(12) [[ADD_PTR]]) +// CHECK-NEXT: ret void +// +void testD2m2D1(D2 *a) { + a->D1::m2(); +} + + +// CHECK-LABEL: define dso_local void @_Z8testD2m3P2D2( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 6 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: call void [[TMP1]](ptr noundef nonnull align 8 dereferenceable(36) [[TMP0]]) +// CHECK-NEXT: ret void +// +void testD2m3(D2 *a) { + a->m3(); +} + + +// CHECK-LABEL: define dso_local void @_Z8testD3m0P2D3( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 0 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: call void [[TMP1]](ptr noundef nonnull align 8 dereferenceable(32) [[TMP0]]) +// CHECK-NEXT: ret void +// +void testD3m0(D3 *a) { + a->m0(); +} + + +// CHECK-LABEL: define dso_local void @_Z8testD3m1P2D3( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 1 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: [[CALL:%.*]] = call noundef ptr [[TMP1]](ptr noundef nonnull align 8 dereferenceable(32) [[TMP0]]) +// CHECK-NEXT: ret void +// +void testD3m1(D3 *a) { + a->m1(); +} + + +// CHECK-LABEL: define dso_local void @_Z8testD3m2P2D3( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VBASE_OFFSET_PTR:%.*]] = getelementptr i8, ptr [[VTABLE]], i64 -24 +// CHECK-NEXT: [[VBASE_OFFSET:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR]], align 8 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[VBASE_OFFSET]] +// CHECK-NEXT: [[VTABLE1:%.*]] = load ptr, ptr [[ADD_PTR]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE1]], i64 2 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: call void [[TMP1]](ptr noundef nonnull align 8 dereferenceable(12) [[ADD_PTR]]) +// CHECK-NEXT: ret void +// +void testD3m2(D3 *a) { + a->m2(); +} + + +// CHECK-LABEL: define dso_local void @_Z17testD3Destructor0P2D3( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[TMP0]], null +// CHECK-NEXT: br i1 [[ISNULL]], label %[[DELETE_END:.*]], label %[[DELETE_NOTNULL:.*]] +// CHECK: [[DELETE_NOTNULL]]: +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 3 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: call void [[TMP1]](ptr noundef nonnull align 8 dereferenceable(32) [[TMP0]]) #[[ATTR5]] +// CHECK-NEXT: br label %[[DELETE_END]] +// CHECK: [[DELETE_END]]: +// CHECK-NEXT: ret void +// +void testD3Destructor0(D3 *a) { + delete a; +} + +// CHECK-LABEL: define dso_local void @_Z17testD3Destructor1P2D3( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[TMP0]], null +// CHECK-NEXT: br i1 [[ISNULL]], label %[[DELETE_END:.*]], label %[[DELETE_NOTNULL:.*]] +// CHECK: [[DELETE_NOTNULL]]: +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[COMPLETE_OFFSET_PTR:%.*]] = getelementptr inbounds i64, ptr [[VTABLE]], i64 -2 +// CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[COMPLETE_OFFSET_PTR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[TMP1]] +// CHECK-NEXT: [[VTABLE1:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE1]], i64 2 +// CHECK-NEXT: [[TMP3:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: call void [[TMP3]](ptr noundef nonnull align 8 dereferenceable(32) [[TMP0]]) #[[ATTR5]] +// CHECK-NEXT: call void @_ZdlPv(ptr noundef [[TMP2]]) #[[ATTR6:[0-9]+]] +// CHECK-NEXT: br label %[[DELETE_END]] +// CHECK: [[DELETE_END]]: +// CHECK-NEXT: ret void +// +void testD3Destructor1(D3 *a) { + ::delete a; +} + +// CHECK-LABEL: define dso_local void @_Z17testD3Destructor2P2D3( +// CHECK-SAME: ptr noundef [[A:%.*]]) +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE]], i64 2 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: call void [[TMP1]](ptr noundef nonnull align 8 dereferenceable(32) [[TMP0]]) #[[ATTR5]] +// CHECK-NEXT: ret void +// +void testD3Destructor2(D3 *a) { + a->~D3(); +} + +// CHECK-LABEL: define dso_local void @_Z23materializeConstructorsv( +// CHECK-SAME: { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[B0:%.*]] = alloca [[CLASS_B0:%.*]], align 8 +// CHECK-NEXT: [[B1:%.*]] = alloca [[CLASS_B1:%.*]], align 8 +// CHECK-NEXT: [[D0:%.*]] = alloca [[CLASS_D0:%.*]], align 8 +// CHECK-NEXT: [[D1:%.*]] = alloca [[CLASS_D1:%.*]], align 8 +// CHECK-NEXT: [[D2:%.*]] = alloca [[CLASS_D2:%.*]], align 8 +// CHECK-NEXT: [[D3:%.*]] = alloca [[CLASS_D3:%.*]], align 8 +// CHECK-NEXT: [[V0:%.*]] = alloca [[CLASS_V0:%.*]], align 8 +// CHECK-NEXT: [[V1:%.*]] = alloca [[CLASS_V1:%.*]], align 8 +// CHECK-NEXT: call void @_ZN2B0C1Ev(ptr noundef nonnull align 8 dereferenceable(12) [[B0]]) #[[ATTR5]] +// CHECK-NEXT: call void @_ZN2B1C1Ev(ptr noundef nonnull align 8 dereferenceable(8) [[B1]]) #[[ATTR5]] +// CHECK-NEXT: call void @_ZN2D0C1Ev(ptr noundef nonnull align 8 dereferenceable(16) [[D0]]) #[[ATTR5]] +// CHECK-NEXT: call void @_ZN2D1C1Ev(ptr noundef nonnull align 8 dereferenceable(16) [[D1]]) #[[ATTR5]] +// CHECK-NEXT: call void @_ZN2D2C1Ev(ptr noundef nonnull align 8 dereferenceable(36) [[D2]]) #[[ATTR5]] +// CHECK-NEXT: call void @_ZN2D3C1Ev(ptr noundef nonnull align 8 dereferenceable(32) [[D3]]) #[[ATTR5]] +// CHECK-NEXT: call void @_ZN2V0C1Ev(ptr noundef nonnull align 8 dereferenceable(12) [[V0]]) #[[ATTR5]] +// CHECK-NEXT: call void @_ZN2V1C1Ev(ptr noundef nonnull align 8 dereferenceable(12) [[V1]]) #[[ATTR5]] +// CHECK-NEXT: call void @_ZN2V1D1Ev(ptr noundef nonnull align 8 dereferenceable(12) [[V1]]) #[[ATTR5]] +// CHECK-NEXT: call void @_ZN2V0D1Ev(ptr noundef nonnull align 8 dereferenceable(12) [[V0]]) #[[ATTR5]] +// CHECK-NEXT: call void @_ZN2D3D1Ev(ptr noundef nonnull align 8 dereferenceable(32) [[D3]]) #[[ATTR5]] +// CHECK-NEXT: call void @_ZN2D2D1Ev(ptr noundef nonnull align 8 dereferenceable(36) [[D2]]) #[[ATTR5]] +// CHECK-NEXT: call void @_ZN2D1D1Ev(ptr noundef nonnull align 8 dereferenceable(16) [[D1]]) #[[ATTR5]] +// CHECK-NEXT: call void @_ZN2D0D1Ev(ptr noundef nonnull align 8 dereferenceable(16) [[D0]]) #[[ATTR5]] +// CHECK-NEXT: call void @_ZN2B0D1Ev(ptr noundef nonnull align 8 dereferenceable(12) [[B0]]) #[[ATTR5]] +// CHECK-NEXT: ret void +// +void materializeConstructors() { + B0 B0; + B1 B1; + D0 D0; + D1 D1; + D2 D2; + D3 D3; + V0 V0; + V1 V1; +} + +//// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +// ELF: {{.*}} diff --git a/clang/test/CodeGenCXX/nopac-vtable-virtual-inheritance-thunk.cpp b/clang/test/CodeGenCXX/nopac-vtable-virtual-inheritance-thunk.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7b244c5265fa4401ab4c7f9ee3deda7331359a7a --- /dev/null +++ b/clang/test/CodeGenCXX/nopac-vtable-virtual-inheritance-thunk.cpp @@ -0,0 +1,571 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -disable-llvm-passes -fptrauth-intrinsics -fptrauth-calls \ +// RUN: -fptrauth-vtable-pointer-type-discrimination -emit-llvm -O0 -o - | FileCheck --check-prefixes=CHECK,ELF %s + +extern "C" int printf(const char *format, ...); + +class __attribute__((nopac)) A { +public: + A() {} + virtual int f(); + virtual int g(); + virtual int h(...); + virtual ~A() {} + +public: + bool necessary_field; +}; + +// CHECK-LABEL: define dso_local void @_ZN1CD1Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: call void @_ZN1CD2Ev(ptr noundef nonnull align 8 dereferenceable(8) [[THIS1]], ptr noundef @_ZTT1C) +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[THIS1]], i64 8 +// CHECK-NEXT: call void @_ZN1BD2Ev(ptr noundef nonnull align 8 dereferenceable(9) [[TMP0]]) +// CHECK-NEXT: ret void +// + +// CHECK-LABEL: define dso_local void @_ZN1DD1Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: call void @_ZN1DD2Ev(ptr noundef nonnull align 8 dereferenceable(8) [[THIS1]], ptr noundef @_ZTT1D) +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[THIS1]], i64 8 +// CHECK-NEXT: call void @_ZN1BD2Ev(ptr noundef nonnull align 8 dereferenceable(9) [[TMP0]]) +// CHECK-NEXT: ret void +// + +// CHECK-LABEL: define dso_local void @_ZN1FD1Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(16) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: call void @_ZN1FD2Ev(ptr noundef nonnull align 8 dereferenceable(16) [[THIS1]], ptr noundef @_ZTT1F) +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[THIS1]], i64 32 +// CHECK-NEXT: call void @_ZN1ED2Ev(ptr noundef nonnull align 8 dereferenceable(8) [[TMP0]]) +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[THIS1]], i64 16 +// CHECK-NEXT: call void @_ZN1BD2Ev(ptr noundef nonnull align 8 dereferenceable(9) [[TMP1]]) +// CHECK-NEXT: ret void +// + +// CHECK-LABEL: define dso_local void @_ZN1GD1Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(16) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: call void @_ZN1GD2Ev(ptr noundef nonnull align 8 dereferenceable(16) [[THIS1]], ptr noundef @_ZTT1G) +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[THIS1]], i64 24 +// CHECK-NEXT: call void @_ZN1BD2Ev(ptr noundef nonnull align 8 dereferenceable(9) [[TMP0]]) +// CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[THIS1]], i64 16 +// CHECK-NEXT: call void @_ZN1ED2Ev(ptr noundef nonnull align 8 dereferenceable(8) [[TMP1]]) +// CHECK-NEXT: ret void +// + +// CHECK-LABEL: define dso_local noundef i32 @_ZN1E1fEv( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 1 +// + +// CHECK-LABEL: define dso_local noundef i32 @_ZN1A1fEv( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(9) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 0 +// + +// CHECK-LABEL: define dso_local noundef i32 @_ZN1E1gEv( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 1 +// + +// CHECK-LABEL: define dso_local noundef i32 @_ZN1A1gEv( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(9) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 0 +// + +// CHECK-LABEL: define dso_local noundef i32 @_ZN1D1gEv( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 0 +// + +// CHECK-LABEL: define dso_local noundef i32 @_ZN1E1hEz( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]], ...) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 1 +// + +// CHECK-LABEL: define dso_local noundef i32 @_ZN1A1hEz( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(9) [[THIS:%.*]], ...) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 0 +// + +// CHECK-LABEL: define dso_local noundef i32 @_ZN1D1hEz( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]], ...) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: ret i32 0 +// + +class __attribute__((nopac)) B : public A { +public: + + + B() : A() {} + virtual ~B() {} +}; + +class __attribute__((nopac)) C : public virtual B { +public: + C() : B() {} + ~C(); +}; + +class __attribute__((nopac)) D : public virtual B { +public: + D() : B() {} + ~D(); + virtual int g(); + virtual int h(...); +}; + +class __attribute__((nopac)) E { +public: + virtual int f(); + virtual int g(); + virtual int h(...); + virtual ~E(){}; +}; + +class __attribute__((nopac)) F : public C, public D, public virtual E { + ~F(); +}; + +class __attribute__((nopac)) G : public virtual E, public C, public D { + ~G(); +}; + +C::~C() {} +D::~D() {} +F::~F() {} +G::~G() {} +int E::f() { return 1; } +int A::f() { return 0; } +int E::g() { return 1; } +int A::g() { return 0; } +int D::g() { return 0; } + +int E::h(...) { return 1; } +int A::h(...) { return 0; } +int D::h(...) { return 0; } + +// CHECK-LABEL: define dso_local noundef i32 @main( +// CHECK-SAME: ) #[[ATTR3:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*]]: +// CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[ANS:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[B:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[E:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4 +// CHECK-NEXT: [[CALL:%.*]] = call noalias noundef nonnull ptr @_Znwm(i64 noundef 24) #[[ATTR8:[0-9]+]] +// CHECK-NEXT: call void @_ZN1CC1Ev(ptr noundef nonnull align 8 dereferenceable(8) [[CALL]]) +// CHECK-NEXT: [[TMP0:%.*]] = icmp eq ptr [[CALL]], null +// CHECK-NEXT: br i1 [[TMP0]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]] +// CHECK: [[CAST_NOTNULL]]: +// CHECK-NEXT: [[VTABLE:%.*]] = load ptr, ptr [[CALL]], align 8 +// CHECK-NEXT: [[VBASE_OFFSET_PTR:%.*]] = getelementptr i8, ptr [[VTABLE]], i64 -24 +// CHECK-NEXT: [[VBASE_OFFSET:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR]], align 8 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 [[VBASE_OFFSET]] +// CHECK-NEXT: br label %[[CAST_END]] +// CHECK: [[CAST_END]]: +// CHECK-NEXT: [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ] +// CHECK-NEXT: store ptr [[CAST_RESULT]], ptr [[ANS]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[ANS]], align 8 +// CHECK-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[TMP1]], null +// CHECK-NEXT: br i1 [[ISNULL]], label %[[DELETE_END:.*]], label %[[DELETE_NOTNULL:.*]] +// CHECK: [[DELETE_NOTNULL]]: +// CHECK-NEXT: [[VTABLE1:%.*]] = load ptr, ptr [[TMP1]], align 8 +// CHECK-NEXT: [[VFN:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE1]], i64 4 +// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[VFN]], align 8 +// CHECK-NEXT: call void [[TMP2]](ptr noundef nonnull align 8 dereferenceable(9) [[TMP1]]) +// CHECK-NEXT: br label %[[DELETE_END]] +// CHECK: [[DELETE_END]]: +// CHECK-NEXT: [[CALL2:%.*]] = call noalias noundef nonnull ptr @_Znwm(i64 noundef 24) #[[ATTR8]] +// CHECK-NEXT: call void @_ZN1DC1Ev(ptr noundef nonnull align 8 dereferenceable(8) [[CALL2]]) +// CHECK-NEXT: [[TMP3:%.*]] = icmp eq ptr [[CALL2]], null +// CHECK-NEXT: br i1 [[TMP3]], label %[[CAST_END8:.*]], label %[[CAST_NOTNULL3:.*]] +// CHECK: [[CAST_NOTNULL3]]: +// CHECK-NEXT: [[VTABLE4:%.*]] = load ptr, ptr [[CALL2]], align 8 +// CHECK-NEXT: [[VBASE_OFFSET_PTR5:%.*]] = getelementptr i8, ptr [[VTABLE4]], i64 -24 +// CHECK-NEXT: [[VBASE_OFFSET6:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR5]], align 8 +// CHECK-NEXT: [[ADD_PTR7:%.*]] = getelementptr inbounds i8, ptr [[CALL2]], i64 [[VBASE_OFFSET6]] +// CHECK-NEXT: br label %[[CAST_END8]] +// CHECK: [[CAST_END8]]: +// CHECK-NEXT: [[CAST_RESULT9:%.*]] = phi ptr [ [[ADD_PTR7]], %[[CAST_NOTNULL3]] ], [ null, %[[DELETE_END]] ] +// CHECK-NEXT: store ptr [[CAST_RESULT9]], ptr [[B]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[B]], align 8 +// CHECK-NEXT: [[VTABLE10:%.*]] = load ptr, ptr [[TMP4]], align 8 +// CHECK-NEXT: [[VFN11:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE10]], i64 0 +// CHECK-NEXT: [[TMP5:%.*]] = load ptr, ptr [[VFN11]], align 8 +// CHECK-NEXT: [[CALL12:%.*]] = call noundef i32 [[TMP5]](ptr noundef nonnull align 8 dereferenceable(9) [[TMP4]]) +// CHECK-NEXT: [[TMP6:%.*]] = load ptr, ptr [[B]], align 8 +// CHECK-NEXT: [[VTABLE13:%.*]] = load ptr, ptr [[TMP6]], align 8 +// CHECK-NEXT: [[VFN14:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE13]], i64 1 +// CHECK-NEXT: [[TMP7:%.*]] = load ptr, ptr [[VFN14]], align 8 +// CHECK-NEXT: [[CALL15:%.*]] = call noundef i32 [[TMP7]](ptr noundef nonnull align 8 dereferenceable(9) [[TMP6]]) +// CHECK-NEXT: [[TMP8:%.*]] = load ptr, ptr [[B]], align 8 +// CHECK-NEXT: [[VTABLE16:%.*]] = load ptr, ptr [[TMP8]], align 8 +// CHECK-NEXT: [[VFN17:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE16]], i64 2 +// CHECK-NEXT: [[TMP9:%.*]] = load ptr, ptr [[VFN17]], align 8 +// CHECK-NEXT: [[CALL18:%.*]] = call noundef i32 (ptr, ...) [[TMP9]](ptr noundef nonnull align 8 dereferenceable(9) [[TMP8]], i32 noundef 1, i32 noundef 2, i32 noundef 3) +// CHECK-NEXT: [[CALL19:%.*]] = call noalias noundef nonnull ptr @_Znwm(i64 noundef 24) #[[ATTR8]] +// CHECK-NEXT: call void @_ZN1CC1Ev(ptr noundef nonnull align 8 dereferenceable(8) [[CALL19]]) +// CHECK-NEXT: [[TMP10:%.*]] = icmp eq ptr [[CALL19]], null +// CHECK-NEXT: br i1 [[TMP10]], label %[[CAST_END25:.*]], label %[[CAST_NOTNULL20:.*]] +// CHECK: [[CAST_NOTNULL20]]: +// CHECK-NEXT: [[VTABLE21:%.*]] = load ptr, ptr [[CALL19]], align 8 +// CHECK-NEXT: [[VBASE_OFFSET_PTR22:%.*]] = getelementptr i8, ptr [[VTABLE21]], i64 -24 +// CHECK-NEXT: [[VBASE_OFFSET23:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR22]], align 8 +// CHECK-NEXT: [[ADD_PTR24:%.*]] = getelementptr inbounds i8, ptr [[CALL19]], i64 [[VBASE_OFFSET23]] +// CHECK-NEXT: br label %[[CAST_END25]] +// CHECK: [[CAST_END25]]: +// CHECK-NEXT: [[CAST_RESULT26:%.*]] = phi ptr [ [[ADD_PTR24]], %[[CAST_NOTNULL20]] ], [ null, %[[CAST_END8]] ] +// CHECK-NEXT: store ptr [[CAST_RESULT26]], ptr [[B]], align 8 +// CHECK-NEXT: [[TMP11:%.*]] = load ptr, ptr [[B]], align 8 +// CHECK-NEXT: [[VTABLE27:%.*]] = load ptr, ptr [[TMP11]], align 8 +// CHECK-NEXT: [[VFN28:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE27]], i64 0 +// CHECK-NEXT: [[TMP12:%.*]] = load ptr, ptr [[VFN28]], align 8 +// CHECK-NEXT: [[CALL29:%.*]] = call noundef i32 [[TMP12]](ptr noundef nonnull align 8 dereferenceable(9) [[TMP11]]) +// CHECK-NEXT: [[TMP13:%.*]] = load ptr, ptr [[B]], align 8 +// CHECK-NEXT: [[VTABLE30:%.*]] = load ptr, ptr [[TMP13]], align 8 +// CHECK-NEXT: [[VFN31:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE30]], i64 2 +// CHECK-NEXT: [[TMP14:%.*]] = load ptr, ptr [[VFN31]], align 8 +// CHECK-NEXT: [[CALL32:%.*]] = call noundef i32 (ptr, ...) [[TMP14]](ptr noundef nonnull align 8 dereferenceable(9) [[TMP13]], i32 noundef 1, i32 noundef 2, i32 noundef 3) +// CHECK-NEXT: [[CALL33:%.*]] = call noalias noundef nonnull ptr @_Znwm(i64 noundef 24) #[[ATTR8]] +// CHECK-NEXT: call void @_ZN1CC1Ev(ptr noundef nonnull align 8 dereferenceable(8) [[CALL33]]) +// CHECK-NEXT: [[TMP15:%.*]] = icmp eq ptr [[CALL33]], null +// CHECK-NEXT: br i1 [[TMP15]], label %[[CAST_END39:.*]], label %[[CAST_NOTNULL34:.*]] +// CHECK: [[CAST_NOTNULL34]]: +// CHECK-NEXT: [[VTABLE35:%.*]] = load ptr, ptr [[CALL33]], align 8 +// CHECK-NEXT: [[VBASE_OFFSET_PTR36:%.*]] = getelementptr i8, ptr [[VTABLE35]], i64 -24 +// CHECK-NEXT: [[VBASE_OFFSET37:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR36]], align 8 +// CHECK-NEXT: [[ADD_PTR38:%.*]] = getelementptr inbounds i8, ptr [[CALL33]], i64 [[VBASE_OFFSET37]] +// CHECK-NEXT: br label %[[CAST_END39]] +// CHECK: [[CAST_END39]]: +// CHECK-NEXT: [[CAST_RESULT40:%.*]] = phi ptr [ [[ADD_PTR38]], %[[CAST_NOTNULL34]] ], [ null, %[[CAST_END25]] ] +// CHECK-NEXT: store ptr [[CAST_RESULT40]], ptr [[B]], align 8 +// CHECK-NEXT: [[TMP16:%.*]] = load ptr, ptr [[B]], align 8 +// CHECK-NEXT: [[VTABLE41:%.*]] = load ptr, ptr [[TMP16]], align 8 +// CHECK-NEXT: [[VFN42:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE41]], i64 0 +// CHECK-NEXT: [[TMP17:%.*]] = load ptr, ptr [[VFN42]], align 8 +// CHECK-NEXT: [[CALL43:%.*]] = call noundef i32 [[TMP17]](ptr noundef nonnull align 8 dereferenceable(9) [[TMP16]]) +// CHECK-NEXT: [[TMP18:%.*]] = load ptr, ptr [[B]], align 8 +// CHECK-NEXT: [[VTABLE44:%.*]] = load ptr, ptr [[TMP18]], align 8 +// CHECK-NEXT: [[VFN45:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE44]], i64 2 +// CHECK-NEXT: [[TMP19:%.*]] = load ptr, ptr [[VFN45]], align 8 +// CHECK-NEXT: [[CALL46:%.*]] = call noundef i32 (ptr, ...) [[TMP19]](ptr noundef nonnull align 8 dereferenceable(9) [[TMP18]], i32 noundef 1, i32 noundef 2, i32 noundef 3) +// CHECK-NEXT: [[CALL47:%.*]] = call noalias noundef nonnull ptr @_Znwm(i64 noundef 40) #[[ATTR8]] +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[CALL47]], i8 0, i64 40, i1 false) +// CHECK-NEXT: call void @_ZN1FC1Ev(ptr noundef nonnull align 8 dereferenceable(16) [[CALL47]]) +// CHECK-NEXT: [[TMP20:%.*]] = icmp eq ptr [[CALL47]], null +// CHECK-NEXT: br i1 [[TMP20]], label %[[CAST_END53:.*]], label %[[CAST_NOTNULL48:.*]] +// CHECK: [[CAST_NOTNULL48]]: +// CHECK-NEXT: [[VTABLE49:%.*]] = load ptr, ptr [[CALL47]], align 8 +// CHECK-NEXT: [[VBASE_OFFSET_PTR50:%.*]] = getelementptr i8, ptr [[VTABLE49]], i64 -24 +// CHECK-NEXT: [[VBASE_OFFSET51:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR50]], align 8 +// CHECK-NEXT: [[ADD_PTR52:%.*]] = getelementptr inbounds i8, ptr [[CALL47]], i64 [[VBASE_OFFSET51]] +// CHECK-NEXT: br label %[[CAST_END53]] +// CHECK: [[CAST_END53]]: +// CHECK-NEXT: [[CAST_RESULT54:%.*]] = phi ptr [ [[ADD_PTR52]], %[[CAST_NOTNULL48]] ], [ null, %[[CAST_END39]] ] +// CHECK-NEXT: store ptr [[CAST_RESULT54]], ptr [[B]], align 8 +// CHECK-NEXT: [[TMP21:%.*]] = load ptr, ptr [[B]], align 8 +// CHECK-NEXT: [[VTABLE55:%.*]] = load ptr, ptr [[TMP21]], align 8 +// CHECK-NEXT: [[VFN56:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE55]], i64 0 +// CHECK-NEXT: [[TMP22:%.*]] = load ptr, ptr [[VFN56]], align 8 +// CHECK-NEXT: [[CALL57:%.*]] = call noundef i32 [[TMP22]](ptr noundef nonnull align 8 dereferenceable(9) [[TMP21]]) +// CHECK-NEXT: [[TMP23:%.*]] = load ptr, ptr [[B]], align 8 +// CHECK-NEXT: [[VTABLE58:%.*]] = load ptr, ptr [[TMP23]], align 8 +// CHECK-NEXT: [[VFN59:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE58]], i64 1 +// CHECK-NEXT: [[TMP24:%.*]] = load ptr, ptr [[VFN59]], align 8 +// CHECK-NEXT: [[CALL60:%.*]] = call noundef i32 [[TMP24]](ptr noundef nonnull align 8 dereferenceable(9) [[TMP23]]) +// CHECK-NEXT: [[TMP25:%.*]] = load ptr, ptr [[B]], align 8 +// CHECK-NEXT: [[VTABLE61:%.*]] = load ptr, ptr [[TMP25]], align 8 +// CHECK-NEXT: [[VFN62:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE61]], i64 2 +// CHECK-NEXT: [[TMP26:%.*]] = load ptr, ptr [[VFN62]], align 8 +// CHECK-NEXT: [[CALL63:%.*]] = call noundef i32 (ptr, ...) [[TMP26]](ptr noundef nonnull align 8 dereferenceable(9) [[TMP25]], i32 noundef 1, i32 noundef 2, i32 noundef 3) +// CHECK-NEXT: [[CALL64:%.*]] = call noalias noundef nonnull ptr @_Znwm(i64 noundef 16) #[[ATTR8]] +// CHECK-NEXT: call void @_ZN1BC1Ev(ptr noundef nonnull align 8 dereferenceable(9) [[CALL64]]) +// CHECK-NEXT: store ptr [[CALL64]], ptr [[ANS]], align 8 +// CHECK-NEXT: [[TMP27:%.*]] = load ptr, ptr [[ANS]], align 8 +// CHECK-NEXT: [[ISNULL65:%.*]] = icmp eq ptr [[TMP27]], null +// CHECK-NEXT: br i1 [[ISNULL65]], label %[[DELETE_END69:.*]], label %[[DELETE_NOTNULL66:.*]] +// CHECK: [[DELETE_NOTNULL66]]: +// CHECK-NEXT: [[VTABLE67:%.*]] = load ptr, ptr [[TMP27]], align 8 +// CHECK-NEXT: [[VFN68:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE67]], i64 4 +// CHECK-NEXT: [[TMP28:%.*]] = load ptr, ptr [[VFN68]], align 8 +// CHECK-NEXT: call void [[TMP28]](ptr noundef nonnull align 8 dereferenceable(9) [[TMP27]]) +// CHECK-NEXT: br label %[[DELETE_END69]] +// CHECK: [[DELETE_END69]]: +// CHECK-NEXT: [[CALL70:%.*]] = call noalias noundef nonnull ptr @_Znwm(i64 noundef 40) #[[ATTR8]] +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[CALL70]], i8 0, i64 40, i1 false) +// CHECK-NEXT: call void @_ZN1FC1Ev(ptr noundef nonnull align 8 dereferenceable(16) [[CALL70]]) +// CHECK-NEXT: [[TMP29:%.*]] = icmp eq ptr [[CALL70]], null +// CHECK-NEXT: br i1 [[TMP29]], label %[[CAST_END76:.*]], label %[[CAST_NOTNULL71:.*]] +// CHECK: [[CAST_NOTNULL71]]: +// CHECK-NEXT: [[VTABLE72:%.*]] = load ptr, ptr [[CALL70]], align 8 +// CHECK-NEXT: [[VBASE_OFFSET_PTR73:%.*]] = getelementptr i8, ptr [[VTABLE72]], i64 -24 +// CHECK-NEXT: [[VBASE_OFFSET74:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR73]], align 8 +// CHECK-NEXT: [[ADD_PTR75:%.*]] = getelementptr inbounds i8, ptr [[CALL70]], i64 [[VBASE_OFFSET74]] +// CHECK-NEXT: br label %[[CAST_END76]] +// CHECK: [[CAST_END76]]: +// CHECK-NEXT: [[CAST_RESULT77:%.*]] = phi ptr [ [[ADD_PTR75]], %[[CAST_NOTNULL71]] ], [ null, %[[DELETE_END69]] ] +// CHECK-NEXT: store ptr [[CAST_RESULT77]], ptr [[ANS]], align 8 +// CHECK-NEXT: [[TMP30:%.*]] = load ptr, ptr [[ANS]], align 8 +// CHECK-NEXT: [[VTABLE78:%.*]] = load ptr, ptr [[TMP30]], align 8 +// CHECK-NEXT: [[VFN79:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE78]], i64 0 +// CHECK-NEXT: [[TMP31:%.*]] = load ptr, ptr [[VFN79]], align 8 +// CHECK-NEXT: [[CALL80:%.*]] = call noundef i32 [[TMP31]](ptr noundef nonnull align 8 dereferenceable(9) [[TMP30]]) +// CHECK-NEXT: [[TMP32:%.*]] = load ptr, ptr [[ANS]], align 8 +// CHECK-NEXT: [[VTABLE81:%.*]] = load ptr, ptr [[TMP32]], align 8 +// CHECK-NEXT: [[VFN82:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE81]], i64 1 +// CHECK-NEXT: [[TMP33:%.*]] = load ptr, ptr [[VFN82]], align 8 +// CHECK-NEXT: [[CALL83:%.*]] = call noundef i32 [[TMP33]](ptr noundef nonnull align 8 dereferenceable(9) [[TMP32]]) +// CHECK-NEXT: [[TMP34:%.*]] = load ptr, ptr [[ANS]], align 8 +// CHECK-NEXT: [[VTABLE84:%.*]] = load ptr, ptr [[TMP34]], align 8 +// CHECK-NEXT: [[VFN85:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE84]], i64 2 +// CHECK-NEXT: [[TMP35:%.*]] = load ptr, ptr [[VFN85]], align 8 +// CHECK-NEXT: [[CALL86:%.*]] = call noundef i32 (ptr, ...) [[TMP35]](ptr noundef nonnull align 8 dereferenceable(9) [[TMP34]], i32 noundef 1, i32 noundef 2, i32 noundef 3) +// CHECK-NEXT: [[TMP36:%.*]] = load ptr, ptr [[ANS]], align 8 +// CHECK-NEXT: [[ISNULL87:%.*]] = icmp eq ptr [[TMP36]], null +// CHECK-NEXT: br i1 [[ISNULL87]], label %[[DELETE_END91:.*]], label %[[DELETE_NOTNULL88:.*]] +// CHECK: [[DELETE_NOTNULL88]]: +// CHECK-NEXT: [[VTABLE89:%.*]] = load ptr, ptr [[TMP36]], align 8 +// CHECK-NEXT: [[VFN90:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE89]], i64 4 +// CHECK-NEXT: [[TMP37:%.*]] = load ptr, ptr [[VFN90]], align 8 +// CHECK-NEXT: call void [[TMP37]](ptr noundef nonnull align 8 dereferenceable(9) [[TMP36]]) +// CHECK-NEXT: br label %[[DELETE_END91]] +// CHECK: [[DELETE_END91]]: +// CHECK-NEXT: [[CALL92:%.*]] = call noalias noundef nonnull ptr @_Znwm(i64 noundef 40) #[[ATTR8]] +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[CALL92]], i8 0, i64 40, i1 false) +// CHECK-NEXT: call void @_ZN1FC1Ev(ptr noundef nonnull align 8 dereferenceable(16) [[CALL92]]) +// CHECK-NEXT: [[TMP38:%.*]] = icmp eq ptr [[CALL92]], null +// CHECK-NEXT: br i1 [[TMP38]], label %[[CAST_END98:.*]], label %[[CAST_NOTNULL93:.*]] +// CHECK: [[CAST_NOTNULL93]]: +// CHECK-NEXT: [[VTABLE94:%.*]] = load ptr, ptr [[CALL92]], align 8 +// CHECK-NEXT: [[VBASE_OFFSET_PTR95:%.*]] = getelementptr i8, ptr [[VTABLE94]], i64 -32 +// CHECK-NEXT: [[VBASE_OFFSET96:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR95]], align 8 +// CHECK-NEXT: [[ADD_PTR97:%.*]] = getelementptr inbounds i8, ptr [[CALL92]], i64 [[VBASE_OFFSET96]] +// CHECK-NEXT: br label %[[CAST_END98]] +// CHECK: [[CAST_END98]]: +// CHECK-NEXT: [[CAST_RESULT99:%.*]] = phi ptr [ [[ADD_PTR97]], %[[CAST_NOTNULL93]] ], [ null, %[[DELETE_END91]] ] +// CHECK-NEXT: store ptr [[CAST_RESULT99]], ptr [[E]], align 8 +// CHECK-NEXT: [[TMP39:%.*]] = load ptr, ptr [[E]], align 8 +// CHECK-NEXT: [[VTABLE100:%.*]] = load ptr, ptr [[TMP39]], align 8 +// CHECK-NEXT: [[VFN101:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE100]], i64 0 +// CHECK-NEXT: [[TMP40:%.*]] = load ptr, ptr [[VFN101]], align 8 +// CHECK-NEXT: [[CALL102:%.*]] = call noundef i32 [[TMP40]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP39]]) +// CHECK-NEXT: [[TMP41:%.*]] = load ptr, ptr [[E]], align 8 +// CHECK-NEXT: [[VTABLE103:%.*]] = load ptr, ptr [[TMP41]], align 8 +// CHECK-NEXT: [[VFN104:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE103]], i64 1 +// CHECK-NEXT: [[TMP42:%.*]] = load ptr, ptr [[VFN104]], align 8 +// CHECK-NEXT: [[CALL105:%.*]] = call noundef i32 [[TMP42]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP41]]) +// CHECK-NEXT: [[TMP43:%.*]] = load ptr, ptr [[E]], align 8 +// CHECK-NEXT: [[VTABLE106:%.*]] = load ptr, ptr [[TMP43]], align 8 +// CHECK-NEXT: [[VFN107:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE106]], i64 2 +// CHECK-NEXT: [[TMP44:%.*]] = load ptr, ptr [[VFN107]], align 8 +// CHECK-NEXT: [[CALL108:%.*]] = call noundef i32 (ptr, ...) [[TMP44]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP43]], i32 noundef 1, i32 noundef 2, i32 noundef 3) +// CHECK-NEXT: [[TMP45:%.*]] = load ptr, ptr [[E]], align 8 +// CHECK-NEXT: [[ISNULL109:%.*]] = icmp eq ptr [[TMP45]], null +// CHECK-NEXT: br i1 [[ISNULL109]], label %[[DELETE_END113:.*]], label %[[DELETE_NOTNULL110:.*]] +// CHECK: [[DELETE_NOTNULL110]]: +// CHECK-NEXT: [[VTABLE111:%.*]] = load ptr, ptr [[TMP45]], align 8 +// CHECK-NEXT: [[VFN112:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE111]], i64 4 +// CHECK-NEXT: [[TMP46:%.*]] = load ptr, ptr [[VFN112]], align 8 +// CHECK-NEXT: call void [[TMP46]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP45]]) +// CHECK-NEXT: br label %[[DELETE_END113]] +// CHECK: [[DELETE_END113]]: +// CHECK-NEXT: [[CALL114:%.*]] = call noalias noundef nonnull ptr @_Znwm(i64 noundef 40) #[[ATTR8]] +// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[CALL114]], i8 0, i64 40, i1 false) +// CHECK-NEXT: call void @_ZN1GC1Ev(ptr noundef nonnull align 8 dereferenceable(16) [[CALL114]]) +// CHECK-NEXT: [[TMP47:%.*]] = icmp eq ptr [[CALL114]], null +// CHECK-NEXT: br i1 [[TMP47]], label %[[CAST_END120:.*]], label %[[CAST_NOTNULL115:.*]] +// CHECK: [[CAST_NOTNULL115]]: +// CHECK-NEXT: [[VTABLE116:%.*]] = load ptr, ptr [[CALL114]], align 8 +// CHECK-NEXT: [[VBASE_OFFSET_PTR117:%.*]] = getelementptr i8, ptr [[VTABLE116]], i64 -32 +// CHECK-NEXT: [[VBASE_OFFSET118:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR117]], align 8 +// CHECK-NEXT: [[ADD_PTR119:%.*]] = getelementptr inbounds i8, ptr [[CALL114]], i64 [[VBASE_OFFSET118]] +// CHECK-NEXT: br label %[[CAST_END120]] +// CHECK: [[CAST_END120]]: +// CHECK-NEXT: [[CAST_RESULT121:%.*]] = phi ptr [ [[ADD_PTR119]], %[[CAST_NOTNULL115]] ], [ null, %[[DELETE_END113]] ] +// CHECK-NEXT: store ptr [[CAST_RESULT121]], ptr [[E]], align 8 +// CHECK-NEXT: [[TMP48:%.*]] = load ptr, ptr [[E]], align 8 +// CHECK-NEXT: [[VTABLE122:%.*]] = load ptr, ptr [[TMP48]], align 8 +// CHECK-NEXT: [[VFN123:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE122]], i64 0 +// CHECK-NEXT: [[TMP49:%.*]] = load ptr, ptr [[VFN123]], align 8 +// CHECK-NEXT: [[CALL124:%.*]] = call noundef i32 [[TMP49]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP48]]) +// CHECK-NEXT: [[TMP50:%.*]] = load ptr, ptr [[E]], align 8 +// CHECK-NEXT: [[VTABLE125:%.*]] = load ptr, ptr [[TMP50]], align 8 +// CHECK-NEXT: [[VFN126:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE125]], i64 1 +// CHECK-NEXT: [[TMP51:%.*]] = load ptr, ptr [[VFN126]], align 8 +// CHECK-NEXT: [[CALL127:%.*]] = call noundef i32 [[TMP51]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP50]]) +// CHECK-NEXT: [[TMP52:%.*]] = load ptr, ptr [[E]], align 8 +// CHECK-NEXT: [[VTABLE128:%.*]] = load ptr, ptr [[TMP52]], align 8 +// CHECK-NEXT: [[VFN129:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE128]], i64 2 +// CHECK-NEXT: [[TMP53:%.*]] = load ptr, ptr [[VFN129]], align 8 +// CHECK-NEXT: [[CALL130:%.*]] = call noundef i32 (ptr, ...) [[TMP53]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP52]], i32 noundef 1, i32 noundef 2, i32 noundef 3) +// CHECK-NEXT: [[TMP54:%.*]] = load ptr, ptr [[E]], align 8 +// CHECK-NEXT: [[ISNULL131:%.*]] = icmp eq ptr [[TMP54]], null +// CHECK-NEXT: br i1 [[ISNULL131]], label %[[DELETE_END135:.*]], label %[[DELETE_NOTNULL132:.*]] +// CHECK: [[DELETE_NOTNULL132]]: +// CHECK-NEXT: [[VTABLE133:%.*]] = load ptr, ptr [[TMP54]], align 8 +// CHECK-NEXT: [[VFN134:%.*]] = getelementptr inbounds ptr, ptr [[VTABLE133]], i64 4 +// CHECK-NEXT: [[TMP55:%.*]] = load ptr, ptr [[VFN134]], align 8 +// CHECK-NEXT: call void [[TMP55]](ptr noundef nonnull align 8 dereferenceable(8) [[TMP54]]) +// CHECK-NEXT: br label %[[DELETE_END135]] +// CHECK: [[DELETE_END135]]: +// CHECK-NEXT: [[TMP56:%.*]] = load i32, ptr [[RETVAL]], align 4 +// CHECK-NEXT: ret i32 [[TMP56]] +// +int main() { + A *ans = new C(); + delete ans; + + B *b = new D(); + b->f(); + b->g(); + b->h(1,2,3); + b = new C(); + b->f(); + b->h(1,2,3); + b = new C(); + b->f(); + b->h(1,2,3); + b = new F(); + b->f(); + b->g(); + b->h(1,2,3); + + ans = new B(); + delete ans; + + ans = new F(); + ans->f(); + ans->g(); + ans->h(1,2,3); + delete ans; + + E *e = new F(); + e->f(); + e->g(); + e->h(1,2,3); + delete e; + e = new G(); + e->f(); + e->g(); + e->h(1,2,3); + delete e; +} + +//// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: +// ELF: {{.*}} + +// CHECK-LABEL: define linkonce_odr void @_ZN1CC1Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[THIS1]], i64 8 +// CHECK-NEXT: call void @_ZN1BC2Ev(ptr noundef nonnull align 8 dereferenceable(9) [[TMP0]]) +// CHECK-NEXT: store ptr getelementptr inbounds inrange(-24, 16) ({ [5 x ptr], [11 x ptr] }, ptr @_ZTV1C, i32 0, i32 0, i32 3), ptr [[THIS1]], align 8 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[THIS1]], i64 8 +// CHECK-NEXT: store ptr getelementptr inbounds inrange(-48, 40) ({ [5 x ptr], [11 x ptr] }, ptr @_ZTV1C, i32 0, i32 1, i32 6), ptr [[ADD_PTR]], align 8 +// CHECK-NEXT: ret void +// + +// CHECK-LABEL: define linkonce_odr void @_ZN1DC1Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[THIS1]], i64 8 +// CHECK-NEXT: call void @_ZN1BC2Ev(ptr noundef nonnull align 8 dereferenceable(9) [[TMP0]]) +// CHECK-NEXT: store ptr getelementptr inbounds inrange(-24, 32) ({ [7 x ptr], [11 x ptr] }, ptr @_ZTV1D, i32 0, i32 0, i32 3), ptr [[THIS1]], align 8 +// CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[THIS1]], i64 8 +// CHECK-NEXT: store ptr getelementptr inbounds inrange(-48, 40) ({ [7 x ptr], [11 x ptr] }, ptr @_ZTV1D, i32 0, i32 1, i32 6), ptr [[ADD_PTR]], align 8 +// CHECK-NEXT: ret void +// + +// CHECK-LABEL: define linkonce_odr void @_ZN1BC1Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(9) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: call void @_ZN1BC2Ev(ptr noundef nonnull align 8 dereferenceable(9) [[THIS1]]) +// CHECK-NEXT: ret void +// + +// CHECK-LABEL: define linkonce_odr void @_ZN1AD1Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(9) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: call void @_ZN1AD2Ev(ptr noundef nonnull align 8 dereferenceable(9) [[THIS1]]) +// CHECK-NEXT: ret void +// + +// CHECK-LABEL: define linkonce_odr void @_ZN1ED1Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(8) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: call void @_ZN1ED2Ev(ptr noundef nonnull align 8 dereferenceable(8) [[THIS1]]) +// CHECK-NEXT: ret void +// + +// CHECK-LABEL: define linkonce_odr void @_ZN1BD1Ev( +// CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(9) [[THIS:%.*]]) unnamed_addr +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[THIS]], ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8 +// CHECK-NEXT: call void @_ZN1BD2Ev(ptr noundef nonnull align 8 dereferenceable(9) [[THIS1]]) +// CHECK-NEXT: ret void +// diff --git a/clang/test/CodeGenCXX/nopac.cpp b/clang/test/CodeGenCXX/nopac.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b0f361cc46a9fade8fba04239ccbcca8c2ca6000 --- /dev/null +++ b/clang/test/CodeGenCXX/nopac.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -emit-llvm -std=c++11 -fexceptions -fcxx-exceptions -o - %s | FileCheck %s + +void f(void); +auto __attribute__((nopac)) &f_ref = f; +// CHECK-NOT: @f_ref = constant ptr ptrauth (ptr @f(), i32 0, i64 18983), align 8 +// CHECK: @f_ref = constant ptr @_Z1fv, align 8 + +// CHECK: define {{(dso_local )?}}void @_Z1gv( +// CHECK-NOT: call void @_Z1fv +// CHECK: call void ptrauth (ptr @_Z1fv, i32 0)() [ "ptrauth"(i32 0, i64 0) ] + +void g() { f_ref(); } + +void foo1(); + +void test_terminate() noexcept { + foo1(); +} + +// CHECK: define {{(dso_local )?}}void @_ZSt9terminatev() #[[ATTR4:.*]] { + +namespace std { + void terminate() noexcept { + } +} + +// CHECK: attributes #[[ATTR4]] = {{{.*}}"ptrauth-calls"{{.*}}} diff --git a/clang/test/CodeGenCXX/nopac_typeinfo b/clang/test/CodeGenCXX/nopac_typeinfo new file mode 100644 index 0000000000000000000000000000000000000000..715492453c09fcfe4c127eb5d7077b06e9a9b5a1 --- /dev/null +++ b/clang/test/CodeGenCXX/nopac_typeinfo @@ -0,0 +1,24 @@ +namespace std { + class __attribute__((nopac)) type_info { + public: + virtual ~type_info(); + const char* name() const { return __name; } + bool operator==(const type_info& __arg) const { + return __name == __arg.__name; + } + + bool operator!=(const type_info& __arg) const { + return !operator==(__arg); + } + + bool before(const type_info& __arg) const { + return __name < __arg.__name; + } + + unsigned long hash_code() const { + return reinterpret_cast(__name); + } + protected: + const char *__name; + }; +} diff --git a/clang/test/CodeGenCXX/ptrauth-member-function-pointer.cpp b/clang/test/CodeGenCXX/ptrauth-member-function-pointer.cpp index 0a9ac3fa510f56535ec0da8af0fb90ec5d1e0b6f..e9436f11b5106e2aff09ca223b6d81199b03a197 100644 --- a/clang/test/CodeGenCXX/ptrauth-member-function-pointer.cpp +++ b/clang/test/CodeGenCXX/ptrauth-member-function-pointer.cpp @@ -1,10 +1,12 @@ // RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -o - %s | FileCheck -check-prefixes=CHECK,NODEBUG,DARWIN %s +// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++17 -O1 -disable-llvm-passes -o - %s | FileCheck -check-prefixes=CHECK,NODEBUG,DARWIN,CXX17 %s // RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -debug-info-kind=limited -o - %s | FileCheck -check-prefixes=CHECK,DARWIN %s // RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -stack-protector 1 -o - %s | FileCheck %s -check-prefix=STACK-PROT // RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -stack-protector 2 -o - %s | FileCheck %s -check-prefix=STACK-PROT // RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -stack-protector 3 -o - %s | FileCheck %s -check-prefix=STACK-PROT // RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -o - %s | FileCheck -check-prefixes=CHECK,NODEBUG,ELF %s +// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++17 -O1 -disable-llvm-passes -o - %s | FileCheck -check-prefixes=CHECK,NODEBUG,ELF,CXX17 %s // RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -debug-info-kind=limited -o - %s | FileCheck -check-prefixes=CHECK,ELF %s // RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -stack-protector 1 -o - %s | FileCheck %s -check-prefix=STACK-PROT // RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -stack-protector 2 -o - %s | FileCheck %s -check-prefix=STACK-PROT @@ -20,6 +22,10 @@ // CHECK: @__const._Z13testArrayInitv.c0 = private unnamed_addr constant %struct.Class0 { { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev, i32 0, i64 35591) to i64), i64 0 } }, align 8 // CHECK: @__const._Z13testArrayInitv.c1 = private unnamed_addr constant %struct.Class0 { { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 35591) to i64), i64 0 } }, align 8 +// CHECK: @_ZN22testNoexceptConversion6mfptr1E = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN22testNoexceptConversion1S19nonvirtual_noexceptEv, i32 0, i64 [[TYPEDISC3:.*]]) to i64), i64 0 }, +// CHECK: @_ZN22testNoexceptConversion6mfptr2E = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN22testNoexceptConversion1S16virtual_noexceptEv_vfpthunk_, i32 0, i64 [[TYPEDISC3]]) to i64), i64 0 }, +// CHECK: @_ZN22testNoexceptConversion15mfptr3_noexceptE = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN22testNoexceptConversion1S19nonvirtual_noexceptEv, i32 0, i64 [[TYPEDISC3]]) to i64), i64 0 }, + // CHECK: @_ZTV5Base0 = unnamed_addr constant { [5 x ptr] } { [5 x ptr] [ptr null, ptr @_ZTI5Base0, // CHECK-SAME: ptr ptrauth (ptr @_ZN5Base08virtual1Ev, i32 0, i64 55600, ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV5Base0, i32 0, i32 0, i32 2)), // CHECK-SAME: ptr ptrauth (ptr @_ZN5Base08virtual3Ev, i32 0, i64 53007, ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV5Base0, i32 0, i32 0, i32 3)), @@ -77,6 +83,9 @@ struct Derived1 : Base0, Base1 { }; typedef void (Base0::*MethodTy0)(); +#if __cplusplus >= 201703L +typedef void (Base0::*NoExceptMethodTy0)() noexcept; +#endif typedef void (Base0::*VariadicMethodTy0)(int, ...); typedef void (Derived0::*MethodTy1)(); @@ -293,6 +302,16 @@ void test1(Base0 *a0, MethodTy0 a1) { (a0->*a1)(); } +// CXX17: define{{.*}} void @_Z14test1_noexceptP5Base0MS_DoFvvE( +// CXX17: %[[V14:.*]] = phi ptr [ %{{.*}}, {{.*}} ], [ %{{.*}}, {{.*}} ] +// CXX17: %[[V15:.*]] = phi i64 [ 0, {{.*}} ], [ [[TYPEDISC0]], {{.*}} ] +// CXX17: call void %[[V14]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %{{.*}}) {{.*}}[ "ptrauth"(i32 0, i64 %[[V15]]) ] +#if __cplusplus >= 201703L +void test1_noexcept(Base0 *a0, NoExceptMethodTy0 a1) { + (a0->*a1)(); +} +#endif + // CHECK: define{{.*}} void @_Z15testConversion0M5Base0FvvEM8Derived0FvvE([2 x i64] %[[METHOD0_COERCE:.*]], [2 x i64] %[[METHOD1_COERCE:.*]]) // CHECK: %[[METHOD0:.*]] = alloca { i64, i64 }, align 8 // CHECK: %[[METHOD1:.*]] = alloca { i64, i64 }, align 8 @@ -438,3 +457,47 @@ void testArrayInit() { void testConvertNull() { VariadicMethodTy0 t = (VariadicMethodTy0)(MethodTy0{}); } + +namespace testNoexceptConversion { + +// CHECK-LABEL: define internal void @__cxx_global_var_init() +// CHECK: %[[V0:.*]] = load { i64, i64 }, ptr @_ZN22testNoexceptConversion15mfptr0_noexceptE, align 8 +// CHECK: store { i64, i64 } %[[V0]], ptr @_ZN22testNoexceptConversion6mfptr4E, align 8 + +// CHECK: define {{.*}}void @_ZN22testNoexceptConversion5test0Ev() +// CHECK: %[[P0:.*]] = alloca { i64, i64 }, align 8 +// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN22testNoexceptConversion1S19nonvirtual_noexceptEv, i32 0, i64 [[TYPEDISC3]]) to i64), i64 0 }, ptr %[[P0]], align 8, + +// CHECK: define {{.*}}void @_ZN22testNoexceptConversion5test1Ev() +// CHECK: %[[P0:.*]] = alloca { i64, i64 }, align 8 +// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN22testNoexceptConversion1S16virtual_noexceptEv_vfpthunk_, i32 0, i64 [[TYPEDISC3]]) to i64), i64 0 }, ptr %[[P0]], align 8, + +// CHECK: define {{.*}}void @_ZN22testNoexceptConversion5test2Ev() +// CHECK: %[[P0:.*]] = alloca { i64, i64 }, align 8 +// CHECK: %[[V0:.*]] = load { i64, i64 }, ptr @_ZN22testNoexceptConversion15mfptr0_noexceptE, align 8 +// CHECK: store { i64, i64 } %[[V0]], ptr %[[P0]], align 8, + +struct S { + void nonvirtual_noexcept() noexcept; + virtual void virtual_noexcept() noexcept; +}; + +void (S::*mfptr0_noexcept)() noexcept; +void (S::*mfptr1)() = &S::nonvirtual_noexcept; +void (S::*mfptr2)() = &S::virtual_noexcept; +void (S::*mfptr3_noexcept)() noexcept = &S::nonvirtual_noexcept; +void (S::*mfptr4)() = mfptr0_noexcept; + +void test0() { + void (S::*p0)() = &S::nonvirtual_noexcept; +} + +void test1() { + void (S::*p0)() = &S::virtual_noexcept; +} + +void test2() { + void (S::*p0)() = mfptr0_noexcept; +} + +} diff --git a/clang/test/CodeGenCXX/ptrauth-rtti-layout.cpp b/clang/test/CodeGenCXX/ptrauth-rtti-layout.cpp index 2b633addd677e004976fdc06a46a8edb5198653a..b50e0908f9db88ee519ae80b7e2bfdc7b37d8293 100644 --- a/clang/test/CodeGenCXX/ptrauth-rtti-layout.cpp +++ b/clang/test/CodeGenCXX/ptrauth-rtti-layout.cpp @@ -5,12 +5,12 @@ struct A { int a; }; +// DARWIN: @_ZTI1A = linkonce_odr hidden constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2), ptr inttoptr (i64 add (i64 ptrtoint (ptr @_ZTS1A to i64), i64 -9223372036854775808) to ptr) } // DARWIN: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr] // DARWIN: @_ZTS1A = linkonce_odr hidden constant [3 x i8] c"1A\00" -// DARWIN: @_ZTI1A = linkonce_odr hidden constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2), ptr inttoptr (i64 add (i64 ptrtoint (ptr @_ZTS1A to i64), i64 -9223372036854775808) to ptr) } +// ELF: @_ZTI1A = linkonce_odr constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2), ptr @_ZTS1A } // ELF: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr] // ELF: @_ZTS1A = linkonce_odr constant [3 x i8] c"1A\00" -// ELF: @_ZTI1A = linkonce_odr constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2), ptr @_ZTS1A } auto ATI = typeid(A); diff --git a/clang/test/CodeGenCXX/ptrauth-type-info-vtable.cpp b/clang/test/CodeGenCXX/ptrauth-type-info-vtable.cpp index 174aeda89d1755a9720ef1f439c034a3f4018ec7..f4396e402703999c97883750ad7a8cfb883c1a17 100644 --- a/clang/test/CodeGenCXX/ptrauth-type-info-vtable.cpp +++ b/clang/test/CodeGenCXX/ptrauth-type-info-vtable.cpp @@ -60,12 +60,13 @@ static_assert(__has_feature(ptrauth_type_info_vtable_pointer_discrimination) == extern "C" int disc_std_type_info = __builtin_ptrauth_string_discriminator("_ZTVSt9type_info"); // CHECK: @_ZTV10TestStruct = unnamed_addr constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr @_ZTI10TestStruct, ptr ptrauth (ptr @_ZN10TestStructD1Ev, i32 0, i64 52216, ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV10TestStruct, i32 0, i32 0, i32 2)), ptr ptrauth (ptr @_ZN10TestStructD0Ev, i32 0, i64 39671, ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV10TestStruct, i32 0, i32 0, i32 3))] }, align 8 -// CHECK: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr] -// CHECK: @_ZTS10TestStruct = constant [13 x i8] c"10TestStruct\00", align 1 // NODISC: @_ZTI10TestStruct = constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2), ptr @_ZTS10TestStruct }, align 8 -// DISC: @_ZTI10TestStruct = constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2, i64 [[STDTYPEINFO_DISC]]), ptr @_ZTS10TestStruct }, align 8 +// DISC: @_ZTI10TestStruct = constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2, i64 [[STDTYPEINFO_DISC]], ptr @_ZTI10TestStruct), ptr @_ZTS10TestStruct }, align 8 + +// CHECK: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr] +// CHECK: @_ZTS10TestStruct = constant [13 x i8] c"10TestStruct\00", align 1 struct TestStruct { virtual ~TestStruct(); diff --git a/clang/test/CodeGenCXX/ptrauth-vtable-virtual-inheritance-thunk.cpp b/clang/test/CodeGenCXX/ptrauth-vtable-virtual-inheritance-thunk.cpp index 031bb48608af7c28b1a6e406378767dfa091e945..b5c15a29eb6b95c895f388d10fefb28ed806cfd1 100644 --- a/clang/test/CodeGenCXX/ptrauth-vtable-virtual-inheritance-thunk.cpp +++ b/clang/test/CodeGenCXX/ptrauth-vtable-virtual-inheritance-thunk.cpp @@ -94,30 +94,30 @@ // CHECK-SAME: ptr ptrauth (ptr @_ZN1AD1Ev, i32 0, i64 2043, ptr getelementptr inbounds ({ [7 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 5)), // CHECK-SAME: ptr ptrauth (ptr @_ZN1AD0Ev, i32 0, i64 63674, ptr getelementptr inbounds ({ [7 x ptr] }, ptr @_ZTV1A, i32 0, i32 0, i32 6))] }, align 8 +// CHECK: @_ZTI1A = constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2), ptr @_ZTS1A }, align 8 + // CHECK: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr] // CHECK: @_ZTS1A = constant [3 x i8] c"1A\00", align 1 -// CHECK: @_ZTI1A = constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2), ptr @_ZTS1A }, align 8 +// CHECK: @_ZTI1C = constant { ptr, ptr, i32, i32, ptr, i64 } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv121__vmi_class_type_infoE, i64 2), i32 2), ptr @_ZTS1C, i32 0, i32 1, ptr @_ZTI1B, i64 -6141 }, align 8 // CHECK: @_ZTVN10__cxxabiv121__vmi_class_type_infoE = external global [0 x ptr] // CHECK: @_ZTS1C = constant [3 x i8] c"1C\00", align 1 +// DARWIN: @_ZTI1B = linkonce_odr hidden constant { ptr, ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), i32 2), ptr inttoptr (i64 add (i64 ptrtoint (ptr @_ZTS1B to i64), i64 -9223372036854775808) to ptr), ptr @_ZTI1A }, align 8 +// ELF: @_ZTI1B = linkonce_odr constant { ptr, ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), i32 2), ptr @_ZTS1B, ptr @_ZTI1A }, comdat, align 8 + // CHECK: @_ZTVN10__cxxabiv120__si_class_type_infoE = external global [0 x ptr] // DARWIN: @_ZTS1B = linkonce_odr hidden constant [3 x i8] c"1B\00", align 1 // ELF: @_ZTS1B = linkonce_odr constant [3 x i8] c"1B\00", comdat, align 1 -// DARWIN: @_ZTI1B = linkonce_odr hidden constant { ptr, ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), i32 2), ptr inttoptr (i64 add (i64 ptrtoint (ptr @_ZTS1B to i64), i64 -9223372036854775808) to ptr), ptr @_ZTI1A }, align 8 -// ELF: @_ZTI1B = linkonce_odr constant { ptr, ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv120__si_class_type_infoE, i64 2), i32 2), ptr @_ZTS1B, ptr @_ZTI1A }, comdat, align 8 - -// CHECK: @_ZTI1C = constant { ptr, ptr, i32, i32, ptr, i64 } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv121__vmi_class_type_infoE, i64 2), i32 2), ptr @_ZTS1C, i32 0, i32 1, ptr @_ZTI1B, i64 -6141 }, align 8 +// CHECK: @_ZTI1D = constant { ptr, ptr, i32, i32, ptr, i64 } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv121__vmi_class_type_infoE, i64 2), i32 2), ptr @_ZTS1D, i32 0, i32 1, ptr @_ZTI1B, i64 -6141 }, align 8 // CHECK: @_ZTS1D = constant [3 x i8] c"1D\00", align 1 -// CHECK: @_ZTI1D = constant { ptr, ptr, i32, i32, ptr, i64 } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv121__vmi_class_type_infoE, i64 2), i32 2), ptr @_ZTS1D, i32 0, i32 1, ptr @_ZTI1B, i64 -6141 }, align 8 - // CHECK: @_ZTV1E = unnamed_addr constant { [7 x ptr] } { [7 x ptr] [ptr null, ptr @_ZTI1E, // CHECK-SAME: ptr ptrauth (ptr @_ZN1E1fEv, i32 0, i64 28408, ptr getelementptr inbounds ({ [7 x ptr] }, ptr @_ZTV1E, i32 0, i32 0, i32 2)), // CHECK-SAME: ptr ptrauth (ptr @_ZN1E1gEv, i32 0, i64 22926, ptr getelementptr inbounds ({ [7 x ptr] }, ptr @_ZTV1E, i32 0, i32 0, i32 3)), @@ -125,10 +125,10 @@ // CHECK-SAME: ptr ptrauth (ptr @_ZN1ED1Ev, i32 0, i64 5817, ptr getelementptr inbounds ({ [7 x ptr] }, ptr @_ZTV1E, i32 0, i32 0, i32 5)), // CHECK-SAME: ptr ptrauth (ptr @_ZN1ED0Ev, i32 0, i64 26464, ptr getelementptr inbounds ({ [7 x ptr] }, ptr @_ZTV1E, i32 0, i32 0, i32 6))] }, align 8 -// CHECK: @_ZTS1E = constant [3 x i8] c"1E\00", align 1 - // CHECK: @_ZTI1E = constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2), ptr @_ZTS1E }, align 8 +// CHECK: @_ZTS1E = constant [3 x i8] c"1E\00", align 1 + // CHECK: @_ZTC1F0_1C = unnamed_addr constant { [5 x ptr], [11 x ptr] } { [5 x ptr] [ptr inttoptr (i64 16 to ptr), ptr null, ptr @_ZTI1C, // CHECK-SAME: ptr ptrauth (ptr @_ZN1CD1Ev, i32 0, i64 31214, ptr getelementptr inbounds ({ [5 x ptr], [11 x ptr] }, ptr @_ZTC1F0_1C, i32 0, i32 0, i32 3)), // CHECK-SAME: ptr ptrauth (ptr @_ZN1CD0Ev, i32 0, i64 8507, ptr getelementptr inbounds ({ [5 x ptr], [11 x ptr] }, ptr @_ZTC1F0_1C, i32 0, i32 0, i32 4))], [11 x ptr] [ptr inttoptr (i64 -16 to ptr), ptr null, ptr null, ptr null, ptr inttoptr (i64 -16 to ptr), ptr @_ZTI1C, @@ -149,10 +149,10 @@ // CHECK-SAME: ptr ptrauth (ptr @_ZTv0_n48_N1DD1Ev, i32 0, i64 2043, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC1F8_1D, i32 0, i32 1, i32 9)), // CHECK-SAME: ptr ptrauth (ptr @_ZTv0_n48_N1DD0Ev, i32 0, i64 63674, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC1F8_1D, i32 0, i32 1, i32 10))] }, align 8 -// CHECK: @_ZTS1F = constant [3 x i8] c"1F\00", align 1 - // CHECK: @_ZTI1F = constant { ptr, ptr, i32, i32, ptr, i64, ptr, i64, ptr, i64 } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv121__vmi_class_type_infoE, i64 2), i32 2), ptr @_ZTS1F, i32 3, i32 3, ptr @_ZTI1C, i64 2, ptr @_ZTI1D, i64 2050, ptr @_ZTI1E, i64 -8189 }, align 8 +// CHECK: @_ZTS1F = constant [3 x i8] c"1F\00", align 1 + // CHECK: @_ZTC1G0_1C = unnamed_addr constant { [5 x ptr], [11 x ptr] } { [5 x ptr] [ptr inttoptr (i64 24 to ptr), ptr null, ptr @_ZTI1C, // CHECK-SAME: ptr ptrauth (ptr @_ZN1CD1Ev, i32 0, i64 31214, ptr getelementptr inbounds ({ [5 x ptr], [11 x ptr] }, ptr @_ZTC1G0_1C, i32 0, i32 0, i32 3)), // CHECK-SAME: ptr ptrauth (ptr @_ZN1CD0Ev, i32 0, i64 8507, ptr getelementptr inbounds ({ [5 x ptr], [11 x ptr] }, ptr @_ZTC1G0_1C, i32 0, i32 0, i32 4))], [11 x ptr] [ptr inttoptr (i64 -24 to ptr), ptr null, ptr null, ptr null, ptr inttoptr (i64 -24 to ptr), ptr @_ZTI1C, @@ -173,10 +173,10 @@ // CHECK-SAME: ptr ptrauth (ptr @_ZTv0_n48_N1DD1Ev, i32 0, i64 2043, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC1G8_1D, i32 0, i32 1, i32 9)), // CHECK-SAME: ptr ptrauth (ptr @_ZTv0_n48_N1DD0Ev, i32 0, i64 63674, ptr getelementptr inbounds ({ [7 x ptr], [11 x ptr] }, ptr @_ZTC1G8_1D, i32 0, i32 1, i32 10))] }, align 8 -// CHECK: @_ZTS1G = constant [3 x i8] c"1G\00", align 1 - // CHECK: @_ZTI1G = constant { ptr, ptr, i32, i32, ptr, i64, ptr, i64, ptr, i64 } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv121__vmi_class_type_infoE, i64 2), i32 2), ptr @_ZTS1G, i32 3, i32 3, ptr @_ZTI1E, i64 -8189, ptr @_ZTI1C, i64 2, ptr @_ZTI1D, i64 2050 }, align 8 +// CHECK: @_ZTS1G = constant [3 x i8] c"1G\00", align 1 + // CHECK: @_ZTV1B = linkonce_odr unnamed_addr constant { [7 x ptr] } { [7 x ptr] [ptr null, ptr @_ZTI1B, // CHECK-SAME: ptr ptrauth (ptr @_ZN1A1fEv, i32 0, i64 55636, ptr getelementptr inbounds ({ [7 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 2)), // CHECK-SAME: ptr ptrauth (ptr @_ZN1A1gEv, i32 0, i64 19402, ptr getelementptr inbounds ({ [7 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 3)), diff --git a/clang/test/CodeGenCXX/rtti-linkage.cpp b/clang/test/CodeGenCXX/rtti-linkage.cpp index ca50a1bc6f01a719ff24d072457f6f320c1eea65..03e7cdedd3462ce64d21124ce2797005ba54b59e 100644 --- a/clang/test/CodeGenCXX/rtti-linkage.cpp +++ b/clang/test/CodeGenCXX/rtti-linkage.cpp @@ -3,73 +3,73 @@ #include +// CHECK-BOTH: _ZTIP1C = internal constant // CHECK-BOTH: _ZTSP1C = internal constant -// CHECK-BOTH: _ZTS1C = internal constant // CHECK-BOTH: _ZTI1C = internal constant -// CHECK-BOTH: _ZTIP1C = internal constant -// CHECK-BOTH: _ZTSPP1C = internal constant +// CHECK-BOTH: _ZTS1C = internal constant // CHECK-BOTH: _ZTIPP1C = internal constant -// CHECK-BOTH: _ZTSM1Ci = internal constant +// CHECK-BOTH: _ZTSPP1C = internal constant // CHECK-BOTH: _ZTIM1Ci = internal constant -// CHECK-BOTH: _ZTSPM1Ci = internal constant +// CHECK-BOTH: _ZTSM1Ci = internal constant // CHECK-BOTH: _ZTIPM1Ci = internal constant -// CHECK-BOTH: _ZTSM1CS_ = internal constant +// CHECK-BOTH: _ZTSPM1Ci = internal constant // CHECK-BOTH: _ZTIM1CS_ = internal constant -// CHECK-BOTH: _ZTSM1CPS_ = internal constant +// CHECK-BOTH: _ZTSM1CS_ = internal constant // CHECK-BOTH: _ZTIM1CPS_ = internal constant +// CHECK-BOTH: _ZTSM1CPS_ = internal constant +// CHECK-BOTH: _ZTIM1A1C = internal constant // CHECK-BOTH: _ZTSM1A1C = internal constant -// CHECK: _ZTS1A = linkonce_odr constant -// CHECK-WITH-HIDDEN: _ZTS1A = linkonce_odr hidden constant // CHECK: _ZTI1A = linkonce_odr constant // CHECK-WITH-HIDDEN: _ZTI1A = linkonce_odr hidden constant -// CHECK-BOTH: _ZTIM1A1C = internal constant -// CHECK-BOTH: _ZTSM1AP1C = internal constant +// CHECK: _ZTS1A = linkonce_odr constant +// CHECK-WITH-HIDDEN: _ZTS1A = linkonce_odr hidden constant // CHECK-BOTH: _ZTIM1AP1C = internal constant +// CHECK-BOTH: _ZTSM1AP1C = internal constant // CHECK-WITH-HIDDEN: _ZTSFN12_GLOBAL__N_11DEvE = internal constant -// CHECK-WITH-HIDDEN: @_ZTSPK2T4 = linkonce_odr hidden constant -// CHECK-WITH-HIDDEN: @_ZTS2T4 = linkonce_odr hidden constant -// CHECK-WITH-HIDDEN: @_ZTI2T4 = linkonce_odr hidden constant -// CHECK-WITH-HIDDEN: @_ZTIPK2T4 = linkonce_odr hidden constant -// CHECK-WITH-HIDDEN: @_ZTSZ2t5vE1A = internal constant +// CHECK-WITH-HIDDEN: @_ZTIPK2T4 = linkonce_odr hidden constant +// CHECK-WITH-HIDDEN: @_ZTSPK2T4 = linkonce_odr hidden constant +// CHECK-WITH-HIDDEN: @_ZTI2T4 = linkonce_odr hidden constant +// CHECK-WITH-HIDDEN: @_ZTS2T4 = linkonce_odr hidden constant // CHECK-WITH-HIDDEN: @_ZTIZ2t5vE1A = internal constant -// CHECK-WITH-HIDDEN: @_ZTSZ2t6vE1A = linkonce_odr hidden constant +// CHECK-WITH-HIDDEN: @_ZTSZ2t5vE1A = internal constant // CHECK-WITH-HIDDEN: @_ZTIZ2t6vE1A = linkonce_odr hidden constant +// CHECK-WITH-HIDDEN: @_ZTSZ2t6vE1A = linkonce_odr hidden constant +// CHECK-WITH-HIDDEN: @_ZTIPZ2t7vE1A = linkonce_odr hidden constant // CHECK-WITH-HIDDEN: @_ZTSPZ2t7vE1A = linkonce_odr hidden constant -// CHECK-WITH-HIDDEN: @_ZTSZ2t7vE1A = linkonce_odr hidden constant // CHECK-WITH-HIDDEN: @_ZTIZ2t7vE1A = linkonce_odr hidden constant -// CHECK-WITH-HIDDEN: @_ZTIPZ2t7vE1A = linkonce_odr hidden constant +// CHECK-WITH-HIDDEN: @_ZTSZ2t7vE1A = linkonce_odr hidden constant -// CHECK: _ZTSN12_GLOBAL__N_11DE = internal constant // CHECK: _ZTIN12_GLOBAL__N_11DE = internal constant -// CHECK: _ZTSPN12_GLOBAL__N_11DE = internal constant +// CHECK: _ZTSN12_GLOBAL__N_11DE = internal constant // CHECK: _ZTIPN12_GLOBAL__N_11DE = internal constant -// CHECK: _ZTSFN12_GLOBAL__N_11DEvE = internal constant +// CHECK: _ZTSPN12_GLOBAL__N_11DE = internal constant // CHECK: _ZTIFN12_GLOBAL__N_11DEvE = internal constant -// CHECK: _ZTSFvN12_GLOBAL__N_11DEE = internal constant +// CHECK: _ZTSFN12_GLOBAL__N_11DEvE = internal constant // CHECK: _ZTIFvN12_GLOBAL__N_11DEE = internal constant +// CHECK: _ZTSFvN12_GLOBAL__N_11DEE = internal constant +// CHECK: _ZTIPFvvE = linkonce_odr constant // CHECK: _ZTSPFvvE = linkonce_odr constant -// CHECK: _ZTSFvvE = linkonce_odr constant // CHECK: _ZTIFvvE = linkonce_odr constant -// CHECK: _ZTIPFvvE = linkonce_odr constant -// CHECK: _ZTSN12_GLOBAL__N_11EE = internal constant +// CHECK: _ZTSFvvE = linkonce_odr constant // CHECK: _ZTIN12_GLOBAL__N_11EE = internal constant -// CHECK: _ZTSA10_i = linkonce_odr constant +// CHECK: _ZTSN12_GLOBAL__N_11EE = internal constant // CHECK: _ZTIA10_i = linkonce_odr constant +// CHECK: _ZTSA10_i = linkonce_odr constant // CHECK: _ZTI1TILj0EE = linkonce_odr constant // CHECK: _ZTI1TILj1EE = weak_odr constant // CHECK: _ZTI1TILj2EE = external constant -// CHECK: _ZTSZ2t5vE1A = internal constant // CHECK: _ZTIZ2t5vE1A = internal constant -// CHECK: _ZTS1B ={{.*}} constant +// CHECK: _ZTSZ2t5vE1A = internal constant // CHECK: _ZTI1B ={{.*}} constant +// CHECK: _ZTS1B ={{.*}} constant // CHECK: _ZTS1F = linkonce_odr constant -// CHECK: _ZTSZ2t6vE1A = linkonce_odr constant // CHECK: _ZTIZ2t6vE1A = linkonce_odr constant +// CHECK: _ZTSZ2t6vE1A = linkonce_odr constant +// CHECK: _ZTIPZ2t7vE1A = linkonce_odr constant // CHECK: _ZTSPZ2t7vE1A = linkonce_odr constant -// CHECK: _ZTSZ2t7vE1A = linkonce_odr constant // CHECK: _ZTIZ2t7vE1A = linkonce_odr constant -// CHECK: _ZTIPZ2t7vE1A = linkonce_odr constant +// CHECK: _ZTSZ2t7vE1A = linkonce_odr constant // CHECK: _ZTIN12_GLOBAL__N_11DE diff --git a/clang/test/CodeGenCXX/rtti-visibility.cpp b/clang/test/CodeGenCXX/rtti-visibility.cpp index 5945be5c73a26064c9300b06ffb704b7254bd546..1813fee658c72e242d6e6dc82c2f18da23c00837 100644 --- a/clang/test/CodeGenCXX/rtti-visibility.cpp +++ b/clang/test/CodeGenCXX/rtti-visibility.cpp @@ -6,10 +6,10 @@ namespace Test1 { // A is explicitly marked hidden, so all RTTI data should also be marked hidden. - // CHECK-TEST1: @_ZTSN5Test11AE = linkonce_odr hidden constant // CHECK-TEST1: @_ZTIN5Test11AE = linkonce_odr hidden constant - // CHECK-TEST1: @_ZTSPN5Test11AE = linkonce_odr hidden constant + // CHECK-TEST1: @_ZTSN5Test11AE = linkonce_odr hidden constant // CHECK-TEST1: @_ZTIPN5Test11AE = linkonce_odr hidden constant + // CHECK-TEST1: @_ZTSPN5Test11AE = linkonce_odr hidden constant struct __attribute__((visibility("hidden"))) A { }; void f() { @@ -20,8 +20,8 @@ namespace Test1 { namespace Test2 { // A is weak, so its linkage should be linkoce_odr, but not marked hidden. - // CHECK-TEST2: @_ZTSN5Test21AE = linkonce_odr constant // CHECK-TEST2: @_ZTIN5Test21AE = linkonce_odr constant + // CHECK-TEST2: @_ZTSN5Test21AE = linkonce_odr constant struct A { }; void f() { (void)typeid(A); diff --git a/clang/test/CodeGenCXX/symbol-partition.cpp b/clang/test/CodeGenCXX/symbol-partition.cpp index ecc58e2a847dc137927ae5a391b32b88dac89545..cefeeac63f0147aaa0b68a3c83b8b989073eb2bc 100644 --- a/clang/test/CodeGenCXX/symbol-partition.cpp +++ b/clang/test/CodeGenCXX/symbol-partition.cpp @@ -2,8 +2,8 @@ // CHECK: @gv = {{.*}}, partition "foo" // CHECK: @_ZTV1S = {{.*}}, partition "foo" -// CHECK: @_ZTS1S = {{.*}}, partition "foo" // CHECK: @_ZTI1S = {{.*}}, partition "foo" +// CHECK: @_ZTS1S = {{.*}}, partition "foo" // CHECK: @_Z5ifuncv = {{.*}}, partition "foo" diff --git a/clang/test/CodeGenCXX/type_visibility.cpp b/clang/test/CodeGenCXX/type_visibility.cpp index 13aafcff0fa13e4fcae76d95a3633f80e3747c33..00833e36944df261839eb25f6e3cfe6edb938b10 100644 --- a/clang/test/CodeGenCXX/type_visibility.cpp +++ b/clang/test/CodeGenCXX/type_visibility.cpp @@ -26,12 +26,12 @@ namespace temp0 { template struct B; // FUNS-LABEL: define weak_odr void @_ZN5temp01BINS_1AEE3fooEv( // VARS: @_ZTVN5temp01BINS_1AEEE = weak_odr unnamed_addr constant - // VARS: @_ZTSN5temp01BINS_1AEEE = weak_odr constant // VARS: @_ZTIN5temp01BINS_1AEEE = weak_odr constant + // VARS: @_ZTSN5temp01BINS_1AEEE = weak_odr constant // FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp01BINS_1AEE3fooEv( // VARS-HIDDEN: @_ZTVN5temp01BINS_1AEEE = weak_odr hidden unnamed_addr constant - // VARS-HIDDEN: @_ZTSN5temp01BINS_1AEEE = weak_odr hidden constant // VARS-HIDDEN: @_ZTIN5temp01BINS_1AEEE = weak_odr hidden constant + // VARS-HIDDEN: @_ZTSN5temp01BINS_1AEEE = weak_odr hidden constant } namespace temp1 { @@ -43,12 +43,12 @@ namespace temp1 { template struct B; // FUNS-LABEL: define weak_odr void @_ZN5temp11BINS_1AEE3fooEv( // VARS: @_ZTVN5temp11BINS_1AEEE = weak_odr unnamed_addr constant - // VARS: @_ZTSN5temp11BINS_1AEEE = weak_odr constant // VARS: @_ZTIN5temp11BINS_1AEEE = weak_odr constant + // VARS: @_ZTSN5temp11BINS_1AEEE = weak_odr constant // FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp11BINS_1AEE3fooEv( // VARS-HIDDEN: @_ZTVN5temp11BINS_1AEEE = weak_odr unnamed_addr constant - // VARS-HIDDEN: @_ZTSN5temp11BINS_1AEEE = weak_odr constant // VARS-HIDDEN: @_ZTIN5temp11BINS_1AEEE = weak_odr constant + // VARS-HIDDEN: @_ZTSN5temp11BINS_1AEEE = weak_odr constant } namespace temp2 { @@ -60,12 +60,12 @@ namespace temp2 { template struct B; // FUNS-LABEL: define weak_odr void @_ZN5temp21BINS_1AEE3fooEv( // VARS: @_ZTVN5temp21BINS_1AEEE = weak_odr unnamed_addr constant - // VARS: @_ZTSN5temp21BINS_1AEEE = weak_odr constant // VARS: @_ZTIN5temp21BINS_1AEEE = weak_odr constant + // VARS: @_ZTSN5temp21BINS_1AEEE = weak_odr constant // FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp21BINS_1AEE3fooEv( // VARS-HIDDEN: @_ZTVN5temp21BINS_1AEEE = weak_odr hidden unnamed_addr constant - // VARS-HIDDEN: @_ZTSN5temp21BINS_1AEEE = weak_odr hidden constant // VARS-HIDDEN: @_ZTIN5temp21BINS_1AEEE = weak_odr hidden constant + // VARS-HIDDEN: @_ZTSN5temp21BINS_1AEEE = weak_odr hidden constant } namespace temp3 { @@ -77,12 +77,12 @@ namespace temp3 { template struct B; // FUNS-LABEL: define weak_odr hidden void @_ZN5temp31BINS_1AEE3fooEv( // VARS: @_ZTVN5temp31BINS_1AEEE = weak_odr hidden unnamed_addr constant - // VARS: @_ZTSN5temp31BINS_1AEEE = weak_odr hidden constant // VARS: @_ZTIN5temp31BINS_1AEEE = weak_odr hidden constant + // VARS: @_ZTSN5temp31BINS_1AEEE = weak_odr hidden constant // FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp31BINS_1AEE3fooEv( // VARS-HIDDEN: @_ZTVN5temp31BINS_1AEEE = weak_odr hidden unnamed_addr constant - // VARS-HIDDEN: @_ZTSN5temp31BINS_1AEEE = weak_odr hidden constant // VARS-HIDDEN: @_ZTIN5temp31BINS_1AEEE = weak_odr hidden constant + // VARS-HIDDEN: @_ZTSN5temp31BINS_1AEEE = weak_odr hidden constant } namespace temp4 { @@ -94,12 +94,12 @@ namespace temp4 { template struct B; // FUNS-LABEL: define weak_odr void @_ZN5temp41BINS_1AEE3fooEv( // VARS: @_ZTVN5temp41BINS_1AEEE = weak_odr hidden unnamed_addr constant - // VARS: @_ZTSN5temp41BINS_1AEEE = weak_odr hidden constant // VARS: @_ZTIN5temp41BINS_1AEEE = weak_odr hidden constant + // VARS: @_ZTSN5temp41BINS_1AEEE = weak_odr hidden constant // FUNS-HIDDEN-LABEL: define weak_odr hidden void @_ZN5temp41BINS_1AEE3fooEv( // VARS-HIDDEN: @_ZTVN5temp41BINS_1AEEE = weak_odr hidden unnamed_addr constant - // VARS-HIDDEN: @_ZTSN5temp41BINS_1AEEE = weak_odr hidden constant // VARS-HIDDEN: @_ZTIN5temp41BINS_1AEEE = weak_odr hidden constant + // VARS-HIDDEN: @_ZTSN5temp41BINS_1AEEE = weak_odr hidden constant } namespace type0 { @@ -110,12 +110,12 @@ namespace type0 { void A::foo() {} // FUNS-LABEL: define void @_ZN5type01A3fooEv( // VARS: @_ZTVN5type01AE = unnamed_addr constant - // VARS: @_ZTSN5type01AE = constant // VARS: @_ZTIN5type01AE = constant + // VARS: @_ZTSN5type01AE = constant // FUNS-HIDDEN-LABEL: define hidden void @_ZN5type01A3fooEv( // VARS-HIDDEN: @_ZTVN5type01AE = unnamed_addr constant - // VARS-HIDDEN: @_ZTSN5type01AE = constant // VARS-HIDDEN: @_ZTIN5type01AE = constant + // VARS-HIDDEN: @_ZTSN5type01AE = constant } namespace type1 { @@ -126,12 +126,12 @@ namespace type1 { void A::foo() {} // FUNS-LABEL: define hidden void @_ZN5type11A3fooEv( // VARS: @_ZTVN5type11AE = unnamed_addr constant - // VARS: @_ZTSN5type11AE = constant // VARS: @_ZTIN5type11AE = constant + // VARS: @_ZTSN5type11AE = constant // FUNS-HIDDEN-LABEL: define hidden void @_ZN5type11A3fooEv( // VARS-HIDDEN: @_ZTVN5type11AE = unnamed_addr constant - // VARS-HIDDEN: @_ZTSN5type11AE = constant // VARS-HIDDEN: @_ZTIN5type11AE = constant + // VARS-HIDDEN: @_ZTSN5type11AE = constant } namespace type2 { @@ -142,12 +142,12 @@ namespace type2 { void A::foo() {} // FUNS-LABEL: define void @_ZN5type21A3fooEv( // VARS: @_ZTVN5type21AE = hidden unnamed_addr constant - // VARS: @_ZTSN5type21AE = hidden constant // VARS: @_ZTIN5type21AE = hidden constant + // VARS: @_ZTSN5type21AE = hidden constant // FUNS-HIDDEN-LABEL: define hidden void @_ZN5type21A3fooEv( // VARS-HIDDEN: @_ZTVN5type21AE = hidden unnamed_addr constant - // VARS-HIDDEN: @_ZTSN5type21AE = hidden constant // VARS-HIDDEN: @_ZTIN5type21AE = hidden constant + // VARS-HIDDEN: @_ZTSN5type21AE = hidden constant } namespace type3 { @@ -158,11 +158,11 @@ namespace type3 { void A::foo() {} // FUNS-LABEL: define void @_ZN5type31A3fooEv( // VARS: @_ZTVN5type31AE = hidden unnamed_addr constant - // VARS: @_ZTSN5type31AE = hidden constant // VARS: @_ZTIN5type31AE = hidden constant + // VARS: @_ZTSN5type31AE = hidden constant // FUNS-HIDDEN-LABEL: define void @_ZN5type31A3fooEv( // VARS-HIDDEN: @_ZTVN5type31AE = hidden unnamed_addr constant - // VARS-HIDDEN: @_ZTSN5type31AE = hidden constant // VARS-HIDDEN: @_ZTIN5type31AE = hidden constant + // VARS-HIDDEN: @_ZTSN5type31AE = hidden constant } diff --git a/clang/test/CodeGenCXX/typeinfo-with-address-space.cpp b/clang/test/CodeGenCXX/typeinfo-with-address-space.cpp index 350303cc6e9b34b7f5a5caaf3775e9cb8bdf0330..0a8e5e4a0f6eaa789e0b37f067ac2f50d097325b 100644 --- a/clang/test/CodeGenCXX/typeinfo-with-address-space.cpp +++ b/clang/test/CodeGenCXX/typeinfo-with-address-space.cpp @@ -15,12 +15,12 @@ class B : A { // NO-AS: @_ZTISt9type_info = external constant ptr // AS: @_ZTIi = external addrspace(1) constant ptr addrspace(1) // NO-AS: @_ZTIi = external constant ptr +// AS: @_ZTI1A = linkonce_odr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1A }, comdat, align 8 +// NO-AS: @_ZTI1A = linkonce_odr constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr @_ZTS1A }, comdat, align 8 // AS: @_ZTVN10__cxxabiv117__class_type_infoE = external addrspace(1) global [0 x ptr addrspace(1)] // NO-AS: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr] // AS: @_ZTS1A = linkonce_odr addrspace(1) constant [3 x i8] c"1A\00", comdat, align 1 // NO-AS: @_ZTS1A = linkonce_odr constant [3 x i8] c"1A\00", comdat, align 1 -// AS: @_ZTI1A = linkonce_odr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1A }, comdat, align 8 -// NO-AS: @_ZTI1A = linkonce_odr constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr @_ZTS1A }, comdat, align 8 // AS: @_ZTIf = external addrspace(1) constant ptr addrspace(1) // NO-AS: @_ZTIf = external constant ptr diff --git a/clang/test/CodeGenCXX/visibility-ms-compat.cpp b/clang/test/CodeGenCXX/visibility-ms-compat.cpp index 525691358832f8781fc910c9e38f489e8b267bdb..0344803909cd44849641bda18f235da6bf761c17 100644 --- a/clang/test/CodeGenCXX/visibility-ms-compat.cpp +++ b/clang/test/CodeGenCXX/visibility-ms-compat.cpp @@ -24,8 +24,8 @@ namespace test0 { // CHECK: declare void @_ZN5test01A3barEv() const std::type_info &ti = typeid(A); - // CHECK-GLOBAL: @_ZTSN5test01AE = linkonce_odr constant // CHECK-GLOBAL: @_ZTIN5test01AE = linkonce_odr constant + // CHECK-GLOBAL: @_ZTSN5test01AE = linkonce_odr constant // CHECK-GLOBAL: @_ZN5test02tiE = hidden constant } @@ -40,8 +40,8 @@ namespace test1 { // CHECK: declare hidden void @_ZN5test11A3barEv() const std::type_info &ti = typeid(A); - // CHECK-GLOBAL: @_ZTSN5test11AE = linkonce_odr hidden constant // CHECK-GLOBAL: @_ZTIN5test11AE = linkonce_odr hidden constant + // CHECK-GLOBAL: @_ZTSN5test11AE = linkonce_odr hidden constant // CHECK-GLOBAL: @_ZN5test12tiE = hidden constant } @@ -56,8 +56,8 @@ namespace test2 { // CHECK: declare void @_ZN5test21A3barEv() const std::type_info &ti = typeid(A); - // CHECK-GLOBAL: @_ZTSN5test21AE = linkonce_odr constant // CHECK-GLOBAL: @_ZTIN5test21AE = linkonce_odr constant + // CHECK-GLOBAL: @_ZTSN5test21AE = linkonce_odr constant // CHECK-GLOBAL: @_ZN5test22tiE = hidden constant } @@ -73,8 +73,8 @@ namespace test3 { // CHECK: declare void @_ZN5test31BINS_1AEE3barEv() const std::type_info &ti = typeid(B); - // CHECK-GLOBAL: @_ZTSN5test31BINS_1AEEE = linkonce_odr constant // CHECK-GLOBAL: @_ZTIN5test31BINS_1AEEE = linkonce_odr constant + // CHECK-GLOBAL: @_ZTSN5test31BINS_1AEEE = linkonce_odr constant } namespace test4 { @@ -89,8 +89,8 @@ namespace test4 { // CHECK: declare void @_ZN5test41BINS_1AEE3barEv() const std::type_info &ti = typeid(B); - // CHECK-GLOBAL: @_ZTSN5test41BINS_1AEEE = linkonce_odr constant // CHECK-GLOBAL: @_ZTIN5test41BINS_1AEEE = linkonce_odr constant + // CHECK-GLOBAL: @_ZTSN5test41BINS_1AEEE = linkonce_odr constant } namespace test5 { @@ -105,6 +105,6 @@ namespace test5 { // CHECK: declare hidden void @_ZN5test51BINS_1AEE3barEv() const std::type_info &ti = typeid(B); - // CHECK-GLOBAL: @_ZTSN5test51BINS_1AEEE = linkonce_odr hidden constant // CHECK-GLOBAL: @_ZTIN5test51BINS_1AEEE = linkonce_odr hidden constant + // CHECK-GLOBAL: @_ZTSN5test51BINS_1AEEE = linkonce_odr hidden constant } diff --git a/clang/test/CodeGenCXX/vtable-align-address-space.cpp b/clang/test/CodeGenCXX/vtable-align-address-space.cpp index 5eac0bd75dc5efa1049da61e79ccd9c84dee5aff..5eccf0a0d77d829539e741aff176ab53ae3b215b 100644 --- a/clang/test/CodeGenCXX/vtable-align-address-space.cpp +++ b/clang/test/CodeGenCXX/vtable-align-address-space.cpp @@ -9,5 +9,5 @@ struct A { void A::f() {} // CHECK: @_ZTV1A ={{.*}} unnamed_addr addrspace(1) constant { [5 x ptr addrspace(1)] } { [5 x ptr addrspace(1)] [ptr addrspace(1) null, ptr addrspace(1) @_ZTI1A, ptr addrspace(1) addrspacecast (ptr @_ZN1A1fEv to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @_ZN1A1gEv to ptr addrspace(1)), ptr addrspace(1) addrspacecast (ptr @_ZN1A1hEv to ptr addrspace(1))] -// CHECK: @_ZTS1A ={{.*}} constant [3 x i8] c"1A\00", align 1 // CHECK: @_ZTI1A ={{.*}} addrspace(1) constant { ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1A }, align 8 +// CHECK: @_ZTS1A ={{.*}} constant [3 x i8] c"1A\00", align 1 diff --git a/clang/test/CodeGenCXX/vtable-align.cpp b/clang/test/CodeGenCXX/vtable-align.cpp index fb8ff1a582ec8301aee6d811ddd093b4307ef640..f1d5e09b9730b211dd8fae9fc438e2c7f668ccff 100644 --- a/clang/test/CodeGenCXX/vtable-align.cpp +++ b/clang/test/CodeGenCXX/vtable-align.cpp @@ -10,8 +10,8 @@ struct A { void A::f() {} // CHECK-32: @_ZTV1A ={{.*}} unnamed_addr constant { [5 x ptr] } { [5 x ptr] [ptr null, ptr @_ZTI1A, ptr @_ZN1A1fEv, ptr @_ZN1A1gEv, ptr @_ZN1A1hEv] }, align 4 -// CHECK-32: @_ZTS1A ={{.*}} constant [3 x i8] c"1A\00", align 1 // CHECK-32: @_ZTI1A ={{.*}} constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i32 2), ptr @_ZTS1A }, align 4 +// CHECK-32: @_ZTS1A ={{.*}} constant [3 x i8] c"1A\00", align 1 // CHECK-64: @_ZTV1A ={{.*}} unnamed_addr constant { [5 x ptr] } { [5 x ptr] [ptr null, ptr @_ZTI1A, ptr @_ZN1A1fEv, ptr @_ZN1A1gEv, ptr @_ZN1A1hEv] }, align 8 -// CHECK-64: @_ZTS1A ={{.*}} constant [3 x i8] c"1A\00", align 1 // CHECK-64: @_ZTI1A ={{.*}} constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr @_ZTS1A }, align 8 +// CHECK-64: @_ZTS1A ={{.*}} constant [3 x i8] c"1A\00", align 1 diff --git a/clang/test/CodeGenCXX/vtable-available-externally.cpp b/clang/test/CodeGenCXX/vtable-available-externally.cpp index a57eb39edfe102914a9df87fbe55f0c424ac0a1b..eb0a8b42d80ae1dfef76ee0df039e6de0839363c 100644 --- a/clang/test/CodeGenCXX/vtable-available-externally.cpp +++ b/clang/test/CodeGenCXX/vtable-available-externally.cpp @@ -49,8 +49,8 @@ void g() { // This tests mainly that the typeinfo and typename constants have their linkage // updated correctly. -// CHECK-TEST2: @_ZTSN5Test21AE ={{.*}} constant // CHECK-TEST2: @_ZTIN5Test21AE ={{.*}} constant +// CHECK-TEST2: @_ZTSN5Test21AE ={{.*}} constant // CHECK-TEST2: @_ZTVN5Test21AE ={{.*}} unnamed_addr constant namespace Test2 { struct A { diff --git a/clang/test/CodeGenCXX/vtable-key-function-arm.cpp b/clang/test/CodeGenCXX/vtable-key-function-arm.cpp index a054fd87c8ea73f1578e98752dd64e1a7933916b..83889bf9f8dbc5a8536dfe5b98459a06c3a7622a 100644 --- a/clang/test/CodeGenCXX/vtable-key-function-arm.cpp +++ b/clang/test/CodeGenCXX/vtable-key-function-arm.cpp @@ -90,8 +90,8 @@ struct Test2a { // V-table should be defined with strong linkage. Test2a::Test2a() { use(typeid(Test2a)); } // CHECK: @_ZTV6Test2a ={{.*}} unnamed_addr constant -// CHECK-LATE: @_ZTS6Test2a ={{.*}} constant // CHECK-LATE: @_ZTI6Test2a ={{.*}} constant +// CHECK-LATE: @_ZTS6Test2a ={{.*}} constant // 'bar' becomes the key function when 'foo' is defined inline. void Test2a::bar() {} @@ -111,8 +111,8 @@ void Test2b::bar() {} // V-table should be defined with strong linkage. Test2b::Test2b() { use(typeid(Test2b)); } // CHECK: @_ZTV6Test2b ={{.*}} unnamed_addr constant -// CHECK-LATE: @_ZTS6Test2b ={{.*}} constant // CHECK-LATE: @_ZTI6Test2b ={{.*}} constant +// CHECK-LATE: @_ZTS6Test2b ={{.*}} constant inline void Test2b::foo() {} @@ -131,8 +131,8 @@ inline void Test2c::foo() {} // V-table should be defined with strong linkage. Test2c::Test2c() { use(typeid(Test2c)); } // CHECK: @_ZTV6Test2c ={{.*}} unnamed_addr constant -// CHECK: @_ZTS6Test2c ={{.*}} constant // CHECK: @_ZTI6Test2c ={{.*}} constant +// CHECK: @_ZTS6Test2c ={{.*}} constant /*** Test3a ******************************************************************/ @@ -145,8 +145,8 @@ struct Test3a { // V-table should be defined with weak linkage. Test3a::Test3a() { use(typeid(Test3a)); } // CHECK: @_ZTV6Test3a = linkonce_odr unnamed_addr constant -// CHECK-LATE: @_ZTS6Test3a = linkonce_odr constant // CHECK-LATE: @_ZTI6Test3a = linkonce_odr constant +// CHECK-LATE: @_ZTS6Test3a = linkonce_odr constant // There ceases to be a key function after these declarations. inline void Test3a::bar() {} @@ -166,8 +166,8 @@ inline void Test3b::bar() {} // V-table should be defined with weak linkage. Test3b::Test3b() { use(typeid(Test3b)); } // CHECK: @_ZTV6Test3b = linkonce_odr unnamed_addr constant -// CHECK-LATE: @_ZTS6Test3b = linkonce_odr constant // CHECK-LATE: @_ZTI6Test3b = linkonce_odr constant +// CHECK-LATE: @_ZTS6Test3b = linkonce_odr constant inline void Test3b::foo() {} @@ -186,8 +186,8 @@ inline void Test3c::foo() {} // V-table should be defined with weak linkage. Test3c::Test3c() { use(typeid(Test3c)); } // CHECK: @_ZTV6Test3c = linkonce_odr unnamed_addr constant -// CHECK: @_ZTS6Test3c = linkonce_odr constant // CHECK: @_ZTI6Test3c = linkonce_odr constant +// CHECK: @_ZTS6Test3c = linkonce_odr constant /*** Test4a ******************************************************************/ @@ -200,8 +200,8 @@ template struct Test4a { // V-table should be defined with weak linkage. template <> Test4a::Test4a() { use(typeid(Test4a)); } // CHECK: @_ZTV6Test4aIiE = linkonce_odr unnamed_addr constant -// CHECK: @_ZTS6Test4aIiE = linkonce_odr constant // CHECK: @_ZTI6Test4aIiE = linkonce_odr constant +// CHECK: @_ZTS6Test4aIiE = linkonce_odr constant // There ceases to be a key function after these declarations. template <> inline void Test4a::bar() {} @@ -221,8 +221,8 @@ template <> inline void Test4b::bar() {} // V-table should be defined with weak linkage. template <> Test4b::Test4b() { use(typeid(Test4b)); } // CHECK: @_ZTV6Test4bIiE = linkonce_odr unnamed_addr constant -// CHECK: @_ZTS6Test4bIiE = linkonce_odr constant // CHECK: @_ZTI6Test4bIiE = linkonce_odr constant +// CHECK: @_ZTS6Test4bIiE = linkonce_odr constant template <> inline void Test4b::foo() {} @@ -241,8 +241,8 @@ template <> inline void Test4c::foo() {} // V-table should be defined with weak linkage. template <> Test4c::Test4c() { use(typeid(Test4c)); } // CHECK: @_ZTV6Test4cIiE = linkonce_odr unnamed_addr constant -// CHECK: @_ZTS6Test4cIiE = linkonce_odr constant // CHECK: @_ZTI6Test4cIiE = linkonce_odr constant +// CHECK: @_ZTS6Test4cIiE = linkonce_odr constant /*** Test5a ******************************************************************/ @@ -258,8 +258,8 @@ template <> inline void Test5a::foo(); // V-table should be defined with weak linkage. template <> Test5a::Test5a() { use(typeid(Test5a)); } // CHECK: @_ZTV6Test5aIiE = linkonce_odr unnamed_addr constant -// CHECK: @_ZTS6Test5aIiE = linkonce_odr constant // CHECK: @_ZTI6Test5aIiE = linkonce_odr constant +// CHECK: @_ZTS6Test5aIiE = linkonce_odr constant // There ceases to be a key function after these declarations. template <> inline void Test5a::bar() {} @@ -280,8 +280,8 @@ template <> inline void Test5b::bar() {} // V-table should be defined with weak linkage. template <> Test5b::Test5b() { use(typeid(Test5b)); } // CHECK: @_ZTV6Test5bIiE = linkonce_odr unnamed_addr constant -// CHECK: @_ZTS6Test5bIiE = linkonce_odr constant // CHECK: @_ZTI6Test5bIiE = linkonce_odr constant +// CHECK: @_ZTS6Test5bIiE = linkonce_odr constant template <> inline void Test5a::foo(); template <> inline void Test5b::foo() {} @@ -303,5 +303,5 @@ template <> inline void Test5c::foo() {} // V-table should be defined with weak linkage. template <> Test5c::Test5c() { use(typeid(Test5c)); } // CHECK: @_ZTV6Test5cIiE = linkonce_odr unnamed_addr constant -// CHECK: @_ZTS6Test5cIiE = linkonce_odr constant // CHECK: @_ZTI6Test5cIiE = linkonce_odr constant +// CHECK: @_ZTS6Test5cIiE = linkonce_odr constant diff --git a/clang/test/CodeGenCXX/vtable-key-function-ios.cpp b/clang/test/CodeGenCXX/vtable-key-function-ios.cpp index ff2793ad51f948f3025a467a21e3e761de8cc442..43abfb62c73a6c2296e510e31d3242e1d8eedfb1 100644 --- a/clang/test/CodeGenCXX/vtable-key-function-ios.cpp +++ b/clang/test/CodeGenCXX/vtable-key-function-ios.cpp @@ -63,8 +63,8 @@ struct Test1a { // V-table needs to be defined weakly. Test1a::Test1a() { use(typeid(Test1a)); } // CHECK: @_ZTV6Test1a = linkonce_odr {{(dso_local )?}}unnamed_addr constant -// CHECK-LATE: @_ZTS6Test1a = linkonce_odr {{(dso_local )?}}constant // CHECK-LATE: @_ZTI6Test1a = linkonce_odr {{(dso_local )?}}constant +// CHECK-LATE: @_ZTS6Test1a = linkonce_odr {{(dso_local )?}}constant // This defines the key function. inline void Test1a::foo() {} @@ -83,8 +83,8 @@ inline void Test1b::foo() {} // V-table should be defined weakly.. Test1b::Test1b() { use(typeid(Test1b)); } // CHECK: @_ZTV6Test1b = linkonce_odr {{(dso_local )?}}unnamed_addr constant -// CHECK: @_ZTS6Test1b = linkonce_odr {{(dso_local )?}}constant // CHECK: @_ZTI6Test1b = linkonce_odr {{(dso_local )?}}constant +// CHECK: @_ZTS6Test1b = linkonce_odr {{(dso_local )?}}constant /*** Test2a ******************************************************************/ @@ -97,8 +97,8 @@ struct Test2a { // V-table should be defined with weak linkage. Test2a::Test2a() { use(typeid(Test2a)); } // CHECK: @_ZTV6Test2a = linkonce_odr {{(dso_local )?}}unnamed_addr constant -// CHECK-LATE: @_ZTS6Test2a = linkonce_odr {{(dso_local )?}}constant // CHECK-LATE: @_ZTI6Test2a = linkonce_odr {{(dso_local )?}}constant +// CHECK-LATE: @_ZTS6Test2a = linkonce_odr {{(dso_local )?}}constant void Test2a::bar() {} inline void Test2a::foo() {} @@ -116,8 +116,8 @@ void Test2b::bar() {} // V-table should be defined with weak linkage. Test2b::Test2b() { use(typeid(Test2b)); } // CHECK: @_ZTV6Test2b = linkonce_odr {{(dso_local )?}}unnamed_addr constant -// CHECK-LATE: @_ZTS6Test2b = linkonce_odr {{(dso_local )?}}constant // CHECK-LATE: @_ZTI6Test2b = linkonce_odr {{(dso_local )?}}constant +// CHECK-LATE: @_ZTS6Test2b = linkonce_odr {{(dso_local )?}}constant inline void Test2b::foo() {} @@ -135,8 +135,8 @@ inline void Test2c::foo() {} // V-table should be defined with weak linkage. Test2c::Test2c() { use(typeid(Test2c)); } // CHECK: @_ZTV6Test2c = linkonce_odr {{(dso_local )?}}unnamed_addr constant -// CHECK: @_ZTS6Test2c = linkonce_odr {{(dso_local )?}}constant // CHECK: @_ZTI6Test2c = linkonce_odr {{(dso_local )?}}constant +// CHECK: @_ZTS6Test2c = linkonce_odr {{(dso_local )?}}constant /*** Test3a ******************************************************************/ @@ -149,8 +149,8 @@ struct Test3a { // V-table should be defined with weak linkage. Test3a::Test3a() { use(typeid(Test3a)); } // CHECK: @_ZTV6Test3a = linkonce_odr {{(dso_local )?}}unnamed_addr constant -// CHECK-LATE: @_ZTS6Test3a = linkonce_odr {{(dso_local )?}}constant // CHECK-LATE: @_ZTI6Test3a = linkonce_odr {{(dso_local )?}}constant +// CHECK-LATE: @_ZTS6Test3a = linkonce_odr {{(dso_local )?}}constant // This defines the key function. inline void Test3a::bar() {} @@ -169,8 +169,8 @@ inline void Test3b::bar() {} // V-table should be defined with weak linkage. Test3b::Test3b() { use(typeid(Test3b)); } // CHECK: @_ZTV6Test3b = linkonce_odr {{(dso_local )?}}unnamed_addr constant -// CHECK-LATE: @_ZTS6Test3b = linkonce_odr {{(dso_local )?}}constant // CHECK-LATE: @_ZTI6Test3b = linkonce_odr {{(dso_local )?}}constant +// CHECK-LATE: @_ZTS6Test3b = linkonce_odr {{(dso_local )?}}constant // This defines the key function. inline void Test3b::foo() {} @@ -190,5 +190,5 @@ inline void Test3c::foo() {} // V-table should be defined with weak linkage. Test3c::Test3c() { use(typeid(Test3c)); } // CHECK: @_ZTV6Test3c = linkonce_odr {{(dso_local )?}}unnamed_addr constant -// CHECK: @_ZTS6Test3c = linkonce_odr {{(dso_local )?}}constant // CHECK: @_ZTI6Test3c = linkonce_odr {{(dso_local )?}}constant +// CHECK: @_ZTS6Test3c = linkonce_odr {{(dso_local )?}}constant diff --git a/clang/test/CodeGenCXX/vtable-key-function-win-comdat.cpp b/clang/test/CodeGenCXX/vtable-key-function-win-comdat.cpp index dd4fd9f8754a8d309ba726041743ff8b55eb6c3b..b3de2f63499995bc8252ceceac5d67df6a05eee0 100644 --- a/clang/test/CodeGenCXX/vtable-key-function-win-comdat.cpp +++ b/clang/test/CodeGenCXX/vtable-key-function-win-comdat.cpp @@ -15,11 +15,11 @@ Test1a::Test1a() { use(typeid(Test1a)); } inline void Test1a::foo() {} // CHECK: $_ZTV6Test1a = comdat any -// CHECK: $_ZTS6Test1a = comdat any // CHECK: $_ZTI6Test1a = comdat any -// CHECK-NOT: $_ZTS6Test1a.1 = comdat any +// CHECK: $_ZTS6Test1a = comdat any // CHECK-NOT: $_ZTI6Test1a.1 = comdat any +// CHECK-NOT: $_ZTS6Test1a.1 = comdat any // CHECK: @_ZTV6Test1a = linkonce_odr dso_local unnamed_addr constant {{.*}} ptr @_ZTI6Test1a -// CHECK: @_ZTS6Test1a = linkonce_odr dso_local constant // CHECK: @_ZTI6Test1a = linkonce_odr dso_local constant {{.*}} ptr @_ZTS6Test1a +// CHECK: @_ZTS6Test1a = linkonce_odr dso_local constant diff --git a/clang/test/CodeGenCXX/weak-extern-typeinfo.cpp b/clang/test/CodeGenCXX/weak-extern-typeinfo.cpp index 932d36f4abbd2b187b3c3a042af68cdd78ff5bce..8c948d16c90ec543b471f1dc3f123b21941e3b19 100644 --- a/clang/test/CodeGenCXX/weak-extern-typeinfo.cpp +++ b/clang/test/CodeGenCXX/weak-extern-typeinfo.cpp @@ -30,17 +30,17 @@ class V2 : public virtual V1 { void V1::foo() { } void V2::foo() { } -// CHECK: @_ZTS1A = weak_odr {{(dso_local |hidden )?}}constant // CHECK: @_ZTI1A = weak_odr {{(dso_local |hidden )?}}constant -// CHECK: @_ZTS1B = weak_odr {{(dso_local |hidden )?}}constant +// CHECK: @_ZTS1A = weak_odr {{(dso_local |hidden )?}}constant // CHECK: @_ZTI1B = weak_odr {{(dso_local |hidden )?}}constant +// CHECK: @_ZTS1B = weak_odr {{(dso_local |hidden )?}}constant +// CHECK: @_ZTI1C = weak_odr {{(dso_local |hidden )?}}constant // CHECK: @_ZTS1C = weak_odr {{(dso_local |hidden )?}}constant -// CHECK: @_ZTS2T1 = linkonce_odr {{(dso_local |hidden )?}}constant // CHECK: @_ZTI2T1 = linkonce_odr {{(dso_local |hidden )?}}constant -// CHECK: @_ZTS1T = linkonce_odr {{(dso_local |hidden )?}}constant +// CHECK: @_ZTS2T1 = linkonce_odr {{(dso_local |hidden )?}}constant // CHECK: @_ZTI1T = linkonce_odr {{(dso_local |hidden )?}}constant -// CHECK: @_ZTI1C = weak_odr {{(dso_local |hidden )?}}constant -// CHECK: @_ZTS2V1 = weak_odr {{(dso_local |hidden )?}}constant +// CHECK: @_ZTS1T = linkonce_odr {{(dso_local |hidden )?}}constant // CHECK: @_ZTI2V1 = weak_odr {{(dso_local |hidden )?}}constant -// CHECK: @_ZTS2V2 = weak_odr {{(dso_local |hidden )?}}constant +// CHECK: @_ZTS2V1 = weak_odr {{(dso_local |hidden )?}}constant // CHECK: @_ZTI2V2 = weak_odr {{(dso_local |hidden )?}}constant +// CHECK: @_ZTS2V2 = weak_odr {{(dso_local |hidden )?}}constant diff --git a/clang/test/CodeGenCXX/windows-itanium-type-info.cpp b/clang/test/CodeGenCXX/windows-itanium-type-info.cpp index 20bd78df5098372ba44814387f183e5ea97dbdaa..95b7b3a4b29e2564af66b92675f666164706966e 100644 --- a/clang/test/CodeGenCXX/windows-itanium-type-info.cpp +++ b/clang/test/CodeGenCXX/windows-itanium-type-info.cpp @@ -33,8 +33,8 @@ void f() { // CHECK-DAG: @_ZTI4base = external dllimport constant -// CHECK-EH-IMPORT: @_ZTS4base = linkonce_odr dso_local constant // CHECK-EH-IMPORT: @_ZTI4base = linkonce_odr dso_local constant +// CHECK-EH-IMPORT: @_ZTS4base = linkonce_odr dso_local constant struct __declspec(dllimport) gatekeeper {}; struct zuul : gatekeeper { diff --git a/clang/test/CodeGenObjCXX/rtti.mm b/clang/test/CodeGenObjCXX/rtti.mm index ee3df349af18d68472387b0fda4f0f33522204ed..2fc6f8722f43984c32e0670bbb4892baaab03ad1 100644 --- a/clang/test/CodeGenObjCXX/rtti.mm +++ b/clang/test/CodeGenObjCXX/rtti.mm @@ -4,19 +4,20 @@ namespace std { class type_info; } -// CHECK: @_ZTI1A = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS1A @interface A @end -// CHECK: @_ZTI1B = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv120__si_class_type_infoE{{.*}}@_ZTS1B{{.*}}@_ZTI1A @interface B : A @end // CHECK: @_ZTIP1B = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv119__pointer_type_infoE{{.*}}@_ZTSP1B{{.*}}, i32 0, {{.*}}@_ZTI1B -// CHECK: @_ZTI11objc_object = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS11objc_object +// CHECK: @_ZTI1B = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv120__si_class_type_infoE{{.*}}@_ZTS1B{{.*}}@_ZTI1A +// CHECK: @_ZTI1A = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS1A + // CHECK: @_ZTIP11objc_object = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv119__pointer_type_infoE{{.*}}@_ZTSP11objc_object{{.*}}@_ZTI11objc_object -// CHECK: @_ZTI10objc_class = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS10objc_class +// CHECK: @_ZTI11objc_object = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS11objc_object // CHECK: @_ZTIP10objc_class = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv119__pointer_type_infoE{{.*}}@_ZTSP10objc_class{{.*}}@_ZTI10objc_class +// CHECK: @_ZTI10objc_class = linkonce_odr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS10objc_class @protocol P; diff --git a/clang/test/Driver/aarch64-ptrauth.c b/clang/test/Driver/aarch64-ptrauth.c index c8e3aeef1640a1b0080037d5f93f257b7bdb261a..d1ed5cd0b9bbf22cbd7a721cad16e5fec8cf31d3 100644 --- a/clang/test/Driver/aarch64-ptrauth.c +++ b/clang/test/Driver/aarch64-ptrauth.c @@ -21,11 +21,15 @@ // RUN: %clang -### -c --target=aarch64-linux-pauthtest %s 2>&1 | FileCheck %s --check-prefix=PAUTHABI1 // PAUTHABI1: "-cc1"{{.*}} "-triple" "aarch64-unknown-linux-pauthtest" // PAUTHABI1-SAME: "-target-abi" "pauthtest" -// PAUTHABI1-SAME: "-fptrauth-intrinsics" "-fptrauth-calls" "-fptrauth-returns" "-fptrauth-auth-traps" "-fptrauth-vtable-pointer-address-discrimination" "-fptrauth-vtable-pointer-type-discrimination" "-fptrauth-indirect-gotos" "-fptrauth-init-fini" +// PAUTHABI1-SAME: "-fptrauth-intrinsics" "-fptrauth-calls" "-fptrauth-icall" "-fptrauth-vcall" "-fptrauth-mfcall" "-fptrauth-vptr" "-fptrauth-returns" "-fptrauth-auth-traps" "-fptrauth-vtable-pointer-address-discrimination" "-fptrauth-vtable-pointer-type-discrimination" "-fptrauth-indirect-gotos" "-fptrauth-init-fini" "-fptrauth-nopac-atexit" "-fptrauth-nopac-throw" "-fptrauth-cxx-function-pointer-zero-discrimination" "-fptrauth-cxx-virtual-function-pointer-zero-discrimination" "-fptrauth-init-fini-zero-discrimination" "-fptrauth-mangle-class" "-fptrauth-mangle-func" "-fptrauth-mangle-cxxabi" // RUN: %clang -### -c --target=aarch64 -mabi=pauthtest -fno-ptrauth-intrinsics \ // RUN: -fno-ptrauth-calls -fno-ptrauth-returns -fno-ptrauth-auth-traps \ // RUN: -fno-ptrauth-vtable-pointer-address-discrimination -fno-ptrauth-vtable-pointer-type-discrimination \ +// RUN: -fno-ptrauth-icall -fno-ptrauth-vcall -fno-ptrauth-mfcall -fno-ptrauth-vptr \ +// RUN: -fno-ptrauth-nopac-atexit -fno-ptrauth-nopac-throw -fno-ptrauth-cxx-function-pointer-zero-discrimination \ +// RUN: -fno-ptrauth-cxx-virtual-function-pointer-zero-discrimination -fno-ptrauth-init-fini-zero-discrimination \ +// RUN: -fno-ptrauth-mangle-class -fno-ptrauth-mangle-func -fno-ptrauth-mangle-cxxabi \ // RUN: -fno-ptrauth-indirect-gotos -fno-ptrauth-init-fini %s 2>&1 | FileCheck %s --check-prefix=PAUTHABI2 // RUN: %clang -### -c --target=aarch64-pauthtest -fno-ptrauth-intrinsics \ // RUN: -fno-ptrauth-calls -fno-ptrauth-returns -fno-ptrauth-auth-traps \ diff --git a/clang/test/Driver/print-supported-extensions-aarch64.c b/clang/test/Driver/print-supported-extensions-aarch64.c index 023647aafc8b7d3bca53ccf61ee5dd63d1ef8571..b1aafd4b82b1853c08857fa0977d929d82d53898 100644 --- a/clang/test/Driver/print-supported-extensions-aarch64.c +++ b/clang/test/Driver/print-supported-extensions-aarch64.c @@ -41,6 +41,7 @@ // CHECK-NEXT: memtag FEAT_MTE, FEAT_MTE2 Enable Memory Tagging Extension // CHECK-NEXT: simd FEAT_AdvSIMD Enable Advanced SIMD instructions // CHECK-NEXT: pauth FEAT_PAuth Enable Armv8.3-A Pointer Authentication extension +// CHECK-NEXT: pauth-hint-only FEAT_PAuthHintOnly Only use Pointer Authentication instructions in the HINT space // CHECK-NEXT: pauth-lr FEAT_PAuth_LR Enable Armv9.5-A PAC enhancements // CHECK-NEXT: pmuv3 FEAT_PMUv3 Enable Armv8.0-A PMUv3 Performance Monitors extension // CHECK-NEXT: predres FEAT_SPECRES Enable Armv8.5-A execution and data prediction invalidation instructions diff --git a/clang/test/Modules/pr97313.cppm b/clang/test/Modules/pr97313.cppm index ebbd0ee4e2c65544c8d7684e58263ffa84ccd81d..32c7112da091ecb16fee9c3f49ec57fb078cb372 100644 --- a/clang/test/Modules/pr97313.cppm +++ b/clang/test/Modules/pr97313.cppm @@ -107,12 +107,12 @@ auto v6 = new Template(); // CHECK: @_ZTVW3Mod11NonTemplate = {{.*}}external // CHECK: @_ZTVW3Mod8TemplateIcE = {{.*}}external // CHECK: @_ZTVW3Mod8TemplateIjE = {{.*}}weak_odr -// CHECK: @_ZTSW3Mod8TemplateIjE = {{.*}}weak_odr // CHECK: @_ZTIW3Mod8TemplateIjE = {{.*}}weak_odr +// CHECK: @_ZTSW3Mod8TemplateIjE = {{.*}}weak_odr // CHECK: @_ZTVW3Mod8TemplateIdE = {{.*}}external // CHECK: @_ZTVW3Mod8TemplateIiE = {{.*}}linkonce_odr -// CHECK: @_ZTSW3Mod8TemplateIiE = {{.*}}linkonce_odr // CHECK: @_ZTIW3Mod8TemplateIiE = {{.*}}linkonce_odr +// CHECK: @_ZTSW3Mod8TemplateIiE = {{.*}}linkonce_odr // CHECK: @_ZTVW3Mod8TemplateIS_11NonTemplateE = {{.*}}linkonce_odr -// CHECK: @_ZTSW3Mod8TemplateIS_11NonTemplateE = {{.*}}linkonce_odr // CHECK: @_ZTIW3Mod8TemplateIS_11NonTemplateE = {{.*}}linkonce_odr +// CHECK: @_ZTSW3Mod8TemplateIS_11NonTemplateE = {{.*}}linkonce_odr diff --git a/clang/test/Preprocessor/ptrauth_feature.c b/clang/test/Preprocessor/ptrauth_feature.c index 14059f827b94c08169fe27d445cb37f592656810..cc51bebd433bf8606673410cbd8fb77d2af80e10 100644 --- a/clang/test/Preprocessor/ptrauth_feature.c +++ b/clang/test/Preprocessor/ptrauth_feature.c @@ -108,3 +108,28 @@ void has_ptrauth_indirect_gotos() {} // NOGOTOS: no_ptrauth_indirect_gotos void no_ptrauth_indirect_gotos() {} #endif + +#if __has_feature(fptrauth_cxx_function_pointer_zero_discrimination) +// FZERODISC: has_fptrauth_cxx_function_pointer_zero_discrimination +void has_fptrauth_cxx_function_pointer_zero_discrimination() {} +#else +// NOFZERODISC: no_fptrauth_cxx_function_pointer_zero_discrimination +void no_fptrauth_cxx_function_pointer_zero_discrimination() {} +#endif + + +#if __has_feature(fptrauth_cxx_virtual_function_pointer_zero_discrimination) +// VFZERODISC: has_fptrauth_cxx_virtual_function_pointer_zero_discrimination +void has_fptrauth_cxx_virtual_function_pointer_zero_discrimination() {} +#else +// NOVFZERODISC: no_fptrauth_cxx_virtual_function_pointer_zero_discrimination +void no_fptrauth_cxx_virtual_function_pointer_zero_discrimination() {} +#endif + +#if __has_feature(fptrauth_init_fini_zero_discrimination) +// INFIZERODISC: has_fptrauth_init_fini_zero_discrimination +void has_fptrauth_init_fini_zero_discrimination() {} +#else +// NOINFIZERODISC: no_fptrauth_init_fini_zero_discrimination +void no_fptrauth_init_fini_zero_discrimination() {} +#endif diff --git a/clang/test/SemaCXX/typeid-ref.cpp b/clang/test/SemaCXX/typeid-ref.cpp index f788b04077ecac793013a1d31e454977f11072ac..025816c42512e14445c9b0624f1f310e25d6de9f 100644 --- a/clang/test/SemaCXX/typeid-ref.cpp +++ b/clang/test/SemaCXX/typeid-ref.cpp @@ -6,7 +6,7 @@ namespace std { struct X { }; void f() { - // CHECK: @_ZTS1X = linkonce_odr {{(dso_local |hidden )?}}constant // CHECK: @_ZTI1X = linkonce_odr {{(dso_local |hidden )?}}constant + // CHECK: @_ZTS1X = linkonce_odr {{(dso_local |hidden )?}}constant (void)typeid(X&); } diff --git a/libcxx/src/include/overridable_function.h b/libcxx/src/include/overridable_function.h index c7639f56eee26f35d4ac28b331a9e83388905366..899feac714658f63cc70f88b4797e8bacb555726 100644 --- a/libcxx/src/include/overridable_function.h +++ b/libcxx/src/include/overridable_function.h @@ -13,7 +13,7 @@ #include <__config> #include -#if __has_feature(ptrauth_calls) +#if __has_feature(ptrauth_calls) || __has_feature(ptrauth_icall) || __has_feature(ptrauth_vcall) || __has_feature(ptrauth_mfcall) || __has_feature(ptrauth_vptr) # include #endif @@ -83,7 +83,7 @@ _LIBCPP_HIDE_FROM_ABI bool __is_function_overridden(_Ret (*__fptr)(_Args...)) no uintptr_t __end = reinterpret_cast(&__lcxx_override_end); uintptr_t __ptr = reinterpret_cast(__fptr); -# if __has_feature(ptrauth_calls) +# if __has_feature(ptrauth_calls) || __has_feature(ptrauth_icall) || __has_feature(ptrauth_vcall) || __has_feature(ptrauth_mfcall) || __has_feature(ptrauth_vptr) // We must pass a void* to ptrauth_strip since it only accepts a pointer type. Also, in particular, // we must NOT pass a function pointer, otherwise we will strip the function pointer, and then attempt // to authenticate and re-sign it when casting it to a uintptr_t again, which will fail because we just diff --git a/libcxxabi/src/private_typeinfo.cpp b/libcxxabi/src/private_typeinfo.cpp index 9dba91e1985e346d29a4ded66842674e287c7954..bbc77514fcdc80ed383fba310578cc319144ddbe 100644 --- a/libcxxabi/src/private_typeinfo.cpp +++ b/libcxxabi/src/private_typeinfo.cpp @@ -51,13 +51,13 @@ #include #endif -#if __has_feature(ptrauth_calls) +#if __has_feature(ptrauth_calls) || __has_feature(ptrauth_icall) || __has_feature(ptrauth_vcall) || __has_feature(ptrauth_mfcall) || __has_feature(ptrauth_vptr) #include #endif template static inline T* strip_vtable(T* vtable) { -#if __has_feature(ptrauth_calls) +#if __has_feature(ptrauth_calls) || __has_feature(ptrauth_icall) || __has_feature(ptrauth_vcall) || __has_feature(ptrauth_mfcall) || __has_feature(ptrauth_vptr) vtable = ptrauth_strip(vtable, ptrauth_key_cxx_vtable_pointer); #endif return vtable; diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index a165c813d4259c535299e49f18c80b4026d6f536..564acf82eb185192a26e52971531f5c78f02a64d 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -1249,8 +1249,10 @@ template void InputSection::writeTo(uint8_t *buf) { // Copy section contents from source object file to output file // and then apply relocations. - memcpy(buf, content().data(), content().size()); - relocate(buf, buf + content().size()); + if (name != ".cfi.modifier.ro" || (*((const int64_t *)content().data()) != 0)) { + memcpy(buf, content().data(), content().size()); + relocate(buf, buf + content().size()); + } } void InputSection::replace(InputSection *other) { diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 29f18f89274f3d6784c6d8283fb08d8bb6a80da7..ef4ab204eb314354fdc2a958b244e3c06418c3c3 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -172,6 +172,10 @@ void OutputSection::commitSection(InputSection *isec) { if (nonAlloc) flags &= ~(uint64_t)SHF_ALLOC; + if (name == ".cfi.modifier.ro") { + flags &= (~SHF_WRITE); + } + addralign = std::max(addralign, isec->addralign); // If this section contains a table of fixed-size entries, sh_entsize diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index 49aa7e637490504a0c23db2d2971f6d24fbc090b..bde96eb3c5ea69ab7570f84266efde38bcb80c43 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -1658,6 +1658,7 @@ unsigned ScriptParser::readPhdrType() { .Case("PT_OPENBSD_SYSCALLS", PT_OPENBSD_SYSCALLS) .Case("PT_OPENBSD_WXNEEDED", PT_OPENBSD_WXNEEDED) .Case("PT_OPENBSD_BOOTDATA", PT_OPENBSD_BOOTDATA) + .Case("PT_OHOS_CFI_MODIFIER", PT_OHOS_CFI_MODIFIER) .Default(-1); if (ret == (unsigned)-1) { diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 41053c6472751ed37ca6ff58356933d5252b2fad..cc9288c9b831832dab49a1debb3a85bdf53db87f 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1631,6 +1631,14 @@ RelocationBaseSection::RelocationBaseSection(StringRef name, uint32_t type, dynamicTag(dynamicTag), sizeDynamicTag(sizeDynamicTag), relocsVec(concurrency), combreloc(combreloc) {} +template void RelocationBaseSection::addReloc(const DynamicReloc &reloc) { + const OutputSection *relOsec = reloc.inputSec->getOutputSection(); + if (relOsec && relOsec->name == ".cfi.modifier.ro") + relocsCfi.push_back(reloc); + else + relocs.push_back(reloc); +} + void RelocationBaseSection::addSymbolReloc( RelType dynType, InputSectionBase &isec, uint64_t offsetInSec, Symbol &sym, int64_t addend, std::optional addendRelType) { @@ -1655,8 +1663,16 @@ void RelocationBaseSection::mergeRels() { for (const auto &v : relocsVec) newSize += v.size(); relocs.reserve(newSize); - for (const auto &v : relocsVec) - llvm::append_range(relocs, v); + + for (const auto &v : relocsVec) { + for (const auto &reloc : v) { + const OutputSection *relOsec = reloc.inputSec->getOutputSection(); + if (relOsec && relOsec->name == ".cfi.modifier.ro") + relocsCfi.push_back(reloc); + else + relocs.push_back(reloc); + } + } relocsVec.clear(); } @@ -1737,6 +1753,12 @@ template void RelocationSection::writeTo(uint8_t *buf) { p->r_addend = rel.addend; buf += config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); } + for (const DynamicReloc &rel : relocsCfi) { + const OutputSection *relOsec = rel.inputSec->getOutputSection(); + uint64_t offset = relOsec->offset + rel.inputSec->getOffset(rel.offsetInSec); + uint64_t *ptr = reinterpret_cast(Out::bufferStart + offset); + *ptr = rel.sym->getVA(rel.addend); + } } RelrBaseSection::RelrBaseSection(unsigned concurrency, bool isAArch64Auth) diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index d4169e1e1acaf6f495039a51b8124e1997bc3649..03aed2a0516d5a85bbbbf435b802567c3da2ea77 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -501,9 +501,8 @@ public: /// Add a dynamic relocation without writing an addend to the output section. /// This overload can be used if the addends are written directly instead of /// using relocations on the input section (e.g. MipsGotSection::writeTo()). - template void addReloc(const DynamicReloc &reloc) { - relocs.push_back(reloc); - } + template void addReloc(const DynamicReloc &reloc); + /// Add a dynamic relocation against \p sym with an optional addend. void addSymbolReloc(RelType dynType, InputSectionBase &isec, uint64_t offsetInSec, Symbol &sym, int64_t addend = 0, @@ -554,6 +553,7 @@ public: } int32_t dynamicTag, sizeDynamicTag; SmallVector relocs; + SmallVector relocsCfi; protected: void computeRels(); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 8e3a746a08eb257222d0f13904804691554af157..b321c144b1ea48b3448bc860a5ab3e60feda09b7 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -2331,6 +2331,9 @@ SmallVector Writer::createPhdrs(Partition &part) { if (OutputSection *cmd = findSection(".note.gnu.property", partNo)) addHdr(PT_GNU_PROPERTY, PF_R)->add(cmd); + if (OutputSection *cmd = findSection(".cfi.modifier.ro", partNo)) + addHdr(PT_OHOS_CFI_MODIFIER, cmd->getPhdrFlags())->add(cmd); + // Create one PT_NOTE per a group of contiguous SHT_NOTE sections with the // same alignment. PhdrEntry *note = nullptr; diff --git a/lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp b/lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp index b6f52cb5cf496d3a33a7a5e039622d2dc7cb468f..90b5ca009c728b10a8b1d27981de68c60d703470 100644 --- a/lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp +++ b/lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp @@ -27,7 +27,7 @@ #include #undef DEBUGSERVER_IS_ARM64E -#if __has_feature(ptrauth_calls) +#if __has_feature(ptrauth_calls) || __has_feature(ptrauth_icall) || __has_feature(ptrauth_vcall) || __has_feature(ptrauth_mfcall) || __has_feature(ptrauth_vptr) #include #if defined(__LP64__) #define DEBUGSERVER_IS_ARM64E 1 @@ -133,7 +133,7 @@ kern_return_t DNBArchMachARM64::SetPC(uint64_t value) { kern_return_t err = GetGPRState(false); if (err == KERN_SUCCESS) { #if defined(__LP64__) -#if __has_feature(ptrauth_calls) +#if __has_feature(ptrauth_calls) || __has_feature(ptrauth_icall) || __has_feature(ptrauth_vcall) || __has_feature(ptrauth_mfcall) || __has_feature(ptrauth_vptr) // The incoming value could be garbage. Strip it to avoid // trapping when it gets resigned in the thread state. value = (uint64_t) ptrauth_strip((void*) value, ptrauth_key_function_pointer); @@ -2314,7 +2314,7 @@ bool DNBArchMachARM64::SetRegisterValue(uint32_t set, uint32_t reg, if (reg <= gpr_pc) { #if defined(__LP64__) uint64_t signed_value = value->value.uint64; -#if __has_feature(ptrauth_calls) +#if __has_feature(ptrauth_calls) || __has_feature(ptrauth_icall) || __has_feature(ptrauth_vcall) || __has_feature(ptrauth_mfcall) || __has_feature(ptrauth_vptr) // The incoming value could be garbage. Strip it to avoid // trapping when it gets resigned in the thread state. signed_value = (uint64_t) ptrauth_strip((void*) signed_value, ptrauth_key_function_pointer); diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index 456cffff6b4a7c2571aa98cd40a38b1e5b392f7f..90270c3fe05070764b866f00233fed7927800653 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -1498,6 +1498,8 @@ enum { PT_OPENBSD_SYSCALLS = 0x65a3dbe9, // System call sites. PT_OPENBSD_BOOTDATA = 0x65a41be6, // Section for boot arguments. + PT_OHOS_CFI_MODIFIER = 0x6833FC30, // CFI modifier section. + // ARM program header types. PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility info // These all contain stack unwind tables. diff --git a/llvm/include/llvm/IR/GlobalVariable.h b/llvm/include/llvm/IR/GlobalVariable.h index bcaf8e91432ba998a8636204c7085a60caa920bb..e7ee83a3fd19175dcff10c464a77d1ac35acd1ac 100644 --- a/llvm/include/llvm/IR/GlobalVariable.h +++ b/llvm/include/llvm/IR/GlobalVariable.h @@ -147,10 +147,16 @@ public: return static_cast(Op<0>().get()); } /// setInitializer - Sets the initializer for this global variable, removing - /// any existing initializer if InitVal==NULL. If this GV has type T*, the - /// initializer must have type T. + /// any existing initializer if InitVal==NULL. The initializer must have the + /// type getValueType(). void setInitializer(Constant *InitVal); + /// replaceInitializer - Sets the initializer for this global variable, and + /// sets the value type of the global to the type of the initializer. The + /// initializer must not be null. This may affect the global's alignment if + /// it isn't explicitly set. + void replaceInitializer(Constant *InitVal); + /// If the value is a global constant, its value is immutable throughout the /// runtime execution of the program. Assigning a value into the constant /// leads to undefined behavior. diff --git a/llvm/include/llvm/Transforms/Utils/AddDiscriminators.h b/llvm/include/llvm/Transforms/Utils/AddDiscriminators.h index 0aee2fe95cad3e64402e1c7b2df89bdc632da267..7f6128f67dc2315c0451298e1e47ea0e6b2c70a8 100644 --- a/llvm/include/llvm/Transforms/Utils/AddDiscriminators.h +++ b/llvm/include/llvm/Transforms/Utils/AddDiscriminators.h @@ -27,6 +27,7 @@ public: static bool isRequired() { return true; } }; +int getPaccLimit(); } // end namespace llvm #endif // LLVM_TRANSFORMS_UTILS_ADDDISCRIMINATORS_H diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp index cc37d7371cce35732d364a3abbfa991bd9841b2c..2bc69cdb712b0abcb5c7aa34aa4b09c4c2ceb732 100644 --- a/llvm/lib/IR/Globals.cpp +++ b/llvm/lib/IR/Globals.cpp @@ -503,6 +503,12 @@ void GlobalVariable::setInitializer(Constant *InitVal) { } } +void GlobalVariable::replaceInitializer(Constant *InitVal) { + assert(InitVal && "Can't compute type of null initializer"); + ValueType = InitVal->getType(); + setInitializer(InitVal); +} + /// Copy all additional attributes (those not needed to create a GlobalVariable) /// from the GlobalVariable Src to this one. void GlobalVariable::copyAttributesFrom(const GlobalVariable *Src) { diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp index c64454cc253c35958d982cb64f3a1fa703a71a8e..ddafb534ecae68da3151fd3fc26bd4d68917cc8f 100644 --- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -24,6 +24,7 @@ #include "MCTargetDesc/AArch64TargetStreamer.h" #include "TargetInfo/AArch64TargetInfo.h" #include "Utils/AArch64BaseInfo.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -86,6 +87,9 @@ class AArch64AsmPrinter : public AsmPrinter { FaultMaps FM; const AArch64Subtarget *STI; bool ShouldEmitWeakSwiftAsyncExtendedFramePointerFlags = false; +#ifndef NDEBUG + unsigned InstsEmitted; +#endif public: AArch64AsmPrinter(TargetMachine &TM, std::unique_ptr Streamer) @@ -143,13 +147,41 @@ public: // Emit the sequence for BRA/BLRA (authenticate + branch/call). void emitPtrauthBranch(const MachineInstr *MI); + // Emit the sequence for BRAHintOnly/BLRAHintOnly (autia1716 + branch/call) + void emitPtrauthBranchHintOnly(const MachineInstr *MI); + // Emit the sequence for AUTH_TCRETURN_HINT_ONLY (autia1716 + branch x17) + void emitPtrauthTailCallHintOnly(const MachineInstr *MI); + + // Emit the sequence for XPAC. + void emitPtrauthStrip(const MachineInstr *MI); + + // Emit the sequence for PAC. + void emitPtrauthSign(const MachineInstr *MI); // Emit the sequence for AUT or AUTPAC. void emitPtrauthAuthResign(const MachineInstr *MI); - // Emit the sequence to compute a discriminator into x17, or reuse AddrDisc. - unsigned emitPtrauthDiscriminator(uint16_t Disc, unsigned AddrDisc, - unsigned &InstsEmitted); + // Emit the sequence to compute the discriminator. + // + // ScratchReg should be x16/x17. + // + // The returned register is either unmodified AddrDisc or x16/x17. + // + // If the expanded pseudo is allowed to clobber AddrDisc register, setting + // MayUseAddrAsScratch may save one MOV instruction, provided the address + // is already in x16/x17 (i.e. return x16/x17 which is the *modified* AddrDisc + // register at the same time): + // + // mov x17, x16 + // movk x17, #1234, lsl #48 + // ; x16 is not used anymore + // + // can be replaced by + // + // movk x16, #1234, lsl #48 + Register emitPtrauthDiscriminator(uint16_t Disc, Register AddrDisc, + Register ScratchReg, + bool MayUseAddrAsScratch = false); // Emit the sequence for LOADauthptrstatic void LowerLOADauthptrstatic(const MachineInstr &MI); @@ -163,6 +195,11 @@ public: bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, const MachineInstr *MI); + void EmitToStreamer(MCStreamer &S, const MCInst &Inst); + void EmitToStreamer(const MCInst &Inst) { + EmitToStreamer(*OutStreamer, Inst); + } + void emitInstruction(const MachineInstr *MI) override; void emitFunctionHeaderComment() override; @@ -227,6 +264,10 @@ private: /// Emit the LOHs contained in AArch64FI. void emitLOHs(); + + void emitMovXReg(Register Dest, Register Src); + void emitMOVZ(Register Dest, uint64_t Imm, unsigned Shift); + void emitMOVK(Register Dest, uint64_t Imm, unsigned Shift); /// Emit instruction to set float register to zero. void emitFMov0(const MachineInstr &MI); @@ -1379,8 +1420,6 @@ void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer, } void AArch64AsmPrinter::LowerHardenedBRJumpTable(const MachineInstr &MI) { - unsigned InstsEmitted = 0; - const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); assert(MJTI && "Can't lower jump-table dispatch without JTI"); @@ -1418,14 +1457,12 @@ void AArch64AsmPrinter::LowerHardenedBRJumpTable(const MachineInstr &MI) { .addReg(AArch64::X16) .addImm(MaxTableEntry) .addImm(0)); - ++InstsEmitted; } else { EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVZXi) .addReg(AArch64::X17) .addImm(static_cast(MaxTableEntry)) .addImm(0)); - ++InstsEmitted; // It's sad that we have to manually materialize instructions, but we can't // trivially reuse the main pseudo expansion logic. // A MOVK sequence is easy enough to generate and handles the general case. @@ -1438,14 +1475,12 @@ void AArch64AsmPrinter::LowerHardenedBRJumpTable(const MachineInstr &MI) { .addReg(AArch64::X17) .addImm(static_cast(MaxTableEntry >> Offset)) .addImm(Offset)); - ++InstsEmitted; - } + } EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXrs) .addReg(AArch64::XZR) .addReg(AArch64::X16) .addReg(AArch64::X17) .addImm(0)); - ++InstsEmitted; } // This picks entry #0 on failure. @@ -1455,7 +1490,6 @@ void AArch64AsmPrinter::LowerHardenedBRJumpTable(const MachineInstr &MI) { .addReg(AArch64::X16) .addReg(AArch64::XZR) .addImm(AArch64CC::LS)); - ++InstsEmitted; // Prepare the @PAGE/@PAGEOFF low/high operands. MachineOperand JTMOHi(JTOp), JTMOLo(JTOp); @@ -1470,14 +1504,12 @@ void AArch64AsmPrinter::LowerHardenedBRJumpTable(const MachineInstr &MI) { EmitToStreamer( *OutStreamer, MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).addOperand(JTMCHi)); - ++InstsEmitted; EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXri) .addReg(AArch64::X17) .addReg(AArch64::X17) .addOperand(JTMCLo) .addImm(0)); - ++InstsEmitted; EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDRSWroX) .addReg(AArch64::X16) @@ -1485,7 +1517,6 @@ void AArch64AsmPrinter::LowerHardenedBRJumpTable(const MachineInstr &MI) { .addReg(AArch64::X16) .addImm(0) .addImm(1)); - ++InstsEmitted; MCSymbol *AdrLabel = MF->getContext().createTempSymbol(); const auto *AdrLabelE = MCSymbolRefExpr::create(AdrLabel, MF->getContext()); @@ -1495,20 +1526,14 @@ void AArch64AsmPrinter::LowerHardenedBRJumpTable(const MachineInstr &MI) { EmitToStreamer( *OutStreamer, MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addExpr(AdrLabelE)); - ++InstsEmitted; EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ADDXrs) .addReg(AArch64::X16) .addReg(AArch64::X17) .addReg(AArch64::X16) .addImm(0)); - ++InstsEmitted; EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BR).addReg(AArch64::X16)); - ++InstsEmitted; - - (void)InstsEmitted; - assert(STI->getInstrInfo()->getInstSizeInBytes(MI) >= InstsEmitted * 4); } void AArch64AsmPrinter::LowerMOPS(llvm::MCStreamer &OutStreamer, @@ -1699,6 +1724,33 @@ void AArch64AsmPrinter::LowerFAULTING_OP(const MachineInstr &FaultingMI) { OutStreamer->emitInstruction(MI, getSubtargetInfo()); } +void AArch64AsmPrinter::emitMovXReg(Register Dest, Register Src) { + EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs) + .addReg(Dest) + .addReg(AArch64::XZR) + .addReg(Src) + .addImm(0)); +} + +void AArch64AsmPrinter::emitMOVZ(Register Dest, uint64_t Imm, unsigned Shift) { + bool Is64Bit = AArch64::GPR64RegClass.contains(Dest); + EmitToStreamer(*OutStreamer, + MCInstBuilder(Is64Bit ? AArch64::MOVZXi : AArch64::MOVZWi) + .addReg(Dest) + .addImm(Imm) + .addImm(Shift)); +} + +void AArch64AsmPrinter::emitMOVK(Register Dest, uint64_t Imm, unsigned Shift) { + bool Is64Bit = AArch64::GPR64RegClass.contains(Dest); + EmitToStreamer(*OutStreamer, + MCInstBuilder(Is64Bit ? AArch64::MOVKXi : AArch64::MOVKWi) + .addReg(Dest) + .addReg(Dest) + .addImm(Imm) + .addImm(Shift)); +} + void AArch64AsmPrinter::emitFMov0(const MachineInstr &MI) { Register DestReg = MI.getOperand(0).getReg(); if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround() && @@ -1742,9 +1794,12 @@ void AArch64AsmPrinter::emitFMov0(const MachineInstr &MI) { } } -unsigned AArch64AsmPrinter::emitPtrauthDiscriminator(uint16_t Disc, - unsigned AddrDisc, - unsigned &InstsEmitted) { +Register AArch64AsmPrinter::emitPtrauthDiscriminator(uint16_t Disc, + Register AddrDisc, + Register ScratchReg, + bool MayUseAddrAsScratch) { + assert(ScratchReg == AArch64::X16 || ScratchReg == AArch64::X17); + // So far we've used NoRegister in pseudos. Now we need real encodings. if (AddrDisc == AArch64::NoRegister) AddrDisc = AArch64::XZR; @@ -1754,71 +1809,143 @@ unsigned AArch64AsmPrinter::emitPtrauthDiscriminator(uint16_t Disc, if (!Disc) return AddrDisc; - // If there's only a constant discriminator, MOV it into x17. + // If there's only a constant discriminator, MOV it into the scratch register. if (AddrDisc == AArch64::XZR) { - EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVZXi) - .addReg(AArch64::X17) - .addImm(Disc) - .addImm(/*shift=*/0)); - ++InstsEmitted; - return AArch64::X17; - } + emitMOVZ(ScratchReg, Disc, 0); + return ScratchReg; + } + + // If there are both, emit a blend into the scratch register. + + // Check if we can save one MOV instruction. + assert(MayUseAddrAsScratch || ScratchReg != AddrDisc); + bool AddrDiscIsSafe = AddrDisc == AArch64::X16 || AddrDisc == AArch64::X17; + if (MayUseAddrAsScratch && AddrDiscIsSafe) + ScratchReg = AddrDisc; + else + emitMovXReg(ScratchReg, AddrDisc); + + emitMOVK(ScratchReg, Disc, 48); + return ScratchReg; +} - // If there are both, emit a blend into x17. - EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs) - .addReg(AArch64::X17) - .addReg(AArch64::XZR) - .addReg(AddrDisc) - .addImm(0)); - ++InstsEmitted; - EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVKXi) - .addReg(AArch64::X17) - .addReg(AArch64::X17) - .addImm(Disc) - .addImm(/*shift=*/48)); - ++InstsEmitted; - return AArch64::X17; +static inline unsigned getPACHintOpc(AArch64PACKey::ID Key) { + if (Key == AArch64PACKey::IA || + Key == AArch64PACKey::DA) + return AArch64::PACIA1716; + + return AArch64::PACIB1716; +} + +static inline unsigned getAUTHintOpc(AArch64PACKey::ID Key) { + if (Key == AArch64PACKey::IA || + Key == AArch64PACKey::DA) + return AArch64::AUTIA1716; + + return AArch64::AUTIB1716; +} + +void AArch64AsmPrinter::emitPtrauthStrip(const MachineInstr *MI) { + unsigned ValReg = MI->getOperand(0).getReg(); + + EmitToStreamer(*OutStreamer, + MCInstBuilder(AArch64::ORRXrs) + .addReg(AArch64::X16) + .addReg(AArch64::XZR) + .addReg(AArch64::LR) + .addImm(0)); + + EmitToStreamer(*OutStreamer, + MCInstBuilder(AArch64::ORRXrs) + .addReg(AArch64::LR) + .addReg(AArch64::XZR) + .addReg(ValReg) + .addImm(0)); + + MCInst PACInst; + PACInst.setOpcode(AArch64::XPACLRI); + EmitToStreamer(*OutStreamer, PACInst); + + EmitToStreamer(*OutStreamer, + MCInstBuilder(AArch64::ORRXrs) + .addReg(ValReg) + .addReg(AArch64::XZR) + .addReg(AArch64::LR) + .addImm(0)); + + EmitToStreamer(*OutStreamer, + MCInstBuilder(AArch64::ORRXrs) + .addReg(AArch64::LR) + .addReg(AArch64::XZR) + .addReg(AArch64::X16) + .addImm(0)); + +} + +void AArch64AsmPrinter::emitPtrauthSign(const MachineInstr *MI) { + auto PACKey = (AArch64PACKey::ID)MI->getOperand(0).getImm(); + uint64_t PACDisc = MI->getOperand(1).getImm(); + unsigned PACAddrDisc = MI->getOperand(2).getReg(); + + assert(isUInt<16>(PACDisc)); + assert(STI->hasPAuthHintOnly()); + + // Compute pac discriminator into x16 + unsigned PACDiscReg = + emitPtrauthDiscriminator(PACDisc, PACAddrDisc, AArch64::X16, false); + + if (PACDiscReg != AArch64::X16) + EmitToStreamer(*OutStreamer, + MCInstBuilder(AArch64::ORRXrs) + .addReg(AArch64::X16) + .addReg(AArch64::XZR) + .addReg(PACDiscReg) + .addImm(0)); + + MCInst PACInst; + unsigned PACOpc = getPACHintOpc(PACKey); + PACInst.setOpcode(PACOpc); + EmitToStreamer(*OutStreamer, PACInst); } void AArch64AsmPrinter::emitPtrauthAuthResign(const MachineInstr *MI) { - unsigned InstsEmitted = 0; const bool IsAUTPAC = MI->getOpcode() == AArch64::AUTPAC; // We can expand AUT/AUTPAC into 3 possible sequences: // - unchecked: - // autia x16, x0 - // pacib x16, x1 ; if AUTPAC + // autia x17, x0 + // pacib x17, x1 ; if AUTPAC // // - checked and clearing: - // mov x17, x0 - // movk x17, #disc, lsl #48 - // autia x16, x17 - // mov x17, x16 + // mov x16, x0 + // movk x16, #disc, lsl #48 + // autia x17, x16 + // mov x16, x17 // xpaci x17 // cmp x16, x17 // b.eq Lsuccess - // mov x16, x17 + // mov x17, x16 // b Lend // Lsuccess: - // mov x17, x1 - // movk x17, #disc, lsl #48 - // pacib x16, x17 + // mov x16, x1 + // movk x16, #disc, lsl #48 + // pacib x17, x16 // Lend: // Where we only emit the AUT if we started with an AUT. // // - checked and trapping: - // mov x17, x0 - // movk x17, #disc, lsl #48 - // autia x16, x0 - // mov x17, x16 + // mov x16, x0 + // movk x16, #disc, lsl #48 + // autia x17, x16 + // mov x16, x17 // xpaci x17 // cmp x16, x17 // b.eq Lsuccess // brk #<0xc470 + aut key> // Lsuccess: - // mov x17, x1 - // movk x17, #disc, lsl #48 - // pacib x16, x17 ; if AUTPAC + // mov x16, x1 + // movk x16, #disc, lsl #48 + // pacib x17, x16 ; if AUTPAC // Where the b.eq skips over the trap if the PAC is valid. // // This sequence is expensive, but we need more information to be able to @@ -1864,27 +1991,42 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(const MachineInstr *MI) { unsigned XPACOpc = getXPACOpcodeForKey(AUTKey); - // Compute aut discriminator into x17 + // Compute aut discriminator into x16 assert(isUInt<16>(AUTDisc)); - unsigned AUTDiscReg = - emitPtrauthDiscriminator(AUTDisc, AUTAddrDisc, InstsEmitted); + Register AUTDiscReg = + emitPtrauthDiscriminator(AUTDisc, AUTAddrDisc, AArch64::X16); + bool AUTZero = AUTDiscReg == AArch64::XZR; - unsigned AUTOpc = getAUTOpcodeForKey(AUTKey, AUTZero); - - // autiza x16 ; if AUTZero - // autia x16, x17 ; if !AUTZero - MCInst AUTInst; - AUTInst.setOpcode(AUTOpc); - AUTInst.addOperand(MCOperand::createReg(AArch64::X16)); - AUTInst.addOperand(MCOperand::createReg(AArch64::X16)); - if (!AUTZero) - AUTInst.addOperand(MCOperand::createReg(AUTDiscReg)); - EmitToStreamer(*OutStreamer, AUTInst); - ++InstsEmitted; + if (STI->hasPAuthHintOnly()) { + if (AUTDiscReg != AArch64::X16) + EmitToStreamer(*OutStreamer, + MCInstBuilder(AArch64::ORRXrs) + .addReg(AArch64::X16) + .addReg(AArch64::XZR) + .addReg(AUTDiscReg) + .addImm(0)); + + unsigned AUTOpc = getAUTHintOpc(AUTKey); + MCInst AUTInst; + AUTInst.setOpcode(AUTOpc); + EmitToStreamer(*OutStreamer, AUTInst); + } else { + + unsigned AUTOpc = getAUTOpcodeForKey(AUTKey, AUTZero); + + // autiza x17 ; if AUTZero + // autia x17, x16 ; if !AUTZero + MCInst AUTInst; + AUTInst.setOpcode(AUTOpc); + AUTInst.addOperand(MCOperand::createReg(AArch64::X17)); + AUTInst.addOperand(MCOperand::createReg(AArch64::X17)); + if (!AUTZero) + AUTInst.addOperand(MCOperand::createReg(AUTDiscReg)); + EmitToStreamer(*OutStreamer, AUTInst); + } // Unchecked or checked-but-non-trapping AUT is just an "AUT": we're done. if (!IsAUTPAC && (!ShouldCheck || !ShouldTrap)) { - assert(STI->getInstrInfo()->getInstSizeInBytes(*MI) >= InstsEmitted * 4); return; } @@ -1894,20 +2036,18 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(const MachineInstr *MI) { if (ShouldCheck) { MCSymbol *SuccessSym = createTempSymbol("auth_success_"); - // XPAC has tied src/dst: use x17 as a temporary copy. - // mov x17, x16 + // XPAC has tied src/dst: use x16 as a temporary copy. + // mov x16, x17 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs) - .addReg(AArch64::X17) - .addReg(AArch64::XZR) .addReg(AArch64::X16) + .addReg(AArch64::XZR) + .addReg(AArch64::X17) .addImm(0)); - ++InstsEmitted; - // xpaci x17 + // xpaci x16 EmitToStreamer( *OutStreamer, - MCInstBuilder(XPACOpc).addReg(AArch64::X17).addReg(AArch64::X17)); - ++InstsEmitted; + MCInstBuilder(XPACOpc).addReg(AArch64::X16).addReg(AArch64::X16)); // cmp x16, x17 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::SUBSXrs) @@ -1915,34 +2055,30 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(const MachineInstr *MI) { .addReg(AArch64::X16) .addReg(AArch64::X17) .addImm(0)); - ++InstsEmitted; // b.eq Lsuccess EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::Bcc) .addImm(AArch64CC::EQ) .addExpr(MCSymbolRefExpr::create( SuccessSym, OutContext))); - ++InstsEmitted; if (ShouldTrap) { // Trapping sequences do a 'brk'. // brk #<0xc470 + aut key> EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::BRK).addImm(0xc470 | AUTKey)); - ++InstsEmitted; } else { - // Non-trapping checked sequences return the stripped result in x16, + // Non-trapping checked sequences return the stripped result in x17, // skipping over the PAC if there is one. - // FIXME: can we simply return the AUT result, already in x16? without.. + // FIXME: can we simply return the AUT result, already in x17? without.. // ..traps this is usable as an oracle anyway, based on high bits // mov x17, x16 EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs) - .addReg(AArch64::X16) - .addReg(AArch64::XZR) .addReg(AArch64::X17) + .addReg(AArch64::XZR) + .addReg(AArch64::X16) .addImm(0)); - ++InstsEmitted; if (IsAUTPAC) { EndSym = createTempSymbol("resign_end_"); @@ -1951,7 +2087,6 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(const MachineInstr *MI) { EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B) .addExpr(MCSymbolRefExpr::create( EndSym, OutContext))); - ++InstsEmitted; } } @@ -1964,7 +2099,6 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(const MachineInstr *MI) { // That left us with trapping AUTs, and AUTPACs. // Trapping AUTs don't need PAC: we're done. if (!IsAUTPAC) { - assert(STI->getInstrInfo()->getInstSizeInBytes(*MI) >= InstsEmitted * 4); return; } @@ -1972,32 +2106,136 @@ void AArch64AsmPrinter::emitPtrauthAuthResign(const MachineInstr *MI) { uint64_t PACDisc = MI->getOperand(4).getImm(); unsigned PACAddrDisc = MI->getOperand(5).getReg(); - // Compute pac discriminator into x17 + // Compute pac discriminator into x16 assert(isUInt<16>(PACDisc)); - unsigned PACDiscReg = - emitPtrauthDiscriminator(PACDisc, PACAddrDisc, InstsEmitted); - bool PACZero = PACDiscReg == AArch64::XZR; - unsigned PACOpc = getPACOpcodeForKey(PACKey, PACZero); + Register PACDiscReg = + emitPtrauthDiscriminator(PACDisc, PACAddrDisc, AArch64::X16); + + if (STI->hasPAuthHintOnly()) { + if (PACDiscReg != AArch64::X16) + EmitToStreamer(*OutStreamer, + MCInstBuilder(AArch64::ORRXrs) + .addReg(AArch64::X16) + .addReg(AArch64::XZR) + .addReg(PACDiscReg) + .addImm(0)); + + MCInst PACInst; + unsigned PACOpc = getPACHintOpc(PACKey); + PACInst.setOpcode(PACOpc); + EmitToStreamer(*OutStreamer, PACInst); + } else { + bool PACZero = PACDiscReg == AArch64::XZR; + unsigned PACOpc = getPACOpcodeForKey(PACKey, PACZero); - // pacizb x16 ; if PACZero - // pacib x16, x17 ; if !PACZero - MCInst PACInst; - PACInst.setOpcode(PACOpc); - PACInst.addOperand(MCOperand::createReg(AArch64::X16)); - PACInst.addOperand(MCOperand::createReg(AArch64::X16)); - if (!PACZero) - PACInst.addOperand(MCOperand::createReg(PACDiscReg)); - EmitToStreamer(*OutStreamer, PACInst); - ++InstsEmitted; + // pacizb x17 ; if PACZero + // pacib x17, x16 ; if !PACZero + MCInst PACInst; + PACInst.setOpcode(PACOpc); + PACInst.addOperand(MCOperand::createReg(AArch64::X17)); + PACInst.addOperand(MCOperand::createReg(AArch64::X17)); + if (!PACZero) + PACInst.addOperand(MCOperand::createReg(PACDiscReg)); + EmitToStreamer(*OutStreamer, PACInst); + } - assert(STI->getInstrInfo()->getInstSizeInBytes(*MI) >= InstsEmitted * 4); // Lend: if (EndSym) OutStreamer->emitLabel(EndSym); } +void AArch64AsmPrinter::emitPtrauthBranchHintOnly(const MachineInstr *MI) { + bool IsCall = MI->getOpcode() == AArch64::BLRAHintOnly; + unsigned BrTarget = MI->getOperand(0).getReg(); + + auto Key = (AArch64PACKey::ID)MI->getOperand(1).getImm(); + assert((Key == AArch64PACKey::IA || Key == AArch64PACKey::IB) && + "Invalid auth call key"); + + uint64_t Disc = MI->getOperand(2).getImm(); + assert(isUInt<16>(Disc)); + + unsigned AddrDisc = MI->getOperand(3).getReg(); + if (Disc) { + if (AddrDisc != AArch64::NoRegister && AddrDisc != AArch64::XZR) { + EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVKXi) + .addReg(AArch64::X16) + .addReg(AArch64::X16) + .addImm(Disc) + .addImm(/*shift=*/48)); + } else { + EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVZXi) + .addReg(AArch64::X16) + .addImm(Disc) + .addImm(/*shift=*/0)); + } + } else { + if (AddrDisc == AArch64::NoRegister) { + EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs) + .addReg(AArch64::X16) + .addReg(AArch64::XZR) + .addReg(AArch64::XZR) + .addImm(0)); + } + } + + MCInst AUTHInst; + unsigned AuthOpc = (Key == AArch64PACKey::IA) ? AArch64::AUTIA1716 : AArch64::AUTIB1716; + AUTHInst.setOpcode(AuthOpc); + EmitToStreamer(*OutStreamer, AUTHInst); + + unsigned Opc = IsCall ? AArch64::BLR : AArch64::BR; + MCInst BRInst; + BRInst.setOpcode(Opc); + BRInst.addOperand(MCOperand::createReg(BrTarget)); + EmitToStreamer(*OutStreamer, BRInst); + + assert(STI->getInstrInfo()->getInstSizeInBytes(*MI) >= InstsEmitted * 4); +} + +void AArch64AsmPrinter::emitPtrauthTailCallHintOnly(const MachineInstr *MI) { + const uint64_t Key = MI->getOperand(2).getImm(); + assert((Key == AArch64PACKey::IA || Key == AArch64PACKey::IB) && + "Invalid auth key for tail-call return"); + unsigned AuthOpc = (Key == AArch64PACKey::IA) ? AArch64::AUTIA1716 : AArch64::AUTIB1716; + + const uint64_t Disc = MI->getOperand(3).getImm(); + assert(isUInt<16>(Disc) && "Integer discriminator is too wide"); + Register AddrDisc = MI->getOperand(4).getReg(); + + if (Disc) { + if (AddrDisc != AArch64::NoRegister && AddrDisc != AArch64::XZR) { + EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVKXi) + .addReg(AArch64::X16) + .addReg(AArch64::X16) + .addImm(Disc) + .addImm(/*shift=*/48)); + } else { + EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVZXi) + .addReg(AArch64::X16) + .addImm(Disc) + .addImm(/*shift=*/0)); + } + } else { + if (AddrDisc == AArch64::NoRegister) { + EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs) + .addReg(AArch64::X16) + .addReg(AArch64::XZR) + .addReg(AArch64::XZR) + .addImm(0)); + } + } + MCInst AuthInst; + AuthInst.setOpcode(AuthOpc); + EmitToStreamer(*OutStreamer, AuthInst); + + MCInst TmpInst; + TmpInst.setOpcode(AArch64::BR); + TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); + EmitToStreamer(*OutStreamer, TmpInst); +} + void AArch64AsmPrinter::emitPtrauthBranch(const MachineInstr *MI) { - unsigned InstsEmitted = 0; bool IsCall = MI->getOpcode() == AArch64::BLRA; unsigned BrTarget = MI->getOperand(0).getReg(); @@ -2010,8 +2248,21 @@ void AArch64AsmPrinter::emitPtrauthBranch(const MachineInstr *MI) { unsigned AddrDisc = MI->getOperand(3).getReg(); - // Compute discriminator into x17 - unsigned DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, InstsEmitted); + // Make sure AddrDisc is solely used to compute the discriminator. + // While hardly meaningful, it is still possible to describe an authentication + // of a pointer against its own value (instead of storage address) with + // intrinsics, so use report_fatal_error instead of assert. + if (BrTarget == AddrDisc) + report_fatal_error("Branch target is signed with its own value"); + + // If we are printing BLRA pseudo instruction, then x16 and x17 are + // implicit-def'ed by the MI and AddrDisc is not used as any other input, so + // try to save one MOV by setting MayUseAddrAsScratch. + // Unlike BLRA, BRA pseudo is used to perform computed goto, and thus not + // declared as clobbering x16/x17. + Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X17, + /*MayUseAddrAsScratch=*/IsCall); + bool IsZeroDisc = DiscReg == AArch64::XZR; unsigned Opc; @@ -2033,9 +2284,6 @@ void AArch64AsmPrinter::emitPtrauthBranch(const MachineInstr *MI) { if (!IsZeroDisc) BRInst.addOperand(MCOperand::createReg(DiscReg)); EmitToStreamer(*OutStreamer, BRInst); - ++InstsEmitted; - - assert(STI->getInstrInfo()->getInstSizeInBytes(*MI) >= InstsEmitted * 4); } const MCExpr * @@ -2074,6 +2322,25 @@ AArch64AsmPrinter::lowerConstantPtrAuth(const ConstantPtrAuth &CPA) { "' out of range [0, " + Twine((unsigned)AArch64PACKey::LAST) + "]"); + // Convert DA/DB to IA/IB if hint-only option is on, since only + // autia1716/autib1716 is used and it will failed for DA/DB. + auto sti = Ctx.getSubtargetInfo(); + auto STI = static_cast(sti); + assert(STI && "Unable to create subtarget info"); + + if (STI && STI->hasPAuthHintOnly()) { + switch ((AArch64PACKey::ID)(KeyID)) { + case AArch64PACKey::DA: + KeyID = AArch64PACKey::IA; + break; + case AArch64PACKey::DB: + KeyID = AArch64PACKey::IB; + break; + default: + break; + } + } + uint64_t Disc = CPA.getDiscriminator()->getZExtValue(); if (!isUInt<16>(Disc)) report_fatal_error("AArch64 PAC Discriminator '" + Twine(Disc) + @@ -2143,12 +2410,6 @@ void AArch64AsmPrinter::LowerLOADauthptrstatic(const MachineInstr &MI) { } void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) { - unsigned InstsEmitted = 0; - auto EmitAndIncrement = [this, &InstsEmitted](const MCInst &Inst) { - EmitToStreamer(*OutStreamer, Inst); - ++InstsEmitted; - }; - const bool IsGOTLoad = MI.getOpcode() == AArch64::LOADgotPAC; MachineOperand GAOp = MI.getOperand(0); const uint64_t KeyC = MI.getOperand(1).getImm(); @@ -2166,36 +2427,36 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) { // Emit: // target materialization: // - via GOT: - // adrp x16, :got:target - // ldr x16, [x16, :got_lo12:target] - // add offset to x16 if offset != 0 + // adrp x17, :got:target + // ldr x17, [x17, :got_lo12:target] + // add offset to x17 if offset != 0 // // - direct: - // adrp x16, target - // add x16, x16, :lo12:target - // add offset to x16 if offset != 0 + // adrp x17, target + // add x17, x17, :lo12:target + // add offset to x17 if offset != 0 // - // add offset to x16: + // add offset to x17: // - abs(offset) fits 24 bits: - // add/sub x16, x16, #[, #lsl 12] (up to 2 instructions) + // add/sub x17, x17, #[, #lsl 12] (up to 2 instructions) // - abs(offset) does not fit 24 bits: // - offset < 0: - // movn+movk sequence filling x17 register with the offset (up to 4 + // movn+movk sequence filling x16 register with the offset (up to 4 // instructions) - // add x16, x16, x17 + // add x17, x17, x16 // - offset > 0: - // movz+movk sequence filling x17 register with the offset (up to 4 + // movz+movk sequence filling x16 register with the offset (up to 4 // instructions) - // add x16, x16, x17 + // add x17, x17, x16 // // signing: // - 0 discriminator: - // paciza x16 + // paciza x17 // - Non-0 discriminator, no address discriminator: // mov x17, #Disc - // pacia x16, x17 + // pacia x17, x16 // - address discriminator (with potentially folded immediate discriminator): - // pacia x16, xAddrDisc + // pacia x17, xAddrDisc MachineOperand GAMOHi(GAOp), GAMOLo(GAOp); MCOperand GAMCHi, GAMCLo; @@ -2210,18 +2471,18 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) { MCInstLowering.lowerOperand(GAMOHi, GAMCHi); MCInstLowering.lowerOperand(GAMOLo, GAMCLo); - EmitAndIncrement( - MCInstBuilder(AArch64::ADRP).addReg(AArch64::X16).addOperand(GAMCHi)); + EmitToStreamer( + MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).addOperand(GAMCHi)); if (IsGOTLoad) { - EmitAndIncrement(MCInstBuilder(AArch64::LDRXui) - .addReg(AArch64::X16) - .addReg(AArch64::X16) + EmitToStreamer(MCInstBuilder(AArch64::LDRXui) + .addReg(AArch64::X17) + .addReg(AArch64::X17) .addOperand(GAMCLo)); } else { - EmitAndIncrement(MCInstBuilder(AArch64::ADDXri) - .addReg(AArch64::X16) - .addReg(AArch64::X16) + EmitToStreamer(MCInstBuilder(AArch64::ADDXri) + .addReg(AArch64::X17) + .addReg(AArch64::X17) .addOperand(GAMCLo) .addImm(0)); } @@ -2232,17 +2493,17 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) { if (isUInt<24>(AbsOffset)) { for (int BitPos = 0; BitPos != 24 && (AbsOffset >> BitPos); BitPos += 12) { - EmitAndIncrement( + EmitToStreamer( MCInstBuilder(IsNeg ? AArch64::SUBXri : AArch64::ADDXri) - .addReg(AArch64::X16) - .addReg(AArch64::X16) + .addReg(AArch64::X17) + .addReg(AArch64::X17) .addImm((AbsOffset >> BitPos) & 0xfff) .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSL, BitPos))); } } else { const uint64_t UOffset = Offset; - EmitAndIncrement(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi) - .addReg(AArch64::X17) + EmitToStreamer(MCInstBuilder(IsNeg ? AArch64::MOVNXi : AArch64::MOVZXi) + .addReg(AArch64::X16) .addImm((IsNeg ? ~UOffset : UOffset) & 0xffff) .addImm(/*shift=*/0)); auto NeedMovk = [IsNeg, UOffset](int BitPos) -> bool { @@ -2256,50 +2517,41 @@ void AArch64AsmPrinter::LowerMOVaddrPAC(const MachineInstr &MI) { return false; }; for (int BitPos = 16; BitPos != 64 && NeedMovk(BitPos); BitPos += 16) { - EmitAndIncrement(MCInstBuilder(AArch64::MOVKXi) - .addReg(AArch64::X17) - .addReg(AArch64::X17) + EmitToStreamer(MCInstBuilder(AArch64::MOVKXi) + .addReg(AArch64::X16) + .addReg(AArch64::X16) .addImm((UOffset >> BitPos) & 0xffff) .addImm(/*shift=*/BitPos)); } - EmitAndIncrement(MCInstBuilder(AArch64::ADDXrs) - .addReg(AArch64::X16) - .addReg(AArch64::X16) + EmitToStreamer(MCInstBuilder(AArch64::ADDXrs) + .addReg(AArch64::X17) .addReg(AArch64::X17) + .addReg(AArch64::X16) .addImm(/*shift=*/0)); } } - unsigned DiscReg = AddrDisc; - if (Disc != 0) { - if (AddrDisc != AArch64::XZR) { - EmitAndIncrement(MCInstBuilder(AArch64::ORRXrs) - .addReg(AArch64::X17) + Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, AArch64::X16); + + if (STI->hasPAuthHintOnly()) { + if (DiscReg == AArch64::XZR) { + EmitToStreamer(MCInstBuilder(AArch64::ORRXrs) + .addReg(AArch64::X16) .addReg(AArch64::XZR) - .addReg(AddrDisc) + .addReg(DiscReg) .addImm(0)); - EmitAndIncrement(MCInstBuilder(AArch64::MOVKXi) - .addReg(AArch64::X17) - .addReg(AArch64::X17) - .addImm(Disc) - .addImm(/*shift=*/48)); - } else { - EmitAndIncrement(MCInstBuilder(AArch64::MOVZXi) - .addReg(AArch64::X17) - .addImm(Disc) - .addImm(/*shift=*/0)); } - DiscReg = AArch64::X17; + unsigned PacOpc = (Key == AArch64PACKey::IA || Key == AArch64PACKey::DA) + ? AArch64::PACIA1716 : AArch64::PACIB1716; + EmitToStreamer(MCInstBuilder(PacOpc)); + } else { + auto MIB = MCInstBuilder(getPACOpcodeForKey(Key, DiscReg == AArch64::XZR)) + .addReg(AArch64::X17) + .addReg(AArch64::X17); + if (DiscReg != AArch64::XZR) + MIB.addReg(DiscReg); + EmitToStreamer(MIB); } - - auto MIB = MCInstBuilder(getPACOpcodeForKey(Key, DiscReg == AArch64::XZR)) - .addReg(AArch64::X16) - .addReg(AArch64::X16); - if (DiscReg != AArch64::XZR) - MIB.addReg(DiscReg); - EmitAndIncrement(MIB); - - assert(STI->getInstrInfo()->getInstSizeInBytes(MI) >= InstsEmitted * 4); } const MCExpr * @@ -2315,12 +2567,25 @@ AArch64AsmPrinter::lowerBlockAddressConstant(const BlockAddress &BA) { return BAE; } +void AArch64AsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) { + S.emitInstruction(Inst, getSubtargetInfo()); +#ifndef NDEBUG + ++InstsEmitted; +#endif +} + // Simple pseudo-instructions have their lowering (with expansion to real // instructions) auto-generated. #include "AArch64GenMCPseudoLowering.inc" void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) { AArch64_MC::verifyInstructionPredicates(MI->getOpcode(), STI->getFeatureBits()); +#ifndef NDEBUG + InstsEmitted = 0; + auto CheckMISize = make_scope_exit([&]() { + assert(STI->getInstrInfo()->getInstSizeInBytes(*MI) >= InstsEmitted * 4); + }); +#endif // Do any auto-generated pseudo lowerings. if (emitPseudoExpansionLowering(*OutStreamer, MI)) @@ -2450,6 +2715,12 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) { return; } + case AArch64::XPAC: + emitPtrauthStrip(MI); + return; + case AArch64::PAC: + emitPtrauthSign(MI); + return; case AArch64::AUT: case AArch64::AUTPAC: emitPtrauthAuthResign(MI); @@ -2469,11 +2740,19 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) { emitPtrauthBranch(MI); return; + case AArch64::BRAHintOnly: + case AArch64::BLRAHintOnly: + emitPtrauthBranchHintOnly(MI); + return; // Tail calls use pseudo instructions so they have the proper code-gen // attributes (isCall, isReturn, etc.). We lower them to the real // instruction here. + case AArch64::AUTH_TCRETURN_HINT_ONLY: + emitPtrauthTailCallHintOnly(MI); + return; case AArch64::AUTH_TCRETURN: case AArch64::AUTH_TCRETURN_BTI: { + Register Callee = MI->getOperand(0).getReg(); const uint64_t Key = MI->getOperand(2).getImm(); assert((Key == AArch64PACKey::IA || Key == AArch64PACKey::IB) && "Invalid auth key for tail-call return"); @@ -2483,39 +2762,21 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) { Register AddrDisc = MI->getOperand(4).getReg(); - Register ScratchReg = MI->getOperand(0).getReg() == AArch64::X16 - ? AArch64::X17 - : AArch64::X16; - - unsigned DiscReg = AddrDisc; - if (Disc) { - if (AddrDisc != AArch64::NoRegister) { - EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::ORRXrs) - .addReg(ScratchReg) - .addReg(AArch64::XZR) - .addReg(AddrDisc) - .addImm(0)); - EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVKXi) - .addReg(ScratchReg) - .addReg(ScratchReg) - .addImm(Disc) - .addImm(/*shift=*/48)); - } else { - EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::MOVZXi) - .addReg(ScratchReg) - .addImm(Disc) - .addImm(/*shift=*/0)); - } - DiscReg = ScratchReg; - } + Register ScratchReg = Callee == AArch64::X16 ? AArch64::X17 : AArch64::X16; + + // See the comments in emitPtrauthBranch. + if (Callee == AddrDisc) + report_fatal_error("Call target is signed with its own value"); + Register DiscReg = emitPtrauthDiscriminator(Disc, AddrDisc, ScratchReg, + /*MayUseAddrAsScratch=*/true); - const bool IsZero = DiscReg == AArch64::NoRegister; + const bool IsZero = DiscReg == AArch64::XZR; const unsigned Opcodes[2][2] = {{AArch64::BRAA, AArch64::BRAAZ}, {AArch64::BRAB, AArch64::BRABZ}}; MCInst TmpInst; TmpInst.setOpcode(Opcodes[Key][IsZero]); - TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); + TmpInst.addOperand(MCOperand::createReg(Callee)); if (!IsZero) TmpInst.addOperand(MCOperand::createReg(DiscReg)); EmitToStreamer(*OutStreamer, TmpInst); @@ -2617,6 +2878,9 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) { TLSDescCall.setOpcode(AArch64::TLSDESCCALL); TLSDescCall.addOperand(Sym); EmitToStreamer(*OutStreamer, TLSDescCall); +#ifndef NDEBUG + --InstsEmitted; // no code emitted +#endif MCInst Blr; Blr.setOpcode(AArch64::BLR); diff --git a/llvm/lib/Target/AArch64/AArch64Features.td b/llvm/lib/Target/AArch64/AArch64Features.td index a4f8f8c2d9629f7567e95b04a5dcc7514bfc37cf..03f68557106ed8bed35990aecba5665c85407797 100644 --- a/llvm/lib/Target/AArch64/AArch64Features.td +++ b/llvm/lib/Target/AArch64/AArch64Features.td @@ -527,6 +527,12 @@ def FeatureTLBIW : ExtensionWithMArch<"tlbiw", "TLBIW", "FEAT_TLBIW", // Other Features //===----------------------------------------------------------------------===// +def FeaturePAuthHintOnly : ExtensionWithMArch<"pauth-hint-only", "PAuthHintOnly", "FEAT_PAuthHintOnly", + "Only use Pointer Authentication instructions in the HINT space", [FeaturePAuth]>; + +//def FeaturePAuthHintOnly : SubtargetFeature<"pauth-hint-only", "UsePAuthHintOnly", "true", +// "Only use Pointer Authentication instructions in the HINT space", [FeaturePAuth]>; + def FeatureOutlineAtomics : SubtargetFeature<"outline-atomics", "OutlineAtomics", "true", "Enable out of line atomics to support LSE instructions">; diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp index 55cc106c08b95653a6d0f70e4cf4cbaa3e3eb749..c985cbdaf9e9e2877d1a645b0cf1756c4aacb698 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp @@ -366,6 +366,8 @@ public: bool tryIndexedLoad(SDNode *N); + void SelectPtrauthStrip(SDNode *N); + void SelectPtrauthSign(SDNode *N); void SelectPtrauthAuth(SDNode *N); void SelectPtrauthResign(SDNode *N); @@ -1517,6 +1519,48 @@ extractPtrauthBlendDiscriminators(SDValue Disc, SelectionDAG *DAG) { AddrDisc); } +static SDNode *SelectPtrauthHintStripNode(SDNode *N, SelectionDAG *CurDAG) { + SDLoc DL(N); + SDValue Val = N->getOperand(1); + + return CurDAG->getMachineNode(AArch64::XPAC, DL, MVT::i64, Val); +} + +void AArch64DAGToDAGISel::SelectPtrauthStrip(SDNode *N) { + if (Subtarget->hasPAuthHintOnly()) + ReplaceNode(N, SelectPtrauthHintStripNode(N, CurDAG)); + else + SelectCode(N); +} + +static SDNode *SelectPtrauthHintSignNode(SDNode *N, SelectionDAG *CurDAG) { + SDLoc DL(N); + // IntrinsicID is operand #0 + SDValue Val = N->getOperand(1); + SDValue AUTKey = N->getOperand(2); + SDValue AUTDisc = N->getOperand(3); + + unsigned AUTKeyC = cast(AUTKey)->getZExtValue(); + AUTKey = CurDAG->getTargetConstant(AUTKeyC, DL, MVT::i64); + + SDValue AUTAddrDisc, AUTConstDisc; + std::tie(AUTConstDisc, AUTAddrDisc) = + extractPtrauthBlendDiscriminators(AUTDisc, CurDAG); + + SDValue X17Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, + AArch64::X17, Val, SDValue()); + SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, X17Copy.getValue(1)}; + + return CurDAG->getMachineNode(AArch64::PAC, DL, MVT::i64, Ops); +} + +void AArch64DAGToDAGISel::SelectPtrauthSign(SDNode *N) { + if (Subtarget->hasPAuthHintOnly()) + ReplaceNode(N, SelectPtrauthHintSignNode(N, CurDAG)); + else + SelectCode(N); +} + void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *N) { SDLoc DL(N); // IntrinsicID is operand #0 @@ -1531,9 +1575,9 @@ void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *N) { std::tie(AUTConstDisc, AUTAddrDisc) = extractPtrauthBlendDiscriminators(AUTDisc, CurDAG); - SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, - AArch64::X16, Val, SDValue()); - SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, X16Copy.getValue(1)}; + SDValue X17Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, + AArch64::X17, Val, SDValue()); + SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, X17Copy.getValue(1)}; SDNode *AUT = CurDAG->getMachineNode(AArch64::AUT, DL, MVT::i64, Ops); ReplaceNode(N, AUT); @@ -1563,11 +1607,11 @@ void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *N) { std::tie(PACConstDisc, PACAddrDisc) = extractPtrauthBlendDiscriminators(PACDisc, CurDAG); - SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, - AArch64::X16, Val, SDValue()); + SDValue X17Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, + AArch64::X17, Val, SDValue()); SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, PACKey, - PACConstDisc, PACAddrDisc, X16Copy.getValue(1)}; + PACConstDisc, PACAddrDisc, X17Copy.getValue(1)}; SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC, DL, MVT::i64, Ops); ReplaceNode(N, AUTPAC); @@ -5531,6 +5575,12 @@ void AArch64DAGToDAGISel::Select(SDNode *Node) { SelectTagP(Node); return; + case Intrinsic::ptrauth_strip: + return SelectPtrauthStrip(Node); + + case Intrinsic::ptrauth_sign: + return SelectPtrauthSign(Node); + case Intrinsic::ptrauth_auth: SelectPtrauthAuth(Node); return; diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index ef2789e96213b560327152a1f45fe275e7907147..40d6198b3f218bcb22e0736ca3b4fd6bc544726d 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -10860,7 +10860,11 @@ SDValue AArch64TargetLowering::LowerBRIND(SDValue Op, SelectionDAG &DAG) const { SDValue Key = DAG.getTargetConstant(AArch64PACKey::IA, DL, MVT::i32); SDValue AddrDisc = DAG.getRegister(AArch64::XZR, MVT::i64); - SDNode *BrA = DAG.getMachineNode(AArch64::BRA, DL, MVT::Other, + unsigned int Opcode = AArch64::BRA; + if (Subtarget->hasPAuthHintOnly()) + Opcode = AArch64::BRAHintOnly; + + SDNode *BrA = DAG.getMachineNode(Opcode, DL, MVT::Other, {Dest, Key, Disc, AddrDisc, Chain}); return SDValue(BrA, 0); } @@ -10903,7 +10907,7 @@ SDValue AArch64TargetLowering::LowerBlockAddress(SDValue Op, SDNode *MOV = DAG.getMachineNode(AArch64::MOVaddrPAC, DL, {MVT::Other, MVT::Glue}, {TargetBA, Key, AddrDisc, Disc}); - return DAG.getCopyFromReg(SDValue(MOV, 0), DL, AArch64::X16, MVT::i64, + return DAG.getCopyFromReg(SDValue(MOV, 0), DL, AArch64::X17, MVT::i64, SDValue(MOV, 1)); } diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index 805684ef69a59289be69371de3f0e3897fc6a793..a5591cdc02e755fd3829ba170120bae61c2459f5 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -2529,6 +2529,7 @@ bool AArch64InstrInfo::isTailCallReturnInst(const MachineInstr &MI) { case AArch64::TCRETURNrinotx16: case AArch64::TCRETURNriALL: case AArch64::AUTH_TCRETURN: + case AArch64::AUTH_TCRETURN_HINT_ONLY: case AArch64::AUTH_TCRETURN_BTI: return true; } diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index 95f2f91f82bd41c96be12b073bee84911c79ce4e..fc01104c62d1b707539830462b291bf375676b8b 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -69,6 +69,9 @@ def HasPAuth : Predicate<"Subtarget->hasPAuth()">, def HasPAuthLR : Predicate<"Subtarget->hasPAuthLR()">, AssemblerPredicateWithAll<(all_of FeaturePAuthLR), "pauth-lr">; +def HasPAuthHintOnly : Predicate<"Subtarget->hasPAuthHintOnly()">, + AssemblerPredicateWithAll<(all_of FeaturePAuthHintOnly), "pauth-hint-only">; + def HasJS : Predicate<"Subtarget->hasJS()">, AssemblerPredicateWithAll<(all_of FeatureJS), "jsconv">; @@ -1004,6 +1007,10 @@ let RecomputePerFunction = 1 in { def TailCallNotX16 : Predicate<[{ !MF->getInfo()->branchTargetEnforcement() && MF->getInfo()->branchProtectionPAuthLR() }]>; // BTI off, PAuthLR off: Any non-callee-saved register def TailCallAny : Predicate<[{ !MF->getInfo()->branchTargetEnforcement() && !MF->getInfo()->branchProtectionPAuthLR() }]>; + // PAuth on but only use instructions in the HINT space (System) + def PAuthHintOnly : Predicate<[{ MF->getSubtarget().hasPAuthHintOnly() }]>; + + def NoPAuthHintOnly : Predicate<[{ !MF->getSubtarget().hasPAuthHintOnly() }]>; def SLSBLRMitigation : Predicate<[{ MF->getSubtarget().hardenSlsBlr() }]>; def NoSLSBLRMitigation : Predicate<[{ !MF->getSubtarget().hardenSlsBlr() }]>; @@ -1770,28 +1777,44 @@ let Predicates = [HasPAuth] in { // materialization here), in part because they're handled in a safer way by // the kernel, notably on Darwin. def BLRA : Pseudo<(outs), (ins GPR64noip:$Rn, i32imm:$Key, i64imm:$Disc, - GPR64noip:$AddrDisc), + GPR64:$AddrDisc), [(AArch64authcall GPR64noip:$Rn, timm:$Key, timm:$Disc, - GPR64noip:$AddrDisc)]>, Sched<[]> { + GPR64:$AddrDisc)]>, Sched<[]> { + let isCodeGenOnly = 1; + let hasSideEffects = 1; + let mayStore = 0; + let mayLoad = 0; + let isCall = 1; + let Size = 12; // 4 fixed + 8 variable, to compute discriminator. + let Defs = [X17,X16,LR]; + let Uses = [SP]; + let Predicates = [NoPAuthHintOnly]; + } + + def BLRAHintOnly : Pseudo<(outs), (ins tcGPRx17:$Rn, i32imm:$Key, i64imm:$Disc, + discGPRx16:$AddrDisc), + [(AArch64authcall tcGPRx17:$Rn, timm:$Key, timm:$Disc, + discGPRx16:$AddrDisc)]>, Sched<[]> { let isCodeGenOnly = 1; let hasSideEffects = 1; let mayStore = 0; let mayLoad = 0; let isCall = 1; let Size = 12; // 4 fixed + 8 variable, to compute discriminator. - let Defs = [X17,LR]; + let Defs = [LR]; let Uses = [SP]; + let Predicates = [PAuthHintOnly]; } def BLRA_RVMARKER : Pseudo< (outs), (ins i64imm:$rvfunc, GPR64noip:$Rn, i32imm:$Key, i64imm:$Disc, - GPR64noip:$AddrDisc), + GPR64:$AddrDisc), [(AArch64authcall_rvmarker tglobaladdr:$rvfunc, GPR64noip:$Rn, timm:$Key, timm:$Disc, - GPR64noip:$AddrDisc)]>, Sched<[]> { + GPR64:$AddrDisc)]>, Sched<[]> { let isCodeGenOnly = 1; let isCall = 1; - let Defs = [X17,LR]; + let Defs = [X16,X17,LR]; let Uses = [SP]; } @@ -1810,7 +1833,23 @@ let Predicates = [HasPAuth] in { let isBarrier = 1; let isIndirectBranch = 1; let Size = 12; // 4 fixed + 8 variable, to compute discriminator. - let Defs = [X17]; + let Defs = [X16]; + let Predicates = [NoPAuthHintOnly]; + } + + def BRAHintOnly : Pseudo<(outs), (ins tcGPRx17:$Rn, i32imm:$Key, i64imm:$Disc, + discGPRx16:$AddrDisc), []>, Sched<[]> { + let isCodeGenOnly = 1; + let hasNoSchedulingInfo = 1; + let hasSideEffects = 1; + let mayStore = 0; + let mayLoad = 0; + let isBranch = 1; + let isTerminator = 1; + let isBarrier = 1; + let isIndirectBranch = 1; + let Size = 12; // 4 fixed + 8 variable, to compute discriminator. + let Predicates = [PAuthHintOnly]; } let isReturn = 1, isTerminator = 1, isBarrier = 1 in { @@ -1823,6 +1862,31 @@ let Predicates = [HasPAuth] in { defm LDRAA : AuthLoad<0, "ldraa", simm10Scaled>; defm LDRAB : AuthLoad<1, "ldrab", simm10Scaled>; + // XPAC pseudo. + // Use for lowering PAC instructions on the HINT space only + def XPAC : Pseudo<(outs GPR64noip:$Rd), (ins GPR64noip:$Rn), + [], "$Rn = $Rd">, Sched<[WriteI, ReadI]> { + let isCodeGenOnly = 1; + let hasSideEffects = 1; + let mayStore = 0; + let mayLoad = 0; + let Size = 32; + let Defs = [X16]; + } + +// PAC pseudo. + // Use for lowering PAC instructions on the HINT space only + def PAC : Pseudo<(outs), (ins i32imm:$Key, i64imm:$Disc, GPR64noip:$AddrDisc), + []>, Sched<[WriteI, ReadI]> { + let isCodeGenOnly = 1; + let hasSideEffects = 1; + let mayStore = 0; + let mayLoad = 0; + let Size = 32; + let Defs = [X17,X16,NZCV]; + let Uses = [X17]; + } + // AUT pseudo. // This directly manipulates x16/x17, which are the only registers the OS // guarantees are safe to use for sensitive operations. @@ -1833,8 +1897,8 @@ let Predicates = [HasPAuth] in { let mayStore = 0; let mayLoad = 0; let Size = 32; - let Defs = [X16,X17,NZCV]; - let Uses = [X16]; + let Defs = [X17,X16,NZCV]; + let Uses = [X17]; } // AUT and re-PAC a value, using different keys/data. @@ -1850,8 +1914,8 @@ let Predicates = [HasPAuth] in { let mayStore = 0; let mayLoad = 0; let Size = 48; - let Defs = [X16,X17,NZCV]; - let Uses = [X16]; + let Defs = [X17,X16,NZCV]; + let Uses = [X17]; } // Materialize a signed global address, with adrp+add and PAC. @@ -1862,7 +1926,7 @@ let Predicates = [HasPAuth] in { let isReMaterializable = 1; let isCodeGenOnly = 1; let Size = 40; // 12 fixed + 28 variable, for pointer offset, and discriminator - let Defs = [X16,X17]; + let Defs = [X17,X16]; } // Materialize a signed global address, using a GOT load and PAC. @@ -1873,7 +1937,7 @@ let Predicates = [HasPAuth] in { let isReMaterializable = 1; let isCodeGenOnly = 1; let Size = 40; // 12 fixed + 28 variable, for pointer offset, and discriminator - let Defs = [X16,X17]; + let Defs = [X17,X16]; } // Load a signed global address from a special $auth_ptr$ stub slot. @@ -1888,7 +1952,7 @@ let Predicates = [HasPAuth] in { // Size 16: 4 fixed + 8 variable, to compute discriminator. let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Size = 16, - Uses = [SP] in { + Defs = [X16,X17], Uses = [SP] in { def AUTH_TCRETURN : Pseudo<(outs), (ins tcGPR64:$dst, i32imm:$FPDiff, i32imm:$Key, i64imm:$Disc, tcGPR64:$AddrDisc), @@ -1897,20 +1961,39 @@ let Predicates = [HasPAuth] in { : Pseudo<(outs), (ins tcGPRx16x17:$dst, i32imm:$FPDiff, i32imm:$Key, i64imm:$Disc, tcGPR64:$AddrDisc), []>, Sched<[WriteBrReg]>; + def AUTH_TCRETURN_HINT_ONLY + : Pseudo<(outs), (ins tcGPRx17:$dst, i32imm:$FPDiff, i32imm:$Key, + i64imm:$Disc, discGPRx16:$AddrDisc), + []>, Sched<[WriteBrReg]>; } - let Predicates = [TailCallAny] in + + let Predicates = [TailCallAny, NoPAuthHintOnly] in def : Pat<(AArch64authtcret tcGPR64:$dst, (i32 timm:$FPDiff), (i32 timm:$Key), (i64 timm:$Disc), tcGPR64:$AddrDisc), (AUTH_TCRETURN tcGPR64:$dst, imm:$FPDiff, imm:$Key, imm:$Disc, tcGPR64:$AddrDisc)>; - let Predicates = [TailCallX16X17] in + let Predicates = [TailCallX16X17, NoPAuthHintOnly] in def : Pat<(AArch64authtcret tcGPRx16x17:$dst, (i32 timm:$FPDiff), (i32 timm:$Key), (i64 timm:$Disc), tcGPR64:$AddrDisc), (AUTH_TCRETURN_BTI tcGPRx16x17:$dst, imm:$FPDiff, imm:$Key, imm:$Disc, tcGPR64:$AddrDisc)>; + let Predicates = [TailCallAny, HasPAuthHintOnly] in + def : Pat<(AArch64authtcret tcGPRx17:$dst, (i32 timm:$FPDiff), + (i32 timm:$Key), (i64 timm:$Disc), + discGPRx16:$AddrDisc), + (AUTH_TCRETURN_HINT_ONLY tcGPRx17:$dst, imm:$FPDiff, imm:$Key, + imm:$Disc, discGPRx16:$AddrDisc)>; + + let Predicates = [TailCallX16X17, HasPAuthHintOnly] in + def : Pat<(AArch64authtcret tcGPRx17:$dst, (i32 timm:$FPDiff), + (i32 timm:$Key), (i64 timm:$Disc), + discGPRx16:$AddrDisc), + (AUTH_TCRETURN_HINT_ONLY tcGPRx17:$dst, imm:$FPDiff, imm:$Key, + imm:$Disc, discGPRx16:$AddrDisc)>; + } // v9.5-A pointer authentication extensions @@ -9689,6 +9772,7 @@ def : Pat<(AArch64tcret tglobaladdr:$dst, (i32 timm:$FPDiff)), def : Pat<(AArch64tcret texternalsym:$dst, (i32 timm:$FPDiff)), (TCRETURNdi texternalsym:$dst, imm:$FPDiff)>; +let Size = 8 in def MOVMCSym : Pseudo<(outs GPR64:$dst), (ins i64imm:$sym), []>, Sched<[]>; def : Pat<(i64 (AArch64LocalRecover mcsym:$sym)), (MOVMCSym mcsym:$sym)>; diff --git a/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp b/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp index 92ab4b5c3d251f385d6af5a3973b92479c7ee394..542855c80069050ae501c4a2b80dc3b9471a1c07 100644 --- a/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp +++ b/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp @@ -186,7 +186,8 @@ void AArch64PointerAuth::authenticateLR( TI != MBB.end() && TI->getOpcode() == AArch64::RET; MCSymbol *PACSym = MFnI->getSigningInstrLabel(); - if (Subtarget->hasPAuth() && TerminatorIsCombinable && !NeedsWinCFI && + if (Subtarget->hasPAuth() && !Subtarget->hasPAuthHintOnly() && + TerminatorIsCombinable && !NeedsWinCFI && !MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack)) { if (MFnI->branchProtectionPAuthLR() && Subtarget->hasPAuthLR()) { assert(PACSym && "No PAC instruction to refer to"); diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td index 4dc33e6168cbdaf5c53d0b17f9229cdba64d2a82..5482695c907cdca5ee9327aeeef3d47efe39ff29 100644 --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td @@ -244,6 +244,9 @@ def GPR64noip : RegisterClass<"AArch64", [i64], 64, (sub GPR64, X16, X17, LR)> { let AltOrderSelect = [{ return 1; }]; } +// Retrict discriminator to be stored in x16 so we can use PACI[A|B]1716 or AUTI[A|B]1716 +def discGPRx16 : RegisterClass<"AArch64", [i64], 64, (add X16)>; + // GPR register classes for post increment amount of vector load/store that // has alternate printing when Rm=31 and prints a constant immediate value // equal to the total number of bytes transferred. diff --git a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp index b4d2a3388c1dfe4be87541ae0fb0caab643efbb5..f842c7abc3d48906e1667a2aca38ae7419aff958 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp @@ -1024,6 +1024,7 @@ static unsigned getCallOpcode(const MachineFunction &CallerF, bool IsIndirect, std::optional &PAI, MachineRegisterInfo &MRI) { const AArch64FunctionInfo *FuncInfo = CallerF.getInfo(); + bool isPAHintOnly = CallerF.getSubtarget().hasPAuthHintOnly(); if (!IsTailCall) { if (!PAI) @@ -1032,6 +1033,8 @@ static unsigned getCallOpcode(const MachineFunction &CallerF, bool IsIndirect, assert(IsIndirect && "Direct call should not be authenticated"); assert((PAI->Key == AArch64PACKey::IA || PAI->Key == AArch64PACKey::IB) && "Invalid auth call key"); + if (isPAHintOnly) + return AArch64::BLRAHintOnly; return AArch64::BLRA; } @@ -1046,7 +1049,7 @@ static unsigned getCallOpcode(const MachineFunction &CallerF, bool IsIndirect, return AArch64::TCRETURNrix17; } if (PAI) - return AArch64::AUTH_TCRETURN_BTI; + return isPAHintOnly ? AArch64::AUTH_TCRETURN_HINT_ONLY : AArch64::AUTH_TCRETURN; return AArch64::TCRETURNrix16x17; } @@ -1056,7 +1059,7 @@ static unsigned getCallOpcode(const MachineFunction &CallerF, bool IsIndirect, } if (PAI) - return AArch64::AUTH_TCRETURN; + return isPAHintOnly ? AArch64::AUTH_TCRETURN_HINT_ONLY : AArch64::AUTH_TCRETURN; return AArch64::TCRETURNri; } @@ -1115,7 +1118,9 @@ bool AArch64CallLowering::lowerTailCall( MIB.addImm(0); // Authenticated tail calls always take key/discriminator arguments. - if (Opc == AArch64::AUTH_TCRETURN || Opc == AArch64::AUTH_TCRETURN_BTI) { + if (Opc == AArch64::AUTH_TCRETURN || + Opc == AArch64::AUTH_TCRETURN_HINT_ONLY || + Opc == AArch64::AUTH_TCRETURN_BTI) { assert((Info.PAI->Key == AArch64PACKey::IA || Info.PAI->Key == AArch64PACKey::IB) && "Invalid auth call key"); @@ -1384,7 +1389,9 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, Mask = getMaskForArgs(OutArgs, Info, *TRI, MF); - if (Opc == AArch64::BLRA || Opc == AArch64::BLRA_RVMARKER) { + if (Opc == AArch64::BLRA || + Opc == AArch64::BLRAHintOnly || + Opc == AArch64::BLRA_RVMARKER) { assert((Info.PAI->Key == AArch64PACKey::IA || Info.PAI->Key == AArch64PACKey::IB) && "Invalid auth call key"); diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp index d33b0ab7b9fcd2bbf6580563055bdfb3e41c94b4..500c1d8f3ab89331eb9262adb5c357b9a2a97a98 100644 --- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -2555,7 +2555,10 @@ bool AArch64InstructionSelector::select(MachineInstr &I) { const Function &Fn = MF.getFunction(); if (std::optional BADisc = STI.getPtrAuthBlockAddressDiscriminatorIfEnabled(Fn)) { - auto MI = MIB.buildInstr(AArch64::BRA, {}, {I.getOperand(0).getReg()}); + unsigned int Opcode = AArch64::BRA; + if (STI.hasPAuthHintOnly()) + Opcode = AArch64::BRAHintOnly; + auto MI = MIB.buildInstr(Opcode, {}, {I.getOperand(0).getReg()}); MI.addImm(AArch64PACKey::IA); MI.addImm(*BADisc); MI.addReg(/*AddrDisc=*/AArch64::XZR); @@ -3487,7 +3490,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) { .addReg(/*AddrDisc=*/AArch64::XZR) .addImm(*BADisc) .constrainAllUses(TII, TRI, RBI); - MIB.buildCopy(I.getOperand(0).getReg(), Register(AArch64::X16)); + MIB.buildCopy(I.getOperand(0).getReg(), Register(AArch64::X17)); RBI.constrainGenericRegister(I.getOperand(0).getReg(), AArch64::GPR64RegClass, MRI); I.eraseFromParent(); @@ -6575,8 +6578,8 @@ bool AArch64InstructionSelector::selectIntrinsic(MachineInstr &I, std::tie(PACConstDiscC, PACAddrDisc) = extractPtrauthBlendDiscriminators(PACDisc, MRI); - MIB.buildCopy({AArch64::X16}, {ValReg}); - MIB.buildInstr(TargetOpcode::IMPLICIT_DEF, {AArch64::X17}, {}); + MIB.buildCopy({AArch64::X17}, {ValReg}); + MIB.buildInstr(TargetOpcode::IMPLICIT_DEF, {AArch64::X16}, {}); MIB.buildInstr(AArch64::AUTPAC) .addImm(AUTKey) .addImm(AUTConstDiscC) @@ -6585,7 +6588,7 @@ bool AArch64InstructionSelector::selectIntrinsic(MachineInstr &I, .addImm(PACConstDiscC) .addUse(PACAddrDisc) .constrainAllUses(TII, TRI, RBI); - MIB.buildCopy({DstReg}, Register(AArch64::X16)); + MIB.buildCopy({DstReg}, Register(AArch64::X17)); RBI.constrainGenericRegister(DstReg, AArch64::GPR64RegClass, MRI); I.eraseFromParent(); @@ -6602,14 +6605,14 @@ bool AArch64InstructionSelector::selectIntrinsic(MachineInstr &I, std::tie(AUTConstDiscC, AUTAddrDisc) = extractPtrauthBlendDiscriminators(AUTDisc, MRI); - MIB.buildCopy({AArch64::X16}, {ValReg}); - MIB.buildInstr(TargetOpcode::IMPLICIT_DEF, {AArch64::X17}, {}); + MIB.buildCopy({AArch64::X17}, {ValReg}); + MIB.buildInstr(TargetOpcode::IMPLICIT_DEF, {AArch64::X16}, {}); MIB.buildInstr(AArch64::AUT) .addImm(AUTKey) .addImm(AUTConstDiscC) .addUse(AUTAddrDisc) .constrainAllUses(TII, TRI, RBI); - MIB.buildCopy({DstReg}, Register(AArch64::X16)); + MIB.buildCopy({DstReg}, Register(AArch64::X17)); RBI.constrainGenericRegister(DstReg, AArch64::GPR64RegClass, MRI); I.eraseFromParent(); @@ -6819,7 +6822,7 @@ bool AArch64InstructionSelector::selectPtrAuthGlobalValue( .addReg(HasAddrDisc ? AddrDisc : AArch64::XZR) .addImm(Disc) .constrainAllUses(TII, TRI, RBI); - MIB.buildCopy(DefReg, Register(AArch64::X16)); + MIB.buildCopy(DefReg, Register(AArch64::X17)); RBI.constrainGenericRegister(DefReg, AArch64::GPR64RegClass, MRI); I.eraseFromParent(); return true; diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp index 19bc841b10529b969aad27460eb1bfd44af97709..445edb19dd37b1f5f95423ab7e8c5d45c9b7b903 100644 --- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp +++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -2291,6 +2291,8 @@ bool DevirtModule::run() { // The rest of the code is only necessary when exporting or during regular // LTO, so we are done. + for (auto *CI : CallsWithPtrAuthBundleRemoved) + CI->eraseFromParent(); return true; } diff --git a/llvm/lib/Transforms/Utils/AddDiscriminators.cpp b/llvm/lib/Transforms/Utils/AddDiscriminators.cpp index f95d5e23c9c812cb720f8c32cf6088e50894108f..2739fe9d23d04d2fd96c89af6a689a4db3ea13af 100644 --- a/llvm/lib/Transforms/Utils/AddDiscriminators.cpp +++ b/llvm/lib/Transforms/Utils/AddDiscriminators.cpp @@ -247,3 +247,13 @@ PreservedAnalyses AddDiscriminatorsPass::run(Function &F, // FIXME: should be all() return PreservedAnalyses::none(); } + +static cl::opt PaccLimit( + "PACCLIMIT", cl::Hidden, + cl::desc("Use this option to configure the entry limit in the section of .cfi.modifier.ro"), + cl::init(-1) +); + +int llvm::getPaccLimit() { + return PaccLimit; +} \ No newline at end of file diff --git a/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp b/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp index 90dc727cde16d77cbf0d895b9e5f340f30b22d1e..ac20f76f67e48f3d9e12682db9b1ff86ea547c4b 100644 --- a/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp +++ b/llvm/lib/Transforms/Utils/CallPromotionUtils.cpp @@ -478,6 +478,20 @@ bool llvm::isLegalToPromote(const CallBase &CB, Function *Callee, return true; } +static CallBase *removeOperandBundlePtrauth(CallBase *CB) +{ + CallBase *CBNew = CallBase::removeOperandBundle(CB, LLVMContext::OB_ptrauth, CB->getIterator()); + if(CBNew == CB) + { + return CB; + } + CBNew->copyMetadata(*CB); + CB->replaceAllUsesWith(CBNew); + CB->eraseFromParent(); + return CBNew; +} + + CallBase &llvm::promoteCall(CallBase &CB, Function *Callee, CastInst **RetBitCast) { assert(!CB.getCalledFunction() && "Only indirect call sites can be promoted"); @@ -495,7 +509,9 @@ CallBase &llvm::promoteCall(CallBase &CB, Function *Callee, // If the function type of the call site matches that of the callee, no // additional work is required. if (CB.getFunctionType() == Callee->getFunctionType()) - return CB; + { + return *removeOperandBundlePtrauth(&CB); + } // Save the return types of the call site and callee. Type *CallSiteRetTy = CB.getType(); @@ -557,7 +573,7 @@ CallBase &llvm::promoteCall(CallBase &CB, Function *Callee, AttributeSet::get(Ctx, RAttrs), NewArgAttrs)); - return CB; + return *removeOperandBundlePtrauth(&CB); } CallBase &llvm::promoteCallWithIfThenElse(CallBase &CB, Function *Callee, diff --git a/llvm/lib/Transforms/Utils/Evaluator.cpp b/llvm/lib/Transforms/Utils/Evaluator.cpp index 23c1ca366a445c58c13fba66921117b0ea2d289a..7289636560cdeebab6e311e6095b877c35fcb40f 100644 --- a/llvm/lib/Transforms/Utils/Evaluator.cpp +++ b/llvm/lib/Transforms/Utils/Evaluator.cpp @@ -75,6 +75,11 @@ isSimpleEnoughValueToCommitHelper(Constant *C, return true; } + if (isa(C)) { + // do not know how to process + return false; + } + // We don't know exactly what relocations are allowed in constant expressions, // so we allow &global+constantoffset, which is safe and uniformly supported // across targets. diff --git a/llvm/lib/Transforms/Utils/ValueMapper.cpp b/llvm/lib/Transforms/Utils/ValueMapper.cpp index 1696e9c7267354e0b6f1067cbe81d5d3a2329da6..c749dd85eb1d4a384f54439e0b465a5bf8eb7c2b 100644 --- a/llvm/lib/Transforms/Utils/ValueMapper.cpp +++ b/llvm/lib/Transforms/Utils/ValueMapper.cpp @@ -516,6 +516,11 @@ Value *Mapper::mapValue(const Value *V) { if (auto *GEPO = dyn_cast(C)) NewSrcTy = TypeMapper->remapType(GEPO->getSourceElementType()); + + if (const auto *PAC = dyn_cast(C)) { + return getVM()[PAC] = ConstantPtrAuth::get(Ops[0], dyn_cast(Ops[1]), dyn_cast(Ops[2]), Ops[3]); + } + if (ConstantExpr *CE = dyn_cast(C)) return getVM()[V] = CE->getWithOperands(Ops, NewTy, false, NewSrcTy); if (isa(C)) diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll index 12a3448111fcb3e92876b3bf307565ba51355d59..41cf5ce04e976cee0efb1ab9c7d134d881421089 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll +++ b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll @@ -99,18 +99,18 @@ define ptr @foo() { define ptr @test_global_zero_disc() { ; ELF-LABEL: test_global_zero_disc: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: paciza x16 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: paciza x17 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_zero_disc: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: paciza x16 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: paciza x17 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 0) @@ -119,20 +119,20 @@ define ptr @test_global_zero_disc() { define ptr @test_global_offset_zero_disc() { ; ELF-LABEL: test_global_offset_zero_disc: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: add x16, x16, #16 -; ELF-NEXT: pacdza x16 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: add x17, x17, #16 +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_offset_zero_disc: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: add x16, x16, #16 -; MACHO-NEXT: pacdza x16 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: add x17, x17, #16 +; MACHO-NEXT: pacdza x17 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 16), i32 2) @@ -141,22 +141,22 @@ define ptr @test_global_offset_zero_disc() { define ptr @test_global_neg_offset_zero_disc() { ; ELF-LABEL: test_global_neg_offset_zero_disc: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: sub x16, x16, #576 -; ELF-NEXT: sub x16, x16, #30, lsl #12 -; ELF-NEXT: pacdza x16 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: sub x17, x17, #576 +; ELF-NEXT: sub x17, x17, #30, lsl #12 +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_neg_offset_zero_disc: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: sub x16, x16, #576 -; MACHO-NEXT: sub x16, x16, #30, lsl #12 -; MACHO-NEXT: pacdza x16 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: sub x17, x17, #576 +; MACHO-NEXT: sub x17, x17, #30, lsl #12 +; MACHO-NEXT: pacdza x17 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456), i32 2) @@ -165,24 +165,24 @@ define ptr @test_global_neg_offset_zero_disc() { define ptr @test_global_big_offset_zero_disc() { ; ELF-LABEL: test_global_big_offset_zero_disc: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: mov x17, #1 -; ELF-NEXT: movk x17, #32769, lsl #16 -; ELF-NEXT: add x16, x16, x17 -; ELF-NEXT: pacdza x16 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: mov x16, #1 +; ELF-NEXT: movk x16, #32769, lsl #16 +; ELF-NEXT: add x17, x17, x16 +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_big_offset_zero_disc: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: mov x17, #1 -; MACHO-NEXT: movk x17, #32769, lsl #16 -; MACHO-NEXT: add x16, x16, x17 -; MACHO-NEXT: pacdza x16 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x16, #1 +; MACHO-NEXT: movk x16, #32769, lsl #16 +; MACHO-NEXT: add x17, x17, x16 +; MACHO-NEXT: pacdza x17 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 add (i64 2147483648, i64 65537)), i32 2) @@ -191,24 +191,24 @@ define ptr @test_global_big_offset_zero_disc() { define ptr @test_global_big_neg_offset_zero_disc() { ; ELF-LABEL: test_global_big_neg_offset_zero_disc: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: mov x17, #-52501 -; ELF-NEXT: movk x17, #63652, lsl #16 -; ELF-NEXT: add x16, x16, x17 -; ELF-NEXT: pacdza x16 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: mov x16, #-52501 +; ELF-NEXT: movk x16, #63652, lsl #16 +; ELF-NEXT: add x17, x17, x16 +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_big_neg_offset_zero_disc: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: mov x17, #-52501 -; MACHO-NEXT: movk x17, #63652, lsl #16 -; MACHO-NEXT: add x16, x16, x17 -; MACHO-NEXT: pacdza x16 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x16, #-52501 +; MACHO-NEXT: movk x16, #63652, lsl #16 +; MACHO-NEXT: add x17, x17, x16 +; MACHO-NEXT: pacdza x17 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456789), i32 2) @@ -217,28 +217,28 @@ define ptr @test_global_big_neg_offset_zero_disc() { define ptr @test_global_huge_neg_offset_zero_disc() { ; ELF-LABEL: test_global_huge_neg_offset_zero_disc: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: mov x17, #-65536 -; ELF-NEXT: movk x17, #0, lsl #16 -; ELF-NEXT: movk x17, #0, lsl #32 -; ELF-NEXT: movk x17, #32768, lsl #48 -; ELF-NEXT: add x16, x16, x17 -; ELF-NEXT: pacdza x16 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: mov x16, #-65536 +; ELF-NEXT: movk x16, #0, lsl #16 +; ELF-NEXT: movk x16, #0, lsl #32 +; ELF-NEXT: movk x16, #32768, lsl #48 +; ELF-NEXT: add x17, x17, x16 +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_huge_neg_offset_zero_disc: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: mov x17, #-65536 -; MACHO-NEXT: movk x17, #0, lsl #16 -; MACHO-NEXT: movk x17, #0, lsl #32 -; MACHO-NEXT: movk x17, #32768, lsl #48 -; MACHO-NEXT: add x16, x16, x17 -; MACHO-NEXT: pacdza x16 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x16, #-65536 +; MACHO-NEXT: movk x16, #0, lsl #16 +; MACHO-NEXT: movk x16, #0, lsl #32 +; MACHO-NEXT: movk x16, #32768, lsl #48 +; MACHO-NEXT: add x17, x17, x16 +; MACHO-NEXT: pacdza x17 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -9223372036854775808), i32 2) @@ -247,20 +247,20 @@ define ptr @test_global_huge_neg_offset_zero_disc() { define ptr @test_global_disc() { ; ELF-LABEL: test_global_disc: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: mov x17, #42 // =0x2a -; ELF-NEXT: pacia x16, x17 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: mov x16, #42 // =0x2a +; ELF-NEXT: pacia x17, x16 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_disc: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: mov x17, #42 ; =0x2a -; MACHO-NEXT: pacia x16, x17 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x16, #42 ; =0x2a +; MACHO-NEXT: pacia x17, x16 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 0, i64 42) @@ -273,12 +273,12 @@ define ptr @test_global_addr_disc() { ; ELF: // %bb.0: ; ELF-NEXT: adrp x8, g.ref.da.42.addr ; ELF-NEXT: add x8, x8, :lo12:g.ref.da.42.addr -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: mov x17, x8 -; ELF-NEXT: movk x17, #42, lsl #48 -; ELF-NEXT: pacda x16, x17 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: mov x16, x8 +; ELF-NEXT: movk x16, #42, lsl #48 +; ELF-NEXT: pacda x17, x16 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_addr_disc: @@ -287,12 +287,12 @@ define ptr @test_global_addr_disc() { ; MACHO-NEXT: adrp x8, _g.ref.da.42.addr@PAGE ; MACHO-NEXT: Lloh{{.*}}: ; MACHO-NEXT: add x8, x8, _g.ref.da.42.addr@PAGEOFF -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: mov x17, x8 -; MACHO-NEXT: movk x17, #42, lsl #48 -; MACHO-NEXT: pacda x16, x17 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x16, x8 +; MACHO-NEXT: movk x16, #42, lsl #48 +; MACHO-NEXT: pacda x17, x16 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 2, i64 42, ptr @g.ref.da.42.addr) @@ -301,18 +301,18 @@ define ptr @test_global_addr_disc() { define ptr @test_global_process_specific() { ; ELF-LABEL: test_global_process_specific: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: pacizb x16 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: pacizb x17 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_process_specific: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: pacizb x16 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: pacizb x17 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 1) @@ -323,18 +323,18 @@ define ptr @test_global_process_specific() { define ptr @test_global_strong_def() { ; ELF-LABEL: test_global_strong_def: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, g_strong_def -; ELF-NEXT: add x16, x16, :lo12:g_strong_def -; ELF-NEXT: pacdza x16 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, g_strong_def +; ELF-NEXT: add x17, x17, :lo12:g_strong_def +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_strong_def: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g_strong_def@PAGE -; MACHO-NEXT: add x16, x16, _g_strong_def@PAGEOFF -; MACHO-NEXT: pacdza x16 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g_strong_def@PAGE +; MACHO-NEXT: add x17, x17, _g_strong_def@PAGEOFF +; MACHO-NEXT: pacdza x17 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr @g_strong_def, i32 2) diff --git a/llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll new file mode 100644 index 0000000000000000000000000000000000000000..9e9ac8463099b055589ce09c5208b94201453d2c --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-basic-pic.ll @@ -0,0 +1,133 @@ +; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=0 -verify-machineinstrs \ +; RUN: -relocation-model=pic -mattr=+pauth -mattr=+fpac %s -o - | FileCheck %s --check-prefixes=CHECK,NOTRAP +; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=0 -verify-machineinstrs \ +; RUN: -relocation-model=pic -mattr=+pauth %s -o - | FileCheck %s --check-prefixes=CHECK,TRAP + +; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=1 -verify-machineinstrs \ +; RUN: -relocation-model=pic -mattr=+pauth -mattr=+fpac %s -o - | FileCheck %s --check-prefixes=CHECK,NOTRAP +; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=1 -verify-machineinstrs \ +; RUN: -relocation-model=pic -mattr=+pauth %s -o - | FileCheck %s --check-prefixes=CHECK,TRAP + +; RUN-NOT: llc -mtriple=aarch64-linux-gnu -global-isel=1 -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -relocation-model=pic -mattr=+pauth -mattr=+fpac %s -o - | FileCheck %s --check-prefixes=CHECK,NOTRAP +; RUN-NOT: llc -mtriple=aarch64-linux-gnu -global-isel=1 -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -relocation-model=pic -mattr=+pauth %s -o - | FileCheck %s --check-prefixes=CHECK,TRAP + +;; Note: for FastISel, we fall back to SelectionDAG + +@var = global i32 0 + +define i32 @get_globalvar() { +; CHECK-LABEL: get_globalvar: +; CHECK: adrp x17, :got_auth:var +; CHECK-NEXT: add x17, x17, :got_auth_lo12:var +; NOTRAP-NEXT: ldr x8, [x17] +; NOTRAP-NEXT: autda x8, x17 +; TRAP-NEXT: ldr x16, [x17] +; TRAP-NEXT: autda x16, x17 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq .Lauth_success_0 +; TRAP-NEXT: brk #0xc472 +; TRAP-NEXT: .Lauth_success_0: +; TRAP-NEXT: mov x8, x16 +; CHECK-NEXT: ldr w0, [x8] +; CHECK-NEXT: ret + + %val = load i32, ptr @var + ret i32 %val +} + +define ptr @get_globalvaraddr() { +; CHECK-LABEL: get_globalvaraddr: +; CHECK: adrp x17, :got_auth:var +; CHECK-NEXT: add x17, x17, :got_auth_lo12:var +; NOTRAP-NEXT: ldr x0, [x17] +; NOTRAP-NEXT: autda x0, x17 +; TRAP-NEXT: ldr x16, [x17] +; TRAP-NEXT: autda x16, x17 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq .Lauth_success_1 +; TRAP-NEXT: brk #0xc472 +; TRAP-NEXT: .Lauth_success_1: +; TRAP-NEXT: mov x0, x16 +; CHECK-NEXT: ret + + %val = load i32, ptr @var + ret ptr @var +} + +declare i32 @foo() + +define ptr @resign_globalfunc() { +; CHECK-LABEL: resign_globalfunc: +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: // %bb.0: +; CHECK: adrp x16, :got_auth:foo +; CHECK-NEXT: add x16, x16, :got_auth_lo12:foo +; CHECK-NEXT: ldr x17, [x16] +; CHECK-NEXT: autia x17, x16 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpaci x16 +; TRAP-NEXT: cmp x17, x16 +; TRAP-NEXT: b.eq .Lauth_success_2 +; TRAP-NEXT: brk #0xc470 +; TRAP-NEXT: .Lauth_success_2: +; CHECK-NEXT: mov x16, #42 +; CHECK-NEXT: pacia x17, x16 +; CHECK-NEXT: mov x0, x17 +; CHECK-NEXT: ret + + ret ptr ptrauth (ptr @foo, i32 0, i64 42) +} + +define ptr @resign_globalvar() { +; CHECK-LABEL: resign_globalvar: +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: // %bb.0: +; CHECK: adrp x16, :got_auth:var +; CHECK-NEXT: add x16, x16, :got_auth_lo12:var +; CHECK-NEXT: ldr x17, [x16] +; CHECK-NEXT: autda x17, x16 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpacd x16 +; TRAP-NEXT: cmp x17, x16 +; TRAP-NEXT: b.eq .Lauth_success_3 +; TRAP-NEXT: brk #0xc472 +; TRAP-NEXT: .Lauth_success_3: +; CHECK-NEXT: mov x16, #43 +; CHECK-NEXT: pacdb x17, x16 +; CHECK-NEXT: mov x0, x17 +; CHECK-NEXT: ret + + ret ptr ptrauth (ptr @var, i32 3, i64 43) +} + +define ptr @resign_globalvar_offset() { +; CHECK-LABEL: resign_globalvar_offset: +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: // %bb.0: +; CHECK: adrp x16, :got_auth:var +; CHECK-NEXT: add x16, x16, :got_auth_lo12:var +; CHECK-NEXT: ldr x17, [x16] +; CHECK-NEXT: autda x17, x16 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpacd x16 +; TRAP-NEXT: cmp x17, x16 +; TRAP-NEXT: b.eq .Lauth_success_4 +; TRAP-NEXT: brk #0xc472 +; TRAP-NEXT: .Lauth_success_4: +; CHECK-NEXT: add x17, x17, #16 +; CHECK-NEXT: mov x16, #44 +; CHECK-NEXT: pacda x17, x16 +; CHECK-NEXT: mov x0, x17 +; CHECK-NEXT: ret + + ret ptr ptrauth (ptr getelementptr (i8, ptr @var, i64 16), i32 2, i64 44) +} + +!llvm.module.flags = !{!0} +!0 = !{i32 8, !"ptrauth-elf-got", i32 1} diff --git a/llvm/test/CodeGen/AArch64/ptrauth-bti-call.ll b/llvm/test/CodeGen/AArch64/ptrauth-bti-call.ll index 0356a46ec105004db82d3d6cb8c6ed1357682196..59cdd6aa5997c40576227349b1f8002effd7444e 100644 --- a/llvm/test/CodeGen/AArch64/ptrauth-bti-call.ll +++ b/llvm/test/CodeGen/AArch64/ptrauth-bti-call.ll @@ -1,13 +1,13 @@ -; RUN: llc -mtriple arm64e-apple-darwin -mattr=+bti -asm-verbose=false \ -; RUN: -o - %s | FileCheck %s --check-prefixes=DARWIN,CHECK -; RUN: llc -mtriple arm64e-apple-darwin -mattr=+bti -global-isel -asm-verbose=false \ -; RUN: -o - %s | FileCheck %s --check-prefixes=DARWIN,CHECK -; RUN: llc -mtriple arm64e-apple-darwin -mattr=+bti -fast-isel -asm-verbose=false \ -; RUN: -o - %s | FileCheck %s --check-prefixes=DARWIN,CHECK +; RUN-NOT: llc -mtriple arm64e-apple-darwin -mattr=+bti -asm-verbose=false \ +; RUN-NOT: -o - %s | FileCheck %s --check-prefixes=DARWIN,CHECK +; RUN-NOT: llc -mtriple arm64e-apple-darwin -mattr=+bti -global-isel -asm-verbose=false \ +; RUN-NOT: -o - %s | FileCheck %s --check-prefixes=DARWIN,CHECK +; RUN-NOT: llc -mtriple arm64e-apple-darwin -mattr=+bti -fast-isel -asm-verbose=false \ +; RUN-NOT: -o - %s | FileCheck %s --check-prefixes=DARWIN,CHECK ; RUN: llc -mtriple aarch64-linux-gnu -mattr=+bti -mattr=+pauth -asm-verbose=false \ ; RUN: -o - %s | FileCheck %s --check-prefixes=ELF,CHECK -; RUN: llc -mtriple aarch64-linux-gnu -mattr=+bti -mattr=+pauth -global-isel -asm-verbose=false \ -; RUN: -o - %s | FileCheck %s --check-prefixes=ELF,CHECK +; RUN-NOT: llc -mtriple aarch64-linux-gnu -mattr=+bti -mattr=+pauth -global-isel -asm-verbose=false \ +; RUN-NOT: -o - %s | FileCheck %s --check-prefixes=ELF,CHECK ; RUN: llc -mtriple aarch64-linux-gnu -mattr=+bti -mattr=+pauth -fast-isel -asm-verbose=false \ ; RUN: -o - %s | FileCheck %s --check-prefixes=ELF,CHECK diff --git a/llvm/test/CodeGen/AArch64/ptrauth-call.ll b/llvm/test/CodeGen/AArch64/ptrauth-call.ll index 9f211b6e1796e648b6bd975ab4a4e92280a5379b..1f0d21518b963386137031223bc4878ffcb98193 100644 --- a/llvm/test/CodeGen/AArch64/ptrauth-call.ll +++ b/llvm/test/CodeGen/AArch64/ptrauth-call.ll @@ -1,12 +1,12 @@ -; RUN: llc -mtriple arm64e-apple-darwin -o - %s -asm-verbose=0 \ -; RUN: | FileCheck %s --check-prefixes=CHECK,DARWIN +; RUN-NOT: llc -mtriple arm64e-apple-darwin -o - %s -asm-verbose=0 \ +; RUN-NOT: | FileCheck %s --check-prefixes=CHECK,DARWIN ; RUN: llc -mtriple aarch64 -mattr=+pauth -o - %s -asm-verbose=0 \ ; RUN: | FileCheck %s --check-prefixes=CHECK,ELF -; RUN: llc -mtriple arm64e-apple-darwin -o - %s -asm-verbose=0 \ -; RUN: -global-isel -global-isel-abort=1 -verify-machineinstrs \ -; RUN: | FileCheck %s --check-prefixes=CHECK,DARWIN +; RUN-NOT: llc -mtriple arm64e-apple-darwin -o - %s -asm-verbose=0 \ +; RUN-NOT: -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: | FileCheck %s --check-prefixes=CHECK,DARWIN ; RUN: llc -mtriple aarch64 -mattr=+pauth -o - %s -asm-verbose=0 \ ; RUN: -global-isel -global-isel-abort=1 -verify-machineinstrs \ @@ -167,6 +167,54 @@ define i32 @test_tailcall_ib_var(ptr %arg0, ptr %arg1) #0 { ret i32 %tmp1 } +define void @test_tailcall_omit_mov_x16_x16(ptr %objptr) #0 { +; CHECK-LABEL: test_tailcall_omit_mov_x16_x16: +; CHECK-NEXT: ldr x17, [x0] +; CHECK-NEXT: mov x16, x0 +; CHECK-NEXT: movk x16, #6503, lsl #48 +; CHECK-NEXT: autda x17, x16 +; CHECK-NEXT: ldr x1, [x17] +; CHECK-NEXT: movk x17, #54167, lsl #48 +; CHECK-NEXT: braa x1, x17 + %vtable.signed = load ptr, ptr %objptr, align 8 + %objptr.int = ptrtoint ptr %objptr to i64 + %vtable.discr = tail call i64 @llvm.ptrauth.blend(i64 %objptr.int, i64 6503) + %vtable.signed.int = ptrtoint ptr %vtable.signed to i64 + %vtable.unsigned.int = tail call i64 @llvm.ptrauth.auth(i64 %vtable.signed.int, i32 2, i64 %vtable.discr) + %vtable.unsigned = inttoptr i64 %vtable.unsigned.int to ptr + %virt.func.signed = load ptr, ptr %vtable.unsigned, align 8 + %virt.func.discr = tail call i64 @llvm.ptrauth.blend(i64 %vtable.unsigned.int, i64 54167) + tail call void %virt.func.signed(ptr %objptr) [ "ptrauth"(i32 0, i64 %virt.func.discr) ] + ret void +} + +define i32 @test_call_omit_extra_moves(ptr %objptr) #0 { +; CHECK-LABEL: test_call_omit_extra_moves: +; DARWIN-NEXT: stp x29, x30, [sp, #-16]! +; ELF-NEXT: str x30, [sp, #-16]! +; CHECK-NEXT: ldr x17, [x0] +; CHECK-NEXT: mov x16, x0 +; CHECK-NEXT: movk x16, #6503, lsl #48 +; CHECK-NEXT: autda x17, x16 +; CHECK-NEXT: ldr x8, [x17] +; CHECK-NEXT: movk x17, #34646, lsl #48 +; CHECK-NEXT: blraa x8, x17 +; CHECK-NEXT: mov w0, #42 +; DARWIN-NEXT: ldp x29, x30, [sp], #16 +; ELF-NEXT: ldr x30, [sp], #16 +; CHECK-NEXT: ret + %vtable.signed = load ptr, ptr %objptr + %objptr.int = ptrtoint ptr %objptr to i64 + %vtable.discr = tail call i64 @llvm.ptrauth.blend(i64 %objptr.int, i64 6503) + %vtable.signed.int = ptrtoint ptr %vtable.signed to i64 + %vtable.int = tail call i64 @llvm.ptrauth.auth(i64 %vtable.signed.int, i32 2, i64 %vtable.discr) + %vtable = inttoptr i64 %vtable.int to ptr + %callee.signed = load ptr, ptr %vtable + %callee.discr = tail call i64 @llvm.ptrauth.blend(i64 %vtable.int, i64 34646) + %call.result = tail call i32 %callee.signed(ptr %objptr) [ "ptrauth"(i32 0, i64 %callee.discr) ] + ret i32 42 +} + define i32 @test_call_ia_arg(ptr %arg0, i64 %arg1) #0 { ; DARWIN-LABEL: test_call_ia_arg: ; DARWIN-NEXT: stp x29, x30, [sp, #-16]! @@ -312,11 +360,11 @@ define i32 @test_direct_call_mismatch() #0 { ; ; ELF-LABEL: test_direct_call_mismatch: ; ELF-NEXT: str x30, [sp, #-16]! -; ELF-NEXT: adrp x16, :got:f -; ELF-NEXT: ldr x16, [x16, :got_lo12:f] -; ELF-NEXT: mov x17, #42 -; ELF-NEXT: pacia x16, x17 -; ELF-NEXT: mov x8, x16 +; ELF-NEXT: adrp x17, :got:f +; ELF-NEXT: ldr x17, [x17, :got_lo12:f] +; ELF-NEXT: mov x16, #42 +; ELF-NEXT: pacia x17, x16 +; ELF-NEXT: mov x8, x17 ; ELF-NEXT: mov x17, #42 ; ELF-NEXT: blrab x8, x17 ; ELF-NEXT: ldr x30, [sp], #16 diff --git a/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll b/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll index 76339a7cc57917345ecb0ba3c01654c0823f495a..8750936a3528bea157e65963a0ab4e05c8ca4f15 100644 --- a/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll +++ b/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll @@ -88,18 +88,18 @@ define ptr @foo() { define ptr @test_global_zero_disc() { ; ELF-LABEL: test_global_zero_disc: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: paciza x16 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: paciza x17 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_zero_disc: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: paciza x16 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: paciza x17 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 0) @@ -108,20 +108,20 @@ define ptr @test_global_zero_disc() { define ptr @test_global_offset_zero_disc() { ; ELF-LABEL: test_global_offset_zero_disc: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: add x16, x16, #16 -; ELF-NEXT: pacdza x16 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: add x17, x17, #16 +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_offset_zero_disc: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: add x16, x16, #16 -; MACHO-NEXT: pacdza x16 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: add x17, x17, #16 +; MACHO-NEXT: pacdza x17 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 16), i32 2) @@ -130,22 +130,22 @@ define ptr @test_global_offset_zero_disc() { define ptr @test_global_neg_offset_zero_disc() { ; ELF-LABEL: test_global_neg_offset_zero_disc: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: sub x16, x16, #576 -; ELF-NEXT: sub x16, x16, #30, lsl #12 -; ELF-NEXT: pacdza x16 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: sub x17, x17, #576 +; ELF-NEXT: sub x17, x17, #30, lsl #12 +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_neg_offset_zero_disc: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: sub x16, x16, #576 -; MACHO-NEXT: sub x16, x16, #30, lsl #12 -; MACHO-NEXT: pacdza x16 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: sub x17, x17, #576 +; MACHO-NEXT: sub x17, x17, #30, lsl #12 +; MACHO-NEXT: pacdza x17 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456), i32 2) @@ -154,24 +154,24 @@ define ptr @test_global_neg_offset_zero_disc() { define ptr @test_global_big_offset_zero_disc() { ; ELF-LABEL: test_global_big_offset_zero_disc: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: mov x17, #1 -; ELF-NEXT: movk x17, #32769, lsl #16 -; ELF-NEXT: add x16, x16, x17 -; ELF-NEXT: pacdza x16 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: mov x16, #1 +; ELF-NEXT: movk x16, #32769, lsl #16 +; ELF-NEXT: add x17, x17, x16 +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_big_offset_zero_disc: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: mov x17, #1 -; MACHO-NEXT: movk x17, #32769, lsl #16 -; MACHO-NEXT: add x16, x16, x17 -; MACHO-NEXT: pacdza x16 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x16, #1 +; MACHO-NEXT: movk x16, #32769, lsl #16 +; MACHO-NEXT: add x17, x17, x16 +; MACHO-NEXT: pacdza x17 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 add (i64 2147483648, i64 65537)), i32 2) @@ -180,24 +180,24 @@ define ptr @test_global_big_offset_zero_disc() { define ptr @test_global_big_neg_offset_zero_disc() { ; ELF-LABEL: test_global_big_neg_offset_zero_disc: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: mov x17, #-52501 -; ELF-NEXT: movk x17, #63652, lsl #16 -; ELF-NEXT: add x16, x16, x17 -; ELF-NEXT: pacdza x16 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: mov x16, #-52501 +; ELF-NEXT: movk x16, #63652, lsl #16 +; ELF-NEXT: add x17, x17, x16 +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_big_neg_offset_zero_disc: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: mov x17, #-52501 -; MACHO-NEXT: movk x17, #63652, lsl #16 -; MACHO-NEXT: add x16, x16, x17 -; MACHO-NEXT: pacdza x16 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x16, #-52501 +; MACHO-NEXT: movk x16, #63652, lsl #16 +; MACHO-NEXT: add x17, x17, x16 +; MACHO-NEXT: pacdza x17 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456789), i32 2) @@ -206,28 +206,28 @@ define ptr @test_global_big_neg_offset_zero_disc() { define ptr @test_global_huge_neg_offset_zero_disc() { ; ELF-LABEL: test_global_huge_neg_offset_zero_disc: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: mov x17, #-65536 -; ELF-NEXT: movk x17, #0, lsl #16 -; ELF-NEXT: movk x17, #0, lsl #32 -; ELF-NEXT: movk x17, #32768, lsl #48 -; ELF-NEXT: add x16, x16, x17 -; ELF-NEXT: pacdza x16 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: mov x16, #-65536 +; ELF-NEXT: movk x16, #0, lsl #16 +; ELF-NEXT: movk x16, #0, lsl #32 +; ELF-NEXT: movk x16, #32768, lsl #48 +; ELF-NEXT: add x17, x17, x16 +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_huge_neg_offset_zero_disc: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: mov x17, #-65536 -; MACHO-NEXT: movk x17, #0, lsl #16 -; MACHO-NEXT: movk x17, #0, lsl #32 -; MACHO-NEXT: movk x17, #32768, lsl #48 -; MACHO-NEXT: add x16, x16, x17 -; MACHO-NEXT: pacdza x16 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x16, #-65536 +; MACHO-NEXT: movk x16, #0, lsl #16 +; MACHO-NEXT: movk x16, #0, lsl #32 +; MACHO-NEXT: movk x16, #32768, lsl #48 +; MACHO-NEXT: add x17, x17, x16 +; MACHO-NEXT: pacdza x17 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -9223372036854775808), i32 2) @@ -236,20 +236,20 @@ define ptr @test_global_huge_neg_offset_zero_disc() { define ptr @test_global_disc() { ; ELF-LABEL: test_global_disc: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: mov x17, #42 // =0x2a -; ELF-NEXT: pacia x16, x17 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: mov x16, #42 // =0x2a +; ELF-NEXT: pacia x17, x16 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_disc: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: mov x17, #42 ; =0x2a -; MACHO-NEXT: pacia x16, x17 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x16, #42 ; =0x2a +; MACHO-NEXT: pacia x17, x16 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 0, i64 42) @@ -262,12 +262,12 @@ define ptr @test_global_addr_disc() { ; ELF: // %bb.0: ; ELF-NEXT: adrp x8, g.ref.da.42.addr ; ELF-NEXT: add x8, x8, :lo12:g.ref.da.42.addr -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: mov x17, x8 -; ELF-NEXT: movk x17, #42, lsl #48 -; ELF-NEXT: pacda x16, x17 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: mov x16, x8 +; ELF-NEXT: movk x16, #42, lsl #48 +; ELF-NEXT: pacda x17, x16 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_addr_disc: @@ -276,12 +276,12 @@ define ptr @test_global_addr_disc() { ; MACHO-NEXT: adrp x8, _g.ref.da.42.addr@PAGE ; MACHO-NEXT: Lloh{{.*}}: ; MACHO-NEXT: add x8, x8, _g.ref.da.42.addr@PAGEOFF -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: mov x17, x8 -; MACHO-NEXT: movk x17, #42, lsl #48 -; MACHO-NEXT: pacda x16, x17 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: mov x16, x8 +; MACHO-NEXT: movk x16, #42, lsl #48 +; MACHO-NEXT: pacda x17, x16 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 2, i64 42, ptr @g.ref.da.42.addr) @@ -290,18 +290,18 @@ define ptr @test_global_addr_disc() { define ptr @test_global_process_specific() { ; ELF-LABEL: test_global_process_specific: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, :got:g -; ELF-NEXT: ldr x16, [x16, :got_lo12:g] -; ELF-NEXT: pacizb x16 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: pacizb x17 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_process_specific: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g@GOTPAGE -; MACHO-NEXT: ldr x16, [x16, _g@GOTPAGEOFF] -; MACHO-NEXT: pacizb x16 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g@GOTPAGE +; MACHO-NEXT: ldr x17, [x17, _g@GOTPAGEOFF] +; MACHO-NEXT: pacizb x17 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr @g, i32 1) @@ -312,18 +312,18 @@ define ptr @test_global_process_specific() { define ptr @test_global_strong_def() { ; ELF-LABEL: test_global_strong_def: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, g_strong_def -; ELF-NEXT: add x16, x16, :lo12:g_strong_def -; ELF-NEXT: pacdza x16 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, g_strong_def +; ELF-NEXT: add x17, x17, :lo12:g_strong_def +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ; MACHO-LABEL: _test_global_strong_def: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, _g_strong_def@PAGE -; MACHO-NEXT: add x16, x16, _g_strong_def@PAGEOFF -; MACHO-NEXT: pacdza x16 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, _g_strong_def@PAGE +; MACHO-NEXT: add x17, x17, _g_strong_def@PAGEOFF +; MACHO-NEXT: pacdza x17 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ret ptr ptrauth (ptr @g_strong_def, i32 2) diff --git a/llvm/test/CodeGen/AArch64/ptrauth-fpac.ll b/llvm/test/CodeGen/AArch64/ptrauth-fpac.ll index d5340dcebad5758969a4a57a66422c2bed376535..c5157a3231a62bfee53475f3a4b0197dc5a11a0b 100644 --- a/llvm/test/CodeGen/AArch64/ptrauth-fpac.ll +++ b/llvm/test/CodeGen/AArch64/ptrauth-fpac.ll @@ -9,9 +9,9 @@ target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" define i64 @test_auth_ia(i64 %arg, i64 %arg1) { ; ALL-LABEL: test_auth_ia: ; ALL: %bb.0: -; ALL-NEXT: mov x16, x0 -; ALL-NEXT: autia x16, x1 -; ALL-NEXT: mov x0, x16 +; ALL-NEXT: mov x17, x0 +; ALL-NEXT: autia x17, x1 +; ALL-NEXT: mov x0, x17 ; ALL-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 %arg1) ret i64 %tmp @@ -20,9 +20,9 @@ define i64 @test_auth_ia(i64 %arg, i64 %arg1) { define i64 @test_auth_ia_zero(i64 %arg) { ; ALL-LABEL: test_auth_ia_zero: ; ALL: %bb.0: -; ALL-NEXT: mov x16, x0 -; ALL-NEXT: autiza x16 -; ALL-NEXT: mov x0, x16 +; ALL-NEXT: mov x17, x0 +; ALL-NEXT: autiza x17 +; ALL-NEXT: mov x0, x17 ; ALL-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 0) ret i64 %tmp @@ -31,9 +31,9 @@ define i64 @test_auth_ia_zero(i64 %arg) { define i64 @test_auth_ib(i64 %arg, i64 %arg1) { ; ALL-LABEL: test_auth_ib: ; ALL: %bb.0: -; ALL-NEXT: mov x16, x0 -; ALL-NEXT: autib x16, x1 -; ALL-NEXT: mov x0, x16 +; ALL-NEXT: mov x17, x0 +; ALL-NEXT: autib x17, x1 +; ALL-NEXT: mov x0, x17 ; ALL-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 1, i64 %arg1) ret i64 %tmp @@ -42,9 +42,9 @@ define i64 @test_auth_ib(i64 %arg, i64 %arg1) { define i64 @test_auth_ib_zero(i64 %arg) { ; ALL-LABEL: test_auth_ib_zero: ; ALL: %bb.0: -; ALL-NEXT: mov x16, x0 -; ALL-NEXT: autizb x16 -; ALL-NEXT: mov x0, x16 +; ALL-NEXT: mov x17, x0 +; ALL-NEXT: autizb x17 +; ALL-NEXT: mov x0, x17 ; ALL-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 1, i64 0) ret i64 %tmp @@ -53,9 +53,9 @@ define i64 @test_auth_ib_zero(i64 %arg) { define i64 @test_auth_da(i64 %arg, i64 %arg1) { ; ALL-LABEL: test_auth_da: ; ALL: %bb.0: -; ALL-NEXT: mov x16, x0 -; ALL-NEXT: autda x16, x1 -; ALL-NEXT: mov x0, x16 +; ALL-NEXT: mov x17, x0 +; ALL-NEXT: autda x17, x1 +; ALL-NEXT: mov x0, x17 ; ALL-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 2, i64 %arg1) ret i64 %tmp @@ -64,9 +64,9 @@ define i64 @test_auth_da(i64 %arg, i64 %arg1) { define i64 @test_auth_da_zero(i64 %arg) { ; ALL-LABEL: test_auth_da_zero: ; ALL: %bb.0: -; ALL-NEXT: mov x16, x0 -; ALL-NEXT: autdza x16 -; ALL-NEXT: mov x0, x16 +; ALL-NEXT: mov x17, x0 +; ALL-NEXT: autdza x17 +; ALL-NEXT: mov x0, x17 ; ALL-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 2, i64 0) ret i64 %tmp @@ -75,9 +75,9 @@ define i64 @test_auth_da_zero(i64 %arg) { define i64 @test_auth_db(i64 %arg, i64 %arg1) { ; ALL-LABEL: test_auth_db: ; ALL: %bb.0: -; ALL-NEXT: mov x16, x0 -; ALL-NEXT: autdb x16, x1 -; ALL-NEXT: mov x0, x16 +; ALL-NEXT: mov x17, x0 +; ALL-NEXT: autdb x17, x1 +; ALL-NEXT: mov x0, x17 ; ALL-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 3, i64 %arg1) ret i64 %tmp @@ -86,9 +86,9 @@ define i64 @test_auth_db(i64 %arg, i64 %arg1) { define i64 @test_auth_db_zero(i64 %arg) { ; ALL-LABEL: test_auth_db_zero: ; ALL: %bb.0: -; ALL-NEXT: mov x16, x0 -; ALL-NEXT: autdzb x16 -; ALL-NEXT: mov x0, x16 +; ALL-NEXT: mov x17, x0 +; ALL-NEXT: autdzb x17 +; ALL-NEXT: mov x0, x17 ; ALL-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 3, i64 0) ret i64 %tmp @@ -99,26 +99,26 @@ define i64 @test_auth_db_zero(i64 %arg) { define i64 @test_resign_ia_ia(i64 %arg, i64 %arg1, i64 %arg2) { ; NOFPAC-LABEL: test_resign_ia_ia: ; NOFPAC: %bb.0: -; NOFPAC-NEXT: mov x16, x0 -; NOFPAC-NEXT: autia x16, x1 -; NOFPAC-NEXT: mov x17, x16 -; NOFPAC-NEXT: xpaci x17 +; NOFPAC-NEXT: mov x17, x0 +; NOFPAC-NEXT: autia x17, x1 +; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: xpaci x16 ; NOFPAC-NEXT: cmp x16, x17 ; NOFPAC-NEXT: b.eq [[L]]auth_success_0 -; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: mov x17, x16 ; NOFPAC-NEXT: b [[L]]resign_end_0 ; NOFPAC-NEXT: Lauth_success_0: -; NOFPAC-NEXT: pacia x16, x2 +; NOFPAC-NEXT: pacia x17, x2 ; NOFPAC-NEXT: Lresign_end_0: -; NOFPAC-NEXT: mov x0, x16 +; NOFPAC-NEXT: mov x0, x17 ; NOFPAC-NEXT: ret ; ; FPAC-LABEL: test_resign_ia_ia: ; FPAC: %bb.0: -; FPAC-NEXT: mov x16, x0 -; FPAC-NEXT: autia x16, x1 -; FPAC-NEXT: pacia x16, x2 -; FPAC-NEXT: mov x0, x16 +; FPAC-NEXT: mov x17, x0 +; FPAC-NEXT: autia x17, x1 +; FPAC-NEXT: pacia x17, x2 +; FPAC-NEXT: mov x0, x17 ; FPAC-NEXT: ret %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 0, i64 %arg1, i32 0, i64 %arg2) ret i64 %tmp @@ -127,26 +127,26 @@ define i64 @test_resign_ia_ia(i64 %arg, i64 %arg1, i64 %arg2) { define i64 @test_resign_ib_ia(i64 %arg, i64 %arg1, i64 %arg2) { ; NOFPAC-LABEL: test_resign_ib_ia: ; NOFPAC: %bb.0: -; NOFPAC-NEXT: mov x16, x0 -; NOFPAC-NEXT: autib x16, x1 -; NOFPAC-NEXT: mov x17, x16 -; NOFPAC-NEXT: xpaci x17 +; NOFPAC-NEXT: mov x17, x0 +; NOFPAC-NEXT: autib x17, x1 +; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: xpaci x16 ; NOFPAC-NEXT: cmp x16, x17 ; NOFPAC-NEXT: b.eq [[L]]auth_success_1 -; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: mov x17, x16 ; NOFPAC-NEXT: b [[L]]resign_end_1 ; NOFPAC-NEXT: Lauth_success_1: -; NOFPAC-NEXT: pacia x16, x2 +; NOFPAC-NEXT: pacia x17, x2 ; NOFPAC-NEXT: Lresign_end_1: -; NOFPAC-NEXT: mov x0, x16 +; NOFPAC-NEXT: mov x0, x17 ; NOFPAC-NEXT: ret ; ; FPAC-LABEL: test_resign_ib_ia: ; FPAC: %bb.0: -; FPAC-NEXT: mov x16, x0 -; FPAC-NEXT: autib x16, x1 -; FPAC-NEXT: pacia x16, x2 -; FPAC-NEXT: mov x0, x16 +; FPAC-NEXT: mov x17, x0 +; FPAC-NEXT: autib x17, x1 +; FPAC-NEXT: pacia x17, x2 +; FPAC-NEXT: mov x0, x17 ; FPAC-NEXT: ret %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 1, i64 %arg1, i32 0, i64 %arg2) ret i64 %tmp @@ -155,26 +155,26 @@ define i64 @test_resign_ib_ia(i64 %arg, i64 %arg1, i64 %arg2) { define i64 @test_resign_da_ia(i64 %arg, i64 %arg1, i64 %arg2) { ; NOFPAC-LABEL: test_resign_da_ia: ; NOFPAC: %bb.0: -; NOFPAC-NEXT: mov x16, x0 -; NOFPAC-NEXT: autda x16, x1 -; NOFPAC-NEXT: mov x17, x16 -; NOFPAC-NEXT: xpacd x17 +; NOFPAC-NEXT: mov x17, x0 +; NOFPAC-NEXT: autda x17, x1 +; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: xpacd x16 ; NOFPAC-NEXT: cmp x16, x17 ; NOFPAC-NEXT: b.eq [[L]]auth_success_2 -; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: mov x17, x16 ; NOFPAC-NEXT: b [[L]]resign_end_2 ; NOFPAC-NEXT: Lauth_success_2: -; NOFPAC-NEXT: pacia x16, x2 +; NOFPAC-NEXT: pacia x17, x2 ; NOFPAC-NEXT: Lresign_end_2: -; NOFPAC-NEXT: mov x0, x16 +; NOFPAC-NEXT: mov x0, x17 ; NOFPAC-NEXT: ret ; ; FPAC-LABEL: test_resign_da_ia: ; FPAC: %bb.0: -; FPAC-NEXT: mov x16, x0 -; FPAC-NEXT: autda x16, x1 -; FPAC-NEXT: pacia x16, x2 -; FPAC-NEXT: mov x0, x16 +; FPAC-NEXT: mov x17, x0 +; FPAC-NEXT: autda x17, x1 +; FPAC-NEXT: pacia x17, x2 +; FPAC-NEXT: mov x0, x17 ; FPAC-NEXT: ret %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %arg1, i32 0, i64 %arg2) ret i64 %tmp @@ -183,26 +183,26 @@ define i64 @test_resign_da_ia(i64 %arg, i64 %arg1, i64 %arg2) { define i64 @test_resign_db_ia(i64 %arg, i64 %arg1, i64 %arg2) { ; NOFPAC-LABEL: test_resign_db_ia: ; NOFPAC: %bb.0: -; NOFPAC-NEXT: mov x16, x0 -; NOFPAC-NEXT: autdb x16, x1 -; NOFPAC-NEXT: mov x17, x16 -; NOFPAC-NEXT: xpacd x17 +; NOFPAC-NEXT: mov x17, x0 +; NOFPAC-NEXT: autdb x17, x1 +; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: xpacd x16 ; NOFPAC-NEXT: cmp x16, x17 ; NOFPAC-NEXT: b.eq [[L]]auth_success_3 -; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: mov x17, x16 ; NOFPAC-NEXT: b [[L]]resign_end_3 ; NOFPAC-NEXT: Lauth_success_3: -; NOFPAC-NEXT: pacia x16, x2 +; NOFPAC-NEXT: pacia x17, x2 ; NOFPAC-NEXT: Lresign_end_3: -; NOFPAC-NEXT: mov x0, x16 +; NOFPAC-NEXT: mov x0, x17 ; NOFPAC-NEXT: ret ; ; FPAC-LABEL: test_resign_db_ia: ; FPAC: %bb.0: -; FPAC-NEXT: mov x16, x0 -; FPAC-NEXT: autdb x16, x1 -; FPAC-NEXT: pacia x16, x2 -; FPAC-NEXT: mov x0, x16 +; FPAC-NEXT: mov x17, x0 +; FPAC-NEXT: autdb x17, x1 +; FPAC-NEXT: pacia x17, x2 +; FPAC-NEXT: mov x0, x17 ; FPAC-NEXT: ret %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 3, i64 %arg1, i32 0, i64 %arg2) ret i64 %tmp @@ -211,26 +211,26 @@ define i64 @test_resign_db_ia(i64 %arg, i64 %arg1, i64 %arg2) { define i64 @test_resign_db_ib(i64 %arg, i64 %arg1, i64 %arg2) { ; NOFPAC-LABEL: test_resign_db_ib: ; NOFPAC: %bb.0: -; NOFPAC-NEXT: mov x16, x0 -; NOFPAC-NEXT: autdb x16, x1 -; NOFPAC-NEXT: mov x17, x16 -; NOFPAC-NEXT: xpacd x17 +; NOFPAC-NEXT: mov x17, x0 +; NOFPAC-NEXT: autdb x17, x1 +; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: xpacd x16 ; NOFPAC-NEXT: cmp x16, x17 ; NOFPAC-NEXT: b.eq [[L]]auth_success_4 -; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: mov x17, x16 ; NOFPAC-NEXT: b [[L]]resign_end_4 ; NOFPAC-NEXT: Lauth_success_4: -; NOFPAC-NEXT: pacib x16, x2 +; NOFPAC-NEXT: pacib x17, x2 ; NOFPAC-NEXT: Lresign_end_4: -; NOFPAC-NEXT: mov x0, x16 +; NOFPAC-NEXT: mov x0, x17 ; NOFPAC-NEXT: ret ; ; FPAC-LABEL: test_resign_db_ib: ; FPAC: %bb.0: -; FPAC-NEXT: mov x16, x0 -; FPAC-NEXT: autdb x16, x1 -; FPAC-NEXT: pacib x16, x2 -; FPAC-NEXT: mov x0, x16 +; FPAC-NEXT: mov x17, x0 +; FPAC-NEXT: autdb x17, x1 +; FPAC-NEXT: pacib x17, x2 +; FPAC-NEXT: mov x0, x17 ; FPAC-NEXT: ret %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 3, i64 %arg1, i32 1, i64 %arg2) ret i64 %tmp @@ -239,26 +239,26 @@ define i64 @test_resign_db_ib(i64 %arg, i64 %arg1, i64 %arg2) { define i64 @test_resign_db_da(i64 %arg, i64 %arg1, i64 %arg2) { ; NOFPAC-LABEL: test_resign_db_da: ; NOFPAC: %bb.0: -; NOFPAC-NEXT: mov x16, x0 -; NOFPAC-NEXT: autdb x16, x1 -; NOFPAC-NEXT: mov x17, x16 -; NOFPAC-NEXT: xpacd x17 +; NOFPAC-NEXT: mov x17, x0 +; NOFPAC-NEXT: autdb x17, x1 +; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: xpacd x16 ; NOFPAC-NEXT: cmp x16, x17 ; NOFPAC-NEXT: b.eq [[L]]auth_success_5 -; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: mov x17, x16 ; NOFPAC-NEXT: b [[L]]resign_end_5 ; NOFPAC-NEXT: Lauth_success_5: -; NOFPAC-NEXT: pacda x16, x2 +; NOFPAC-NEXT: pacda x17, x2 ; NOFPAC-NEXT: Lresign_end_5: -; NOFPAC-NEXT: mov x0, x16 +; NOFPAC-NEXT: mov x0, x17 ; NOFPAC-NEXT: ret ; ; FPAC-LABEL: test_resign_db_da: ; FPAC: %bb.0: -; FPAC-NEXT: mov x16, x0 -; FPAC-NEXT: autdb x16, x1 -; FPAC-NEXT: pacda x16, x2 -; FPAC-NEXT: mov x0, x16 +; FPAC-NEXT: mov x17, x0 +; FPAC-NEXT: autdb x17, x1 +; FPAC-NEXT: pacda x17, x2 +; FPAC-NEXT: mov x0, x17 ; FPAC-NEXT: ret %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 3, i64 %arg1, i32 2, i64 %arg2) ret i64 %tmp @@ -267,26 +267,26 @@ define i64 @test_resign_db_da(i64 %arg, i64 %arg1, i64 %arg2) { define i64 @test_resign_db_db(i64 %arg, i64 %arg1, i64 %arg2) { ; NOFPAC-LABEL: test_resign_db_db: ; NOFPAC: %bb.0: -; NOFPAC-NEXT: mov x16, x0 -; NOFPAC-NEXT: autdb x16, x1 -; NOFPAC-NEXT: mov x17, x16 -; NOFPAC-NEXT: xpacd x17 +; NOFPAC-NEXT: mov x17, x0 +; NOFPAC-NEXT: autdb x17, x1 +; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: xpacd x16 ; NOFPAC-NEXT: cmp x16, x17 ; NOFPAC-NEXT: b.eq [[L]]auth_success_6 -; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: mov x17, x16 ; NOFPAC-NEXT: b [[L]]resign_end_6 ; NOFPAC-NEXT: Lauth_success_6: -; NOFPAC-NEXT: pacdb x16, x2 +; NOFPAC-NEXT: pacdb x17, x2 ; NOFPAC-NEXT: Lresign_end_6: -; NOFPAC-NEXT: mov x0, x16 +; NOFPAC-NEXT: mov x0, x17 ; NOFPAC-NEXT: ret ; ; FPAC-LABEL: test_resign_db_db: ; FPAC: %bb.0: -; FPAC-NEXT: mov x16, x0 -; FPAC-NEXT: autdb x16, x1 -; FPAC-NEXT: pacdb x16, x2 -; FPAC-NEXT: mov x0, x16 +; FPAC-NEXT: mov x17, x0 +; FPAC-NEXT: autdb x17, x1 +; FPAC-NEXT: pacdb x17, x2 +; FPAC-NEXT: mov x0, x17 ; FPAC-NEXT: ret %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 3, i64 %arg1, i32 3, i64 %arg2) ret i64 %tmp @@ -295,26 +295,26 @@ define i64 @test_resign_db_db(i64 %arg, i64 %arg1, i64 %arg2) { define i64 @test_resign_iza_db(i64 %arg, i64 %arg1, i64 %arg2) { ; NOFPAC-LABEL: test_resign_iza_db: ; NOFPAC: %bb.0: -; NOFPAC-NEXT: mov x16, x0 -; NOFPAC-NEXT: autiza x16 -; NOFPAC-NEXT: mov x17, x16 -; NOFPAC-NEXT: xpaci x17 +; NOFPAC-NEXT: mov x17, x0 +; NOFPAC-NEXT: autiza x17 +; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: xpaci x16 ; NOFPAC-NEXT: cmp x16, x17 ; NOFPAC-NEXT: b.eq [[L]]auth_success_7 -; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: mov x17, x16 ; NOFPAC-NEXT: b [[L]]resign_end_7 ; NOFPAC-NEXT: Lauth_success_7: -; NOFPAC-NEXT: pacdb x16, x2 +; NOFPAC-NEXT: pacdb x17, x2 ; NOFPAC-NEXT: Lresign_end_7: -; NOFPAC-NEXT: mov x0, x16 +; NOFPAC-NEXT: mov x0, x17 ; NOFPAC-NEXT: ret ; ; FPAC-LABEL: test_resign_iza_db: ; FPAC: %bb.0: -; FPAC-NEXT: mov x16, x0 -; FPAC-NEXT: autiza x16 -; FPAC-NEXT: pacdb x16, x2 -; FPAC-NEXT: mov x0, x16 +; FPAC-NEXT: mov x17, x0 +; FPAC-NEXT: autiza x17 +; FPAC-NEXT: pacdb x17, x2 +; FPAC-NEXT: mov x0, x17 ; FPAC-NEXT: ret %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 0, i64 0, i32 3, i64 %arg2) ret i64 %tmp @@ -323,26 +323,26 @@ define i64 @test_resign_iza_db(i64 %arg, i64 %arg1, i64 %arg2) { define i64 @test_resign_da_dzb(i64 %arg, i64 %arg1, i64 %arg2) { ; NOFPAC-LABEL: test_resign_da_dzb: ; NOFPAC: %bb.0: -; NOFPAC-NEXT: mov x16, x0 -; NOFPAC-NEXT: autda x16, x1 -; NOFPAC-NEXT: mov x17, x16 -; NOFPAC-NEXT: xpacd x17 +; NOFPAC-NEXT: mov x17, x0 +; NOFPAC-NEXT: autda x17, x1 +; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: xpacd x16 ; NOFPAC-NEXT: cmp x16, x17 ; NOFPAC-NEXT: b.eq [[L]]auth_success_8 -; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: mov x17, x16 ; NOFPAC-NEXT: b [[L]]resign_end_8 ; NOFPAC-NEXT: Lauth_success_8: -; NOFPAC-NEXT: pacdzb x16 +; NOFPAC-NEXT: pacdzb x17 ; NOFPAC-NEXT: Lresign_end_8: -; NOFPAC-NEXT: mov x0, x16 +; NOFPAC-NEXT: mov x0, x17 ; NOFPAC-NEXT: ret ; ; FPAC-LABEL: test_resign_da_dzb: ; FPAC: %bb.0: -; FPAC-NEXT: mov x16, x0 -; FPAC-NEXT: autda x16, x1 -; FPAC-NEXT: pacdzb x16 -; FPAC-NEXT: mov x0, x16 +; FPAC-NEXT: mov x17, x0 +; FPAC-NEXT: autda x17, x1 +; FPAC-NEXT: pacdzb x17 +; FPAC-NEXT: mov x0, x17 ; FPAC-NEXT: ret %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %arg1, i32 3, i64 0) ret i64 %tmp @@ -351,22 +351,22 @@ define i64 @test_resign_da_dzb(i64 %arg, i64 %arg1, i64 %arg2) { define i64 @test_auth_trap_attribute(i64 %arg, i64 %arg1) "ptrauth-auth-traps" { ; NOFPAC-LABEL: test_auth_trap_attribute: ; NOFPAC: %bb.0: -; NOFPAC-NEXT: mov x16, x0 -; NOFPAC-NEXT: autia x16, x1 -; NOFPAC-NEXT: mov x17, x16 -; NOFPAC-NEXT: xpaci x17 +; NOFPAC-NEXT: mov x17, x0 +; NOFPAC-NEXT: autia x17, x1 +; NOFPAC-NEXT: mov x16, x17 +; NOFPAC-NEXT: xpaci x16 ; NOFPAC-NEXT: cmp x16, x17 ; NOFPAC-NEXT: b.eq [[L]]auth_success_9 ; NOFPAC-NEXT: brk #0xc470 ; NOFPAC-NEXT: Lauth_success_9: -; NOFPAC-NEXT: mov x0, x16 +; NOFPAC-NEXT: mov x0, x17 ; NOFPAC-NEXT: ret ; ; FPAC-LABEL: test_auth_trap_attribute: ; FPAC: %bb.0: -; FPAC-NEXT: mov x16, x0 -; FPAC-NEXT: autia x16, x1 -; FPAC-NEXT: mov x0, x16 +; FPAC-NEXT: mov x17, x0 +; FPAC-NEXT: autia x17, x1 +; FPAC-NEXT: mov x0, x17 ; FPAC-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 %arg1) ret i64 %tmp diff --git a/llvm/test/CodeGen/AArch64/ptrauth-hint-only-basic-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-basic-pic.ll new file mode 100644 index 0000000000000000000000000000000000000000..01b44ae3dc4842af62055230dad718fed896b200 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-basic-pic.ll @@ -0,0 +1,189 @@ +; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=0 -verify-machineinstrs \ +; RUN: -relocation-model=pic -mattr=+pauth -mattr=+fpac %s -o - \ +; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-ELF +; RUN-NOT: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=0 -verify-machineinstrs \ +; RUN-NOT: -relocation-model=pic -mattr=+pauth %s -o - \ +; RUN-NOT: | FileCheck %s --check-prefixes=CHECK,CHECK-ELF,TRAP-ELF + +; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=0 -verify-machineinstrs \ +; RUN: -relocation-model=pic -mattr=+pauth -mattr=+pauth-hint-only -mattr=+fpac %s -o - \ +; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-HINT +; RUN-NOT: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=0 -verify-machineinstrs \ +; RUN-NOT: -relocation-model=pic -mattr=+pauth -mattr=+pauth-hint-only %s -o - \ +; RUN-NOT: | FileCheck %s --check-prefixes=CHECK,CHECK-HINT,TRAP-HINT + +; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=1 -verify-machineinstrs \ +; RUN: -relocation-model=pic -mattr=+pauth -mattr=+fpac %s -o - \ +; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-ELF +; RUN-NOT: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=1 -verify-machineinstrs \ +; RUN-NOT: -relocation-model=pic -mattr=+pauth %s -o - \ +; RUN-NOT: | FileCheck %s --check-prefixes=CHECK,CHECK-ELF,TRAP-ELF + +; RUN: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=1 -verify-machineinstrs \ +; RUN: -relocation-model=pic -mattr=+pauth -mattr=+pauth-hint-only -mattr=+fpac %s -o - \ +; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-HINT +; RUN-NOT: llc -mtriple=aarch64-linux-gnu -global-isel=0 -fast-isel=1 -verify-machineinstrs \ +; RUN-NOT: -relocation-model=pic -mattr=+pauth -mattr=+pauth-hint-only %s -o - \ +; RUN-NOT: | FileCheck %s --check-prefixes=CHECK,CHECK-HINT,TRAP-HINT + +;; Note: for FastISel, we fall back to SelectionDAG + +@var = global i32 0 + +define i32 @get_globalvar() { +; CHECK-LABEL: get_globalvar: +; CHECK-ELF-NEXT: .cfi_startproc +; CHECK-ELF-NEXT: // %bb.0: +; CHECK: adrp x8, :got:var +; CHECK-NEXT: ldr x8, [x8, :got_lo12:var] +; CHECK-NEXT: ldr w0, [x8] +; CHECK-NEXT: ret + + %val = load i32, ptr @var + ret i32 %val +} + +define ptr @get_globalvaraddr() { +; CHECK-LABEL: get_globalvaraddr: +; CHECK-ELF-NEXT: .cfi_startproc +; CHECK-ELF-NEXT: // %bb.0: +; CHECK: adrp [[TmpReg:x[0-9]+]], :got:var +; CHECK-NEXT: ldr x0, [[[TmpReg]], :got_lo12:var] +; CHECK-NEXT: ret + + %val = load i32, ptr @var + ret ptr @var +} + +declare i32 @foo() + +define ptr @resign_globalfunc() { +; CHECK-ELF-LABEL: resign_globalfunc: +; CHECK-ELF-NEXT: .cfi_startproc +; CHECK-ELF-NEXT: // %bb.0: +; CHECK-ELF: adrp x17, :got:foo +; CHECK-ELF-NEXT: ldr x17, [x17, :got_lo12:foo] + +; TRAP-ELF-NEXT: mov x16, x17 +; TRAP-ELF-NEXT: xpaci x16 +; TRAP-ELF-NEXT: cmp x17, x16 +; TRAP-ELF-NEXT: b.eq .Lauth_success_2 +; TRAP-ELF-NEXT: brk #0xc470 +; TRAP-ELF-NEXT: .Lauth_success_2: + +; CHECK-ELF-NEXT: mov x16, #42 +; CHECK-ELF-NEXT: pacia x17, x16 +; CHECK-ELF-NEXT: mov x0, x17 +; CHECK-ELF-NEXT: ret + + +; CHECK-HINT-LABEL: resign_globalfunc: +; CHECK-HINT-NEXT: .cfi_startproc +; CHECK-HINT-NEXT: // %bb.0: +; CHECK-HINT: adrp x17, :got:foo +; CHECK-HINT-NEXT: ldr x17, [x17, :got_lo12:foo] + +; TRAP-HINT-NEXT: mov x30, x17 +; TRAP-HINT-NEXT: xpaclri +; TRAP-HINT-NEXT: mov x16, x30 +; TRAP-HINT-NEXT: cmp x17, x16 +; TRAP-HINT-NEXT: b.eq .Lauth_success_2 +; TRAP-HINT-NEXT: brk #0xc470 +; TRAP-HINT-NEXT: .Lauth_success_2: + +; CHECK-HINT-NEXT: mov x16, #42 +; CHECK-HINT-NEXT: pacia1716 +; CHECK-HINT-NEXT: mov x0, x17 +; CHECK-HINT-NEXT: ret + + ret ptr ptrauth (ptr @foo, i32 0, i64 42) +} + +define ptr @resign_globalvar() { +; CHECK-ELF-LABEL: resign_globalvar: +; CHECK-ELF-NEXT: .cfi_startproc +; CHECK-ELF-NEXT: // %bb.0: +; CHECK-ELF: adrp x17, :got:var +; CHECK-ELF-NEXT: ldr x17, [x17, :got_lo12:var] + +; TRAP-ELF-NEXT: mov x16, x17 +; TRAP-ELF-NEXT: xpacd x16 +; TRAP-ELF-NEXT: cmp x17, x16 +; TRAP-ELF-NEXT: b.eq .Lauth_success_3 +; TRAP-ELF-NEXT: brk #0xc472 +; TRAP-ELF-NEXT: .Lauth_success_3: + +; CHECK-ELF-NEXT: mov x16, #43 +; CHECK-ELF-NEXT: pacdb x17, x16 +; CHECK-ELF-NEXT: mov x0, x17 +; CHECK-ELF-NEXT: ret + + +; CHECK-HINT-LABEL: resign_globalvar: +; CHECK-HINT-NEXT: .cfi_startproc +; CHECK-HINT-NEXT: // %bb.0: +; CHECK-HINT: adrp x17, :got:var +; CHECK-HINT-NEXT: ldr x17, [x17, :got_lo12:var] + +; TRAP-HINT-NEXT: mov x30, x17 +; TRAP-HINT-NEXT: xpaclri +; TRAP-HINT-NEXT: mov x16, x30 +; TRAP-HINT-NEXT: cmp x17, x16 +; TRAP-HINT-NEXT: b.eq .Lauth_success_3 +; TRAP-HINT-NEXT: brk #0xc472 +; TRAP-HINT-NEXT: .Lauth_success_3: + +; CHECK-HINT-NEXT: mov x16, #43 +; CHECK-HINT-NEXT: pacib1716 +; CHECK-HINT-NEXT: mov x0, x17 +; CHECK-HINT-NEXT: ret + + ret ptr ptrauth (ptr @var, i32 3, i64 43) +} + +define ptr @resign_globalvar_offset() { +; CHECK-ELF-LABEL: resign_globalvar_offset: +; CHECK-ELF-NEXT: .cfi_startproc +; CHECK-ELF-NEXT: // %bb.0: +; CHECK-ELF: adrp x17, :got:var +; CHECK-ELF-NEXT: ldr x17, [x17, :got_lo12:var] + +; TRAP-ELF-NEXT: mov x16, x17 +; TRAP-ELF-NEXT: xpacd x16 +; TRAP-ELF-NEXT: cmp x17, x16 +; TRAP-ELF-NEXT: b.eq .Lauth_success_4 +; TRAP-ELF-NEXT: brk #0xc472 +; TRAP-ELF-NEXT: .Lauth_success_4: + +; CHECK-ELF-NEXT: add x17, x17, #16 +; CHECK-ELF-NEXT: mov x16, #44 +; CHECK-ELF-NEXT: pacda x17, x16 +; CHECK-ELF-NEXT: mov x0, x17 +; CHECK-ELF-NEXT: ret + + +; CHECK-HINT-LABEL: resign_globalvar_offset: +; CHECK-HINT-NEXT: .cfi_startproc +; CHECK-HINT-NEXT: // %bb.0: +; CHECK-HINT: adrp x17, :got:var +; CHECK-HINT-NEXT: ldr x17, [x17, :got_lo12:var] + +; TRAP-HINT-NEXT: mov x30, x17 +; TRAP-HINT-NEXT: xpaclri +; TRAP-HINT-NEXT: mov x16, x30 +; TRAP-HINT-NEXT: cmp x17, x16 +; TRAP-HINT-NEXT: b.eq .Lauth_success_4 +; TRAP-HINT-NEXT: brk #0xc472 +; TRAP-HINT-NEXT: .Lauth_success_4: + +; CHECK-HINT-NEXT: add x17, x17, #16 +; CHECK-HINT-NEXT: mov x16, #44 +; CHECK-HINT-NEXT: pacia1716 +; CHECK-HINT-NEXT: mov x0, x17 +; CHECK-HINT-NEXT: ret + + ret ptr ptrauth (ptr getelementptr (i8, ptr @var, i64 16), i32 2, i64 44) +} + +!llvm.module.flags = !{!0} +!0 = !{i32 8, !"ptrauth-elf-got", i32 1} diff --git a/llvm/test/CodeGen/AArch64/ptrauth-hint-only-bti-call.ll b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-bti-call.ll new file mode 100644 index 0000000000000000000000000000000000000000..23971370bef9accb3fff648ea888150a4fdeabff --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-bti-call.ll @@ -0,0 +1,186 @@ + +; RUN: llc -mtriple aarch64-linux-gnu -mattr=+bti -mattr=+pauth \ +; RUN: -asm-verbose=false -o - %s | FileCheck %s --check-prefixes=ELF +; RUN-NOT: llc -mtriple aarch64-linux-gnu -mattr=+bti -mattr=+pauth -global-isel \ +; RUN-NOT: -asm-verbose=false -o - %s | FileCheck %s --check-prefixes=ELF +; RUN: llc -mtriple aarch64-linux-gnu -mattr=+bti -mattr=+pauth -fast-isel \ +; RUN: -asm-verbose=false -o - %s | FileCheck %s --check-prefixes=ELF + +; RUN: llc -mtriple aarch64-linux-gnu -mattr=+bti -mattr=+pauth -mattr=+pauth-hint-only \ +; RUN: -asm-verbose=false -o - %s | FileCheck %s --check-prefixes=HINT +; RUN-NOT: llc -mtriple aarch64-linux-gnu -mattr=+bti -mattr=+pauth -mattr=+pauth-hint-only -global-isel \ +; RUN-NOT: -asm-verbose=false -o - %s | FileCheck %s --check-prefixes=HINT +; RUN: llc -mtriple aarch64-linux-gnu -mattr=+bti -mattr=+pauth -mattr=+pauth-hint-only -fast-isel \ +; RUN: -asm-verbose=false -o - %s | FileCheck %s --check-prefixes=HINT + +; ptrauth tail-calls can only use x16/x17 with BTI. + +; ELF-LABEL: test_tailcall_ia_0: +; ELF-NEXT: bti c +; ELF-NEXT: mov x16, x0 +; ELF-NEXT: braaz x16 + +; HINT-LABEL: test_tailcall_ia_0: +; HINT-NEXT: bti c +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: autia1716 +; HINT-NEXT: br x17 +define i32 @test_tailcall_ia_0(i32 ()* %arg0) #0 { + %tmp0 = tail call i32 %arg0() [ "ptrauth"(i32 0, i64 0) ] + ret i32 %tmp0 +} + +; ELF-LABEL: test_tailcall_ib_0: +; ELF-NEXT: bti c +; ELF-NEXT: mov x16, x0 +; ELF-NEXT: brabz x16 + +; HINT-LABEL: test_tailcall_ib_0: +; HINT-NEXT: bti c +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: autib1716 +; HINT-NEXT: br x17 +define i32 @test_tailcall_ib_0(i32 ()* %arg0) #0 { + %tmp0 = tail call i32 %arg0() [ "ptrauth"(i32 1, i64 0) ] + ret i32 %tmp0 +} + +; ELF-LABEL: test_tailcall_ia_imm: +; ELF-NEXT: bti c +; ELF-NEXT: mov x16, x0 +; ELF-NEXT: mov x17, #42 +; ELF-NEXT: braa x16, x17 + +; HINT-LABEL: test_tailcall_ia_imm: +; HINT-NEXT: bti c +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, #42 +; HINT-NEXT: autia1716 +; HINT-NEXT: br x17 +define i32 @test_tailcall_ia_imm(i32 ()* %arg0) #0 { + %tmp0 = tail call i32 %arg0() [ "ptrauth"(i32 0, i64 42) ] + ret i32 %tmp0 +} + +; ELF-LABEL: test_tailcall_ib_imm: +; ELF-NEXT: bti c +; ELF-NEXT: mov x16, x0 +; ELF-NEXT: mov x17, #42 +; ELF-NEXT: brab x16, x17 + +; HINT-LABEL: test_tailcall_ib_imm: +; HINT-NEXT: bti c +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, #42 +; HINT-NEXT: autib1716 +; HINT-NEXT: br x17 +define i32 @test_tailcall_ib_imm(i32 ()* %arg0) #0 { + %tmp0 = tail call i32 %arg0() [ "ptrauth"(i32 1, i64 42) ] + ret i32 %tmp0 +} + +; ELF-LABEL: test_tailcall_ia_var: +; ELF-NEXT: bti c +; ELF-NEXT: ldr x1, [x1] +; ELF-NEXT: mov x16, x0 +; ELF-NEXT: braa x16, x1 + +; HINT-LABEL: test_tailcall_ia_var: +; HINT-NEXT: bti c +; HINT-NEXT: ldr x16, [x1] +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: autia1716 +; HINT-NEXT: br x17 +define i32 @test_tailcall_ia_var(i32 ()* %arg0, i64* %arg1) #0 { + %tmp0 = load i64, i64* %arg1 + %tmp1 = tail call i32 %arg0() [ "ptrauth"(i32 0, i64 %tmp0) ] + ret i32 %tmp1 +} + +; ELF-LABEL: test_tailcall_ib_var: +; ELF-NEXT: bti c +; ELF-NEXT: ldr x1, [x1] +; ELF-NEXT: mov x16, x0 +; ELF-NEXT: brab x16, x1 + +; HINT-LABEL: test_tailcall_ib_var: +; HINT-NEXT: bti c +; HINT-NEXT: ldr x16, [x1] +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: autib1716 +; HINT-NEXT: br x17 +define i32 @test_tailcall_ib_var(i32 ()* %arg0, i64* %arg1) #0 { + %tmp0 = load i64, i64* %arg1 + %tmp1 = tail call i32 %arg0() [ "ptrauth"(i32 1, i64 %tmp0) ] + ret i32 %tmp1 +} + +; ELF-LABEL: test_tailcall_ia_arg: +; ELF-NEXT: bti c +; ELF-NEXT: mov x16, x0 +; ELF-NEXT: braa x16, x1 + +; HINT-LABEL: test_tailcall_ia_arg: +; HINT-NEXT: bti c +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: autia1716 +; HINT-NEXT: br x17 +define i32 @test_tailcall_ia_arg(i32 ()* %arg0, i64 %arg1) #0 { + %tmp0 = tail call i32 %arg0() [ "ptrauth"(i32 0, i64 %arg1) ] + ret i32 %tmp0 +} + +; ELF-LABEL: test_tailcall_ib_arg: +; ELF-NEXT: bti c +; ELF-NEXT: mov x16, x0 +; ELF-NEXT: brab x16, x1 + +; HINT-LABEL: test_tailcall_ib_arg: +; HINT-NEXT: bti c +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: autib1716 +; HINT-NEXT: br x17 +define i32 @test_tailcall_ib_arg(i32 ()* %arg0, i64 %arg1) #0 { + %tmp0 = tail call i32 %arg0() [ "ptrauth"(i32 1, i64 %arg1) ] + ret i32 %tmp0 +} + +; ELF-LABEL: test_tailcall_ia_arg_ind: +; ELF-NEXT: bti c +; ELF-NEXT: ldr x16, [x0] +; ELF-NEXT: braa x16, x1 + +; HINT-LABEL: test_tailcall_ia_arg_ind: +; HINT-NEXT: bti c +; HINT-NEXT: ldr x17, [x0] +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: autia1716 +; HINT-NEXT: br x17 +define i32 @test_tailcall_ia_arg_ind(i32 ()** %arg0, i64 %arg1) #0 { + %tmp0 = load i32 ()*, i32 ()** %arg0 + %tmp1 = tail call i32 %tmp0() [ "ptrauth"(i32 0, i64 %arg1) ] + ret i32 %tmp1 +} + +; ELF-LABEL: test_tailcall_ib_arg_ind: +; ELF-NEXT: bti c +; ELF-NEXT: ldr x16, [x0] +; ELF-NEXT: brab x16, x1 + +; HINT-LABEL: test_tailcall_ib_arg_ind: +; HINT-NEXT: bti c +; HINT-NEXT: ldr x17, [x0] +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: autib1716 +; HINT-NEXT: br x17 +define i32 @test_tailcall_ib_arg_ind(i32 ()** %arg0, i64 %arg1) #0 { + %tmp0 = load i32 ()*, i32 ()** %arg0 + %tmp1 = tail call i32 %tmp0() [ "ptrauth"(i32 1, i64 %arg1) ] + ret i32 %tmp1 +} + +attributes #0 = { nounwind "branch-target-enforcement"="true" } diff --git a/llvm/test/CodeGen/AArch64/ptrauth-hint-only-call.ll b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-call.ll new file mode 100644 index 0000000000000000000000000000000000000000..84e2ad232cd956ba9d5b7b1af2a26fe1531f353d --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-call.ll @@ -0,0 +1,529 @@ +; RUN: llc -mtriple aarch64 -mattr=+pauth -o - %s -asm-verbose=0 \ +; RUN: | FileCheck %s --check-prefixes=CHECK,ELF + +; RUN: llc -mtriple aarch64 -mattr=+pauth -mattr=+pauth-hint-only -o - %s -asm-verbose=0 \ +; RUN: | FileCheck %s --check-prefixes=CHECK,HINT + +; RUN: llc -mtriple aarch64 -mattr=+pauth -o - %s -asm-verbose=0 -global-isel \ +; RUN: -global-isel-abort=1 -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,ELF + +; FIXME: GISel swaps the order of two move instructions (e.g; test_tailcall_ia_arg) with respect +; FIXME: the SelectionDAGISel +; RUN-NOT: llc -mtriple aarch64 -mattr=+pauth -mattr=+pauth-hint-only -o - %s -asm-verbose=0 -global-isel \ +; RUN-NOT: -global-isel-abort=1 -verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,HINT + +define i32 @test_call_ia_0(ptr %arg0) #0 { +; ELF-LABEL: test_call_ia_0: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: blraaz x0 +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + +; HINT-LABEL: test_call_ia_0: +; HINT-NEXT: str x30, [sp, #-16]! +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: autia1716 +; HINT-NEXT: blr x17 +; HINT-NEXT: ldr x30, [sp], #16 +; HINT-NEXT: ret + %tmp0 = call i32 %arg0() [ "ptrauth"(i32 0, i64 0) ] + ret i32 %tmp0 +} + +define i32 @test_call_ib_0(ptr %arg0) #0 { +; ELF-LABEL: test_call_ib_0: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: blrabz x0 +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + +; HINT-LABEL: test_call_ib_0: +; HINT-NEXT: str x30, [sp, #-16]! +; HINT: mov x17, x0 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: autib1716 +; HINT-NEXT: blr x17 +; HINT-NEXT: ldr x30, [sp], #16 +; HINT-NEXT: ret + %tmp0 = call i32 %arg0() [ "ptrauth"(i32 1, i64 0) ] + ret i32 %tmp0 +} + +define i32 @test_tailcall_ia_0(ptr %arg0) #0 { +; ELF-LABEL: test_tailcall_ia_0: +; ELF-NEXT: braaz x0 + +; HINT-LABEL: test_tailcall_ia_0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: autia1716 +; HINT-NEXT: br x17 + %tmp0 = tail call i32 %arg0() [ "ptrauth"(i32 0, i64 0) ] + ret i32 %tmp0 +} + +define i32 @test_tailcall_ib_0(ptr %arg0) #0 { +; ELF-LABEL: test_tailcall_ib_0: +; ELF-NEXT: brabz x0 + +; HINT-LABEL: test_tailcall_ib_0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: autib1716 +; HINT-NEXT: br x17 + %tmp0 = tail call i32 %arg0() [ "ptrauth"(i32 1, i64 0) ] + ret i32 %tmp0 +} + +define i32 @test_call_ia_imm(ptr %arg0) #0 { +; ELF-LABEL: test_call_ia_imm: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: mov x17, #42 +; ELF-NEXT: blraa x0, x17 +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + +; HINT-LABEL: test_call_ia_imm: +; HINT-NEXT: str x30, [sp, #-16]! +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, #42 +; HINT-NEXT: autia1716 +; HINT-NEXT: blr x17 +; HINT-NEXT: ldr x30, [sp], #16 +; HINT-NEXT: ret + %tmp0 = call i32 %arg0() [ "ptrauth"(i32 0, i64 42) ] + ret i32 %tmp0 +} + +define i32 @test_call_ib_imm(ptr %arg0) #0 { +; ELF-LABEL: test_call_ib_imm: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: mov x17, #42 +; ELF-NEXT: blrab x0, x17 +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + +; HINT-LABEL: test_call_ib_imm: +; HINT-NEXT: str x30, [sp, #-16]! +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, #42 +; HINT-NEXT: autib1716 +; HINT-NEXT: blr x17 +; HINT-NEXT: ldr x30, [sp], #16 +; HINT-NEXT: ret + %tmp0 = call i32 %arg0() [ "ptrauth"(i32 1, i64 42) ] + ret i32 %tmp0 +} + +define i32 @test_tailcall_ia_imm(ptr %arg0) #0 { +; ELF-LABEL: test_tailcall_ia_imm: +; ELF-NEXT: mov x16, #42 +; ELF-NEXT: braa x0, x16 + +; HINT-LABEL: test_tailcall_ia_imm: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, #42 +; HINT-NEXT: autia1716 +; HINT-NEXT: br x17 + %tmp0 = tail call i32 %arg0() [ "ptrauth"(i32 0, i64 42) ] + ret i32 %tmp0 +} + +define i32 @test_tailcall_ib_imm(ptr %arg0) #0 { +; ELF-LABEL: test_tailcall_ib_imm: +; ELF-NEXT: mov x16, #42 +; ELF-NEXT: brab x0, x16 + +; HINT-LABEL: test_tailcall_ib_imm: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, #42 +; HINT-NEXT: autib1716 +; HINT-NEXT: br x17 + %tmp0 = tail call i32 %arg0() [ "ptrauth"(i32 1, i64 42) ] + ret i32 %tmp0 +} + +define i32 @test_call_ia_var(ptr %arg0, ptr %arg1) #0 { +; ELF-LABEL: test_call_ia_var: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: ldr x8, [x1] +; ELF-NEXT: blraa x0, x8 +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + +; HINT-LABEL: test_call_ia_var: +; HINT-NEXT: str x30, [sp, #-16]! +; HINT-NEXT: ldr x16, [x1] +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: autia1716 +; HINT-NEXT: blr x17 +; HINT-NEXT: ldr x30, [sp], #16 +; HINT-NEXT: ret + %tmp0 = load i64, ptr %arg1 + %tmp1 = call i32 %arg0() [ "ptrauth"(i32 0, i64 %tmp0) ] + ret i32 %tmp1 +} + +define i32 @test_call_ib_var(ptr %arg0, ptr %arg1) #0 { +; ELF-LABEL: test_call_ib_var: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: ldr x8, [x1] +; ELF-NEXT: blrab x0, x8 +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + +; HINT-LABEL: test_call_ib_var: +; HINT-NEXT: str x30, [sp, #-16]! +; HINT-NEXT: ldr x16, [x1] +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: autib1716 +; HINT-NEXT: blr x17 +; HINT-NEXT: ldr x30, [sp], #16 +; HINT-NEXT: ret + %tmp0 = load i64, ptr %arg1 + %tmp1 = call i32 %arg0() [ "ptrauth"(i32 1, i64 %tmp0) ] + ret i32 %tmp1 +} + +define i32 @test_tailcall_ia_var(ptr %arg0, ptr %arg1) #0 { +; ELF-LABEL: test_tailcall_ia_var: +; ELF: ldr x1, [x1] +; ELF: braa x0, x1 + +; HINT-LABEL: test_tailcall_ia_var: +; HINT-NEXT: ldr x16, [x1] +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: autia1716 +; HINT-NEXT: br x17 + %tmp0 = load i64, ptr %arg1 + %tmp1 = tail call i32 %arg0() [ "ptrauth"(i32 0, i64 %tmp0) ] + ret i32 %tmp1 +} + +define i32 @test_tailcall_ib_var(ptr %arg0, ptr %arg1) #0 { +; ELF-LABEL: test_tailcall_ib_var: +; ELF: ldr x1, [x1] +; ELF: brab x0, x1 + +; HINT-LABEL: test_tailcall_ib_var: +; HINT-NEXT: ldr x16, [x1] +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: autib1716 +; HINT-NEXT: br x17 + %tmp0 = load i64, ptr %arg1 + %tmp1 = tail call i32 %arg0() [ "ptrauth"(i32 1, i64 %tmp0) ] + ret i32 %tmp1 +} + +define void @test_tailcall_omit_mov_x16_x16(ptr %objptr) #0 { +; ELF-LABEL: test_tailcall_omit_mov_x16_x16: +; ELF-NEXT: ldr x17, [x0] +; ELF-NEXT: mov x16, x0 +; ELF-NEXT: movk x16, #6503, lsl #48 +; ELF-NEXT: autda x17, x16 +; ELF-NEXT: ldr x1, [x17] +; ELF-NEXT: movk x17, #54167, lsl #48 +; ELF-NEXT: braa x1, x17 + +; HINT-LABEL: test_tailcall_omit_mov_x16_x16: +; HINT-NEXT: ldr x17, [x0] +; HINT-NEXT: mov x16, x0 +; HINT-NEXT: movk x16, #6503, lsl #48 +; HINT-NEXT: autia1716 +; HINT-NEXT: mov x16, x17 +; HINT-NEXT: ldr x17, [x17] +; HINT-NEXT: movk x16, #54167, lsl #48 +; HINT-NEXT: autia1716 +; HINT-NEXT: br x17 + + %vtable.signed = load ptr, ptr %objptr, align 8 + %objptr.int = ptrtoint ptr %objptr to i64 + %vtable.discr = tail call i64 @llvm.ptrauth.blend(i64 %objptr.int, i64 6503) + %vtable.signed.int = ptrtoint ptr %vtable.signed to i64 + %vtable.unsigned.int = tail call i64 @llvm.ptrauth.auth(i64 %vtable.signed.int, i32 2, i64 %vtable.discr) + %vtable.unsigned = inttoptr i64 %vtable.unsigned.int to ptr + %virt.func.signed = load ptr, ptr %vtable.unsigned, align 8 + %virt.func.discr = tail call i64 @llvm.ptrauth.blend(i64 %vtable.unsigned.int, i64 54167) + tail call void %virt.func.signed(ptr %objptr) [ "ptrauth"(i32 0, i64 %virt.func.discr) ] + ret void +} + +define i32 @test_call_omit_extra_moves(ptr %objptr) #0 { +; ELF-LABEL: test_call_omit_extra_moves: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: ldr x17, [x0] +; ELF-NEXT: mov x16, x0 +; ELF-NEXT: movk x16, #6503, lsl #48 +; ELF-NEXT: autda x17, x16 +; ELF-NEXT: ldr x8, [x17] +; ELF-NEXT: movk x17, #34646, lsl #48 +; ELF-NEXT: blraa x8, x17 +; ELF-NEXT: mov w0, #42 +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + +; HINT-LABEL: test_call_omit_extra_moves: +; HINT-NEXT: str x30, [sp, #-16]! +; HINT-NEXT: ldr x17, [x0] +; HINT-NEXT: mov x16, x0 +; HINT-NEXT: movk x16, #6503, lsl #48 +; HINT-NEXT: autia1716 +; HINT-NEXT: mov x16, x17 +; HINT-NEXT: ldr x17, [x17] +; HINT-NEXT: movk x16, #34646, lsl #48 +; HINT-NEXT: autia1716 +; HINT-NEXT: blr x17 +; HINT-NEXT: mov w0, #42 +; HINT-NEXT: ldr x30, [sp], #16 +; HINT-NEXT: ret + + %vtable.signed = load ptr, ptr %objptr + %objptr.int = ptrtoint ptr %objptr to i64 + %vtable.discr = tail call i64 @llvm.ptrauth.blend(i64 %objptr.int, i64 6503) + %vtable.signed.int = ptrtoint ptr %vtable.signed to i64 + %vtable.int = tail call i64 @llvm.ptrauth.auth(i64 %vtable.signed.int, i32 2, i64 %vtable.discr) + %vtable = inttoptr i64 %vtable.int to ptr + %callee.signed = load ptr, ptr %vtable + %callee.discr = tail call i64 @llvm.ptrauth.blend(i64 %vtable.int, i64 34646) + %call.result = tail call i32 %callee.signed(ptr %objptr) [ "ptrauth"(i32 0, i64 %callee.discr) ] + ret i32 42 +} + +define i32 @test_call_ia_arg(ptr %arg0, i64 %arg1) #0 { +; ELF-LABEL: test_call_ia_arg: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: blraa x0, x1 +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + +; HINT-LABEL: test_call_ia_arg: +; HINT-NEXT: str x30, [sp, #-16]! +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: autia1716 +; HINT-NEXT: blr x17 +; HINT-NEXT: ldr x30, [sp], #16 +; HINT-NEXT: ret + %tmp0 = call i32 %arg0() [ "ptrauth"(i32 0, i64 %arg1) ] + ret i32 %tmp0 +} + +define i32 @test_call_ib_arg(ptr %arg0, i64 %arg1) #0 { +; ELF-LABEL: test_call_ib_arg: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: blrab x0, x1 +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + +; HINT-LABEL: test_call_ib_arg: +; HINT-NEXT: str x30, [sp, #-16]! +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: autib1716 +; HINT-NEXT: blr x17 +; HINT-NEXT: ldr x30, [sp], #16 +; HINT-NEXT: ret + %tmp0 = call i32 %arg0() [ "ptrauth"(i32 1, i64 %arg1) ] + ret i32 %tmp0 +} + +define i32 @test_tailcall_ia_arg(ptr %arg0, i64 %arg1) #0 { +; ELF-LABEL: test_tailcall_ia_arg: +; ELF: braa x0, x1 + +; HINT-LABEL: test_tailcall_ia_arg: +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: autia1716 +; HINT-NEXT: br x17 + %tmp0 = tail call i32 %arg0() [ "ptrauth"(i32 0, i64 %arg1) ] + ret i32 %tmp0 +} + +define i32 @test_tailcall_ib_arg(ptr %arg0, i64 %arg1) #0 { +; ELF-LABEL: test_tailcall_ib_arg: +; ELF: brab x0, x1 + +; HINT-LABEL: test_tailcall_ib_arg: +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: autib1716 +; HINT-NEXT: br x17 + %tmp0 = tail call i32 %arg0() [ "ptrauth"(i32 1, i64 %arg1) ] + ret i32 %tmp0 +} + +define i32 @test_call_ia_arg_ind(ptr %arg0, i64 %arg1) #0 { +; ELF-LABEL: test_call_ia_arg_ind: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: ldr x8, [x0] +; ELF-NEXT: blraa x8, x1 +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + +; HINT-LABEL: test_call_ia_arg_ind: +; HINT-NEXT: str x30, [sp, #-16]! +; HINT-NEXT: ldr x17, [x0] +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: autia1716 +; HINT-NEXT: blr x17 +; HINT-NEXT: ldr x30, [sp], #16 +; HINT-NEXT: ret + %tmp0 = load ptr, ptr %arg0 + %tmp1 = call i32 %tmp0() [ "ptrauth"(i32 0, i64 %arg1) ] + ret i32 %tmp1 +} + +define i32 @test_call_ib_arg_ind(ptr %arg0, i64 %arg1) #0 { +; ELF-LABEL: test_call_ib_arg_ind: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: ldr x8, [x0] +; ELF-NEXT: blrab x8, x1 +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + +; HINT-LABEL: test_call_ib_arg_ind: +; HINT-NEXT: str x30, [sp, #-16]! +; HINT-NEXT: ldr x17, [x0] +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: autib1716 +; HINT-NEXT: blr x17 +; HINT-NEXT: ldr x30, [sp], #16 +; HINT-NEXT: ret + %tmp0 = load ptr, ptr %arg0 + %tmp1 = call i32 %tmp0() [ "ptrauth"(i32 1, i64 %arg1) ] + ret i32 %tmp1 +} + +define i32 @test_tailcall_ia_arg_ind(ptr %arg0, i64 %arg1) #0 { +; ELF-LABEL: test_tailcall_ia_arg_ind: +; ELF: ldr x0, [x0] +; ELF: braa x0, x1 + +; HINT-LABEL: test_tailcall_ia_arg_ind: +; HINT: ldr x17, [x0] +; HINT: mov x16, x1 +; HINT: autia1716 +; HINT: br x17 + %tmp0 = load ptr, ptr %arg0 + %tmp1 = tail call i32 %tmp0() [ "ptrauth"(i32 0, i64 %arg1) ] + ret i32 %tmp1 +} + +define i32 @test_tailcall_ib_arg_ind(ptr %arg0, i64 %arg1) #0 { +; ELF-LABEL: test_tailcall_ib_arg_ind: +; ELF: ldr x0, [x0] +; ELF: brab x0, x1 + +; HINT-LABEL: test_tailcall_ib_arg_ind: +; HINT: ldr x17, [x0] +; HINT: mov x16, x1 +; HINT: autib1716 +; HINT: br x17 + %tmp0 = load ptr, ptr %arg0 + %tmp1 = tail call i32 %tmp0() [ "ptrauth"(i32 1, i64 %arg1) ] + ret i32 %tmp1 +} + +; Test direct calls + +define i32 @test_direct_call() #0 { +; CHECK-LABEL: test_direct_call: +; CHECK-NEXT: str x30, [sp, #-16]! +; CHECK-NEXT: bl f +; CHECK-NEXT: ldr x30, [sp], #16 +; CHECK-NEXT: ret + %tmp0 = call i32 ptrauth(ptr @f, i32 0, i64 42)() [ "ptrauth"(i32 0, i64 42) ] + ret i32 %tmp0 +} + +define i32 @test_direct_tailcall(ptr %arg0) #0 { +; CHECK-LABEL: test_direct_tailcall: +; CHECK-NEXT: b f + %tmp0 = tail call i32 ptrauth(ptr @f, i32 0, i64 42)() [ "ptrauth"(i32 0, i64 42) ] + ret i32 %tmp0 +} + +define i32 @test_direct_call_mismatch() #0 { +; ELF-LABEL: test_direct_call_mismatch: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: adrp x17, :got:f +; ELF-NEXT: ldr x17, [x17, :got_lo12:f] +; ELF-NEXT: mov x16, #42 +; ELF-NEXT: pacia x17, x16 +; ELF-NEXT: mov x8, x17 +; ELF-NEXT: mov x17, #42 +; ELF-NEXT: blrab x8, x17 +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + +; HINT-LABEL: test_direct_call_mismatch: +; HINT-NEXT: str x30, [sp, #-16]! +; HINT-NEXT: adrp x17, :got:f +; HINT-NEXT: ldr x17, [x17, :got_lo12:f] +; HINT-NEXT: mov x16, #42 +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x16, #42 +; HINT-NEXT: autib1716 +; HINT-NEXT: blr x17 +; HINT-NEXT: ldr x30, [sp], #16 +; HINT-NEXT: ret + + %tmp0 = call i32 ptrauth(ptr @f, i32 0, i64 42)() [ "ptrauth"(i32 1, i64 42) ] + ret i32 %tmp0 +} + +define i32 @test_direct_call_addr() #0 { +; ELF-LABEL: test_direct_call_addr: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: bl f +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + %tmp0 = call i32 ptrauth(ptr @f, i32 1, i64 0, ptr @f.ref.ib.0.addr)() [ "ptrauth"(i32 1, i64 ptrtoint (ptr @f.ref.ib.0.addr to i64)) ] + ret i32 %tmp0 +} + +define i32 @test_direct_call_addr_blend() #0 { +; ELF-LABEL: test_direct_call_addr_blend: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: bl f +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + %tmp0 = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @f.ref.ib.42.addr to i64), i64 42) + %tmp1 = call i32 ptrauth(ptr @f, i32 1, i64 42, ptr @f.ref.ib.42.addr)() [ "ptrauth"(i32 1, i64 %tmp0) ] + ret i32 %tmp1 +} + +define i32 @test_direct_call_addr_gep_different_index_types() #0 { +; ELF-LABEL: test_direct_call_addr_gep_different_index_types: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: bl f +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + %tmp0 = call i32 ptrauth(ptr @f, i32 1, i64 0, ptr getelementptr ({ ptr }, ptr @f_struct.ref.ib.0.addr, i64 0, i32 0))() [ "ptrauth"(i32 1, i64 ptrtoint (ptr getelementptr ({ ptr }, ptr @f_struct.ref.ib.0.addr, i32 0, i32 0) to i64)) ] + ret i32 %tmp0 +} + +define i32 @test_direct_call_addr_blend_gep_different_index_types() #0 { +; ELF-LABEL: test_direct_call_addr_blend_gep_different_index_types: +; ELF-NEXT: str x30, [sp, #-16]! +; ELF-NEXT: bl f +; ELF-NEXT: ldr x30, [sp], #16 +; ELF-NEXT: ret + %tmp0 = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr getelementptr ({ ptr }, ptr @f_struct.ref.ib.123.addr, i32 0, i32 0) to i64), i64 123) + %tmp1 = call i32 ptrauth(ptr @f, i32 1, i64 123, ptr getelementptr ({ ptr }, ptr @f_struct.ref.ib.123.addr, i64 0, i32 0))() [ "ptrauth"(i32 1, i64 %tmp0) ] + ret i32 %tmp1 +} + +@f.ref.ib.42.addr = external global ptr +@f.ref.ib.0.addr = external global ptr +@f_struct.ref.ib.0.addr = external global ptr +@f_struct.ref.ib.123.addr = external global ptr + +declare void @f() + +declare i64 @llvm.ptrauth.auth(i64, i32, i64) +declare i64 @llvm.ptrauth.blend(i64, i64) + +attributes #0 = { nounwind } diff --git a/llvm/test/CodeGen/AArch64/ptrauth-hint-only-constant-in-code.ll b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-constant-in-code.ll new file mode 100644 index 0000000000000000000000000000000000000000..eb8fb01427ad0f1ce90a71bbd221dce1c8ce1ca4 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-constant-in-code.ll @@ -0,0 +1,409 @@ +; RUN: rm -rf %t && split-file %s %t && cd %t + +;--- err1.ll + +; RUN: not --crash llc < err1.ll -mtriple aarch64-elf -mattr=+pauth \ +; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR1 %s + +; RUN: not --crash llc < err1.ll -mtriple aarch64-elf -mattr=+pauth -mattr=+pauth-hint-only \ +; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR1 %s + +@g = external global i32 + +define ptr @foo() { +; ERR1: LLVM ERROR: key in ptrauth global out of range [0, 3] + ret ptr ptrauth (ptr @g, i32 4) +} + +;--- err2.ll + +; RUN: not --crash llc < err2.ll -mtriple aarch64-elf -mattr=+pauth \ +; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR2 %s + +; RUN: not --crash llc < err2.ll -mtriple aarch64-elf -mattr=+pauth -mattr=+pauth-hint-only \ +; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR2 %s + +@g = external global i32 + +define ptr @foo() { +; ERR2: LLVM ERROR: constant discriminator in ptrauth global out of range [0, 0xffff] + ret ptr ptrauth (ptr @g, i32 2, i64 65536) +} + +;--- err3.ll + +; RUN: not --crash llc < err3.ll -mtriple aarch64-elf -mattr=+pauth \ +; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR3 %s + +; RUN: not --crash llc < err3.ll -mtriple aarch64-elf -mattr=+pauth -mattr=+pauth-hint-only \ +; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR3 %s + +@g_weak = extern_weak global i32 + +define ptr @foo() { +; ERR3: LLVM ERROR: unsupported non-zero offset in weak ptrauth global reference + ret ptr ptrauth (ptr getelementptr (i8, ptr @g_weak, i64 16), i32 2, i64 42) +} + +;--- err4.ll + +; RUN: not --crash llc < err4.ll -mtriple aarch64-elf -mattr=+pauth \ +; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR4 %s + +; RUN: not --crash llc < err4.ll -mtriple aarch64-elf -mattr=+pauth -mattr=+pauth-hint-only \ +; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR4 %s + +@g_weak = extern_weak global i32 +@g_weak.ref.da.42.addr = dso_local constant ptr ptrauth (ptr @g_weak, i32 2, i64 42, ptr @g_weak.ref.da.42.addr) + +define ptr @foo() { +; ERR4: LLVM ERROR: unsupported weak addr-div ptrauth global + ret ptr ptrauth (ptr @g_weak, i32 0, i64 42, ptr @g_weak.ref.da.42.addr) +} + +;--- err5.ll + +; RUN: not --crash llc < err5.ll -mtriple aarch64-windows -mattr=+pauth \ +; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR5 %s + +; RUN: not --crash llc < err5.ll -mtriple aarch64-windows -mattr=+pauth -mattr=+pauth-hint-only \ +; RUN: -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR5 %s + +@g = external global i32 + +define ptr @foo() { +; ERR5: LLVM ERROR: ptrauth global lowering only supported on MachO/ELF + ret ptr ptrauth (ptr @g, i32 0) +} + +;--- ok.ll + +; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=0 \ +; RUN: -verify-machineinstrs | FileCheck %s --check-prefix=ELF +; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=0 \ +; RUN: -verify-machineinstrs -filetype=obj + +; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -mattr=+pauth-hint-only -global-isel=0 \ +; RUN: -verify-machineinstrs | FileCheck %s --check-prefix=HINT +; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -mattr=+pauth-hint-only -global-isel=0 \ +; RUN: -verify-machineinstrs -filetype=obj + + +@g = external global i32 +@g_weak = extern_weak global i32 +@g_strong_def = dso_local constant i32 42 + +define ptr @test_global_zero_disc() { +; ELF-LABEL: test_global_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: paciza x17 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_global_zero_disc: +; HINT: // %bb.0: +; HINT-NEXT: adrp x17, :got:g +; HINT-NEXT: ldr x17, [x17, :got_lo12:g] +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + + + ret ptr ptrauth (ptr @g, i32 0) +} + +define ptr @test_global_offset_zero_disc() { +; ELF-LABEL: test_global_offset_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: add x17, x17, #16 +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_global_offset_zero_disc: +; HINT: // %bb.0: +; HINT-NEXT: adrp x17, :got:g +; HINT-NEXT: ldr x17, [x17, :got_lo12:g] +; HINT-NEXT: add x17, x17, #16 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + + ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 16), i32 2) +} + +define ptr @test_global_neg_offset_zero_disc() { +; ELF-LABEL: test_global_neg_offset_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: sub x17, x17, #576 +; ELF-NEXT: sub x17, x17, #30, lsl #12 +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_global_neg_offset_zero_disc: +; HINT: // %bb.0: +; HINT-NEXT: adrp x17, :got:g +; HINT-NEXT: ldr x17, [x17, :got_lo12:g] +; HINT-NEXT: sub x17, x17, #576 +; HINT-NEXT: sub x17, x17, #30, lsl #12 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + + + ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456), i32 2) +} + +define ptr @test_global_big_offset_zero_disc() { +; ELF-LABEL: test_global_big_offset_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: mov x16, #1 +; ELF-NEXT: movk x16, #32769, lsl #16 +; ELF-NEXT: add x17, x17, x16 +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_global_big_offset_zero_disc: +; HINT: // %bb.0: +; HINT-NEXT: adrp x17, :got:g +; HINT-NEXT: ldr x17, [x17, :got_lo12:g] +; HINT-NEXT: mov x16, #1 +; HINT-NEXT: movk x16, #32769, lsl #16 +; HINT-NEXT: add x17, x17, x16 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + + + ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 add (i64 2147483648, i64 65537)), i32 2) +} + +define ptr @test_global_big_neg_offset_zero_disc() { +; ELF-LABEL: test_global_big_neg_offset_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: mov x16, #-52501 +; ELF-NEXT: movk x16, #63652, lsl #16 +; ELF-NEXT: add x17, x17, x16 +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_global_big_neg_offset_zero_disc: +; HINT: // %bb.0: +; HINT-NEXT: adrp x17, :got:g +; HINT-NEXT: ldr x17, [x17, :got_lo12:g] +; HINT-NEXT: mov x16, #-52501 +; HINT-NEXT: movk x16, #63652, lsl #16 +; HINT-NEXT: add x17, x17, x16 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + + + ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456789), i32 2) +} + +define ptr @test_global_huge_neg_offset_zero_disc() { +; ELF-LABEL: test_global_huge_neg_offset_zero_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: mov x16, #-65536 +; ELF-NEXT: movk x16, #0, lsl #16 +; ELF-NEXT: movk x16, #0, lsl #32 +; ELF-NEXT: movk x16, #32768, lsl #48 +; ELF-NEXT: add x17, x17, x16 +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_global_huge_neg_offset_zero_disc: +; HINT: // %bb.0: +; HINT-NEXT: adrp x17, :got:g +; HINT-NEXT: ldr x17, [x17, :got_lo12:g] +; HINT-NEXT: mov x16, #-65536 +; HINT-NEXT: movk x16, #0, lsl #16 +; HINT-NEXT: movk x16, #0, lsl #32 +; HINT-NEXT: movk x16, #32768, lsl #48 +; HINT-NEXT: add x17, x17, x16 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + + + ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -9223372036854775808), i32 2) +} + +define ptr @test_global_disc() { +; ELF-LABEL: test_global_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: mov x16, #42 // =0x2a +; ELF-NEXT: pacia x17, x16 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_global_disc: +; HINT: // %bb.0: +; HINT-NEXT: adrp x17, :got:g +; HINT-NEXT: ldr x17, [x17, :got_lo12:g] +; HINT-NEXT: mov x16, #42 // =0x2a +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + + + + ret ptr ptrauth (ptr @g, i32 0, i64 42) +} + +@g.ref.da.42.addr = dso_local constant ptr ptrauth (ptr @g, i32 2, i64 42, ptr @g.ref.da.42.addr) + +define ptr @test_global_addr_disc() { +; ELF-LABEL: test_global_addr_disc: +; ELF: // %bb.0: +; ELF-NEXT: adrp x8, g.ref.da.42.addr +; ELF-NEXT: add x8, x8, :lo12:g.ref.da.42.addr +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: mov x16, x8 +; ELF-NEXT: movk x16, #42, lsl #48 +; ELF-NEXT: pacda x17, x16 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_global_addr_disc: +; HINT: // %bb.0: +; HINT-NEXT: adrp x8, g.ref.da.42.addr +; HINT-NEXT: add x8, x8, :lo12:g.ref.da.42.addr +; HINT-NEXT: adrp x17, :got:g +; HINT-NEXT: ldr x17, [x17, :got_lo12:g] +; HINT-NEXT: mov x16, x8 +; HINT-NEXT: movk x16, #42, lsl #48 +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + + + ret ptr ptrauth (ptr @g, i32 2, i64 42, ptr @g.ref.da.42.addr) +} + +define ptr @test_global_process_specific() { +; ELF-LABEL: test_global_process_specific: +; ELF: // %bb.0: +; ELF-NEXT: adrp x17, :got:g +; ELF-NEXT: ldr x17, [x17, :got_lo12:g] +; ELF-NEXT: pacizb x17 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_global_process_specific: +; HINT: // %bb.0: +; HINT-NEXT: adrp x17, :got:g +; HINT-NEXT: ldr x17, [x17, :got_lo12:g] +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: pacib1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + + + + ret ptr ptrauth (ptr @g, i32 1) +} + +; Non-external symbols don't need to be accessed through the GOT. + +define ptr @test_global_strong_def() { +; ELF-LABEL: test_global_strong_def: +; ELF: // %bb.0: +; ELF-NEXT: adrp x17, g_strong_def +; ELF-NEXT: add x17, x17, :lo12:g_strong_def +; ELF-NEXT: pacdza x17 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_global_strong_def: +; HINT: // %bb.0: +; HINT-NEXT: adrp x17, g_strong_def +; HINT-NEXT: add x17, x17, :lo12:g_strong_def +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + + + + ret ptr ptrauth (ptr @g_strong_def, i32 2) +} + +; weak symbols can't be assumed to be non-nil. Use $auth_ptr$ stub slot always. +; The alternative is to emit a null-check here, but that'd be redundant with +; whatever null-check follows in user code. + +define ptr @test_global_weak() { +; ELF-LABEL: test_global_weak: +; ELF: // %bb.0: +; ELF-NEXT: adrp x0, g_weak$auth_ptr$ia$42 +; ELF-NEXT: ldr x0, [x0, :lo12:g_weak$auth_ptr$ia$42] +; ELF-NEXT: ret + +; HINT-LABEL: test_global_weak: +; HINT: // %bb.0: +; HINT-NEXT: adrp x0, g_weak$auth_ptr$ia$42 +; HINT-NEXT: ldr x0, [x0, :lo12:g_weak$auth_ptr$ia$42] +; HINT-NEXT: ret + + ret ptr ptrauth (ptr @g_weak, i32 0, i64 42) +} + +; Test another weak symbol to check that stubs are emitted in a stable order. + +@g_weak_2 = extern_weak global i32 + +define ptr @test_global_weak_2() { +; ELF-LABEL: test_global_weak_2: +; ELF: // %bb.0: +; ELF-NEXT: adrp x0, g_weak_2$auth_ptr$ia$42 +; ELF-NEXT: ldr x0, [x0, :lo12:g_weak_2$auth_ptr$ia$42] +; ELF-NEXT: ret + +; HINT-LABEL: test_global_weak_2: +; HINT: // %bb.0: +; HINT-NEXT: adrp x0, g_weak_2$auth_ptr$ia$42 +; HINT-NEXT: ldr x0, [x0, :lo12:g_weak_2$auth_ptr$ia$42] +; HINT-NEXT: ret + + + + ret ptr ptrauth (ptr @g_weak_2, i32 0, i64 42) +} + +; ELF-LABEL: g_weak$auth_ptr$ia$42: +; ELF-NEXT: .xword g_weak@AUTH(ia,42) +; ELF-LABEL: g_weak_2$auth_ptr$ia$42: +; ELF-NEXT: .xword g_weak_2@AUTH(ia,42) + +; HINT-LABEL: g_weak$auth_ptr$ia$42: +; HINT-NEXT: .xword g_weak@AUTH(ia,42) +; HINT-LABEL: g_weak_2$auth_ptr$ia$42: +; HINT-NEXT: .xword g_weak_2@AUTH(ia,42) + diff --git a/llvm/test/CodeGen/AArch64/ptrauth-hint-only-fpac.ll b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-fpac.ll new file mode 100644 index 0000000000000000000000000000000000000000..63ef7c897f42fb4df9cdab6e718e651e7aed6c03 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-fpac.ll @@ -0,0 +1,731 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py + +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -verify-machineinstrs \ +; RUN: | FileCheck %s -DL=".L" --check-prefixes=ELF,ELF-NOFPAC +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -mattr=+fpac -verify-machineinstrs \ +; RUN: | FileCheck %s -DL=".L" --check-prefixes=ELF,ELF-FPAC + +; FIXME: When we have support for nofpac, we should reeable this +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -mattr=+pauth-hint-only -verify-machineinstrs \ +; RUN-NOT: | FileCheck %s -DL=".L" --check-prefixes=HINT,HINT-NOFPAC +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -mattr=+pauth-hint-only -mattr=+fpac -verify-machineinstrs \ +; RUN: | FileCheck %s -DL=".L" --check-prefixes=HINT,HINT-FPAC + +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + +define i64 @test_auth_ia(i64 %arg, i64 %arg1) { +; ELF-LABEL: test_auth_ia: +; ELF: %bb.0: +; ELF-NEXT: mov x17, x0 +; ELF-NEXT: autia x17, x1 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_auth_ia: +; HINT: %bb.0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: autia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_auth_ia_zero(i64 %arg) { +; ELF-LABEL: test_auth_ia_zero: +; ELF: %bb.0: +; ELF-NEXT: mov x17, x0 +; ELF-NEXT: autiza x17 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_auth_ia_zero: +; HINT: %bb.0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: autia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 0) + ret i64 %tmp +} + +define i64 @test_auth_ib(i64 %arg, i64 %arg1) { +; ELF-LABEL: test_auth_ib: +; ELF: %bb.0: +; ELF-NEXT: mov x17, x0 +; ELF-NEXT: autib x17, x1 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_auth_ib: +; HINT: %bb.0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: autib1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 1, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_auth_ib_zero(i64 %arg) { +; ELF-LABEL: test_auth_ib_zero: +; ELF: %bb.0: +; ELF-NEXT: mov x17, x0 +; ELF-NEXT: autizb x17 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_auth_ib_zero: +; HINT: %bb.0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: autib1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 1, i64 0) + ret i64 %tmp +} + +define i64 @test_auth_da(i64 %arg, i64 %arg1) { +; ELF-LABEL: test_auth_da: +; ELF: %bb.0: +; ELF-NEXT: mov x17, x0 +; ELF-NEXT: autda x17, x1 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_auth_da: +; HINT: %bb.0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: autia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 2, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_auth_da_zero(i64 %arg) { +; ELF-LABEL: test_auth_da_zero: +; ELF: %bb.0: +; ELF-NEXT: mov x17, x0 +; ELF-NEXT: autdza x17 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_auth_da_zero: +; HINT: %bb.0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: autia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 2, i64 0) + ret i64 %tmp +} + +define i64 @test_auth_db(i64 %arg, i64 %arg1) { +; ELF-LABEL: test_auth_db: +; ELF: %bb.0: +; ELF-NEXT: mov x17, x0 +; ELF-NEXT: autdb x17, x1 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_auth_db: +; HINT: %bb.0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: autib1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 3, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_auth_db_zero(i64 %arg) { +; ELF-LABEL: test_auth_db_zero: +; ELF: %bb.0: +; ELF-NEXT: mov x17, x0 +; ELF-NEXT: autdzb x17 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret + +; HINT-LABEL: test_auth_db_zero: +; HINT: %bb.0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: autib1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 3, i64 0) + ret i64 %tmp +} + +; Note that this might seem like a no-op but is actually a valid way to enforce +; the validity of a signature. +define i64 @test_resign_ia_ia(i64 %arg, i64 %arg1, i64 %arg2) { +; ELF-NOFPAC-LABEL: test_resign_ia_ia: +; ELF-NOFPAC: %bb.0: +; ELF-NOFPAC-NEXT: mov x17, x0 +; ELF-NOFPAC-NEXT: autia x17, x1 +; ELF-NOFPAC-NEXT: mov x16, x17 +; ELF-NOFPAC-NEXT: xpaci x16 +; ELF-NOFPAC-NEXT: cmp x16, x17 +; ELF-NOFPAC-NEXT: b.eq [[L]]auth_success_0 +; ELF-NOFPAC-NEXT: mov x17, x16 +; ELF-NOFPAC-NEXT: b [[L]]resign_end_0 +; ELF-NOFPAC-NEXT: Lauth_success_0: +; ELF-NOFPAC-NEXT: pacia x17, x2 +; ELF-NOFPAC-NEXT: Lresign_end_0: +; ELF-NOFPAC-NEXT: mov x0, x17 +; ELF-NOFPAC-NEXT: ret +; +; ELF-FPAC-LABEL: test_resign_ia_ia: +; ELF-FPAC: %bb.0: +; ELF-FPAC-NEXT: mov x17, x0 +; ELF-FPAC-NEXT: autia x17, x1 +; ELF-FPAC-NEXT: pacia x17, x2 +; ELF-FPAC-NEXT: mov x0, x17 +; ELF-FPAC-NEXT: ret + +; HINT-NOFPAC-LABEL: test_resign_ia_ia: +; HINT-NOFPAC: %bb.0: +; HINT-NOFPAC-NEXT: mov x17, x0 +; HINT-NOFPAC-NEXT: mov x16, x1 +; HINT-NOFPAC-NEXT: autia1716 +; HINT-NOFPAC-NEXT: mov x30, x17 +; HINT-NOFPAC-NEXT: xpaclri +; HINT-NOFPAC-NEXT: mov x16, x30 +; HINT-NOFPAC-NEXT: cmp x16, x17 +; HINT-NOFPAC-NEXT: b.eq [[L]]auth_success_0 +; HINT-NOFPAC-NEXT: mov x17, x16 +; HINT-NOFPAC-NEXT: b [[L]]resign_end_0 +; HINT-NOFPAC-NEXT: Lauth_success_0: +; HINT-NOFPAC-NEXT: mov x16, x2 +; HINT-NOFPAC-NEXT: pacia1716 +; HINT-NOFPAC-NEXT: Lresign_end_0: +; HINT-NOFPAC-NEXT: mov x0, x17 +; HINT-NOFPAC-NEXT: ret +; +; HINT-FPAC-LABEL: test_resign_ia_ia: +; HINT-FPAC: %bb.0: +; HINT-FPAC-NEXT: mov x17, x0 +; HINT-FPAC-NEXT: mov x16, x1 +; HINT-FPAC-NEXT: autia1716 +; HINT-FPAC-NEXT: mov x16, x2 +; HINT-FPAC-NEXT: pacia1716 +; HINT-FPAC-NEXT: mov x0, x17 +; HINT-FPAC-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 0, i64 %arg1, i32 0, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_ib_ia(i64 %arg, i64 %arg1, i64 %arg2) { +; ELF-NOFPAC-LABEL: test_resign_ib_ia: +; ELF-NOFPAC: %bb.0: +; ELF-NOFPAC-NEXT: mov x17, x0 +; ELF-NOFPAC-NEXT: autib x17, x1 +; ELF-NOFPAC-NEXT: mov x16, x17 +; ELF-NOFPAC-NEXT: xpaci x16 +; ELF-NOFPAC-NEXT: cmp x16, x17 +; ELF-NOFPAC-NEXT: b.eq [[L]]auth_success_1 +; ELF-NOFPAC-NEXT: mov x17, x16 +; ELF-NOFPAC-NEXT: b [[L]]resign_end_1 +; ELF-NOFPAC-NEXT: Lauth_success_1: +; ELF-NOFPAC-NEXT: pacia x17, x2 +; ELF-NOFPAC-NEXT: Lresign_end_1: +; ELF-NOFPAC-NEXT: mov x0, x17 +; ELF-NOFPAC-NEXT: ret +; +; ELF-FPAC-LABEL: test_resign_ib_ia: +; ELF-FPAC: %bb.0: +; ELF-FPAC-NEXT: mov x17, x0 +; ELF-FPAC-NEXT: autib x17, x1 +; ELF-FPAC-NEXT: pacia x17, x2 +; ELF-FPAC-NEXT: mov x0, x17 +; ELF-FPAC-NEXT: ret +; +; HINT-NOFPAC-LABEL: test_resign_ib_ia: +; HINT-NOFPAC: %bb.0: +; HINT-NOFPAC-NEXT: mov x17, x0 +; HINT-NOFPAC-NEXT: mov x16, x1 +; HINT-NOFPAC-NEXT: autib1716 +; HINT-NOFPAC-NEXT: mov x30, x17 +; HINT-NOFPAC-NEXT: xpaclri +; HINT-NOFPAC-NEXT: mov x16, x30 +; HINT-NOFPAC-NEXT: cmp x16, x17 +; HINT-NOFPAC-NEXT: b.eq [[L]]auth_success_1 +; HINT-NOFPAC-NEXT: mov x17, x16 +; HINT-NOFPAC-NEXT: b [[L]]resign_end_1 +; HINT-NOFPAC-NEXT: Lauth_success_1: +; HINT-NOFPAC-NEXT: mov x16, x2 +; HINT-NOFPAC-NEXT: pacia1716 +; HINT-NOFPAC-NEXT: Lresign_end_1: +; HINT-NOFPAC-NEXT: mov x0, x17 +; HINT-NOFPAC-NEXT: ret +; +; HINT-FPAC-LABEL: test_resign_ib_ia: +; HINT-FPAC: %bb.0: +; HINT-FPAC-NEXT: mov x17, x0 +; HINT-FPAC-NEXT: mov x16, x1 +; HINT-FPAC-NEXT: autib1716 +; HINT-FPAC-NEXT: mov x16, x2 +; HINT-FPAC-NEXT: pacia1716 +; HINT-FPAC-NEXT: mov x0, x17 +; HINT-FPAC-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 1, i64 %arg1, i32 0, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_da_ia(i64 %arg, i64 %arg1, i64 %arg2) { +; ELF-NOFPAC-LABEL: test_resign_da_ia: +; ELF-NOFPAC: %bb.0: +; ELF-NOFPAC-NEXT: mov x17, x0 +; ELF-NOFPAC-NEXT: autda x17, x1 +; ELF-NOFPAC-NEXT: mov x16, x17 +; ELF-NOFPAC-NEXT: xpacd x16 +; ELF-NOFPAC-NEXT: cmp x16, x17 +; ELF-NOFPAC-NEXT: b.eq [[L]]auth_success_2 +; ELF-NOFPAC-NEXT: mov x17, x16 +; ELF-NOFPAC-NEXT: b [[L]]resign_end_2 +; ELF-NOFPAC-NEXT: Lauth_success_2: +; ELF-NOFPAC-NEXT: pacia x17, x2 +; ELF-NOFPAC-NEXT: Lresign_end_2: +; ELF-NOFPAC-NEXT: mov x0, x17 +; ELF-NOFPAC-NEXT: ret +; +; ELF-FPAC-LABEL: test_resign_da_ia: +; ELF-FPAC: %bb.0: +; ELF-FPAC-NEXT: mov x17, x0 +; ELF-FPAC-NEXT: autda x17, x1 +; ELF-FPAC-NEXT: pacia x17, x2 +; ELF-FPAC-NEXT: mov x0, x17 +; ELF-FPAC-NEXT: ret +; +; HINT-NOFPAC-LABEL: test_resign_da_ia: +; HINT-NOFPAC: %bb.0: +; HINT-NOFPAC-NEXT: mov x17, x0 +; HINT-NOFPAC-NEXT: mov x16, x1 +; HINT-NOFPAC-NEXT: autia1716 +; HINT-NOFPAC-NEXT: mov x30, x17 +; HINT-NOFPAC-NEXT: xpaclri +; HINT-NOFPAC-NEXT: mov x16, x30 +; HINT-NOFPAC-NEXT: cmp x16, x17 +; HINT-NOFPAC-NEXT: b.eq [[L]]auth_success_2 +; HINT-NOFPAC-NEXT: mov x17, x16 +; HINT-NOFPAC-NEXT: b [[L]]resign_end_2 +; HINT-NOFPAC-NEXT: Lauth_success_2: +; HINT-NOFPAC-NEXT: mov x16, x2 +; HINT-NOFPAC-NEXT: pacia1716 +; HINT-NOFPAC-NEXT: Lresign_end_2: +; HINT-NOFPAC-NEXT: mov x0, x17 +; HINT-NOFPAC-NEXT: ret +; +; HINT-FPAC-LABEL: test_resign_da_ia: +; HINT-FPAC: %bb.0: +; HINT-FPAC-NEXT: mov x17, x0 +; HINT-FPAC-NEXT: mov x16, x1 +; HINT-FPAC-NEXT: autia1716 +; HINT-FPAC-NEXT: mov x16, x2 +; HINT-FPAC-NEXT: pacia1716 +; HINT-FPAC-NEXT: mov x0, x17 +; HINT-FPAC-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %arg1, i32 0, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_db_ia(i64 %arg, i64 %arg1, i64 %arg2) { +; ELF-NOFPAC-LABEL: test_resign_db_ia: +; ELF-NOFPAC: %bb.0: +; ELF-NOFPAC-NEXT: mov x17, x0 +; ELF-NOFPAC-NEXT: autdb x17, x1 +; ELF-NOFPAC-NEXT: mov x16, x17 +; ELF-NOFPAC-NEXT: xpacd x16 +; ELF-NOFPAC-NEXT: cmp x16, x17 +; ELF-NOFPAC-NEXT: b.eq [[L]]auth_success_3 +; ELF-NOFPAC-NEXT: mov x17, x16 +; ELF-NOFPAC-NEXT: b [[L]]resign_end_3 +; ELF-NOFPAC-NEXT: Lauth_success_3: +; ELF-NOFPAC-NEXT: pacia x17, x2 +; ELF-NOFPAC-NEXT: Lresign_end_3: +; ELF-NOFPAC-NEXT: mov x0, x17 +; ELF-NOFPAC-NEXT: ret +; +; ELF-FPAC-LABEL: test_resign_db_ia: +; ELF-FPAC: %bb.0: +; ELF-FPAC-NEXT: mov x17, x0 +; ELF-FPAC-NEXT: autdb x17, x1 +; ELF-FPAC-NEXT: pacia x17, x2 +; ELF-FPAC-NEXT: mov x0, x17 +; ELF-FPAC-NEXT: ret +; +; HINT-NOFPAC-LABEL: test_resign_db_ia: +; HINT-NOFPAC: %bb.0: +; HINT-NOFPAC-NEXT: mov x17, x0 +; HINT-NOFPAC-NEXT: mov x16, x1 +; HINT-NOFPAC-NEXT: autib1716 +; HINT-NOFPAC-NEXT: mov x30, x17 +; HINT-NOFPAC-NEXT: xpaclri +; HINT-NOFPAC-NEXT: mov x16, x30 +; HINT-NOFPAC-NEXT: cmp x16, x17 +; HINT-NOFPAC-NEXT: b.eq [[L]]auth_success_3 +; HINT-NOFPAC-NEXT: mov x17, x16 +; HINT-NOFPAC-NEXT: b [[L]]resign_end_3 +; HINT-NOFPAC-NEXT: Lauth_success_3: +; HINT-NOFPAC-NEXT: mov x16, x2 +; HINT-NOFPAC-NEXT: pacia1716 +; HINT-NOFPAC-NEXT: Lresign_end_3: +; HINT-NOFPAC-NEXT: mov x0, x17 +; HINT-NOFPAC-NEXT: ret +; +; HINT-FPAC-LABEL: test_resign_db_ia: +; HINT-FPAC: %bb.0: +; HINT-FPAC-NEXT: mov x17, x0 +; HINT-FPAC-NEXT: mov x16, x1 +; HINT-FPAC-NEXT: autib1716 +; HINT-FPAC-NEXT: mov x16, x2 +; HINT-FPAC-NEXT: pacia1716 +; HINT-FPAC-NEXT: mov x0, x17 +; HINT-FPAC-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 3, i64 %arg1, i32 0, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_db_ib(i64 %arg, i64 %arg1, i64 %arg2) { +; ELF-NOFPAC-LABEL: test_resign_db_ib: +; ELF-NOFPAC: %bb.0: +; ELF-NOFPAC-NEXT: mov x17, x0 +; ELF-NOFPAC-NEXT: autdb x17, x1 +; ELF-NOFPAC-NEXT: mov x16, x17 +; ELF-NOFPAC-NEXT: xpacd x16 +; ELF-NOFPAC-NEXT: cmp x16, x17 +; ELF-NOFPAC-NEXT: b.eq [[L]]auth_success_4 +; ELF-NOFPAC-NEXT: mov x17, x16 +; ELF-NOFPAC-NEXT: b [[L]]resign_end_4 +; ELF-NOFPAC-NEXT: Lauth_success_4: +; ELF-NOFPAC-NEXT: pacib x17, x2 +; ELF-NOFPAC-NEXT: Lresign_end_4: +; ELF-NOFPAC-NEXT: mov x0, x17 +; ELF-NOFPAC-NEXT: ret +; +; ELF-FPAC-LABEL: test_resign_db_ib: +; ELF-FPAC: %bb.0: +; ELF-FPAC-NEXT: mov x17, x0 +; ELF-FPAC-NEXT: autdb x17, x1 +; ELF-FPAC-NEXT: pacib x17, x2 +; ELF-FPAC-NEXT: mov x0, x17 +; ELF-FPAC-NEXT: ret +; +; HINT-NOFPAC-LABEL: test_resign_db_ib: +; HINT-NOFPAC: %bb.0: +; HINT-NOFPAC-NEXT: mov x17, x0 +; HINT-NOFPAC-NEXT: mov x16, x1 +; HINT-NOFPAC-NEXT: autib1716 +; HINT-NOFPAC-NEXT: mov x30, x17 +; HINT-NOFPAC-NEXT: xpaclri +; HINT-NOFPAC-NEXT: mov x16, x30 +; HINT-NOFPAC-NEXT: cmp x16, x17 +; HINT-NOFPAC-NEXT: b.eq [[L]]auth_success_4 +; HINT-NOFPAC-NEXT: mov x17, x16 +; HINT-NOFPAC-NEXT: b [[L]]resign_end_4 +; HINT-NOFPAC-NEXT: Lauth_success_4: +; HINT-NOFPAC-NEXT: mov x16, x2 +; HINT-NOFPAC-NEXT: pacib1716 +; HINT-NOFPAC-NEXT: Lresign_end_4: +; HINT-NOFPAC-NEXT: mov x0, x17 +; HINT-NOFPAC-NEXT: ret +; +; HINT-FPAC-LABEL: test_resign_db_ib: +; HINT-FPAC: %bb.0: +; HINT-FPAC-NEXT: mov x17, x0 +; HINT-FPAC-NEXT: mov x16, x1 +; HINT-FPAC-NEXT: autib1716 +; HINT-FPAC-NEXT: mov x16, x2 +; HINT-FPAC-NEXT: pacib1716 +; HINT-FPAC-NEXT: mov x0, x17 +; HINT-FPAC-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 3, i64 %arg1, i32 1, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_db_da(i64 %arg, i64 %arg1, i64 %arg2) { +; ELF-NOFPAC-LABEL: test_resign_db_da: +; ELF-NOFPAC: %bb.0: +; ELF-NOFPAC-NEXT: mov x17, x0 +; ELF-NOFPAC-NEXT: autdb x17, x1 +; ELF-NOFPAC-NEXT: mov x16, x17 +; ELF-NOFPAC-NEXT: xpacd x16 +; ELF-NOFPAC-NEXT: cmp x16, x17 +; ELF-NOFPAC-NEXT: b.eq [[L]]auth_success_5 +; ELF-NOFPAC-NEXT: mov x17, x16 +; ELF-NOFPAC-NEXT: b [[L]]resign_end_5 +; ELF-NOFPAC-NEXT: Lauth_success_5: +; ELF-NOFPAC-NEXT: pacda x17, x2 +; ELF-NOFPAC-NEXT: Lresign_end_5: +; ELF-NOFPAC-NEXT: mov x0, x17 +; ELF-NOFPAC-NEXT: ret +; +; ELF-FPAC-LABEL: test_resign_db_da: +; ELF-FPAC: %bb.0: +; ELF-FPAC-NEXT: mov x17, x0 +; ELF-FPAC-NEXT: autdb x17, x1 +; ELF-FPAC-NEXT: pacda x17, x2 +; ELF-FPAC-NEXT: mov x0, x17 +; ELF-FPAC-NEXT: ret +; +; HINT-NOFPAC-LABEL: test_resign_db_da: +; HINT-NOFPAC: %bb.0: +; HINT-NOFPAC-NEXT: mov x17, x0 +; HINT-NOFPAC-NEXT: mov x16, x1 +; HINT-NOFPAC-NEXT: autib1716 +; HINT-NOFPAC-NEXT: mov x30, x17 +; HINT-NOFPAC-NEXT: xpaclri +; HINT-NOFPAC-NEXT: mov x16, x30 +; HINT-NOFPAC-NEXT: cmp x16, x17 +; HINT-NOFPAC-NEXT: b.eq [[L]]auth_success_5 +; HINT-NOFPAC-NEXT: mov x17, x16 +; HINT-NOFPAC-NEXT: b [[L]]resign_end_5 +; HINT-NOFPAC-NEXT: Lauth_success_5: +; HINT-NOFPAC-NEXT: mov x16, x2 +; HINT-NOFPAC-NEXT: pacia1716 +; HINT-NOFPAC-NEXT: Lresign_end_5: +; HINT-NOFPAC-NEXT: mov x0, x17 +; HINT-NOFPAC-NEXT: ret +; +; HINT-FPAC-LABEL: test_resign_db_da: +; HINT-FPAC: %bb.0: +; HINT-FPAC-NEXT: mov x17, x0 +; HINT-FPAC-NEXT: mov x16, x1 +; HINT-FPAC-NEXT: autib1716 +; HINT-FPAC-NEXT: mov x16, x2 +; HINT-FPAC-NEXT: pacia1716 +; HINT-FPAC-NEXT: mov x0, x17 +; HINT-FPAC-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 3, i64 %arg1, i32 2, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_db_db(i64 %arg, i64 %arg1, i64 %arg2) { +; ELF-NOFPAC-LABEL: test_resign_db_db: +; ELF-NOFPAC: %bb.0: +; ELF-NOFPAC-NEXT: mov x17, x0 +; ELF-NOFPAC-NEXT: autdb x17, x1 +; ELF-NOFPAC-NEXT: mov x16, x17 +; ELF-NOFPAC-NEXT: xpacd x16 +; ELF-NOFPAC-NEXT: cmp x16, x17 +; ELF-NOFPAC-NEXT: b.eq [[L]]auth_success_6 +; ELF-NOFPAC-NEXT: mov x17, x16 +; ELF-NOFPAC-NEXT: b [[L]]resign_end_6 +; ELF-NOFPAC-NEXT: Lauth_success_6: +; ELF-NOFPAC-NEXT: pacdb x17, x2 +; ELF-NOFPAC-NEXT: Lresign_end_6: +; ELF-NOFPAC-NEXT: mov x0, x17 +; ELF-NOFPAC-NEXT: ret +; +; ELF-FPAC-LABEL: test_resign_db_db: +; ELF-FPAC: %bb.0: +; ELF-FPAC-NEXT: mov x17, x0 +; ELF-FPAC-NEXT: autdb x17, x1 +; ELF-FPAC-NEXT: pacdb x17, x2 +; ELF-FPAC-NEXT: mov x0, x17 +; ELF-FPAC-NEXT: ret +; +; HINT-NOFPAC-LABEL: test_resign_db_db: +; HINT-NOFPAC: %bb.0: +; HINT-NOFPAC-NEXT: mov x17, x0 +; HINT-NOFPAC-NEXT: mov x16, x1 +; HINT-NOFPAC-NEXT: autib1716 +; HINT-NOFPAC-NEXT: mov x30, x17 +; HINT-NOFPAC-NEXT: xpaclri +; HINT-NOFPAC-NEXT: mov x16, x30 +; HINT-NOFPAC-NEXT: cmp x16, x17 +; HINT-NOFPAC-NEXT: b.eq [[L]]auth_success_6 +; HINT-NOFPAC-NEXT: mov x17, x16 +; HINT-NOFPAC-NEXT: b [[L]]resign_end_6 +; HINT-NOFPAC-NEXT: Lauth_success_6: +; HINT-NOFPAC-NEXT: mov x16, x2 +; HINT-NOFPAC-NEXT: pacib1716 +; HINT-NOFPAC-NEXT: Lresign_end_6: +; HINT-NOFPAC-NEXT: mov x0, x17 +; HINT-NOFPAC-NEXT: ret +; +; HINT-FPAC-LABEL: test_resign_db_db: +; HINT-FPAC: %bb.0: +; HINT-FPAC-NEXT: mov x17, x0 +; HINT-FPAC-NEXT: mov x16, x1 +; HINT-FPAC-NEXT: autib1716 +; HINT-FPAC-NEXT: mov x16, x2 +; HINT-FPAC-NEXT: pacib1716 +; HINT-FPAC-NEXT: mov x0, x17 +; HINT-FPAC-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 3, i64 %arg1, i32 3, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_iza_db(i64 %arg, i64 %arg1, i64 %arg2) { +; ELF-NOFPAC-LABEL: test_resign_iza_db: +; ELF-NOFPAC: %bb.0: +; ELF-NOFPAC-NEXT: mov x17, x0 +; ELF-NOFPAC-NEXT: autiza x17 +; ELF-NOFPAC-NEXT: mov x16, x17 +; ELF-NOFPAC-NEXT: xpaci x16 +; ELF-NOFPAC-NEXT: cmp x16, x17 +; ELF-NOFPAC-NEXT: b.eq [[L]]auth_success_7 +; ELF-NOFPAC-NEXT: mov x17, x16 +; ELF-NOFPAC-NEXT: b [[L]]resign_end_7 +; ELF-NOFPAC-NEXT: Lauth_success_7: +; ELF-NOFPAC-NEXT: pacdb x17, x2 +; ELF-NOFPAC-NEXT: Lresign_end_7: +; ELF-NOFPAC-NEXT: mov x0, x17 +; ELF-NOFPAC-NEXT: ret +; +; ELF-FPAC-LABEL: test_resign_iza_db: +; ELF-FPAC: %bb.0: +; ELF-FPAC-NEXT: mov x17, x0 +; ELF-FPAC-NEXT: autiza x17 +; ELF-FPAC-NEXT: pacdb x17, x2 +; ELF-FPAC-NEXT: mov x0, x17 +; ELF-FPAC-NEXT: ret +; +; HINT-NOFPAC-LABEL: test_resign_iza_db: +; HINT-NOFPAC: %bb.0: +; HINT-NOFPAC-NEXT: mov x17, x0 +; HINT-NOFPAC-NEXT: mov x16, xzr +; HINT-NOFPAC-NEXT: autia1716 +; HINT-NOFPAC-NEXT: mov x30, x17 +; HINT-NOFPAC-NEXT: xpaclri +; HINT-NOFPAC-NEXT: mov x16, x30 +; HINT-NOFPAC-NEXT: cmp x16, x17 +; HINT-NOFPAC-NEXT: b.eq [[L]]auth_success_7 +; HINT-NOFPAC-NEXT: mov x17, x16 +; HINT-NOFPAC-NEXT: b [[L]]resign_end_7 +; HINT-NOFPAC-NEXT: Lauth_success_7: +; HINT-NOFPAC-NEXT: mov x16, x2 +; HINT-NOFPAC-NEXT: pacib1716 +; HINT-NOFPAC-NEXT: Lresign_end_7: +; HINT-NOFPAC-NEXT: mov x0, x17 +; HINT-NOFPAC-NEXT: ret +; +; HINT-FPAC-LABEL: test_resign_iza_db: +; HINT-FPAC: %bb.0: +; HINT-FPAC-NEXT: mov x17, x0 +; HINT-FPAC-NEXT: mov x16, xzr +; HINT-FPAC-NEXT: autia1716 +; HINT-FPAC-NEXT: mov x16, x2 +; HINT-FPAC-NEXT: pacib1716 +; HINT-FPAC-NEXT: mov x0, x17 +; HINT-FPAC-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 0, i64 0, i32 3, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_da_dzb(i64 %arg, i64 %arg1, i64 %arg2) { +; ELF-NOFPAC-LABEL: test_resign_da_dzb: +; ELF-NOFPAC: %bb.0: +; ELF-NOFPAC-NEXT: mov x17, x0 +; ELF-NOFPAC-NEXT: autda x17, x1 +; ELF-NOFPAC-NEXT: mov x16, x17 +; ELF-NOFPAC-NEXT: xpacd x16 +; ELF-NOFPAC-NEXT: cmp x16, x17 +; ELF-NOFPAC-NEXT: b.eq [[L]]auth_success_8 +; ELF-NOFPAC-NEXT: mov x17, x16 +; ELF-NOFPAC-NEXT: b [[L]]resign_end_8 +; ELF-NOFPAC-NEXT: Lauth_success_8: +; ELF-NOFPAC-NEXT: pacdzb x17 +; ELF-NOFPAC-NEXT: Lresign_end_8: +; ELF-NOFPAC-NEXT: mov x0, x17 +; ELF-NOFPAC-NEXT: ret +; +; ELF-FPAC-LABEL: test_resign_da_dzb: +; ELF-FPAC: %bb.0: +; ELF-FPAC-NEXT: mov x17, x0 +; ELF-FPAC-NEXT: autda x17, x1 +; ELF-FPAC-NEXT: pacdzb x17 +; ELF-FPAC-NEXT: mov x0, x17 +; ELF-FPAC-NEXT: ret +; +; HINT-NOFPAC-LABEL: test_resign_da_dzb: +; HINT-NOFPAC: %bb.0: +; HINT-NOFPAC-NEXT: mov x17, x0 +; HINT-NOFPAC-NEXT: mov x16, x1 +; HINT-NOFPAC-NEXT: autia1716 +; HINT-NOFPAC-NEXT: mov x30, x17 +; HINT-NOFPAC-NEXT: xpaclri +; HINT-NOFPAC-NEXT: mov x16, x30 +; HINT-NOFPAC-NEXT: cmp x16, x17 +; HINT-NOFPAC-NEXT: b.eq [[L]]auth_success_8 +; HINT-NOFPAC-NEXT: mov x17, x16 +; HINT-NOFPAC-NEXT: b [[L]]resign_end_8 +; HINT-NOFPAC-NEXT: Lauth_success_8: +; HINT-NOFPAC-NEXT: mov x16, xzr +; HINT-NOFPAC-NEXT: pacib1716 +; HINT-NOFPAC-NEXT: Lresign_end_8: +; HINT-NOFPAC-NEXT: mov x0, x17 +; HINT-NOFPAC-NEXT: ret +; +; HINT-FPAC-LABEL: test_resign_da_dzb: +; HINT-FPAC: %bb.0: +; HINT-FPAC-NEXT: mov x17, x0 +; HINT-FPAC-NEXT: mov x16, x1 +; HINT-FPAC-NEXT: autia1716 +; HINT-FPAC-NEXT: mov x16, xzr +; HINT-FPAC-NEXT: pacib1716 +; HINT-FPAC-NEXT: mov x0, x17 +; HINT-FPAC-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %arg1, i32 3, i64 0) + ret i64 %tmp +} + +define i64 @test_auth_trap_attribute(i64 %arg, i64 %arg1) "ptrauth-auth-traps" { +; ELF-NOFPAC-LABEL: test_auth_trap_attribute: +; ELF-NOFPAC: %bb.0: +; ELF-NOFPAC-NEXT: mov x17, x0 +; ELF-NOFPAC-NEXT: autia x17, x1 +; ELF-NOFPAC-NEXT: mov x16, x17 +; ELF-NOFPAC-NEXT: xpaci x16 +; ELF-NOFPAC-NEXT: cmp x16, x17 +; ELF-NOFPAC-NEXT: b.eq [[L]]auth_success_9 +; ELF-NOFPAC-NEXT: brk #0xc470 +; ELF-NOFPAC-NEXT: Lauth_success_9: +; ELF-NOFPAC-NEXT: mov x0, x17 +; ELF-NOFPAC-NEXT: ret +; +; ELF-FPAC-LABEL: test_auth_trap_attribute: +; ELF-FPAC: %bb.0: +; ELF-FPAC-NEXT: mov x17, x0 +; ELF-FPAC-NEXT: autia x17, x1 +; ELF-FPAC-NEXT: mov x0, x17 +; ELF-FPAC-NEXT: ret +; +; HINT-NOFPAC-LABEL: test_auth_trap_attribute: +; HINT-NOFPAC: %bb.0: +; HINT-NOFPAC-NEXT: mov x17, x0 +; HINT-NOFPAC-NEXT: mov x16, x1 +; HINT-NOFPAC-NEXT: autia1716 +; HINT-NOFPAC-NEXT: mov x30, x17 +; HINT-NOFPAC-NEXT: xpaclri +; HINT-NOFPAC-NEXT: mov x16, x30 +; HINT-NOFPAC-NEXT: cmp x16, x17 +; HINT-NOFPAC-NEXT: b.eq [[L]]auth_success_9 +; HINT-NOFPAC-NEXT: brk #0xc470 +; HINT-NOFPAC-NEXT: Lauth_success_9: +; HINT-NOFPAC-NEXT: mov x0, x17 +; HINT-NOFPAC-NEXT: ret + +; HINT-FPAC-LABEL: test_auth_trap_attribute: +; HINT-FPAC: %bb.0: +; HINT-FPAC-NEXT: mov x17, x0 +; HINT-FPAC-NEXT: mov x16, x1 +; HINT-FPAC-NEXT: autia1716 +; HINT-FPAC-NEXT: mov x0, x17 +; HINT-FPAC-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 %arg1) + ret i64 %tmp +} + +declare i64 @llvm.ptrauth.auth(i64, i32, i64) +declare i64 @llvm.ptrauth.resign(i64, i32, i64, i32, i64) diff --git a/llvm/test/CodeGen/AArch64/ptrauth-hint-only-indirectbr.ll b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-indirectbr.ll new file mode 100644 index 0000000000000000000000000000000000000000..daf9596e1692da010905bc9b330d86ce534c7824 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-indirectbr.ll @@ -0,0 +1,251 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 + +; RUN: llc -mtriple aarch64-elf -mattr=+pauth \ +; RUN: \ +; RUN: -aarch64-min-jump-table-entries=1 -aarch64-enable-atomic-cfg-tidy=0 \ +; RUN: -o - %s | FileCheck %s --check-prefix=ELF + +; RUN: llc -mtriple aarch64-elf -mattr=+pauth \ +; RUN: -fast-isel \ +; RUN: -aarch64-min-jump-table-entries=1 -aarch64-enable-atomic-cfg-tidy=0 \ +; RUN: -o - %s | FileCheck %s --check-prefix=ELF + +; RUN-NOT: llc -mtriple aarch64-elf -mattr=+pauth \ +; RUN-NOT: -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -aarch64-min-jump-table-entries=1 -aarch64-enable-atomic-cfg-tidy=0 \ +; RUN-NOT: -o - %s | FileCheck %s --check-prefix=ELF + +; RUN: llc -mtriple aarch64 -mattr=+pauth -mattr=+pauth-hint-only \ +; RUN: \ +; RUN: -aarch64-min-jump-table-entries=1 -aarch64-enable-atomic-cfg-tidy=0 \ +; RUN: -o - %s | FileCheck %s --check-prefix=HINT + +; RUN: llc -mtriple aarch64 -mattr=+pauth -mattr=+pauth-hint-only \ +; RUN: -fast-isel \ +; RUN: -aarch64-min-jump-table-entries=1 -aarch64-enable-atomic-cfg-tidy=0 \ +; RUN: -o - %s | FileCheck %s --check-prefix=HINT + +; RUN-NOT: llc -mtriple aarch64 -mattr=+pauth -mattr=+pauth-hint-only \ +; RUN-NOT: -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -aarch64-min-jump-table-entries=1 -aarch64-enable-atomic-cfg-tidy=0 \ +; RUN-NOT: -o - %s | FileCheck %s --check-prefix=HINT + +;; The discriminator is the same for all blockaddresses in the function. +;; ptrauth_string_discriminator("test_indirectbr blockaddress") == 34947 + +define i32 @test_indirectbr() #0 { +; ELF-LABEL: test_indirectbr: +; ELF: // %bb.0: // %entry +; ELF-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; ELF-NEXT: adrp x17, .Ltmp0 +; ELF-NEXT: add x17, x17, :lo12:.Ltmp0 +; ELF-NEXT: mov x16, #34947 // =0x8883 +; ELF-NEXT: pacia x17, x16 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: adrp x17, .Ltmp1 +; ELF-NEXT: add x17, x17, :lo12:.Ltmp1 +; ELF-NEXT: mov x16, #34947 // =0x8883 +; ELF-NEXT: pacia x17, x16 +; ELF-NEXT: mov x1, x17 +; ELF-NEXT: bl dummy_choose +; ELF-NEXT: mov x17, #34947 // =0x8883 +; ELF-NEXT: braa x0, x17 +; ELF-NEXT: .Ltmp0: // Block address taken +; ELF-NEXT: .LBB0_1: // %bb1 +; ELF-NEXT: mov w0, #1 // =0x1 +; ELF-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; ELF-NEXT: ret +; ELF-NEXT: .Ltmp1: // Block address taken +; ELF-NEXT: .LBB0_2: // %bb2 +; ELF-NEXT: mov w0, #2 // =0x2 +; ELF-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; ELF-NEXT: ret +; +; HINT-LABEL: test_indirectbr: +; HINT: // %bb.0: // %entry +; HINT-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; HINT-NEXT: adrp x17, .Ltmp0 +; HINT-NEXT: add x17, x17, :lo12:.Ltmp0 +; HINT-NEXT: mov x16, #34947 // =0x8883 +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: adrp x17, .Ltmp1 +; HINT-NEXT: add x17, x17, :lo12:.Ltmp1 +; HINT-NEXT: mov x16, #34947 // =0x8883 +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x1, x17 +; HINT-NEXT: bl dummy_choose +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, #34947 // =0x8883 +; HINT-NEXT: autia1716 +; HINT-NEXT: br x17 +; HINT-NEXT: .Ltmp0: // Block address taken +; HINT-NEXT: .LBB0_1: // %bb1 +; HINT-NEXT: mov w0, #1 // =0x1 +; HINT-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; HINT-NEXT: ret +; HINT-NEXT: .Ltmp1: // Block address taken +; HINT-NEXT: .LBB0_2: // %bb2 +; HINT-NEXT: mov w0, #2 // =0x2 +; HINT-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; HINT-NEXT: ret +entry: + %tmp0 = call ptr @dummy_choose(ptr blockaddress(@test_indirectbr, %bb1), ptr blockaddress(@test_indirectbr, %bb2)) + indirectbr ptr %tmp0, [label %bb1, label %bb2] + +bb1: + ret i32 1 + +bb2: + ret i32 2 +} + +define ptr @test_indirectbr_other_function() #0 { +; ELF-LABEL: test_indirectbr_other_function: +; ELF: // %bb.0: +; ELF-NEXT: adrp x17, .Ltmp0 +; ELF-NEXT: add x17, x17, :lo12:.Ltmp0 +; ELF-NEXT: mov x16, #34947 // =0x8883 +; ELF-NEXT: pacia x17, x16 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: ret +; +; HINT-LABEL: test_indirectbr_other_function: +; HINT: // %bb.0: +; HINT-NEXT: adrp x17, .Ltmp0 +; HINT-NEXT: add x17, x17, :lo12:.Ltmp0 +; HINT-NEXT: mov x16, #34947 // =0x8883 +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + ret ptr blockaddress(@test_indirectbr, %bb1) +} + +;; Test another function to compare the discriminator. +;; ptrauth_string_discriminator("test_indirectbr_2 blockaddress") == 40224 + +define i32 @test_indirectbr_2() #0 { +; ELF-LABEL: test_indirectbr_2: +; ELF: // %bb.0: // %entry +; ELF-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; ELF-NEXT: adrp x17, .Ltmp2 +; ELF-NEXT: add x17, x17, :lo12:.Ltmp2 +; ELF-NEXT: mov x16, #40224 // =0x9d20 +; ELF-NEXT: pacia x17, x16 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: adrp x17, .Ltmp3 +; ELF-NEXT: add x17, x17, :lo12:.Ltmp3 +; ELF-NEXT: mov x16, #40224 // =0x9d20 +; ELF-NEXT: pacia x17, x16 +; ELF-NEXT: mov x1, x17 +; ELF-NEXT: bl dummy_choose +; ELF-NEXT: mov x17, #40224 // =0x9d20 +; ELF-NEXT: braa x0, x17 +; ELF-NEXT: .Ltmp2: // Block address taken +; ELF-NEXT: .LBB2_1: // %bb1 +; ELF-NEXT: mov w0, #1 // =0x1 +; ELF-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; ELF-NEXT: ret +; ELF-NEXT: .Ltmp3: // Block address taken +; ELF-NEXT: .LBB2_2: // %bb2 +; ELF-NEXT: mov w0, #2 // =0x2 +; ELF-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; ELF-NEXT: ret +; +; HINT-LABEL: test_indirectbr_2: +; HINT: // %bb.0: // %entry +; HINT-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; HINT-NEXT: adrp x17, .Ltmp2 +; HINT-NEXT: add x17, x17, :lo12:.Ltmp2 +; HINT-NEXT: mov x16, #40224 // =0x9d20 +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: adrp x17, .Ltmp3 +; HINT-NEXT: add x17, x17, :lo12:.Ltmp3 +; HINT-NEXT: mov x16, #40224 // =0x9d20 +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x1, x17 +; HINT-NEXT: bl dummy_choose +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, #40224 // =0x9d20 +; HINT-NEXT: autia1716 +; HINT-NEXT: br x17 +; HINT-NEXT: .Ltmp2: // Block address taken +; HINT-NEXT: .LBB2_1: // %bb1 +; HINT-NEXT: mov w0, #1 // =0x1 +; HINT-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; HINT-NEXT: ret +; HINT-NEXT: .Ltmp3: // Block address taken +; HINT-NEXT: .LBB2_2: // %bb2 +; HINT-NEXT: mov w0, #2 // =0x2 +; HINT-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; HINT-NEXT: ret +entry: + %tmp0 = call ptr @dummy_choose(ptr blockaddress(@test_indirectbr_2, %bb1), ptr blockaddress(@test_indirectbr_2, %bb2)) + indirectbr ptr %tmp0, [label %bb1, label %bb2] + +bb1: + ret i32 1 + +bb2: + ret i32 2 +} + +;; Check we don't interfere with jump-table BRIND lowering. +; ELF-LABEL: test_jumptable: +; ELF: adrp x9, .LJTI3_0 +; ELF-NEXT: add x9, x9, :lo12:.LJTI3_0 +; ELF-NEXT: adr x10, .LBB3_2 +; ELF-NEXT: ldrb w11, [x9, x8] +; ELF-NEXT: add x10, x10, x11, lsl #2 +; ELF-NEXT: br x10 +; +; HINT-LABEL: test_jumptable: +; HINT: adrp x9, .LJTI3_0 +; HINT-NEXT: add x9, x9, :lo12:.LJTI3_0 +; HINT-NEXT: adr x10, .LBB3_2 +; HINT-NEXT: ldrb w11, [x9, x8] +; HINT-NEXT: add x10, x10, x11, lsl #2 +; HINT-NEXT: br x10 +define i32 @test_jumptable(i32 %in) #0 { + switch i32 %in, label %def [ + i32 0, label %lbl1 + i32 1, label %lbl2 + ] + +def: + ret i32 0 + +lbl1: + ret i32 1 + +lbl2: + ret i32 2 +} + +; ELF-LABEL: .globl test_indirectbr_array +; ELF-NEXT: .p2align 4, 0x0 +; ELF-NEXT: test_indirectbr_array: +; ELF-NEXT: .xword .Ltmp0@AUTH(ia,34947) +; ELF-NEXT: .xword .Ltmp1@AUTH(ia,34947) +; ELF-NEXT: .xword .Ltmp2@AUTH(ia,40224) +; ELF-NEXT: .xword .Ltmp3@AUTH(ia,40224) +; ELF-NEXT: .size test_indirectbr_array, 32 + +; HINT-LABEL: .globl test_indirectbr_array +; HINT-NEXT: .p2align 4, 0x0 +; HINT-NEXT: test_indirectbr_array: +; HINT-NEXT: .xword .Ltmp0@AUTH(ia,34947) +; HINT-NEXT: .xword .Ltmp1@AUTH(ia,34947) +; HINT-NEXT: .xword .Ltmp2@AUTH(ia,40224) +; HINT-NEXT: .xword .Ltmp3@AUTH(ia,40224) +; HINT-NEXT: .size test_indirectbr_array, 32 + +@test_indirectbr_array = constant [4 x ptr] [ + ptr blockaddress(@test_indirectbr, %bb1), ptr blockaddress(@test_indirectbr, %bb2), + ptr blockaddress(@test_indirectbr_2, %bb1), ptr blockaddress(@test_indirectbr_2, %bb2) +] + +declare ptr @dummy_choose(ptr, ptr) + +attributes #0 = { "ptrauth-indirect-gotos" nounwind } diff --git a/llvm/test/CodeGen/AArch64/ptrauth-hint-only-intrinsic-auth-resign-with-blend.ll b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-intrinsic-auth-resign-with-blend.ll new file mode 100644 index 0000000000000000000000000000000000000000..926c80bc22238ba68b1f74d3b106d023678bddd9 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-intrinsic-auth-resign-with-blend.ll @@ -0,0 +1,485 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py + +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel=0 -verify-machineinstrs \ +; RUN: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL=".L" --check-prefixes=UNCHECKED-ELF +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL=".L" --check-prefixes=UNCHECKED-ELF + +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -mattr=+pauth-hint-only -global-isel=0 -verify-machineinstrs \ +; RUN: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL="L" --check-prefixes=UNCHECKED-HINT +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -mattr=+pauth-hint-only -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL="L" --check-prefixes=UNCHECKED-HINT + + +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel=0 -verify-machineinstrs \ +; RUN: | FileCheck %s -DL=".L" --check-prefixes=CHECKED-ELF +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: | FileCheck %s -DL=".L" --check-prefixes=CHECKED-ELF + +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -mattr=+pauth-hint-only -global-isel=0 -verify-machineinstrs \ +; RUN: | FileCheck %s -DL=".L" --check-prefixes=CHECKED-HINT +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -mattr=+pauth-hint-only -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: | FileCheck %s -DL=".L" --check-prefixes=CHECKED-HINT + + +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel=0 -verify-machineinstrs \ +; RUN: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL=".L" --check-prefixes=TRAP-ELF +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL=".L" --check-prefixes=TRAP-ELF + +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -mattr=+pauth-hint-only -global-isel=0 -verify-machineinstrs \ +; RUN: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL=".L" --check-prefixes=TRAP-HINT +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -mattr=+pauth-hint-only -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL=".L" --check-prefixes=TRAP-HINT + +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + +define i64 @test_auth_blend(i64 %arg, i64 %arg1) { +; UNCHECKED-ELF-LABEL: test_auth_blend: +; UNCHECKED-ELF: %bb.0: +; UNCHECKED-ELF-NEXT: mov x17, x0 +; UNCHECKED-ELF-NEXT: mov x16, x1 +; UNCHECKED-ELF-NEXT: movk x16, #65535, lsl #48 +; UNCHECKED-ELF-NEXT: autda x17, x16 +; UNCHECKED-ELF-NEXT: mov x0, x17 +; UNCHECKED-ELF-NEXT: ret +; +; UNCHECKED-HINT-LABEL: test_auth_blend: +; UNCHECKED-HINT: %bb.0: +; UNCHECKED-HINT-NEXT: mov x17, x0 +; UNCHECKED-HINT-NEXT: mov x16, x1 +; UNCHECKED-HINT-NEXT: movk x16, #65535, lsl #48 +; UNCHECKED-HINT-NEXT: autia1716 +; UNCHECKED-HINT-NEXT: mov x0, x17 +; UNCHECKED-HINT-NEXT: ret +; +; CHECKED-ELF-LABEL: test_auth_blend: +; CHECKED-ELF: %bb.0: +; CHECKED-ELF-NEXT: mov x17, x0 +; CHECKED-ELF-NEXT: mov x16, x1 +; CHECKED-ELF-NEXT: movk x16, #65535, lsl #48 +; CHECKED-ELF-NEXT: autda x17, x16 +; CHECKED-ELF-NEXT: mov x0, x17 +; CHECKED-ELF-NEXT: ret +; +; CHECKED-HINT-LABEL: test_auth_blend: +; CHECKED-HINT: %bb.0: +; CHECKED-HINT-NEXT: mov x17, x0 +; CHECKED-HINT-NEXT: mov x16, x1 +; CHECKED-HINT-NEXT: movk x16, #65535, lsl #48 +; CHECKED-HINT-NEXT: autia1716 +; CHECKED-HINT-NEXT: mov x0, x17 +; CHECKED-HINT-NEXT: ret +; +; TRAP-ELF-LABEL: test_auth_blend: +; TRAP-ELF: %bb.0: +; TRAP-ELF-NEXT: mov x17, x0 +; TRAP-ELF-NEXT: mov x16, x1 +; TRAP-ELF-NEXT: movk x16, #65535, lsl #48 +; TRAP-ELF-NEXT: autda x17, x16 +; TRAP-ELF-NEXT: mov x16, x17 +; TRAP-ELF-NEXT: xpacd x16 +; TRAP-ELF-NEXT: cmp x16, x17 +; TRAP-ELF-NEXT: b.eq [[L]]auth_success_0 +; TRAP-ELF-NEXT: brk #0xc472 +; TRAP-ELF-NEXT: Lauth_success_0: +; TRAP-ELF-NEXT: mov x0, x17 +; TRAP-ELF-NEXT: ret +; +; TRAP-HINT-LABEL: test_auth_blend: +; TRAP-HINT: %bb.0: +; TRAP-HINT-NEXT: mov x17, x0 +; TRAP-HINT-NEXT: mov x16, x1 +; TRAP-HINT-NEXT: movk x16, #65535, lsl #48 +; TRAP-HINT-NEXT: autia1716 +; TRAP-HINT-NEXT: mov x16, x17 +; TRAP-HINT-NEXT: xpacd x16 +; TRAP-HINT-NEXT: cmp x16, x17 +; TRAP-HINT-NEXT: b.eq [[L]]auth_success_0 +; TRAP-HINT-NEXT: brk #0xc472 +; TRAP-HINT-NEXT: Lauth_success_0: +; TRAP-HINT-NEXT: mov x0, x17 +; TRAP-HINT-NEXT: ret + %tmp0 = call i64 @llvm.ptrauth.blend(i64 %arg1, i64 65535) + %tmp1 = call i64 @llvm.ptrauth.auth(i64 %arg, i32 2, i64 %tmp0) + ret i64 %tmp1 +} + +define i64 @test_resign_blend(i64 %arg, i64 %arg1, i64 %arg2) { +; UNCHECKED-ELF-LABEL: test_resign_blend: +; UNCHECKED-ELF: %bb.0: +; UNCHECKED-ELF-NEXT: mov x17, x0 +; UNCHECKED-ELF-NEXT: mov x16, x1 +; UNCHECKED-ELF-NEXT: movk x16, #12345, lsl #48 +; UNCHECKED-ELF-NEXT: autda x17, x16 +; UNCHECKED-ELF-NEXT: mov x16, x2 +; UNCHECKED-ELF-NEXT: movk x16, #56789, lsl #48 +; UNCHECKED-ELF-NEXT: pacdb x17, x16 +; UNCHECKED-ELF-NEXT: mov x0, x17 +; UNCHECKED-ELF-NEXT: ret +; +; UNCHECKED-HINT-LABEL: test_resign_blend: +; UNCHECKED-HINT: %bb.0: +; UNCHECKED-HINT-NEXT: mov x17, x0 +; UNCHECKED-HINT-NEXT: mov x16, x1 +; UNCHECKED-HINT-NEXT: movk x16, #12345, lsl #48 +; UNCHECKED-HINT-NEXT: autia1716 +; UNCHECKED-HINT-NEXT: mov x16, x2 +; UNCHECKED-HINT-NEXT: movk x16, #56789, lsl #48 +; UNCHECKED-HINT-NEXT: pacib1716 +; UNCHECKED-HINT-NEXT: mov x0, x17 +; UNCHECKED-HINT-NEXT: ret +; +; CHECKED-ELF-LABEL: test_resign_blend: +; CHECKED-ELF: %bb.0: +; CHECKED-ELF-NEXT: mov x17, x0 +; CHECKED-ELF-NEXT: mov x16, x1 +; CHECKED-ELF-NEXT: movk x16, #12345, lsl #48 +; CHECKED-ELF-NEXT: autda x17, x16 +; CHECKED-ELF-NEXT: mov x16, x17 +; CHECKED-ELF-NEXT: xpacd x16 +; CHECKED-ELF-NEXT: cmp x16, x17 +; CHECKED-ELF-NEXT: b.eq [[L]]auth_success_0 +; CHECKED-ELF-NEXT: mov x17, x16 +; CHECKED-ELF-NEXT: b [[L]]resign_end_0 +; CHECKED-ELF-NEXT: Lauth_success_0: +; CHECKED-ELF-NEXT: mov x16, x2 +; CHECKED-ELF-NEXT: movk x16, #56789, lsl #48 +; CHECKED-ELF-NEXT: pacdb x17, x16 +; CHECKED-ELF-NEXT: Lresign_end_0: +; CHECKED-ELF-NEXT: mov x0, x17 +; CHECKED-ELF-NEXT: ret +; +; CHECKED-HINT-LABEL: test_resign_blend: +; CHECKED-HINT: %bb.0: +; CHECKED-HINT-NEXT: mov x17, x0 +; CHECKED-HINT-NEXT: mov x16, x1 +; CHECKED-HINT-NEXT: movk x16, #12345, lsl #48 +; CHECKED-HINT-NEXT: autia1716 +; CHECKED-HINT-NEXT: mov x16, x17 +; CHECKED-HINT-NEXT: xpacd x16 +; CHECKED-HINT-NEXT: cmp x16, x17 +; CHECKED-HINT-NEXT: b.eq [[L]]auth_success_0 +; CHECKED-HINT-NEXT: mov x17, x16 +; CHECKED-HINT-NEXT: b [[L]]resign_end_0 +; CHECKED-HINT-NEXT: Lauth_success_0: +; CHECKED-HINT-NEXT: mov x16, x2 +; CHECKED-HINT-NEXT: movk x16, #56789, lsl #48 +; CHECKED-HINT-NEXT: pacib1716 +; CHECKED-HINT-NEXT: Lresign_end_0: +; CHECKED-HINT-NEXT: mov x0, x17 +; CHECKED-HINT-NEXT: ret +; +; TRAP-ELF-LABEL: test_resign_blend: +; TRAP-ELF: %bb.0: +; TRAP-ELF-NEXT: mov x17, x0 +; TRAP-ELF-NEXT: mov x16, x1 +; TRAP-ELF-NEXT: movk x16, #12345, lsl #48 +; TRAP-ELF-NEXT: autda x17, x16 +; TRAP-ELF-NEXT: mov x16, x17 +; TRAP-ELF-NEXT: xpacd x16 +; TRAP-ELF-NEXT: cmp x16, x17 +; TRAP-ELF-NEXT: b.eq [[L]]auth_success_1 +; TRAP-ELF-NEXT: brk #0xc472 +; TRAP-ELF-NEXT: Lauth_success_1: +; TRAP-ELF-NEXT: mov x16, x2 +; TRAP-ELF-NEXT: movk x16, #56789, lsl #48 +; TRAP-ELF-NEXT: pacdb x17, x16 +; TRAP-ELF-NEXT: mov x0, x17 +; TRAP-ELF-NEXT: ret +; +; TRAP-HINT-LABEL: test_resign_blend: +; TRAP-HINT: %bb.0: +; TRAP-HINT-NEXT: mov x17, x0 +; TRAP-HINT-NEXT: mov x16, x1 +; TRAP-HINT-NEXT: movk x16, #12345, lsl #48 +; TRAP-HINT-NEXT: autia1716 +; TRAP-HINT-NEXT: mov x16, x17 +; TRAP-HINT-NEXT: xpacd x16 +; TRAP-HINT-NEXT: cmp x16, x17 +; TRAP-HINT-NEXT: b.eq [[L]]auth_success_1 +; TRAP-HINT-NEXT: brk #0xc472 +; TRAP-HINT-NEXT: Lauth_success_1: +; TRAP-HINT-NEXT: mov x16, x2 +; TRAP-HINT-NEXT: movk x16, #56789, lsl #48 +; TRAP-HINT-NEXT: pacib1716 +; TRAP-HINT-NEXT: mov x0, x17 +; TRAP-HINT-NEXT: ret + %tmp0 = call i64 @llvm.ptrauth.blend(i64 %arg1, i64 12345) + %tmp1 = call i64 @llvm.ptrauth.blend(i64 %arg2, i64 56789) + %tmp2 = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %tmp0, i32 3, i64 %tmp1) + ret i64 %tmp2 +} + +define i64 @test_resign_blend_and_const(i64 %arg, i64 %arg1) { +; UNCHECKED-ELF-LABEL: test_resign_blend_and_const: +; UNCHECKED-ELF: %bb.0: +; UNCHECKED-ELF-NEXT: mov x17, x0 +; UNCHECKED-ELF-NEXT: mov x16, x1 +; UNCHECKED-ELF-NEXT: movk x16, #12345, lsl #48 +; UNCHECKED-ELF-NEXT: autda x17, x16 +; UNCHECKED-ELF-NEXT: mov x16, #56789 +; UNCHECKED-ELF-NEXT: pacdb x17, x16 +; UNCHECKED-ELF-NEXT: mov x0, x17 +; UNCHECKED-ELF-NEXT: ret +; +; UNCHECKED-HINT-LABEL: test_resign_blend_and_const: +; UNCHECKED-HINT: %bb.0: +; UNCHECKED-HINT-NEXT: mov x17, x0 +; UNCHECKED-HINT-NEXT: mov x16, x1 +; UNCHECKED-HINT-NEXT: movk x16, #12345, lsl #48 +; UNCHECKED-HINT-NEXT: autia1716 +; UNCHECKED-HINT-NEXT: mov x16, #56789 +; UNCHECKED-HINT-NEXT: pacib1716 +; UNCHECKED-HINT-NEXT: mov x0, x17 +; UNCHECKED-HINT-NEXT: ret +; +; CHECKED-ELF-LABEL: test_resign_blend_and_const: +; CHECKED-ELF: %bb.0: +; CHECKED-ELF-NEXT: mov x17, x0 +; CHECKED-ELF-NEXT: mov x16, x1 +; CHECKED-ELF-NEXT: movk x16, #12345, lsl #48 +; CHECKED-ELF-NEXT: autda x17, x16 +; CHECKED-ELF-NEXT: mov x16, x17 +; CHECKED-ELF-NEXT: xpacd x16 +; CHECKED-ELF-NEXT: cmp x16, x17 +; CHECKED-ELF-NEXT: b.eq [[L]]auth_success_1 +; CHECKED-ELF-NEXT: mov x17, x16 +; CHECKED-ELF-NEXT: b [[L]]resign_end_1 +; CHECKED-ELF-NEXT: Lauth_success_1: +; CHECKED-ELF-NEXT: mov x16, #56789 +; CHECKED-ELF-NEXT: pacdb x17, x16 +; CHECKED-ELF-NEXT: Lresign_end_1: +; CHECKED-ELF-NEXT: mov x0, x17 +; CHECKED-ELF-NEXT: ret +; +; CHECKED-HINT-LABEL: test_resign_blend_and_const: +; CHECKED-HINT: %bb.0: +; CHECKED-HINT-NEXT: mov x17, x0 +; CHECKED-HINT-NEXT: mov x16, x1 +; CHECKED-HINT-NEXT: movk x16, #12345, lsl #48 +; CHECKED-HINT-NEXT: autia1716 +; CHECKED-HINT-NEXT: mov x16, x17 +; CHECKED-HINT-NEXT: xpacd x16 +; CHECKED-HINT-NEXT: cmp x16, x17 +; CHECKED-HINT-NEXT: b.eq [[L]]auth_success_1 +; CHECKED-HINT-NEXT: mov x17, x16 +; CHECKED-HINT-NEXT: b [[L]]resign_end_1 +; CHECKED-HINT-NEXT: Lauth_success_1: +; CHECKED-HINT-NEXT: mov x16, #56789 +; CHECKED-HINT-NEXT: pacib1716 +; CHECKED-HINT-NEXT: Lresign_end_1: +; CHECKED-HINT-NEXT: mov x0, x17 +; CHECKED-HINT-NEXT: ret +; +; TRAP-ELF-LABEL: test_resign_blend_and_const: +; TRAP-ELF: %bb.0: +; TRAP-ELF-NEXT: mov x17, x0 +; TRAP-ELF-NEXT: mov x16, x1 +; TRAP-ELF-NEXT: movk x16, #12345, lsl #48 +; TRAP-ELF-NEXT: autda x17, x16 +; TRAP-ELF-NEXT: mov x16, x17 +; TRAP-ELF-NEXT: xpacd x16 +; TRAP-ELF-NEXT: cmp x16, x17 +; TRAP-ELF-NEXT: b.eq [[L]]auth_success_2 +; TRAP-ELF-NEXT: brk #0xc472 +; TRAP-ELF-NEXT: Lauth_success_2: +; TRAP-ELF-NEXT: mov x16, #56789 +; TRAP-ELF-NEXT: pacdb x17, x16 +; TRAP-ELF-NEXT: mov x0, x17 +; TRAP-ELF-NEXT: ret +; +; TRAP-HINT-LABEL: test_resign_blend_and_const: +; TRAP-HINT: %bb.0: +; TRAP-HINT-NEXT: mov x17, x0 +; TRAP-HINT-NEXT: mov x16, x1 +; TRAP-HINT-NEXT: movk x16, #12345, lsl #48 +; TRAP-HINT-NEXT: autia1716 +; TRAP-HINT-NEXT: mov x16, x17 +; TRAP-HINT-NEXT: xpacd x16 +; TRAP-HINT-NEXT: cmp x16, x17 +; TRAP-HINT-NEXT: b.eq [[L]]auth_success_2 +; TRAP-HINT-NEXT: brk #0xc472 +; TRAP-HINT-NEXT: Lauth_success_2: +; TRAP-HINT-NEXT: mov x16, #56789 +; TRAP-HINT-NEXT: pacib1716 +; TRAP-HINT-NEXT: mov x0, x17 +; TRAP-HINT-NEXT: ret + %tmp0 = call i64 @llvm.ptrauth.blend(i64 %arg1, i64 12345) + %tmp1 = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %tmp0, i32 3, i64 56789) + ret i64 %tmp1 +} + +define i64 @test_resign_blend_and_addr(i64 %arg, i64 %arg1, i64 %arg2) { +; UNCHECKED-ELF-LABEL: test_resign_blend_and_addr: +; UNCHECKED-ELF: %bb.0: +; UNCHECKED-ELF-NEXT: mov x17, x0 +; UNCHECKED-ELF-NEXT: mov x16, x1 +; UNCHECKED-ELF-NEXT: movk x16, #12345, lsl #48 +; UNCHECKED-ELF-NEXT: autda x17, x16 +; UNCHECKED-ELF-NEXT: pacdb x17, x2 +; UNCHECKED-ELF-NEXT: mov x0, x17 +; UNCHECKED-ELF-NEXT: ret +; +; UNCHECKED-HINT-LABEL: test_resign_blend_and_addr: +; UNCHECKED-HINT: %bb.0: +; UNCHECKED-HINT-NEXT: mov x17, x0 +; UNCHECKED-HINT-NEXT: mov x16, x1 +; UNCHECKED-HINT-NEXT: movk x16, #12345, lsl #48 +; UNCHECKED-HINT-NEXT: autia1716 +; UNCHECKED-HINT-NEXT: mov x16, x2 +; UNCHECKED-HINT-NEXT: pacib1716 +; UNCHECKED-HINT-NEXT: mov x0, x17 +; UNCHECKED-HINT-NEXT: ret +; +; CHECKED-ELF-LABEL: test_resign_blend_and_addr: +; CHECKED-ELF: %bb.0: +; CHECKED-ELF-NEXT: mov x17, x0 +; CHECKED-ELF-NEXT: mov x16, x1 +; CHECKED-ELF-NEXT: movk x16, #12345, lsl #48 +; CHECKED-ELF-NEXT: autda x17, x16 +; CHECKED-ELF-NEXT: mov x16, x17 +; CHECKED-ELF-NEXT: xpacd x16 +; CHECKED-ELF-NEXT: cmp x16, x17 +; CHECKED-ELF-NEXT: b.eq [[L]]auth_success_2 +; CHECKED-ELF-NEXT: mov x17, x16 +; CHECKED-ELF-NEXT: b [[L]]resign_end_2 +; CHECKED-ELF-NEXT: Lauth_success_2: +; CHECKED-ELF-NEXT: pacdb x17, x2 +; CHECKED-ELF-NEXT: Lresign_end_2: +; CHECKED-ELF-NEXT: mov x0, x17 +; CHECKED-ELF-NEXT: ret +; +; CHECKED-HINT-LABEL: test_resign_blend_and_addr: +; CHECKED-HINT: %bb.0: +; CHECKED-HINT-NEXT: mov x17, x0 +; CHECKED-HINT-NEXT: mov x16, x1 +; CHECKED-HINT-NEXT: movk x16, #12345, lsl #48 +; CHECKED-HINT-NEXT: autia1716 +; CHECKED-HINT-NEXT: mov x16, x17 +; CHECKED-HINT-NEXT: xpacd x16 +; CHECKED-HINT-NEXT: cmp x16, x17 +; CHECKED-HINT-NEXT: b.eq [[L]]auth_success_2 +; CHECKED-HINT-NEXT: mov x17, x16 +; CHECKED-HINT-NEXT: b [[L]]resign_end_2 +; CHECKED-HINT-NEXT: Lauth_success_2: +; CHECKED-HINT-NEXT: mov x16, x2 +; CHECKED-HINT-NEXT: pacib1716 +; CHECKED-HINT-NEXT: Lresign_end_2: +; CHECKED-HINT-NEXT: mov x0, x17 +; CHECKED-HINT-NEXT: ret +; +; TRAP-ELF-LABEL: test_resign_blend_and_addr: +; TRAP-ELF: %bb.0: +; TRAP-ELF-NEXT: mov x17, x0 +; TRAP-ELF-NEXT: mov x16, x1 +; TRAP-ELF-NEXT: movk x16, #12345, lsl #48 +; TRAP-ELF-NEXT: autda x17, x16 +; TRAP-ELF-NEXT: mov x16, x17 +; TRAP-ELF-NEXT: xpacd x16 +; TRAP-ELF-NEXT: cmp x16, x17 +; TRAP-ELF-NEXT: b.eq [[L]]auth_success_3 +; TRAP-ELF-NEXT: brk #0xc472 +; TRAP-ELF-NEXT: Lauth_success_3: +; TRAP-ELF-NEXT: pacdb x17, x2 +; TRAP-ELF-NEXT: mov x0, x17 +; TRAP-ELF-NEXT: ret +; +; TRAP-HINT-LABEL: test_resign_blend_and_addr: +; TRAP-HINT: %bb.0: +; TRAP-HINT-NEXT: mov x17, x0 +; TRAP-HINT-NEXT: mov x16, x1 +; TRAP-HINT-NEXT: movk x16, #12345, lsl #48 +; TRAP-HINT-NEXT: autia1716 +; TRAP-HINT-NEXT: mov x16, x17 +; TRAP-HINT-NEXT: xpacd x16 +; TRAP-HINT-NEXT: cmp x16, x17 +; TRAP-HINT-NEXT: b.eq [[L]]auth_success_3 +; TRAP-HINT-NEXT: brk #0xc472 +; TRAP-HINT-NEXT: Lauth_success_3: +; TRAP-HINT-NEXT: mov x16, x2 +; TRAP-HINT-NEXT: pacib1716 +; TRAP-HINT-NEXT: mov x0, x17 +; TRAP-HINT-NEXT: ret + %tmp0 = call i64 @llvm.ptrauth.blend(i64 %arg1, i64 12345) + %tmp1 = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %tmp0, i32 3, i64 %arg2) + ret i64 %tmp1 +} + +define i64 @test_auth_too_large_discriminator(i64 %arg, i64 %arg1) { +; UNCHECKED-ELF-LABEL: test_auth_too_large_discriminator: +; UNCHECKED-ELF: %bb.0: +; UNCHECKED-ELF-NEXT: mov w8, #65536 +; UNCHECKED-ELF-NEXT: mov x17, x0 +; UNCHECKED-ELF-NEXT: bfi x1, x8, #48, #16 +; UNCHECKED-ELF-NEXT: autda x17, x1 +; UNCHECKED-ELF-NEXT: mov x0, x17 +; UNCHECKED-ELF-NEXT: ret +; +; UNCHECKED-HINT-LABEL: test_auth_too_large_discriminator: +; UNCHECKED-HINT: %bb.0: +; UNCHECKED-HINT-NEXT: mov w8, #65536 +; UNCHECKED-HINT-NEXT: mov x17, x0 +; UNCHECKED-HINT-NEXT: bfi x1, x8, #48, #16 +; UNCHECKED-HINT-NEXT: mov x16, x1 +; UNCHECKED-HINT-NEXT: autia1716 +; UNCHECKED-HINT-NEXT: mov x0, x17 +; UNCHECKED-HINT-NEXT: ret +; +; CHECKED-ELF-LABEL: test_auth_too_large_discriminator: +; CHECKED-ELF: %bb.0: +; CHECKED-ELF-NEXT: mov w8, #65536 +; CHECKED-ELF-NEXT: mov x17, x0 +; CHECKED-ELF-NEXT: bfi x1, x8, #48, #16 +; CHECKED-ELF-NEXT: autda x17, x1 +; CHECKED-ELF-NEXT: mov x0, x17 +; CHECKED-ELF-NEXT: ret +; +; CHECKED-HINT-LABEL: test_auth_too_large_discriminator: +; CHECKED-HINT: %bb.0: +; CHECKED-HINT-NEXT: mov w8, #65536 +; CHECKED-HINT-NEXT: mov x17, x0 +; CHECKED-HINT-NEXT: bfi x1, x8, #48, #16 +; CHECKED-HINT-NEXT: mov x16, x1 +; CHECKED-HINT-NEXT: autia1716 +; CHECKED-HINT-NEXT: mov x0, x17 +; CHECKED-HINT-NEXT: ret +; +; TRAP-ELF-LABEL: test_auth_too_large_discriminator: +; TRAP-ELF: %bb.0: +; TRAP-ELF-NEXT: mov w8, #65536 +; TRAP-ELF-NEXT: mov x17, x0 +; TRAP-ELF-NEXT: bfi x1, x8, #48, #16 +; TRAP-ELF-NEXT: autda x17, x1 +; TRAP-ELF-NEXT: mov x16, x17 +; TRAP-ELF-NEXT: xpacd x16 +; TRAP-ELF-NEXT: cmp x16, x17 +; TRAP-ELF-NEXT: b.eq [[L]]auth_success_4 +; TRAP-ELF-NEXT: brk #0xc472 +; TRAP-ELF-NEXT: Lauth_success_4: +; TRAP-ELF-NEXT: mov x0, x17 +; TRAP-ELF-NEXT: ret +; +; TRAP-HINT-LABEL: test_auth_too_large_discriminator: +; TRAP-HINT: %bb.0: +; TRAP-HINT-NEXT: mov w8, #65536 +; TRAP-HINT-NEXT: mov x17, x0 +; TRAP-HINT-NEXT: bfi x1, x8, #48, #16 +; TRAP-HINT-NEXT: mov x16, x1 +; TRAP-HINT-NEXT: autia1716 +; TRAP-HINT-NEXT: mov x16, x17 +; TRAP-HINT-NEXT: xpacd x16 +; TRAP-HINT-NEXT: cmp x16, x17 +; TRAP-HINT-NEXT: b.eq [[L]]auth_success_4 +; TRAP-HINT-NEXT: brk #0xc472 +; TRAP-HINT-NEXT: Lauth_success_4: +; TRAP-HINT-NEXT: mov x0, x17 +; TRAP-HINT-NEXT: ret + %tmp0 = call i64 @llvm.ptrauth.blend(i64 %arg1, i64 65536) + %tmp1 = call i64 @llvm.ptrauth.auth(i64 %arg, i32 2, i64 %tmp0) + ret i64 %tmp1 +} + +declare i64 @llvm.ptrauth.auth(i64, i32, i64) +declare i64 @llvm.ptrauth.resign(i64, i32, i64, i32, i64) +declare i64 @llvm.ptrauth.blend(i64, i64) diff --git a/llvm/test/CodeGen/AArch64/ptrauth-hint-only-intrinsic-auth-resign.ll b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-intrinsic-auth-resign.ll new file mode 100644 index 0000000000000000000000000000000000000000..e8cac78c351ff70730e872bc4346724d946128ab --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-intrinsic-auth-resign.ll @@ -0,0 +1,1268 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py + +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel=0 \ +; RUN-NOT: -verify-machineinstrs -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL=".L" --check-prefix=ELF-UNCHECKED +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 \ +; RUN-NOT: -verify-machineinstrs -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL=".L" --check-prefix=ELF-UNCHECKED + +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -mattr=+pauth-hint-only -global-isel=0 \ +; RUN: -verify-machineinstrs -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL=".L" --check-prefix=HINT-UNCHECKED +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -mattr=+pauth-hint-only -global-isel -global-isel-abort=1 \ +; RUN-NOT: -verify-machineinstrs -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL=".L" --check-prefix=HINT-UNCHECKED + +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel=0 \ +; RUN: -verify-machineinstrs | FileCheck %s -DL=".L" --check-prefix=ELF-CHECKED +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 \ +; RUN-NOT: -verify-machineinstrs | FileCheck %s -DL=".L" --check-prefix=ELF-CHECKED + +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -mattr=+pauth-hint-only -global-isel=0 \ +; RUN: -verify-machineinstrs | FileCheck %s -DL=".L" --check-prefix=HINT-CHECKED +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -mattr=+pauth-hint-only -global-isel -global-isel-abort=1 \ +; RUN-NOT: -verify-machineinstrs | FileCheck %s -DL=".L" --check-prefix=HINT-CHECKED + +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel=0 \ +; RUN: -verify-machineinstrs -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL=".L" --check-prefix=ELF-TRAP +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 \ +; RUN-NOT: -verify-machineinstrs -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL=".L" --check-prefix=ELF-TRAP + +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -mattr=+pauth-hint-only -global-isel=0 \ +; RUN: -verify-machineinstrs -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL=".L" --check-prefix=HINT-TRAP +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -mattr=+pauth-hint-only -global-isel -global-isel-abort=1 \ +; RUN-NOT: -verify-machineinstrs -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL=".L" --check-prefix=HINT-TRAP + +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + +define i64 @test_auth_ia(i64 %arg, i64 %arg1) { +; ELF-UNCHECKED-LABEL: test_auth_ia: +; ELF-UNCHECKED: %bb.0: +; ELF-UNCHECKED-NEXT: mov x17, x0 +; ELF-UNCHECKED-NEXT: autia x17, x1 +; ELF-UNCHECKED-NEXT: mov x0, x17 +; ELF-UNCHECKED-NEXT: ret +; +; HINT-UNCHECKED-LABEL: test_auth_ia: +; HINT-UNCHECKED: %bb.0: +; HINT-UNCHECKED-NEXT: mov x17, x0 +; HINT-UNCHECKED-NEXT: mov x16, x1 +; HINT-UNCHECKED-NEXT: autia1716 +; HINT-UNCHECKED-NEXT: mov x0, x17 +; HINT-UNCHECKED-NEXT: ret +; +; ELF-CHECKED-LABEL: test_auth_ia: +; ELF-CHECKED: %bb.0: +; ELF-CHECKED-NEXT: mov x17, x0 +; ELF-CHECKED-NEXT: autia x17, x1 +; ELF-CHECKED-NEXT: mov x0, x17 +; ELF-CHECKED-NEXT: ret +; +; HINT-CHECKED-LABEL: test_auth_ia: +; HINT-CHECKED: %bb.0: +; HINT-CHECKED-NEXT: mov x17, x0 +; HINT-CHECKED-NEXT: mov x16, x1 +; HINT-CHECKED-NEXT: autia1716 +; HINT-CHECKED-NEXT: mov x0, x17 +; HINT-CHECKED-NEXT: ret +; +; ELF-TRAP-LABEL: test_auth_ia: +; ELF-TRAP: %bb.0: +; ELF-TRAP-NEXT: mov x17, x0 +; ELF-TRAP-NEXT: autia x17, x1 +; ELF-TRAP-NEXT: mov x16, x17 +; ELF-TRAP-NEXT: xpaci x16 +; ELF-TRAP-NEXT: cmp x16, x17 +; ELF-TRAP-NEXT: b.eq [[L]]auth_success_0 +; ELF-TRAP-NEXT: brk #0xc470 +; ELF-TRAP-NEXT: Lauth_success_0: +; ELF-TRAP-NEXT: mov x0, x17 +; ELF-TRAP-NEXT: ret +; +; HINT-TRAP-LABEL: test_auth_ia: +; HINT-TRAP: %bb.0: +; HINT-TRAP-NEXT: mov x17, x0 +; HINT-TRAP-NEXT: mov x16, x1 +; HINT-TRAP-NEXT: autia1716 +; HINT-TRAP-NEXT: mov x16, x17 +; HINT-TRAP-NEXT: xpaci x16 +; HINT-TRAP-NEXT: cmp x16, x17 +; HINT-TRAP-NEXT: b.eq [[L]]auth_success_0 +; HINT-TRAP-NEXT: brk #0xc470 +; HINT-TRAP-NEXT: Lauth_success_0: +; HINT-TRAP-NEXT: mov x0, x17 +; HINT-TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_auth_ia_zero(i64 %arg) { +; ELF-UNCHECKED-LABEL: test_auth_ia_zero: +; ELF-UNCHECKED: %bb.0: +; ELF-UNCHECKED-NEXT: mov x17, x0 +; ELF-UNCHECKED-NEXT: autiza x17 +; ELF-UNCHECKED-NEXT: mov x0, x17 +; ELF-UNCHECKED-NEXT: ret +; +; HINT-UNCHECKED-LABEL: test_auth_ia_zero: +; HINT-UNCHECKED: %bb.0: +; HINT-UNCHECKED-NEXT: mov x17, x0 +; HINT-UNCHECKED-NEXT: mov x16, xzr +; HINT-UNCHECKED-NEXT: autia1716 +; HINT-UNCHECKED-NEXT: mov x0, x17 +; HINT-UNCHECKED-NEXT: ret +; +; ELF-CHECKED-LABEL: test_auth_ia_zero: +; ELF-CHECKED: %bb.0: +; ELF-CHECKED-NEXT: mov x17, x0 +; ELF-CHECKED-NEXT: autiza x17 +; ELF-CHECKED-NEXT: mov x0, x17 +; ELF-CHECKED-NEXT: ret +; +; HINT-CHECKED-LABEL: test_auth_ia_zero: +; HINT-CHECKED: %bb.0: +; HINT-CHECKED-NEXT: mov x17, x0 +; HINT-CHECKED-NEXT: mov x16, xzr +; HINT-CHECKED-NEXT: autia1716 +; HINT-CHECKED-NEXT: mov x0, x17 +; HINT-CHECKED-NEXT: ret +; +; ELF-TRAP-LABEL: test_auth_ia_zero: +; ELF-TRAP: %bb.0: +; ELF-TRAP-NEXT: mov x17, x0 +; ELF-TRAP-NEXT: autiza x17 +; ELF-TRAP-NEXT: mov x16, x17 +; ELF-TRAP-NEXT: xpaci x16 +; ELF-TRAP-NEXT: cmp x16, x17 +; ELF-TRAP-NEXT: b.eq [[L]]auth_success_1 +; ELF-TRAP-NEXT: brk #0xc470 +; ELF-TRAP-NEXT: Lauth_success_1: +; ELF-TRAP-NEXT: mov x0, x17 +; ELF-TRAP-NEXT: ret +; +; HINT-TRAP-LABEL: test_auth_ia_zero: +; HINT-TRAP: %bb.0: +; HINT-TRAP-NEXT: mov x17, x0 +; HINT-TRAP-NEXT: mov x16, xzr +; HINT-TRAP-NEXT: autia1716 +; HINT-TRAP-NEXT: mov x16, x17 +; HINT-TRAP-NEXT: xpaci x16 +; HINT-TRAP-NEXT: cmp x16, x17 +; HINT-TRAP-NEXT: b.eq [[L]]auth_success_1 +; HINT-TRAP-NEXT: brk #0xc470 +; HINT-TRAP-NEXT: Lauth_success_1: +; HINT-TRAP-NEXT: mov x0, x17 +; HINT-TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 0) + ret i64 %tmp +} + +define i64 @test_auth_ib(i64 %arg, i64 %arg1) { +; ELF-UNCHECKED-LABEL: test_auth_ib: +; ELF-UNCHECKED: %bb.0: +; ELF-UNCHECKED-NEXT: mov x17, x0 +; ELF-UNCHECKED-NEXT: autib x17, x1 +; ELF-UNCHECKED-NEXT: mov x0, x17 +; ELF-UNCHECKED-NEXT: ret +; +; HINT-UNCHECKED-LABEL: test_auth_ib: +; HINT-UNCHECKED: %bb.0: +; HINT-UNCHECKED-NEXT: mov x17, x0 +; HINT-UNCHECKED-NEXT: mov x16, x1 +; HINT-UNCHECKED-NEXT: autib1716 +; HINT-UNCHECKED-NEXT: mov x0, x17 +; HINT-UNCHECKED-NEXT: ret +; +; ELF-CHECKED-LABEL: test_auth_ib: +; ELF-CHECKED: %bb.0: +; ELF-CHECKED-NEXT: mov x17, x0 +; ELF-CHECKED-NEXT: autib x17, x1 +; ELF-CHECKED-NEXT: mov x0, x17 +; ELF-CHECKED-NEXT: ret +; +; HINT-CHECKED-LABEL: test_auth_ib: +; HINT-CHECKED: %bb.0: +; HINT-CHECKED-NEXT: mov x17, x0 +; HINT-CHECKED-NEXT: mov x16, x1 +; HINT-CHECKED-NEXT: autib1716 +; HINT-CHECKED-NEXT: mov x0, x17 +; HINT-CHECKED-NEXT: ret +; +; ELF-TRAP-LABEL: test_auth_ib: +; ELF-TRAP: %bb.0: +; ELF-TRAP-NEXT: mov x17, x0 +; ELF-TRAP-NEXT: autib x17, x1 +; ELF-TRAP-NEXT: mov x16, x17 +; ELF-TRAP-NEXT: xpaci x16 +; ELF-TRAP-NEXT: cmp x16, x17 +; ELF-TRAP-NEXT: b.eq [[L]]auth_success_2 +; ELF-TRAP-NEXT: brk #0xc471 +; ELF-TRAP-NEXT: Lauth_success_2: +; ELF-TRAP-NEXT: mov x0, x17 +; ELF-TRAP-NEXT: ret +; +; HINT-TRAP-LABEL: test_auth_ib: +; HINT-TRAP: %bb.0: +; HINT-TRAP-NEXT: mov x17, x0 +; HINT-TRAP-NEXT: mov x16, x1 +; HINT-TRAP-NEXT: autib1716 +; HINT-TRAP-NEXT: mov x16, x17 +; HINT-TRAP-NEXT: xpaci x16 +; HINT-TRAP-NEXT: cmp x16, x17 +; HINT-TRAP-NEXT: b.eq [[L]]auth_success_2 +; HINT-TRAP-NEXT: brk #0xc471 +; HINT-TRAP-NEXT: Lauth_success_2: +; HINT-TRAP-NEXT: mov x0, x17 +; HINT-TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 1, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_auth_ib_zero(i64 %arg) { +; ELF-UNCHECKED-LABEL: test_auth_ib_zero: +; ELF-UNCHECKED: %bb.0: +; ELF-UNCHECKED-NEXT: mov x17, x0 +; ELF-UNCHECKED-NEXT: autizb x17 +; ELF-UNCHECKED-NEXT: mov x0, x17 +; ELF-UNCHECKED-NEXT: ret +; +; HINT-UNCHECKED-LABEL: test_auth_ib_zero: +; HINT-UNCHECKED: %bb.0: +; HINT-UNCHECKED-NEXT: mov x17, x0 +; HINT-UNCHECKED-NEXT: mov x16, xzr +; HINT-UNCHECKED-NEXT: autib1716 +; HINT-UNCHECKED-NEXT: mov x0, x17 +; HINT-UNCHECKED-NEXT: ret +; +; ELF-CHECKED-LABEL: test_auth_ib_zero: +; ELF-CHECKED: %bb.0: +; ELF-CHECKED-NEXT: mov x17, x0 +; ELF-CHECKED-NEXT: autizb x17 +; ELF-CHECKED-NEXT: mov x0, x17 +; ELF-CHECKED-NEXT: ret +; +; HINT-CHECKED-LABEL: test_auth_ib_zero: +; HINT-CHECKED: %bb.0: +; HINT-CHECKED-NEXT: mov x17, x0 +; HINT-CHECKED-NEXT: mov x16, xzr +; HINT-CHECKED-NEXT: autib1716 +; HINT-CHECKED-NEXT: mov x0, x17 +; HINT-CHECKED-NEXT: ret +; +; ELF-TRAP-LABEL: test_auth_ib_zero: +; ELF-TRAP: %bb.0: +; ELF-TRAP-NEXT: mov x17, x0 +; ELF-TRAP-NEXT: autizb x17 +; ELF-TRAP-NEXT: mov x16, x17 +; ELF-TRAP-NEXT: xpaci x16 +; ELF-TRAP-NEXT: cmp x16, x17 +; ELF-TRAP-NEXT: b.eq [[L]]auth_success_3 +; ELF-TRAP-NEXT: brk #0xc471 +; ELF-TRAP-NEXT: Lauth_success_3: +; ELF-TRAP-NEXT: mov x0, x17 +; ELF-TRAP-NEXT: ret +; +; HINT-TRAP-LABEL: test_auth_ib_zero: +; HINT-TRAP: %bb.0: +; HINT-TRAP-NEXT: mov x17, x0 +; HINT-TRAP-NEXT: mov x16, xzr +; HINT-TRAP-NEXT: autib1716 +; HINT-TRAP-NEXT: mov x16, x17 +; HINT-TRAP-NEXT: xpaci x16 +; HINT-TRAP-NEXT: cmp x16, x17 +; HINT-TRAP-NEXT: b.eq [[L]]auth_success_3 +; HINT-TRAP-NEXT: brk #0xc471 +; HINT-TRAP-NEXT: Lauth_success_3: +; HINT-TRAP-NEXT: mov x0, x17 +; HINT-TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 1, i64 0) + ret i64 %tmp +} + +define i64 @test_auth_da(i64 %arg, i64 %arg1) { +; ELF-UNCHECKED-LABEL: test_auth_da: +; ELF-UNCHECKED: %bb.0: +; ELF-UNCHECKED-NEXT: mov x17, x0 +; ELF-UNCHECKED-NEXT: autda x17, x1 +; ELF-UNCHECKED-NEXT: mov x0, x17 +; ELF-UNCHECKED-NEXT: ret +; +; HINT-UNCHECKED-LABEL: test_auth_da: +; HINT-UNCHECKED: %bb.0: +; HINT-UNCHECKED-NEXT: mov x17, x0 +; HINT-UNCHECKED-NEXT: mov x16, x1 +; HINT-UNCHECKED-NEXT: autia1716 +; HINT-UNCHECKED-NEXT: mov x0, x17 +; HINT-UNCHECKED-NEXT: ret +; +; ELF-CHECKED-LABEL: test_auth_da: +; ELF-CHECKED: %bb.0: +; ELF-CHECKED-NEXT: mov x17, x0 +; ELF-CHECKED-NEXT: autda x17, x1 +; ELF-CHECKED-NEXT: mov x0, x17 +; ELF-CHECKED-NEXT: ret +; +; HINT-CHECKED-LABEL: test_auth_da: +; HINT-CHECKED: %bb.0: +; HINT-CHECKED-NEXT: mov x17, x0 +; HINT-CHECKED-NEXT: mov x16, x1 +; HINT-CHECKED-NEXT: autia1716 +; HINT-CHECKED-NEXT: mov x0, x17 +; HINT-CHECKED-NEXT: ret +; +; ELF-TRAP-LABEL: test_auth_da: +; ELF-TRAP: %bb.0: +; ELF-TRAP-NEXT: mov x17, x0 +; ELF-TRAP-NEXT: autda x17, x1 +; ELF-TRAP-NEXT: mov x16, x17 +; ELF-TRAP-NEXT: xpacd x16 +; ELF-TRAP-NEXT: cmp x16, x17 +; ELF-TRAP-NEXT: b.eq [[L]]auth_success_4 +; ELF-TRAP-NEXT: brk #0xc472 +; ELF-TRAP-NEXT: Lauth_success_4: +; ELF-TRAP-NEXT: mov x0, x17 +; ELF-TRAP-NEXT: ret +; +; HINT-TRAP-LABEL: test_auth_da: +; HINT-TRAP: %bb.0: +; HINT-TRAP-NEXT: mov x17, x0 +; HINT-TRAP-NEXT: mov x16, x1 +; HINT-TRAP-NEXT: autia1716 +; HINT-TRAP-NEXT: mov x16, x17 +; HINT-TRAP-NEXT: xpacd x16 +; HINT-TRAP-NEXT: cmp x16, x17 +; HINT-TRAP-NEXT: b.eq [[L]]auth_success_4 +; HINT-TRAP-NEXT: brk #0xc472 +; HINT-TRAP-NEXT: Lauth_success_4: +; HINT-TRAP-NEXT: mov x0, x17 +; HINT-TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 2, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_auth_da_zero(i64 %arg) { +; ELF-UNCHECKED-LABEL: test_auth_da_zero: +; ELF-UNCHECKED: %bb.0: +; ELF-UNCHECKED-NEXT: mov x17, x0 +; ELF-UNCHECKED-NEXT: autdza x17 +; ELF-UNCHECKED-NEXT: mov x0, x17 +; ELF-UNCHECKED-NEXT: ret +; +; HINT-UNCHECKED-LABEL: test_auth_da_zero: +; HINT-UNCHECKED: %bb.0: +; HINT-UNCHECKED-NEXT: mov x17, x0 +; HINT-UNCHECKED-NEXT: mov x16, xzr +; HINT-UNCHECKED-NEXT: autia1716 +; HINT-UNCHECKED-NEXT: mov x0, x17 +; HINT-UNCHECKED-NEXT: ret +; +; ELF-CHECKED-LABEL: test_auth_da_zero: +; ELF-CHECKED: %bb.0: +; ELF-CHECKED-NEXT: mov x17, x0 +; ELF-CHECKED-NEXT: autdza x17 +; ELF-CHECKED-NEXT: mov x0, x17 +; ELF-CHECKED-NEXT: ret +; +; HINT-CHECKED-LABEL: test_auth_da_zero: +; HINT-CHECKED: %bb.0: +; HINT-CHECKED-NEXT: mov x17, x0 +; HINT-CHECKED-NEXT: mov x16, xzr +; HINT-CHECKED-NEXT: autia1716 +; HINT-CHECKED-NEXT: mov x0, x17 +; HINT-CHECKED-NEXT: ret +; +; ELF-TRAP-LABEL: test_auth_da_zero: +; ELF-TRAP: %bb.0: +; ELF-TRAP-NEXT: mov x17, x0 +; ELF-TRAP-NEXT: autdza x17 +; ELF-TRAP-NEXT: mov x16, x17 +; ELF-TRAP-NEXT: xpacd x16 +; ELF-TRAP-NEXT: cmp x16, x17 +; ELF-TRAP-NEXT: b.eq [[L]]auth_success_5 +; ELF-TRAP-NEXT: brk #0xc472 +; ELF-TRAP-NEXT: Lauth_success_5: +; ELF-TRAP-NEXT: mov x0, x17 +; ELF-TRAP-NEXT: ret +; +; HINT-TRAP-LABEL: test_auth_da_zero: +; HINT-TRAP: %bb.0: +; HINT-TRAP-NEXT: mov x17, x0 +; HINT-TRAP-NEXT: mov x16, xzr +; HINT-TRAP-NEXT: autia1716 +; HINT-TRAP-NEXT: mov x16, x17 +; HINT-TRAP-NEXT: xpacd x16 +; HINT-TRAP-NEXT: cmp x16, x17 +; HINT-TRAP-NEXT: b.eq [[L]]auth_success_5 +; HINT-TRAP-NEXT: brk #0xc472 +; HINT-TRAP-NEXT: Lauth_success_5: +; HINT-TRAP-NEXT: mov x0, x17 +; HINT-TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 2, i64 0) + ret i64 %tmp +} + +define i64 @test_auth_db(i64 %arg, i64 %arg1) { +; ELF-UNCHECKED-LABEL: test_auth_db: +; ELF-UNCHECKED: %bb.0: +; ELF-UNCHECKED-NEXT: mov x17, x0 +; ELF-UNCHECKED-NEXT: autdb x17, x1 +; ELF-UNCHECKED-NEXT: mov x0, x17 +; ELF-UNCHECKED-NEXT: ret +; +; HINT-UNCHECKED-LABEL: test_auth_db: +; HINT-UNCHECKED: %bb.0: +; HINT-UNCHECKED-NEXT: mov x17, x0 +; HINT-UNCHECKED-NEXT: mov x16, x1 +; HINT-UNCHECKED-NEXT: autib1716 +; HINT-UNCHECKED-NEXT: mov x0, x17 +; HINT-UNCHECKED-NEXT: ret +; +; ELF-CHECKED-LABEL: test_auth_db: +; ELF-CHECKED: %bb.0: +; ELF-CHECKED-NEXT: mov x17, x0 +; ELF-CHECKED-NEXT: autdb x17, x1 +; ELF-CHECKED-NEXT: mov x0, x17 +; ELF-CHECKED-NEXT: ret +; +; HINT-CHECKED-LABEL: test_auth_db: +; HINT-CHECKED: %bb.0: +; HINT-CHECKED-NEXT: mov x17, x0 +; HINT-CHECKED-NEXT: mov x16, x1 +; HINT-CHECKED-NEXT: autib1716 +; HINT-CHECKED-NEXT: mov x0, x17 +; HINT-CHECKED-NEXT: ret +; +; ELF-TRAP-LABEL: test_auth_db: +; ELF-TRAP: %bb.0: +; ELF-TRAP-NEXT: mov x17, x0 +; ELF-TRAP-NEXT: autdb x17, x1 +; ELF-TRAP-NEXT: mov x16, x17 +; ELF-TRAP-NEXT: xpacd x16 +; ELF-TRAP-NEXT: cmp x16, x17 +; ELF-TRAP-NEXT: b.eq [[L]]auth_success_6 +; ELF-TRAP-NEXT: brk #0xc473 +; ELF-TRAP-NEXT: Lauth_success_6: +; ELF-TRAP-NEXT: mov x0, x17 +; ELF-TRAP-NEXT: ret +; +; HINT-TRAP-LABEL: test_auth_db: +; HINT-TRAP: %bb.0: +; HINT-TRAP-NEXT: mov x17, x0 +; HINT-TRAP-NEXT: mov x16, x1 +; HINT-TRAP-NEXT: autib1716 +; HINT-TRAP-NEXT: mov x16, x17 +; HINT-TRAP-NEXT: xpacd x16 +; HINT-TRAP-NEXT: cmp x16, x17 +; HINT-TRAP-NEXT: b.eq [[L]]auth_success_6 +; HINT-TRAP-NEXT: brk #0xc473 +; HINT-TRAP-NEXT: Lauth_success_6: +; HINT-TRAP-NEXT: mov x0, x17 +; HINT-TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 3, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_auth_db_zero(i64 %arg) { +; ELF-UNCHECKED-LABEL: test_auth_db_zero: +; ELF-UNCHECKED: %bb.0: +; ELF-UNCHECKED-NEXT: mov x17, x0 +; ELF-UNCHECKED-NEXT: autdzb x17 +; ELF-UNCHECKED-NEXT: mov x0, x17 +; ELF-UNCHECKED-NEXT: ret +; +; HINT-UNCHECKED-LABEL: test_auth_db_zero: +; HINT-UNCHECKED: %bb.0: +; HINT-UNCHECKED-NEXT: mov x17, x0 +; HINT-UNCHECKED-NEXT: mov x16, xzr +; HINT-UNCHECKED-NEXT: autib1716 +; HINT-UNCHECKED-NEXT: mov x0, x17 +; HINT-UNCHECKED-NEXT: ret +; +; ELF-CHECKED-LABEL: test_auth_db_zero: +; ELF-CHECKED: %bb.0: +; ELF-CHECKED-NEXT: mov x17, x0 +; ELF-CHECKED-NEXT: autdzb x17 +; ELF-CHECKED-NEXT: mov x0, x17 +; ELF-CHECKED-NEXT: ret +; +; HINT-CHECKED-LABEL: test_auth_db_zero: +; HINT-CHECKED: %bb.0: +; HINT-CHECKED-NEXT: mov x17, x0 +; HINT-CHECKED-NEXT: mov x16, xzr +; HINT-CHECKED-NEXT: autib1716 +; HINT-CHECKED-NEXT: mov x0, x17 +; HINT-CHECKED-NEXT: ret +; +; ELF-TRAP-LABEL: test_auth_db_zero: +; ELF-TRAP: %bb.0: +; ELF-TRAP-NEXT: mov x17, x0 +; ELF-TRAP-NEXT: autdzb x17 +; ELF-TRAP-NEXT: mov x16, x17 +; ELF-TRAP-NEXT: xpacd x16 +; ELF-TRAP-NEXT: cmp x16, x17 +; ELF-TRAP-NEXT: b.eq [[L]]auth_success_7 +; ELF-TRAP-NEXT: brk #0xc473 +; ELF-TRAP-NEXT: Lauth_success_7: +; ELF-TRAP-NEXT: mov x0, x17 +; ELF-TRAP-NEXT: ret +; +; HINT-TRAP-LABEL: test_auth_db_zero: +; HINT-TRAP: %bb.0: +; HINT-TRAP-NEXT: mov x17, x0 +; HINT-TRAP-NEXT: mov x16, xzr +; HINT-TRAP-NEXT: autib1716 +; HINT-TRAP-NEXT: mov x16, x17 +; HINT-TRAP-NEXT: xpacd x16 +; HINT-TRAP-NEXT: cmp x16, x17 +; HINT-TRAP-NEXT: b.eq [[L]]auth_success_7 +; HINT-TRAP-NEXT: brk #0xc473 +; HINT-TRAP-NEXT: Lauth_success_7: +; HINT-TRAP-NEXT: mov x0, x17 +; HINT-TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 3, i64 0) + ret i64 %tmp +} + +;; Note that this might seem like a no-op but is actually a valid way to enforce +;; the validity of a signature. +define i64 @test_resign_ia_ia(i64 %arg, i64 %arg1, i64 %arg2) { +; ELF-UNCHECKED-LABEL: test_resign_ia_ia: +; ELF-UNCHECKED: %bb.0: +; ELF-UNCHECKED-NEXT: mov x17, x0 +; ELF-UNCHECKED-NEXT: autia x17, x1 +; ELF-UNCHECKED-NEXT: pacia x17, x2 +; ELF-UNCHECKED-NEXT: mov x0, x17 +; ELF-UNCHECKED-NEXT: ret +; +; HINT-UNCHECKED-LABEL: test_resign_ia_ia: +; HINT-UNCHECKED: %bb.0: +; HINT-UNCHECKED-NEXT: mov x17, x0 +; HINT-UNCHECKED-NEXT: mov x16, x1 +; HINT-UNCHECKED-NEXT: autia1716 +; HINT-UNCHECKED-NEXT: mov x16, x2 +; HINT-UNCHECKED-NEXT: pacia1716 +; HINT-UNCHECKED-NEXT: mov x0, x17 +; HINT-UNCHECKED-NEXT: ret +; +; ELF-CHECKED-LABEL: test_resign_ia_ia: +; ELF-CHECKED: %bb.0: +; ELF-CHECKED-NEXT: mov x17, x0 +; ELF-CHECKED-NEXT: autia x17, x1 +; ELF-CHECKED-NEXT: mov x16, x17 +; ELF-CHECKED-NEXT: xpaci x16 +; ELF-CHECKED-NEXT: cmp x16, x17 +; ELF-CHECKED-NEXT: b.eq [[L]]auth_success_0 +; ELF-CHECKED-NEXT: mov x17, x16 +; ELF-CHECKED-NEXT: b [[L]]resign_end_0 +; ELF-CHECKED-NEXT: Lauth_success_0: +; ELF-CHECKED-NEXT: pacia x17, x2 +; ELF-CHECKED-NEXT: Lresign_end_0: +; ELF-CHECKED-NEXT: mov x0, x17 +; ELF-CHECKED-NEXT: ret +; +; HINT-CHECKED-LABEL: test_resign_ia_ia: +; HINT-CHECKED: %bb.0: +; HINT-CHECKED-NEXT: mov x17, x0 +; HINT-CHECKED-NEXT: mov x16, x1 +; HINT-CHECKED-NEXT: autia1716 +; HINT-CHECKED-NEXT: mov x16, x17 +; HINT-CHECKED-NEXT: xpaci x16 +; HINT-CHECKED-NEXT: cmp x16, x17 +; HINT-CHECKED-NEXT: b.eq [[L]]auth_success_0 +; HINT-CHECKED-NEXT: mov x17, x16 +; HINT-CHECKED-NEXT: b [[L]]resign_end_0 +; HINT-CHECKED-NEXT: Lauth_success_0: +; HINT-CHECKED-NEXT: mov x16, x2 +; HINT-CHECKED-NEXT: pacia1716 +; HINT-CHECKED-NEXT: Lresign_end_0: +; HINT-CHECKED-NEXT: mov x0, x17 +; HINT-CHECKED-NEXT: ret +; +; ELF-TRAP-LABEL: test_resign_ia_ia: +; ELF-TRAP: %bb.0: +; ELF-TRAP-NEXT: mov x17, x0 +; ELF-TRAP-NEXT: autia x17, x1 +; ELF-TRAP-NEXT: mov x16, x17 +; ELF-TRAP-NEXT: xpaci x16 +; ELF-TRAP-NEXT: cmp x16, x17 +; ELF-TRAP-NEXT: b.eq [[L]]auth_success_8 +; ELF-TRAP-NEXT: brk #0xc470 +; ELF-TRAP-NEXT: Lauth_success_8: +; ELF-TRAP-NEXT: pacia x17, x2 +; ELF-TRAP-NEXT: mov x0, x17 +; ELF-TRAP-NEXT: ret +; +; HINT-TRAP-LABEL: test_resign_ia_ia: +; HINT-TRAP: %bb.0: +; HINT-TRAP-NEXT: mov x17, x0 +; HINT-TRAP-NEXT: mov x16, x1 +; HINT-TRAP-NEXT: autia1716 +; HINT-TRAP-NEXT: mov x16, x17 +; HINT-TRAP-NEXT: xpaci x16 +; HINT-TRAP-NEXT: cmp x16, x17 +; HINT-TRAP-NEXT: b.eq [[L]]auth_success_8 +; HINT-TRAP-NEXT: brk #0xc470 +; HINT-TRAP-NEXT: Lauth_success_8: +; HINT-TRAP-NEXT: mov x16, x2 +; HINT-TRAP-NEXT: pacia1716 +; HINT-TRAP-NEXT: mov x0, x17 +; HINT-TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 0, i64 %arg1, i32 0, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_ib_ia(i64 %arg, i64 %arg1, i64 %arg2) { +; ELF-UNCHECKED-LABEL: test_resign_ib_ia: +; ELF-UNCHECKED: %bb.0: +; ELF-UNCHECKED-NEXT: mov x17, x0 +; ELF-UNCHECKED-NEXT: autib x17, x1 +; ELF-UNCHECKED-NEXT: pacia x17, x2 +; ELF-UNCHECKED-NEXT: mov x0, x17 +; ELF-UNCHECKED-NEXT: ret +; +; HINT-UNCHECKED-LABEL: test_resign_ib_ia: +; HINT-UNCHECKED: %bb.0: +; HINT-UNCHECKED-NEXT: mov x17, x0 +; HINT-UNCHECKED-NEXT: mov x16, x1 +; HINT-UNCHECKED-NEXT: autib1716 +; HINT-UNCHECKED-NEXT: mov x16, x2 +; HINT-UNCHECKED-NEXT: pacia1716 +; HINT-UNCHECKED-NEXT: mov x0, x17 +; HINT-UNCHECKED-NEXT: ret +; +; ELF-CHECKED-LABEL: test_resign_ib_ia: +; ELF-CHECKED: %bb.0: +; ELF-CHECKED-NEXT: mov x17, x0 +; ELF-CHECKED-NEXT: autib x17, x1 +; ELF-CHECKED-NEXT: mov x16, x17 +; ELF-CHECKED-NEXT: xpaci x16 +; ELF-CHECKED-NEXT: cmp x16, x17 +; ELF-CHECKED-NEXT: b.eq [[L]]auth_success_1 +; ELF-CHECKED-NEXT: mov x17, x16 +; ELF-CHECKED-NEXT: b [[L]]resign_end_1 +; ELF-CHECKED-NEXT: Lauth_success_1: +; ELF-CHECKED-NEXT: pacia x17, x2 +; ELF-CHECKED-NEXT: Lresign_end_1: +; ELF-CHECKED-NEXT: mov x0, x17 +; ELF-CHECKED-NEXT: ret +; +; HINT-CHECKED-LABEL: test_resign_ib_ia: +; HINT-CHECKED: %bb.0: +; HINT-CHECKED-NEXT: mov x17, x0 +; HINT-CHECKED-NEXT: mov x16, x1 +; HINT-CHECKED-NEXT: autib1716 +; HINT-CHECKED-NEXT: mov x16, x17 +; HINT-CHECKED-NEXT: xpaci x16 +; HINT-CHECKED-NEXT: cmp x16, x17 +; HINT-CHECKED-NEXT: b.eq [[L]]auth_success_1 +; HINT-CHECKED-NEXT: mov x17, x16 +; HINT-CHECKED-NEXT: b [[L]]resign_end_1 +; HINT-CHECKED-NEXT: Lauth_success_1: +; HINT-CHECKED-NEXT: mov x16, x2 +; HINT-CHECKED-NEXT: pacia1716 +; HINT-CHECKED-NEXT: Lresign_end_1: +; HINT-CHECKED-NEXT: mov x0, x17 +; HINT-CHECKED-NEXT: ret +; +; ELF-TRAP-LABEL: test_resign_ib_ia: +; ELF-TRAP: %bb.0: +; ELF-TRAP-NEXT: mov x17, x0 +; ELF-TRAP-NEXT: autib x17, x1 +; ELF-TRAP-NEXT: mov x16, x17 +; ELF-TRAP-NEXT: xpaci x16 +; ELF-TRAP-NEXT: cmp x16, x17 +; ELF-TRAP-NEXT: b.eq [[L]]auth_success_9 +; ELF-TRAP-NEXT: brk #0xc471 +; ELF-TRAP-NEXT: Lauth_success_9: +; ELF-TRAP-NEXT: pacia x17, x2 +; ELF-TRAP-NEXT: mov x0, x17 +; ELF-TRAP-NEXT: ret +; +; HINT-TRAP-LABEL: test_resign_ib_ia: +; HINT-TRAP: %bb.0: +; HINT-TRAP-NEXT: mov x17, x0 +; HINT-TRAP-NEXT: mov x16, x1 +; HINT-TRAP-NEXT: autib1716 +; HINT-TRAP-NEXT: mov x16, x17 +; HINT-TRAP-NEXT: xpaci x16 +; HINT-TRAP-NEXT: cmp x16, x17 +; HINT-TRAP-NEXT: b.eq [[L]]auth_success_9 +; HINT-TRAP-NEXT: brk #0xc471 +; HINT-TRAP-NEXT: Lauth_success_9: +; HINT-TRAP-NEXT: mov x16, x2 +; HINT-TRAP-NEXT: pacia1716 +; HINT-TRAP-NEXT: mov x0, x17 +; HINT-TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 1, i64 %arg1, i32 0, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_da_ia(i64 %arg, i64 %arg1, i64 %arg2) { +; ELF-UNCHECKED-LABEL: test_resign_da_ia: +; ELF-UNCHECKED: %bb.0: +; ELF-UNCHECKED-NEXT: mov x17, x0 +; ELF-UNCHECKED-NEXT: autda x17, x1 +; ELF-UNCHECKED-NEXT: pacia x17, x2 +; ELF-UNCHECKED-NEXT: mov x0, x17 +; ELF-UNCHECKED-NEXT: ret +; +; HINT-UNCHECKED-LABEL: test_resign_da_ia: +; HINT-UNCHECKED: %bb.0: +; HINT-UNCHECKED-NEXT: mov x17, x0 +; HINT-UNCHECKED-NEXT: mov x16, x1 +; HINT-UNCHECKED-NEXT: autia1716 +; HINT-UNCHECKED-NEXT: mov x16, x2 +; HINT-UNCHECKED-NEXT: pacia1716 +; HINT-UNCHECKED-NEXT: mov x0, x17 +; HINT-UNCHECKED-NEXT: ret +; +; ELF-CHECKED-LABEL: test_resign_da_ia: +; ELF-CHECKED: %bb.0: +; ELF-CHECKED-NEXT: mov x17, x0 +; ELF-CHECKED-NEXT: autda x17, x1 +; ELF-CHECKED-NEXT: mov x16, x17 +; ELF-CHECKED-NEXT: xpacd x16 +; ELF-CHECKED-NEXT: cmp x16, x17 +; ELF-CHECKED-NEXT: b.eq [[L]]auth_success_2 +; ELF-CHECKED-NEXT: mov x17, x16 +; ELF-CHECKED-NEXT: b [[L]]resign_end_2 +; ELF-CHECKED-NEXT: Lauth_success_2: +; ELF-CHECKED-NEXT: pacia x17, x2 +; ELF-CHECKED-NEXT: Lresign_end_2: +; ELF-CHECKED-NEXT: mov x0, x17 +; ELF-CHECKED-NEXT: ret +; +; HINT-CHECKED-LABEL: test_resign_da_ia: +; HINT-CHECKED: %bb.0: +; HINT-CHECKED-NEXT: mov x17, x0 +; HINT-CHECKED-NEXT: mov x16, x1 +; HINT-CHECKED-NEXT: autia1716 +; HINT-CHECKED-NEXT: mov x16, x17 +; HINT-CHECKED-NEXT: xpacd x16 +; HINT-CHECKED-NEXT: cmp x16, x17 +; HINT-CHECKED-NEXT: b.eq [[L]]auth_success_2 +; HINT-CHECKED-NEXT: mov x17, x16 +; HINT-CHECKED-NEXT: b [[L]]resign_end_2 +; HINT-CHECKED-NEXT: Lauth_success_2: +; HINT-CHECKED-NEXT: mov x16, x2 +; HINT-CHECKED-NEXT: pacia1716 +; HINT-CHECKED-NEXT: Lresign_end_2: +; HINT-CHECKED-NEXT: mov x0, x17 +; HINT-CHECKED-NEXT: ret +; +; ELF-TRAP-LABEL: test_resign_da_ia: +; ELF-TRAP: %bb.0: +; ELF-TRAP-NEXT: mov x17, x0 +; ELF-TRAP-NEXT: autda x17, x1 +; ELF-TRAP-NEXT: mov x16, x17 +; ELF-TRAP-NEXT: xpacd x16 +; ELF-TRAP-NEXT: cmp x16, x17 +; ELF-TRAP-NEXT: b.eq [[L]]auth_success_10 +; ELF-TRAP-NEXT: brk #0xc472 +; ELF-TRAP-NEXT: Lauth_success_10: +; ELF-TRAP-NEXT: pacia x17, x2 +; ELF-TRAP-NEXT: mov x0, x17 +; ELF-TRAP-NEXT: ret +; +; HINT-TRAP-LABEL: test_resign_da_ia: +; HINT-TRAP: %bb.0: +; HINT-TRAP-NEXT: mov x17, x0 +; HINT-TRAP-NEXT: mov x16, x1 +; HINT-TRAP-NEXT: autia1716 +; HINT-TRAP-NEXT: mov x16, x17 +; HINT-TRAP-NEXT: xpacd x16 +; HINT-TRAP-NEXT: cmp x16, x17 +; HINT-TRAP-NEXT: b.eq [[L]]auth_success_10 +; HINT-TRAP-NEXT: brk #0xc472 +; HINT-TRAP-NEXT: Lauth_success_10: +; HINT-TRAP-NEXT: mov x16, x2 +; HINT-TRAP-NEXT: pacia1716 +; HINT-TRAP-NEXT: mov x0, x17 +; HINT-TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %arg1, i32 0, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_db_da(i64 %arg, i64 %arg1, i64 %arg2) { +; ELF-UNCHECKED-LABEL: test_resign_db_da: +; ELF-UNCHECKED: %bb.0: +; ELF-UNCHECKED-NEXT: mov x17, x0 +; ELF-UNCHECKED-NEXT: autdb x17, x1 +; ELF-UNCHECKED-NEXT: pacda x17, x2 +; ELF-UNCHECKED-NEXT: mov x0, x17 +; ELF-UNCHECKED-NEXT: ret +; +; HINT-UNCHECKED-LABEL: test_resign_db_da: +; HINT-UNCHECKED: %bb.0: +; HINT-UNCHECKED-NEXT: mov x17, x0 +; HINT-UNCHECKED-NEXT: mov x16, x1 +; HINT-UNCHECKED-NEXT: autib1716 +; HINT-UNCHECKED-NEXT: mov x16, x2 +; HINT-UNCHECKED-NEXT: pacia1716 +; HINT-UNCHECKED-NEXT: mov x0, x17 +; HINT-UNCHECKED-NEXT: ret +; +; ELF-CHECKED-LABEL: test_resign_db_da: +; ELF-CHECKED: %bb.0: +; ELF-CHECKED-NEXT: mov x17, x0 +; ELF-CHECKED-NEXT: autdb x17, x1 +; ELF-CHECKED-NEXT: mov x16, x17 +; ELF-CHECKED-NEXT: xpacd x16 +; ELF-CHECKED-NEXT: cmp x16, x17 +; ELF-CHECKED-NEXT: b.eq [[L]]auth_success_3 +; ELF-CHECKED-NEXT: mov x17, x16 +; ELF-CHECKED-NEXT: b [[L]]resign_end_3 +; ELF-CHECKED-NEXT: Lauth_success_3: +; ELF-CHECKED-NEXT: pacda x17, x2 +; ELF-CHECKED-NEXT: Lresign_end_3: +; ELF-CHECKED-NEXT: mov x0, x17 +; ELF-CHECKED-NEXT: ret +; +; HINT-CHECKED-LABEL: test_resign_db_da: +; HINT-CHECKED: %bb.0: +; HINT-CHECKED-NEXT: mov x17, x0 +; HINT-CHECKED-NEXT: mov x16, x1 +; HINT-CHECKED-NEXT: autib1716 +; HINT-CHECKED-NEXT: mov x16, x17 +; HINT-CHECKED-NEXT: xpacd x16 +; HINT-CHECKED-NEXT: cmp x16, x17 +; HINT-CHECKED-NEXT: b.eq [[L]]auth_success_3 +; HINT-CHECKED-NEXT: mov x17, x16 +; HINT-CHECKED-NEXT: b [[L]]resign_end_3 +; HINT-CHECKED-NEXT: Lauth_success_3: +; HINT-CHECKED-NEXT: mov x16, x2 +; HINT-CHECKED-NEXT: pacia1716 +; HINT-CHECKED-NEXT: Lresign_end_3: +; HINT-CHECKED-NEXT: mov x0, x17 +; HINT-CHECKED-NEXT: ret +; +; ELF-TRAP-LABEL: test_resign_db_da: +; ELF-TRAP: %bb.0: +; ELF-TRAP-NEXT: mov x17, x0 +; ELF-TRAP-NEXT: autdb x17, x1 +; ELF-TRAP-NEXT: mov x16, x17 +; ELF-TRAP-NEXT: xpacd x16 +; ELF-TRAP-NEXT: cmp x16, x17 +; ELF-TRAP-NEXT: b.eq [[L]]auth_success_11 +; ELF-TRAP-NEXT: brk #0xc473 +; ELF-TRAP-NEXT: Lauth_success_11: +; ELF-TRAP-NEXT: pacda x17, x2 +; ELF-TRAP-NEXT: mov x0, x17 +; ELF-TRAP-NEXT: ret +; +; HINT-TRAP-LABEL: test_resign_db_da: +; HINT-TRAP: %bb.0: +; HINT-TRAP-NEXT: mov x17, x0 +; HINT-TRAP-NEXT: mov x16, x1 +; HINT-TRAP-NEXT: autib1716 +; HINT-TRAP-NEXT: mov x16, x17 +; HINT-TRAP-NEXT: xpacd x16 +; HINT-TRAP-NEXT: cmp x16, x17 +; HINT-TRAP-NEXT: b.eq [[L]]auth_success_11 +; HINT-TRAP-NEXT: brk #0xc473 +; HINT-TRAP-NEXT: Lauth_success_11: +; HINT-TRAP-NEXT: mov x16, x2 +; HINT-TRAP-NEXT: pacia1716 +; HINT-TRAP-NEXT: mov x0, x17 +; HINT-TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 3, i64 %arg1, i32 2, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_iza_db(i64 %arg, i64 %arg1, i64 %arg2) { +; ELF-UNCHECKED-LABEL: test_resign_iza_db: +; ELF-UNCHECKED: %bb.0: +; ELF-UNCHECKED-NEXT: mov x17, x0 +; ELF-UNCHECKED-NEXT: autiza x17 +; ELF-UNCHECKED-NEXT: pacdb x17, x2 +; ELF-UNCHECKED-NEXT: mov x0, x17 +; ELF-UNCHECKED-NEXT: ret +; +; HINT-UNCHECKED-LABEL: test_resign_iza_db: +; HINT-UNCHECKED: %bb.0: +; HINT-UNCHECKED-NEXT: mov x17, x0 +; HINT-UNCHECKED-NEXT: mov x16, xzr +; HINT-UNCHECKED-NEXT: autia1716 +; HINT-UNCHECKED-NEXT: mov x16, x2 +; HINT-UNCHECKED-NEXT: pacib1716 +; HINT-UNCHECKED-NEXT: mov x0, x17 +; HINT-UNCHECKED-NEXT: ret +; +; ELF-CHECKED-LABEL: test_resign_iza_db: +; ELF-CHECKED: %bb.0: +; ELF-CHECKED-NEXT: mov x17, x0 +; ELF-CHECKED-NEXT: autiza x17 +; ELF-CHECKED-NEXT: mov x16, x17 +; ELF-CHECKED-NEXT: xpaci x16 +; ELF-CHECKED-NEXT: cmp x16, x17 +; ELF-CHECKED-NEXT: b.eq [[L]]auth_success_4 +; ELF-CHECKED-NEXT: mov x17, x16 +; ELF-CHECKED-NEXT: b [[L]]resign_end_4 +; ELF-CHECKED-NEXT: Lauth_success_4: +; ELF-CHECKED-NEXT: pacdb x17, x2 +; ELF-CHECKED-NEXT: Lresign_end_4: +; ELF-CHECKED-NEXT: mov x0, x17 +; ELF-CHECKED-NEXT: ret +; +; HINT-CHECKED-LABEL: test_resign_iza_db: +; HINT-CHECKED: %bb.0: +; HINT-CHECKED-NEXT: mov x17, x0 +; HINT-CHECKED-NEXT: mov x16, xzr +; HINT-CHECKED-NEXT: autia1716 +; HINT-CHECKED-NEXT: mov x16, x17 +; HINT-CHECKED-NEXT: xpaci x16 +; HINT-CHECKED-NEXT: cmp x16, x17 +; HINT-CHECKED-NEXT: b.eq [[L]]auth_success_4 +; HINT-CHECKED-NEXT: mov x17, x16 +; HINT-CHECKED-NEXT: b [[L]]resign_end_4 +; HINT-CHECKED-NEXT: Lauth_success_4: +; HINT-CHECKED-NEXT: mov x16, x2 +; HINT-CHECKED-NEXT: pacib1716 +; HINT-CHECKED-NEXT: Lresign_end_4: +; HINT-CHECKED-NEXT: mov x0, x17 +; HINT-CHECKED-NEXT: ret +; +; ELF-TRAP-LABEL: test_resign_iza_db: +; ELF-TRAP: %bb.0: +; ELF-TRAP-NEXT: mov x17, x0 +; ELF-TRAP-NEXT: autiza x17 +; ELF-TRAP-NEXT: mov x16, x17 +; ELF-TRAP-NEXT: xpaci x16 +; ELF-TRAP-NEXT: cmp x16, x17 +; ELF-TRAP-NEXT: b.eq [[L]]auth_success_12 +; ELF-TRAP-NEXT: brk #0xc470 +; ELF-TRAP-NEXT: Lauth_success_12: +; ELF-TRAP-NEXT: pacdb x17, x2 +; ELF-TRAP-NEXT: mov x0, x17 +; ELF-TRAP-NEXT: ret +; +; HINT-TRAP-LABEL: test_resign_iza_db: +; HINT-TRAP: %bb.0: +; HINT-TRAP-NEXT: mov x17, x0 +; HINT-TRAP-NEXT: mov x16, xzr +; HINT-TRAP-NEXT: autia1716 +; HINT-TRAP-NEXT: mov x16, x17 +; HINT-TRAP-NEXT: xpaci x16 +; HINT-TRAP-NEXT: cmp x16, x17 +; HINT-TRAP-NEXT: b.eq [[L]]auth_success_12 +; HINT-TRAP-NEXT: brk #0xc470 +; HINT-TRAP-NEXT: Lauth_success_12: +; HINT-TRAP-NEXT: mov x16, x2 +; HINT-TRAP-NEXT: pacib1716 +; HINT-TRAP-NEXT: mov x0, x17 +; HINT-TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 0, i64 0, i32 3, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_da_dzb(i64 %arg, i64 %arg1, i64 %arg2) { +; ELF-UNCHECKED-LABEL: test_resign_da_dzb: +; ELF-UNCHECKED: %bb.0: +; ELF-UNCHECKED-NEXT: mov x17, x0 +; ELF-UNCHECKED-NEXT: autda x17, x1 +; ELF-UNCHECKED-NEXT: pacdzb x17 +; ELF-UNCHECKED-NEXT: mov x0, x17 +; ELF-UNCHECKED-NEXT: ret +; +; HINT-UNCHECKED-LABEL: test_resign_da_dzb: +; HINT-UNCHECKED: %bb.0: +; HINT-UNCHECKED-NEXT: mov x17, x0 +; HINT-UNCHECKED-NEXT: mov x16, x1 +; HINT-UNCHECKED-NEXT: autia1716 +; HINT-UNCHECKED-NEXT: mov x16, xzr +; HINT-UNCHECKED-NEXT: pacib1716 +; HINT-UNCHECKED-NEXT: mov x0, x17 +; HINT-UNCHECKED-NEXT: ret +; +; ELF-CHECKED-LABEL: test_resign_da_dzb: +; ELF-CHECKED: %bb.0: +; ELF-CHECKED-NEXT: mov x17, x0 +; ELF-CHECKED-NEXT: autda x17, x1 +; ELF-CHECKED-NEXT: mov x16, x17 +; ELF-CHECKED-NEXT: xpacd x16 +; ELF-CHECKED-NEXT: cmp x16, x17 +; ELF-CHECKED-NEXT: b.eq [[L]]auth_success_5 +; ELF-CHECKED-NEXT: mov x17, x16 +; ELF-CHECKED-NEXT: b [[L]]resign_end_5 +; ELF-CHECKED-NEXT: Lauth_success_5: +; ELF-CHECKED-NEXT: pacdzb x17 +; ELF-CHECKED-NEXT: Lresign_end_5: +; ELF-CHECKED-NEXT: mov x0, x17 +; ELF-CHECKED-NEXT: ret +; +; HINT-CHECKED-LABEL: test_resign_da_dzb: +; HINT-CHECKED: %bb.0: +; HINT-CHECKED-NEXT: mov x17, x0 +; HINT-CHECKED-NEXT: mov x16, x1 +; HINT-CHECKED-NEXT: autia1716 +; HINT-CHECKED-NEXT: mov x16, x17 +; HINT-CHECKED-NEXT: xpacd x16 +; HINT-CHECKED-NEXT: cmp x16, x17 +; HINT-CHECKED-NEXT: b.eq [[L]]auth_success_5 +; HINT-CHECKED-NEXT: mov x17, x16 +; HINT-CHECKED-NEXT: b [[L]]resign_end_5 +; HINT-CHECKED-NEXT: Lauth_success_5: +; HINT-CHECKED-NEXT: mov x16, xzr +; HINT-CHECKED-NEXT: pacib1716 +; HINT-CHECKED-NEXT: Lresign_end_5: +; HINT-CHECKED-NEXT: mov x0, x17 +; HINT-CHECKED-NEXT: ret +; +; ELF-TRAP-LABEL: test_resign_da_dzb: +; ELF-TRAP: %bb.0: +; ELF-TRAP-NEXT: mov x17, x0 +; ELF-TRAP-NEXT: autda x17, x1 +; ELF-TRAP-NEXT: mov x16, x17 +; ELF-TRAP-NEXT: xpacd x16 +; ELF-TRAP-NEXT: cmp x16, x17 +; ELF-TRAP-NEXT: b.eq [[L]]auth_success_13 +; ELF-TRAP-NEXT: brk #0xc472 +; ELF-TRAP-NEXT: Lauth_success_13: +; ELF-TRAP-NEXT: pacdzb x17 +; ELF-TRAP-NEXT: mov x0, x17 +; ELF-TRAP-NEXT: ret +; +; HINT-TRAP-LABEL: test_resign_da_dzb: +; HINT-TRAP: %bb.0: +; HINT-TRAP-NEXT: mov x17, x0 +; HINT-TRAP-NEXT: mov x16, x1 +; HINT-TRAP-NEXT: autia1716 +; HINT-TRAP-NEXT: mov x16, x17 +; HINT-TRAP-NEXT: xpacd x16 +; HINT-TRAP-NEXT: cmp x16, x17 +; HINT-TRAP-NEXT: b.eq [[L]]auth_success_13 +; HINT-TRAP-NEXT: brk #0xc472 +; HINT-TRAP-NEXT: Lauth_success_13: +; HINT-TRAP-NEXT: mov x16, xzr +; HINT-TRAP-NEXT: pacib1716 +; HINT-TRAP-NEXT: mov x0, x17 +; HINT-TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %arg1, i32 3, i64 0) + ret i64 %tmp +} + +define i64 @test_auth_trap_attribute(i64 %arg, i64 %arg1) "ptrauth-auth-traps" { +; ELF-UNCHECKED-LABEL: test_auth_trap_attribute: +; ELF-UNCHECKED: %bb.0: +; ELF-UNCHECKED-NEXT: mov x17, x0 +; ELF-UNCHECKED-NEXT: autia x17, x1 +; ELF-UNCHECKED-NEXT: mov x0, x17 +; ELF-UNCHECKED-NEXT: ret +; +; HINT-UNCHECKED-LABEL: test_auth_trap_attribute: +; HINT-UNCHECKED: %bb.0: +; HINT-UNCHECKED-NEXT: mov x17, x0 +; HINT-UNCHECKED-NEXT: mov x16, x1 +; HINT-UNCHECKED-NEXT: autia1716 +; HINT-UNCHECKED-NEXT: mov x0, x17 +; HINT-UNCHECKED-NEXT: ret +; +; ELF-CHECKED-LABEL: test_auth_trap_attribute: +; ELF-CHECKED: %bb.0: +; ELF-CHECKED-NEXT: mov x17, x0 +; ELF-CHECKED-NEXT: autia x17, x1 +; ELF-CHECKED-NEXT: mov x16, x17 +; ELF-CHECKED-NEXT: xpaci x16 +; ELF-CHECKED-NEXT: cmp x16, x17 +; ELF-CHECKED-NEXT: b.eq [[L]]auth_success_6 +; ELF-CHECKED-NEXT: brk #0xc470 +; ELF-CHECKED-NEXT: Lauth_success_6: +; ELF-CHECKED-NEXT: mov x0, x17 +; ELF-CHECKED-NEXT: ret +; +; HINT-CHECKED-LABEL: test_auth_trap_attribute: +; HINT-CHECKED: %bb.0: +; HINT-CHECKED-NEXT: mov x17, x0 +; HINT-CHECKED-NEXT: mov x16, x1 +; HINT-CHECKED-NEXT: autia1716 +; HINT-CHECKED-NEXT: mov x16, x17 +; HINT-CHECKED-NEXT: xpaci x16 +; HINT-CHECKED-NEXT: cmp x16, x17 +; HINT-CHECKED-NEXT: b.eq [[L]]auth_success_6 +; HINT-CHECKED-NEXT: brk #0xc470 +; HINT-CHECKED-NEXT: Lauth_success_6: +; HINT-CHECKED-NEXT: mov x0, x17 +; HINT-CHECKED-NEXT: ret +; +; ELF-TRAP-LABEL: test_auth_trap_attribute: +; ELF-TRAP: %bb.0: +; ELF-TRAP-NEXT: mov x17, x0 +; ELF-TRAP-NEXT: autia x17, x1 +; ELF-TRAP-NEXT: mov x16, x17 +; ELF-TRAP-NEXT: xpaci x16 +; ELF-TRAP-NEXT: cmp x16, x17 +; ELF-TRAP-NEXT: b.eq [[L]]auth_success_14 +; ELF-TRAP-NEXT: brk #0xc470 +; ELF-TRAP-NEXT: Lauth_success_14: +; ELF-TRAP-NEXT: mov x0, x17 +; ELF-TRAP-NEXT: ret +; +; HINT-TRAP-LABEL: test_auth_trap_attribute: +; HINT-TRAP: %bb.0: +; HINT-TRAP-NEXT: mov x17, x0 +; HINT-TRAP-NEXT: mov x16, x1 +; HINT-TRAP-NEXT: autia1716 +; HINT-TRAP-NEXT: mov x16, x17 +; HINT-TRAP-NEXT: xpaci x16 +; HINT-TRAP-NEXT: cmp x16, x17 +; HINT-TRAP-NEXT: b.eq [[L]]auth_success_14 +; HINT-TRAP-NEXT: brk #0xc470 +; HINT-TRAP-NEXT: Lauth_success_14: +; HINT-TRAP-NEXT: mov x0, x17 +; HINT-TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_auth_ia_constdisc(i64 %arg) { +; ELF-UNCHECKED-LABEL: test_auth_ia_constdisc: +; ELF-UNCHECKED: %bb.0: +; ELF-UNCHECKED-NEXT: mov x17, x0 +; ELF-UNCHECKED-NEXT: mov x16, #256 +; ELF-UNCHECKED-NEXT: autia x17, x16 +; ELF-UNCHECKED-NEXT: mov x0, x17 +; ELF-UNCHECKED-NEXT: ret +; +; HINT-UNCHECKED-LABEL: test_auth_ia_constdisc: +; HINT-UNCHECKED: %bb.0: +; HINT-UNCHECKED-NEXT: mov x17, x0 +; HINT-UNCHECKED-NEXT: mov x16, #256 +; HINT-UNCHECKED-NEXT: autia1716 +; HINT-UNCHECKED-NEXT: mov x0, x17 +; HINT-UNCHECKED-NEXT: ret +; +; ELF-CHECKED-LABEL: test_auth_ia_constdisc: +; ELF-CHECKED: %bb.0: +; ELF-CHECKED-NEXT: mov x17, x0 +; ELF-CHECKED-NEXT: mov x16, #256 +; ELF-CHECKED-NEXT: autia x17, x16 +; ELF-CHECKED-NEXT: mov x0, x17 +; ELF-CHECKED-NEXT: ret +; +; HINT-CHECKED-LABEL: test_auth_ia_constdisc: +; HINT-CHECKED: %bb.0: +; HINT-CHECKED-NEXT: mov x17, x0 +; HINT-CHECKED-NEXT: mov x16, #256 +; HINT-CHECKED-NEXT: autia1716 +; HINT-CHECKED-NEXT: mov x0, x17 +; HINT-CHECKED-NEXT: ret +; +; ELF-TRAP-LABEL: test_auth_ia_constdisc: +; ELF-TRAP: %bb.0: +; ELF-TRAP-NEXT: mov x17, x0 +; ELF-TRAP-NEXT: mov x16, #256 +; ELF-TRAP-NEXT: autia x17, x16 +; ELF-TRAP-NEXT: mov x16, x17 +; ELF-TRAP-NEXT: xpaci x16 +; ELF-TRAP-NEXT: cmp x16, x17 +; ELF-TRAP-NEXT: b.eq [[L]]auth_success_15 +; ELF-TRAP-NEXT: brk #0xc470 +; ELF-TRAP-NEXT: Lauth_success_15: +; ELF-TRAP-NEXT: mov x0, x17 +; ELF-TRAP-NEXT: ret +; +; HINT-TRAP-LABEL: test_auth_ia_constdisc: +; HINT-TRAP: %bb.0: +; HINT-TRAP-NEXT: mov x17, x0 +; HINT-TRAP-NEXT: mov x16, #256 +; HINT-TRAP-NEXT: autia1716 +; HINT-TRAP-NEXT: mov x16, x17 +; HINT-TRAP-NEXT: xpaci x16 +; HINT-TRAP-NEXT: cmp x16, x17 +; HINT-TRAP-NEXT: b.eq [[L]]auth_success_15 +; HINT-TRAP-NEXT: brk #0xc470 +; HINT-TRAP-NEXT: Lauth_success_15: +; HINT-TRAP-NEXT: mov x0, x17 +; HINT-TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 256) + ret i64 %tmp +} + +define i64 @test_resign_da_constdisc(i64 %arg, i64 %arg1) { +; ELF-UNCHECKED-LABEL: test_resign_da_constdisc: +; ELF-UNCHECKED: %bb.0: +; ELF-UNCHECKED-NEXT: mov x17, x0 +; ELF-UNCHECKED-NEXT: autda x17, x1 +; ELF-UNCHECKED-NEXT: mov x16, #256 +; ELF-UNCHECKED-NEXT: pacda x17, x16 +; ELF-UNCHECKED-NEXT: mov x0, x17 +; ELF-UNCHECKED-NEXT: ret +; +; HINT-UNCHECKED-LABEL: test_resign_da_constdisc: +; HINT-UNCHECKED: %bb.0: +; HINT-UNCHECKED-NEXT: mov x17, x0 +; HINT-UNCHECKED-NEXT: mov x16, x1 +; HINT-UNCHECKED-NEXT: autia1716 +; HINT-UNCHECKED-NEXT: mov x16, #256 +; HINT-UNCHECKED-NEXT: pacia1716 +; HINT-UNCHECKED-NEXT: mov x0, x17 +; HINT-UNCHECKED-NEXT: ret +; +; ELF-CHECKED-LABEL: test_resign_da_constdisc: +; ELF-CHECKED: %bb.0: +; ELF-CHECKED-NEXT: mov x17, x0 +; ELF-CHECKED-NEXT: autda x17, x1 +; ELF-CHECKED-NEXT: mov x16, x17 +; ELF-CHECKED-NEXT: xpacd x16 +; ELF-CHECKED-NEXT: cmp x16, x17 +; ELF-CHECKED-NEXT: b.eq [[L]]auth_success_7 +; ELF-CHECKED-NEXT: mov x17, x16 +; ELF-CHECKED-NEXT: b [[L]]resign_end_6 +; ELF-CHECKED-NEXT: Lauth_success_7: +; ELF-CHECKED-NEXT: mov x16, #256 +; ELF-CHECKED-NEXT: pacda x17, x16 +; ELF-CHECKED-NEXT: Lresign_end_6: +; ELF-CHECKED-NEXT: mov x0, x17 +; ELF-CHECKED-NEXT: ret +; +; HINT-CHECKED-LABEL: test_resign_da_constdisc: +; HINT-CHECKED: %bb.0: +; HINT-CHECKED-NEXT: mov x17, x0 +; HINT-CHECKED-NEXT: mov x16, x1 +; HINT-CHECKED-NEXT: autia1716 +; HINT-CHECKED-NEXT: mov x16, x17 +; HINT-CHECKED-NEXT: xpacd x16 +; HINT-CHECKED-NEXT: cmp x16, x17 +; HINT-CHECKED-NEXT: b.eq [[L]]auth_success_7 +; HINT-CHECKED-NEXT: mov x17, x16 +; HINT-CHECKED-NEXT: b [[L]]resign_end_6 +; HINT-CHECKED-NEXT: Lauth_success_7: +; HINT-CHECKED-NEXT: mov x16, #256 +; HINT-CHECKED-NEXT: pacia1716 +; HINT-CHECKED-NEXT: Lresign_end_6: +; HINT-CHECKED-NEXT: mov x0, x17 +; HINT-CHECKED-NEXT: ret +; +; ELF-TRAP-LABEL: test_resign_da_constdisc: +; ELF-TRAP: %bb.0: +; ELF-TRAP-NEXT: mov x17, x0 +; ELF-TRAP-NEXT: autda x17, x1 +; ELF-TRAP-NEXT: mov x16, x17 +; ELF-TRAP-NEXT: xpacd x16 +; ELF-TRAP-NEXT: cmp x16, x17 +; ELF-TRAP-NEXT: b.eq [[L]]auth_success_16 +; ELF-TRAP-NEXT: brk #0xc472 +; ELF-TRAP-NEXT: Lauth_success_16: +; ELF-TRAP-NEXT: mov x16, #256 +; ELF-TRAP-NEXT: pacda x17, x16 +; ELF-TRAP-NEXT: mov x0, x17 +; ELF-TRAP-NEXT: ret +; +; HINT-TRAP-LABEL: test_resign_da_constdisc: +; HINT-TRAP: %bb.0: +; HINT-TRAP-NEXT: mov x17, x0 +; HINT-TRAP-NEXT: mov x16, x1 +; HINT-TRAP-NEXT: autia1716 +; HINT-TRAP-NEXT: mov x16, x17 +; HINT-TRAP-NEXT: xpacd x16 +; HINT-TRAP-NEXT: cmp x16, x17 +; HINT-TRAP-NEXT: b.eq [[L]]auth_success_16 +; HINT-TRAP-NEXT: brk #0xc472 +; HINT-TRAP-NEXT: Lauth_success_16: +; HINT-TRAP-NEXT: mov x16, #256 +; HINT-TRAP-NEXT: pacia1716 +; HINT-TRAP-NEXT: mov x0, x17 +; HINT-TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %arg1, i32 2, i64 256) + ret i64 %tmp +} + +declare i64 @llvm.ptrauth.auth(i64, i32, i64) +declare i64 @llvm.ptrauth.resign(i64, i32, i64, i32, i64) diff --git a/llvm/test/CodeGen/AArch64/ptrauth-hint-only-intrinsic-sign-generic.ll b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-intrinsic-sign-generic.ll new file mode 100644 index 0000000000000000000000000000000000000000..79bbe652df86977696f8c8b787929d5d86d49380 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-intrinsic-sign-generic.ll @@ -0,0 +1,18 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py + +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -verify-machineinstrs -global-isel=0 | FileCheck %s +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -verify-machineinstrs -global-isel=1 -global-isel-abort=1 | FileCheck %s + +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -mattr=+pauth-hint-only -verify-machineinstrs -global-isel=0 | FileCheck %s +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -mattr=+pauth-hint-only -verify-machineinstrs -global-isel=1 -global-isel-abort=1 | FileCheck %store + +define i64 @test_sign_generic(i64 %arg, i64 %arg1) { +; CHECK-LABEL: test_sign_generic: +; CHECK: %bb.0: +; CHECK-NEXT: pacga x0, x0, x1 +; CHECK-NEXT: ret + %tmp = call i64 @llvm.ptrauth.sign.generic(i64 %arg, i64 %arg1) + ret i64 %tmp +} + +declare i64 @llvm.ptrauth.sign.generic(i64, i64) diff --git a/llvm/test/CodeGen/AArch64/ptrauth-hint-only-intrinsic-sign.ll b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-intrinsic-sign.ll new file mode 100644 index 0000000000000000000000000000000000000000..068da1039b75bb6a06bddf92fe3af7a9cebfcfee --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-intrinsic-sign.ll @@ -0,0 +1,145 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py + +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -verify-machineinstrs -global-isel=0 | FileCheck %s --check-prefix=CHECK +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -verify-machineinstrs -global-isel=1 -global-isel-abort=1 | FileCheck %s + +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth,+pauth-hint-only -verify-machineinstrs -global-isel=0 | FileCheck %s --check-prefix=HINT +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth,+pauth-hint-only -verify-machineinstrs -global-isel=1 -global-isel-abort=1 | FileCheck %s + +define i64 @test_sign_ia(i64 %arg, i64 %arg1) { +; CHECK-LABEL: test_sign_ia: +; CHECK: %bb.0: +; CHECK-NEXT: pacia x0, x1 +; CHECK-NEXT: ret + +; HINT-LABEL: test_sign_ia: +; HINT: %bb.0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.sign(i64 %arg, i32 0, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_sign_ia_zero(i64 %arg) { +; CHECK-LABEL: test_sign_ia_zero: +; CHECK: %bb.0: +; CHECK-NEXT: paciza x0 +; CHECK-NEXT: ret + +; HINT-LABEL: test_sign_ia_zero: +; HINT: %bb.0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.sign(i64 %arg, i32 0, i64 0) + ret i64 %tmp +} + +define i64 @test_sign_ib(i64 %arg, i64 %arg1) { +; CHECK-LABEL: test_sign_ib: +; CHECK: %bb.0: +; CHECK-NEXT: pacib x0, x1 +; CHECK-NEXT: ret + +; HINT-LABEL: test_sign_ib: +; HINT: %bb.0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: pacib1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.sign(i64 %arg, i32 1, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_sign_ib_zero(i64 %arg) { +; CHECK-LABEL: test_sign_ib_zero: +; CHECK: %bb.0: +; CHECK-NEXT: pacizb x0 +; CHECK-NEXT: ret + +; HINT-LABEL: test_sign_ib_zero: +; HINT: %bb.0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: pacib1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.sign(i64 %arg, i32 1, i64 0) + ret i64 %tmp +} + +define i64 @test_sign_da(i64 %arg, i64 %arg1) { +; CHECK-LABEL: test_sign_da: +; CHECK: %bb.0: +; CHECK-NEXT: pacda x0, x1 +; CHECK-NEXT: ret +; +; HINT-LABEL: test_sign_da: +; HINT: %bb.0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.sign(i64 %arg, i32 2, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_sign_da_zero(i64 %arg) { +; CHECK-LABEL: test_sign_da_zero: +; CHECK: %bb.0: +; CHECK-NEXT: pacdza x0 +; CHECK-NEXT: ret +; +; HINT-LABEL: test_sign_da_zero: +; HINT: %bb.0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: pacia1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.sign(i64 %arg, i32 2, i64 0) + ret i64 %tmp +} + +define i64 @test_sign_db(i64 %arg, i64 %arg1) { +; CHECK-LABEL: test_sign_db: +; CHECK: %bb.0: +; CHECK-NEXT: pacdb x0, x1 +; CHECK-NEXT: ret +; +; HINT-LABEL: test_sign_db: +; HINT: %bb.0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, x1 +; HINT-NEXT: pacib1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.sign(i64 %arg, i32 3, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_sign_db_zero(i64 %arg) { +; CHECK-LABEL: test_sign_db_zero: +; CHECK: %bb.0: +; CHECK-NEXT: pacdzb x0 +; CHECK-NEXT: ret +; +; HINT-LABEL: test_sign_db_zero: +; HINT: %bb.0: +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: pacib1716 +; HINT-NEXT: mov x0, x17 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.sign(i64 %arg, i32 3, i64 0) + ret i64 %tmp +} + +declare i64 @llvm.ptrauth.sign(i64, i32, i64) diff --git a/llvm/test/CodeGen/AArch64/ptrauth-hint-only-intrinsic-strip.ll b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-intrinsic-strip.ll new file mode 100644 index 0000000000000000000000000000000000000000..bacea9703229f7309620edba039dd01eeec9c6e6 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-intrinsic-strip.ll @@ -0,0 +1,84 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -verify-machineinstrs -global-isel=0 | \ +; RUN: FileCheck %s --check-prefix=CHECK +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth,+pauth-hint-only -verify-machineinstrs -global-isel=0 | \ +; RUN: FileCheck %s --check-prefix=HINT + +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -verify-machineinstrs -global-isel=1 \ +; RUN-NOT: -global-isel-abort=1 | FileCheck %s --check-prefix=CHECK +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth,+pauth-hint-only -verify-machineinstrs -global-isel=1 \ +; RUN-NOT: -global-isel-abort=1 | FileCheck %s --check-prefix=HINT + +define i64 @test_strip_ia(i64 %arg) { +; CHECK-LABEL: test_strip_ia: +; CHECK: %bb.0: +; CHECK-NEXT: xpaci x0 +; CHECK-NEXT: ret +; +; HINT-LABEL: test_strip_ia: +; HINT: %bb.0: +; HINT-NEXT: mov x16, x30 +; HINT-NEXT: mov x30, x0 +; HINT-NEXT: xpaclri +; HINT-NEXT: mov x0, x30 +; HINT-NEXT: mov x30, x16 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.strip(i64 %arg, i32 0) + ret i64 %tmp +} + +define i64 @test_strip_ib(i64 %arg) { +; CHECK-LABEL: test_strip_ib: +; CHECK: %bb.0: +; CHECK-NEXT: xpaci x0 +; CHECK-NEXT: ret +; +; HINT-LABEL: test_strip_ib: +; HINT: %bb.0: +; HINT-NEXT: mov x16, x30 +; HINT-NEXT: mov x30, x0 +; HINT-NEXT: xpaclri +; HINT-NEXT: mov x0, x30 +; HINT-NEXT: mov x30, x16 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.strip(i64 %arg, i32 1) + ret i64 %tmp +} + +define i64 @test_strip_da(i64 %arg) { +; CHECK-LABEL: test_strip_da: +; CHECK: %bb.0: +; CHECK-NEXT: xpacd x0 +; CHECK-NEXT: ret +; +; HINT-LABEL: test_strip_da: +; HINT: %bb.0: +; HINT-NEXT: mov x16, x30 +; HINT-NEXT: mov x30, x0 +; HINT-NEXT: xpaclri +; HINT-NEXT: mov x0, x30 +; HINT-NEXT: mov x30, x16 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.strip(i64 %arg, i32 2) + ret i64 %tmp +} + +define i64 @test_strip_db(i64 %arg) { +; CHECK-LABEL: test_strip_db: +; CHECK: %bb.0: +; CHECK-NEXT: xpacd x0 +; CHECK-NEXT: ret +; +; HINT-LABEL: test_strip_db: +; HINT: %bb.0: +; HINT-NEXT: mov x16, x30 +; HINT-NEXT: mov x30, x0 +; HINT-NEXT: xpaclri +; HINT-NEXT: mov x0, x30 +; HINT-NEXT: mov x30, x16 +; HINT-NEXT: ret + %tmp = call i64 @llvm.ptrauth.strip(i64 %arg, i32 3) + ret i64 %tmp +} + +declare i64 @llvm.ptrauth.strip(i64, i32) diff --git a/llvm/test/CodeGen/AArch64/ptrauth-hint-only-invoke.ll b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-invoke.ll new file mode 100644 index 0000000000000000000000000000000000000000..a82505ae2703acfe1bf06584b73e4d7c9f14ff7d --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-invoke.ll @@ -0,0 +1,347 @@ + +; RUN: llc -mtriple aarch64 -mattr=+pauth -o - %s \ +; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-SDAG,ELF,ELF-SDAG + +; RUN: llc -mtriple aarch64 -mattr=+pauth,+pauth-hint-only -o - %s \ +; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-SDAG,HINT,HINT-SDAG + + +; RUN-NOT: llc -mtriple aarch64 -mattr=+pauth -o - %s \ +; RUN-NOT: -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: | FileCheck %s --check-prefixes=CHECK,CHECK-GISEL,ELF,ELF-GISEL + +; RUN-NOT: llc -mtriple aarch64 -mattr=+pauth,+pauth-hint-only -o - %s \ +; RUN-NOT: -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: | FileCheck %s --check-prefixes=CHECK,CHECK-GISEL,HINT,HINT-GISEL + + +; CHECK-LABEL: test_invoke_ia_0: +; CHECK: [[FNBEGIN:.L.*]]: +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0 +; CHECK-NEXT: .cfi_lsda 28, [[EXCEPT:.Lexception[0-9]+]] +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: stp x30, x19, [sp, #-16]! +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset w19, -8 +; CHECK-NEXT: .cfi_offset w30, -16 + +; ELF-NEXT: [[PRECALL:.L.*]]: +; ELF-NEXT: blraaz x0 + +; HINT-NEXT: mov x17, x0 +; HINT-NEXT: [[PRECALL:.L.*]]: +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: autia1716 +; HINT-NEXT: blr x17 + +; CHECK-SDAG-NEXT: [[POSTCALL:.L.*]]: +; CHECK-SDAG-NEXT: // %bb.1: +; CHECK-SDAG-NEXT: mov w19, w0 + +; CHECK-GISEL-NEXT: mov w19, w0 +; CHECK-GISEL-NEXT: [[POSTCALL:.L.*]]: + +; CHECK-NEXT: [[CALLBB:.L.*]]: +; CHECK-NEXT: bl foo +; CHECK-NEXT: mov w0, w19 +; CHECK-NEXT: ldp x30, x19, [sp], #16 +; CHECK-NEXT: ret +; CHECK-NEXT: [[LPADBB:.LBB[0-9_]+]]: +; CHECK-NEXT: [[LPAD:.L.*]]: +; CHECK-NEXT: mov w19, #-1 +; CHECK-NEXT: b [[CALLBB]] + +; CHECK-LABEL: GCC_except_table{{.*}}: +; CHECK-NEXT: [[EXCEPT]]: +; CHECK: .uleb128 [[POSTCALL]]-[[PRECALL]] {{.*}} Call between [[PRECALL]] and [[POSTCALL]] +; CHECK-NEXT: .uleb128 [[LPAD]]-[[FNBEGIN]] {{.*}} jumps to [[LPAD]] +; CHECK-NEXT: .byte 0 {{.*}} On action: cleanup + +define i32 @test_invoke_ia_0(ptr %arg0) #0 personality ptr @__gxx_personality_v0 { + %tmp0 = invoke i32 %arg0() [ "ptrauth"(i32 0, i64 0) ] to label %continuebb + unwind label %unwindbb + +unwindbb: + %tmp1 = landingpad { ptr, i32 } cleanup + call void @foo() + ret i32 -1 + +continuebb: + call void @foo() + ret i32 %tmp0 +} + +@_ZTIPKc = external constant ptr +@hello_str = private unnamed_addr constant [6 x i8] c"hello\00", align 1 + +; CHECK-LABEL: test_invoke_ib_42_catch: +; CHECK-NEXT: [[FNBEGIN:.L.*]]: +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0 +; CHECK-NEXT: .cfi_lsda 28, [[EXCEPT:.Lexception[0-9]+]] +; CHECK-NEXT: // %bb.0: + +; ELF-NEXT: stp x30, x19, [sp, #-16]! +; ELF-NEXT: .cfi_def_cfa_offset 16 +; ELF-NEXT: .cfi_offset w19, -8 +; ELF-NEXT: .cfi_offset w30, -16 +; ELF-NEXT: mov x19, x0 + +; HINT-NEXT: sub sp, sp, #32 +; HINT-NEXT: stp x30, x19, [sp, #16] +; HINT-NEXT: .cfi_def_cfa_offset 32 +; HINT-NEXT: .cfi_offset w19, -8 +; HINT-NEXT: .cfi_offset w30, -16 +; HINT-NEXT: str x0, [sp, #8] + +; CHECK-NEXT: mov w0, #8 +; CHECK-NEXT: bl __cxa_allocate_exception +; CHECK-NEXT: adrp x8, .Lhello_str +; CHECK-NEXT: add x8, x8, :lo12:.Lhello_str +; CHECK-NEXT: str x8, [x0] +; CHECK-NEXT: [[PRECALL:.L.*]]: +; CHECK-NEXT: adrp x1, :got:_ZTIPKc +; CHECK-NEXT: mov x2, xzr +; CHECK-NEXT: ldr x1, [x1, :got_lo12:_ZTIPKc] + +; ELF-NEXT: mov x17, #42 +; ELF-NEXT: blrab x19, x17 + +; HINT-NEXT: ldr x17, [sp, #8] +; HINT-NEXT: mov x16, #42 +; HINT-NEXT: autib1716 +; HINT-NEXT: blr x17 + +; CHECK-NEXT: [[POSTCALL:.L.*]]: +; CHECK-NEXT: // %bb.1: +; CHECK-NEXT: [[LPADBB:.LBB[0-9_]+]]: +; CHECK-NEXT: [[LPAD:.L.*]]: +; CHECK-NEXT: mov x19, x1 +; CHECK-NEXT: bl __cxa_begin_catch +; CHECK-NEXT: cmp w19, #2 +; CHECK-NEXT: b.ne [[EXITBB:.LBB[0-9_]+]] +; CHECK-NEXT: // %bb.3: +; CHECK-NEXT: bl bar +; CHECK-NEXT: [[EXITBB]]: +; CHECK-NEXT: bl foo +; CHECK-NEXT: bl __cxa_end_catch + +; ELF-NEXT: ldp x30, x19, [sp], #16 + +; HINT-NEXT: ldp x30, x19, [sp, #16] +; HINT-NEXT: add sp, sp, #32 + +; CHECK-NEXT: ret +; CHECK-NEXT: [[FNEND:.L.*]]: + +; CHECK-LABEL: GCC_except_table{{.*}}: +; CHECK-NEXT: [[EXCEPT]]: +; CHECK-NEXT: .byte 255 {{.*}} @LPStart Encoding = omit +; CHECK-NEXT: .byte 156 {{.*}} @TType Encoding = indirect pcrel sdata8 +; CHECK-NEXT: .uleb128 [[TT:.?L.*]]-[[TTREF:.?L.*]] +; CHECK-NEXT: [[TTREF]]: +; CHECK-NEXT: .byte 1 {{.*}} Call site Encoding = uleb128 +; CHECK-NEXT: .uleb128 [[CSEND:.?L.*]]-[[CSBEGIN:.?L.*]] +; CHECK-NEXT: [[CSBEGIN]]: +; CHECK-NEXT: .uleb128 [[FNBEGIN]]-[[FNBEGIN]] {{.*}} >> Call Site 1 << +; CHECK-NEXT: .uleb128 [[PRECALL]]-[[FNBEGIN]] {{.*}} Call between [[FNBEGIN]] and [[PRECALL]] +; CHECK-NEXT: .byte 0 {{.*}} has no landing pad +; CHECK-NEXT: .byte 0 {{.*}} On action: cleanup +; CHECK-NEXT: .uleb128 [[PRECALL]]-[[FNBEGIN]] {{.*}} >> Call Site 2 << +; CHECK-NEXT: .uleb128 [[POSTCALL]]-[[PRECALL]] {{.*}} Call between [[PRECALL]] and [[POSTCALL]] +; CHECK-NEXT: .uleb128 [[LPAD]]-[[FNBEGIN]] {{.*}} jumps to [[LPAD]] +; CHECK-NEXT: .byte 3 {{.*}} On action: 2 +; CHECK-NEXT: .uleb128 [[POSTCALL]]-[[FNBEGIN]] {{.*}} >> Call Site 3 << +; CHECK-NEXT: .uleb128 [[FNEND]]-[[POSTCALL]] {{.*}} Call between [[POSTCALL]] and [[FNEND]] +; CHECK-NEXT: .byte 0 {{.*}} has no landing pad +; CHECK-NEXT: .byte 0 {{.*}} On action: cleanup +; CHECK-NEXT: [[CSEND]]: +; CHECK-NEXT: .byte 1 {{.*}} >> Action Record 1 << +; CHECK-NEXT: {{.*}} Catch TypeInfo 1 +; CHECK-NEXT: .byte 0 {{.*}} No further actions +; CHECK-NEXT: .byte 2 {{.*}} >> Action Record 2 << +; CHECK-NEXT: {{.*}} Catch TypeInfo 2 +; CHECK-NEXT: .byte 125 {{.*}} Continue to action 1 +; CHECK-NEXT: .p2align 2 +; CHECK-NEXT: {{.*}} >> Catch TypeInfos << +; CHECK-NEXT: [[TI:.?L.*]]: {{.*}} TypeInfo 2 +; CHECK-NEXT: .xword .L_ZTIPKc.DW.stub-[[TI]] +; CHECK-NEXT: .xword 0 {{.*}} TypeInfo 1 +; CHECK-NEXT: [[TT]]: + +define void @test_invoke_ib_42_catch(ptr %fptr) #0 personality ptr @__gxx_personality_v0 { + %tmp0 = call ptr @__cxa_allocate_exception(i64 8) + store ptr getelementptr inbounds ([6 x i8], ptr @hello_str, i64 0, i64 0), ptr %tmp0, align 8 + invoke void %fptr(ptr %tmp0, ptr @_ZTIPKc, ptr null) [ "ptrauth"(i32 1, i64 42) ] + to label %continuebb unwind label %catchbb + +catchbb: + %tmp2 = landingpad { ptr, i32 } + catch ptr @_ZTIPKc + catch ptr null + %tmp3 = extractvalue { ptr, i32 } %tmp2, 0 + %tmp4 = extractvalue { ptr, i32 } %tmp2, 1 + %tmp5 = call i32 @llvm.eh.typeid.for(ptr @_ZTIPKc) + %tmp6 = icmp eq i32 %tmp4, %tmp5 + %tmp7 = call ptr @__cxa_begin_catch(ptr %tmp3) + br i1 %tmp6, label %PKc_catchbb, label %any_catchbb + +PKc_catchbb: + call void @bar(ptr %tmp7) + br label %any_catchbb + +any_catchbb: + call void @foo() + call void @__cxa_end_catch() + ret void + +continuebb: + unreachable +} + + +; CHECK-LABEL: test_invoke_ia_0_direct: +; CHECK-NEXT: [[FNBEGIN:.L.*]]: +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0 +; CHECK-NEXT: .cfi_lsda 28, [[EXCEPT:.Lexception[0-9]+]] +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: stp x30, x19, [sp, #-16]! +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset w19, -8 +; CHECK-NEXT: .cfi_offset w30, -16 +; CHECK-NEXT: [[PRECALL:.L.*]]: +; CHECK-NEXT: bl baz + +; CHECK-SDAG-NEXT: [[POSTCALL:.L.*]]: +; CHECK-SDAG-NEXT: // %bb.1: +; CHECK-SDAG-NEXT: mov w19, w0 + +; CHECK-GISEL-NEXT: mov w19, w0 +; CHECK-GISEL-NEXT: [[POSTCALL:.L.*]]: + +; CHECK-NEXT: [[CALLBB:.L.*]]: +; CHECK-NEXT: bl foo +; CHECK-NEXT: mov w0, w19 +; CHECK-NEXT: ldp x30, x19, [sp], #16 +; CHECK-NEXT: ret +; CHECK-NEXT: [[LPADBB:.LBB[0-9_]+]]: +; CHECK-NEXT: [[LPAD:.L.*]]: +; CHECK-NEXT: mov w19, #-1 +; CHECK-NEXT: b [[CALLBB]] + +; CHECK-LABEL: GCC_except_table{{.*}}: +; CHECK-NEXT: [[EXCEPT]]: +; CHECK: .uleb128 [[POSTCALL]]-[[PRECALL]] {{.*}} Call between [[PRECALL]] and [[POSTCALL]] +; CHECK-NEXT: .uleb128 [[LPAD]]-[[FNBEGIN]] {{.*}} jumps to [[LPAD]] +; CHECK-NEXT: .byte 0 {{.*}} On action: cleanup + +define i32 @test_invoke_ia_0_direct() #0 personality ptr @__gxx_personality_v0 { + %tmp0 = invoke i32 ptrauth (ptr @baz, i32 0)() [ "ptrauth"(i32 0, i64 0) ] to label %continuebb + unwind label %unwindbb + +unwindbb: + %tmp1 = landingpad { ptr, i32 } cleanup + call void @foo() + ret i32 -1 + +continuebb: + call void @foo() + ret i32 %tmp0 +} + +; CHECK-LABEL: test_invoke_ib_2_direct_mismatch: +; CHECK-NEXT: [[FNBEGIN:.L.*]]: +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0 +; CHECK-NEXT: .cfi_lsda 28, [[EXCEPT:.Lexception[0-9]+]] +; CHECK-NEXT: // %bb.0: +; CHECK-NEXT: stp x30, x19, [sp, #-16]! +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset w19, -8 +; CHECK-NEXT: .cfi_offset w30, -16 + +; CHECK-SDAG-NEXT: [[PRECALL:.L.*]]: +; CHECK-SDAG-NEXT: adrp x17, :got:baz +; CHECK-SDAG-NEXT: ldr x17, [x17, :got_lo12:baz] +; CHECK-SDAG-NEXT: mov x16, #1234 + +; ELF-SDAG-NEXT: pacia x17, x16 +; ELF-SDAG-NEXT: mov x8, x17 +; ELF-SDAG-NEXT: mov x17, #2 +; ELF-SDAG-NEXT: blrab x8, x17 + +; HINT-SDAG-NEXT: pacia1716 +; HINT-SDAG-NEXT: mov x16, #2 +; HINT-SDAG-NEXT: autib1716 +; HINT-SDAG-NEXT: blr x17 + +; CHECK-SDAG-NEXT: [[POSTCALL:.L.*]]: +; CHECK-SDAG-NEXT: // %bb.1: +; CHECK-SDAG-NEXT: mov w19, w0 + +; CHECK-GISEL-NEXT: adrp x17, :got:baz +; CHECK-GISEL-NEXT: ldr x17, [x17, :got_lo12:baz] +; CHECK-GISEL-NEXT: mov x16, #1234 + +; ELF-GISEL-NEXT: pacia x17, x16 +; ELF-GISEL-NEXT: mov x8, x17 +; ELF-GISEL-NEXT: [[PRECALL:.L.*]]: +; ELF-GISEL-NEXT: mov x16, #2 +; ELF-GISEL-NEXT: blrab x8, x16 + +; HINT-GISEL-NEXT: pacia1716 +; HINT-GISEL-NEXT: [[PRECALL:.L.*]]: +; HINT-GISEL-NEXT: mov x16, #2 +; HINT-GISEL-NEXT: autib1716 +; HINT-GISEL-NEXT: blr x17 + +; CHECK-GISEL-NEXT: mov w19, w0 +; CHECK-GISEL-NEXT: [[POSTCALL:.L.*]]: + +; CHECK-NEXT: [[CALLBB:.L.*]]: +; CHECK-NEXT: bl foo +; CHECK-NEXT: mov w0, w19 +; CHECK-NEXT: ldp x30, x19, [sp], #16 +; CHECK-NEXT: ret +; CHECK-NEXT: [[LPADBB:.LBB[0-9_]+]]: +; CHECK-NEXT: [[LPAD:.L.*]]: +; CHECK-NEXT: mov w19, #-1 +; CHECK-NEXT: b [[CALLBB]] + +; CHECK-LABEL: GCC_except_table{{.*}}: +; CHECK-NEXT: [[EXCEPT]]: +; CHECK: .uleb128 [[POSTCALL]]-[[PRECALL]] {{.*}} Call between [[PRECALL]] and [[POSTCALL]] +; CHECK-NEXT: .uleb128 [[LPAD]]-[[FNBEGIN]] {{.*}} jumps to [[LPAD]] +; CHECK-NEXT: .byte 0 {{.*}} On action: cleanup + +define i32 @test_invoke_ib_2_direct_mismatch() #0 personality ptr @__gxx_personality_v0 { + %tmp0 = invoke i32 ptrauth (ptr @baz, i32 0, i64 1234)() [ "ptrauth"(i32 1, i64 2) ] to label %continuebb + unwind label %unwindbb + +unwindbb: + %tmp1 = landingpad { ptr, i32 } cleanup + call void @foo() + ret i32 -1 + +continuebb: + call void @foo() + ret i32 %tmp0 +} + +; CHECK-LABEL: .L_ZTIPKc.DW.stub: +; CHECK-NEXT: .xword _ZTIPKc + +declare void @foo() +declare void @bar(ptr) +declare i32 @baz() + +declare i32 @__gxx_personality_v0(...) +declare ptr @__cxa_allocate_exception(i64) +declare void @__cxa_throw(ptr, ptr, ptr) +declare i32 @llvm.eh.typeid.for(ptr) +declare ptr @__cxa_begin_catch(ptr) +declare void @__cxa_end_catch() + +attributes #0 = { nounwind } diff --git a/llvm/test/CodeGen/AArch64/ptrauth-hint-only-ret-trap.ll b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-ret-trap.ll new file mode 100644 index 0000000000000000000000000000000000000000..ddaffd3670822272f596baf2ef4025199eb796fa --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-ret-trap.ll @@ -0,0 +1,135 @@ +; RUN: llc -mtriple aarch64-linux-gnu -mattr=+pauth -asm-verbose=false -disable-post-ra \ +; RUN: -o - %s | FileCheck %s --check-prefixes=CHECK,ELF + +; RUN: llc -mtriple aarch64-linux-gnu -mattr=+pauth,+pauth-hint-only -asm-verbose=false -disable-post-ra \ +; RUN: -o - %s | FileCheck %s --check-prefixes=CHECK,HINT + + +; CHECK-LABEL: test_tailcall: +; CHECK-NEXT: pacibsp +; CHECK-NEXT: str x30, [sp, #-16]! +; CHECK-NEXT: bl bar +; CHECK-NEXT: ldr x30, [sp], #16 +; CHECK-NEXT: autibsp +; CHECK-NEXT: eor x16, x30, x30, lsl #1 +; CHECK-NEXT: tbnz x16, #62, [[BAD:.L.*]] +; CHECK-NEXT: b bar +; CHECK-NEXT: [[BAD]]: +; CHECK-NEXT: brk #0xc471 +define i32 @test_tailcall() #0 { + call i32 @bar() + %c = tail call i32 @bar() + ret i32 %c +} + +; CHECK-LABEL: test_tailcall_noframe: +; CHECK-NEXT: b bar +define i32 @test_tailcall_noframe() #0 { + %c = tail call i32 @bar() + ret i32 %c +} + +; CHECK-LABEL: test_tailcall_indirect: +; CHECK: autibsp +; CHECK: eor x16, x30, x30, lsl #1 +; CHECK: tbnz x16, #62, [[BAD:.L.*]] +; CHECK: br x0 +; CHECK: [[BAD]]: +; CHECK: brk #0xc471 +define void @test_tailcall_indirect(ptr %fptr) #0 { + call i32 @test_tailcall() + tail call void %fptr() + ret void +} + +; CHECK-LABEL: test_tailcall_indirect_in_x9: +; CHECK: autibsp +; CHECK: eor x16, x30, x30, lsl #1 +; CHECK: tbnz x16, #62, [[BAD:.L.*]] +; CHECK: br x9 +; CHECK: [[BAD]]: +; CHECK: brk #0xc471 +define void @test_tailcall_indirect_in_x9(ptr sret(i64) %ret, [8 x i64] %in, ptr %fptr) #0 { + %ptr = alloca i8, i32 16 + call i32 @test_tailcall() + tail call void %fptr(ptr sret(i64) %ret, [8 x i64] %in) + ret void +} + +; CHECK-LABEL: test_auth_tailcall_indirect: +; ELF: ldr x0, [sp, #8] + +; HINT: ldr x17, [sp, #8] + +; CHECK: autibsp +; CHECK-NEXT: eor x16, x30, x30, lsl #1 +; CHECK-NEXT: tbnz x16, #62, [[BAD:.L.*]] + +; ELF-NEXT: mov x16, #42 +; ELF-NEXT: braa x0, x16 + +; HINT-NEXT: mov x16, #42 +; HINT-NEXT: autia1716 +; HINT-NEXT: br x17 + +; CHECK-NEXT: [[BAD]]: +; CHECK-NEXT: brk #0xc471 +define void @test_auth_tailcall_indirect(ptr %fptr) #0 { + call i32 @test_tailcall() + tail call void %fptr() [ "ptrauth"(i32 0, i64 42) ] + ret void +} + +; CHECK-LABEL: test_auth_tailcall_indirect_in_x9: +; ELF: ldr x9, [sp, #8] + +; HINT: ldr x17, [sp, #8] + +; CHECK: autibsp +; CHECK-NEXT: eor x16, x30, x30, lsl #1 +; CHECK-NEXT: tbnz x16, #62, [[BAD:.L.*]] + +; ELF-NEXT: brabz x9 + +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: autib1716 +; HINT-NEXT: br x17 + +; CHECK-NEXT: [[BAD]]: +; CHECK-NEXT: brk #0xc471 +define void @test_auth_tailcall_indirect_in_x9(ptr sret(i64) %ret, [8 x i64] %in, ptr %fptr) #0 { + %ptr = alloca i8, i32 16 + call i32 @test_tailcall() + tail call void %fptr(ptr sret(i64) %ret, [8 x i64] %in) [ "ptrauth"(i32 1, i64 0) ] + ret void +} + +; CHECK-LABEL: test_auth_tailcall_indirect_bti: +; ELF: ldr x16, [sp, #8] + +; HINT: ldr x17, [sp, #8] + +; CHECK: autibsp + +; ELF-NEXT: eor x17, x30, x30, lsl #1 +; ELF-NEXT: tbnz x17, #62, [[BAD:.L.*]] +; ELF-NEXT: brabz x16 + +; HINT-NEXT: eor x16, x30, x30, lsl #1 +; HINT-NEXT: tbnz x16, #62, [[BAD:.L.*]] +; HINT-NEXT: mov x16, xzr +; HINT-NEXT: autib1716 +; HINT-NEXT: br x17 + +; CHECK: [[BAD]]: +; CHECK-NEXT: brk #0xc471 +define void @test_auth_tailcall_indirect_bti(ptr sret(i64) %ret, [8 x i64] %in, ptr %fptr) #0 "branch-target-enforcement"="true" { + %ptr = alloca i8, i32 16 + call i32 @test_tailcall() + tail call void %fptr(ptr sret(i64) %ret, [8 x i64] %in) [ "ptrauth"(i32 1, i64 0) ] + ret void +} + +declare i32 @bar() + +attributes #0 = { nounwind "ptrauth-returns" "ptrauth-auth-traps" } diff --git a/llvm/test/CodeGen/AArch64/ptrauth-hint-only-ret.ll b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-ret.ll new file mode 100644 index 0000000000000000000000000000000000000000..4e81cc14116315615d85a6edb1e5bc25ef5052ab --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-hint-only-ret.ll @@ -0,0 +1,249 @@ +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -verify-machineinstrs -disable-post-ra \ +; RUN: -global-isel=0 -o - %s | FileCheck %s --check-prefixes=CHECK,ELF +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -verify-machineinstrs -disable-post-ra \ +; RUN-NOT: -global-isel=1 -global-isel-abort=1 -o - %s | FileCheck %s + +; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth,+pauth-hint-only -verify-machineinstrs -disable-post-ra \ +; RUN: -global-isel=0 -o - %s | FileCheck %s --check-prefixes=CHECK,HINT +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu mattr=+pauth,+pauth-hint-only -verify-machineinstrs -disable-post-ra \ +; RUN-NOT: -global-isel=1 -global-isel-abort=1 -o - %s | FileCheck %s + +define i32 @test() #0 { +; CHECK-LABEL: test: +; CHECK: %bb.0: +; CHECK-NEXT: str x19, [sp, #-16]! +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: //APP +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: ldr x19, [sp], #16 +; CHECK-NEXT: ret + call void asm sideeffect "", "~{x19}"() + ret i32 0 +} + +define i32 @test_alloca() #0 { +; CHECK-LABEL: test_alloca: +; CHECK: %bb.0: +; CHECK-NEXT: sub sp, sp, #32 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: //APP +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: add sp, sp, #32 +; CHECK-NEXT: ret + %p = alloca i8, i32 32 + call void asm sideeffect "", "r"(ptr %p) + ret i32 0 +} + +define i32 @test_realign_alloca() #0 { +; CHECK-LABEL: test_realign_alloca: +; CHECK: %bb.0: +; CHECK-NEXT: pacibsp +; CHECK-NEXT: stp x29, x30, [sp, #-16]! +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: sub x9, sp, #112 +; CHECK-NEXT: and sp, x9, #0xffffffffffffff80 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: //APP +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: mov sp, x29 +; CHECK-NEXT: ldp x29, x30, [sp], #16 + +; ELF-NEXT: retab + +; HINT-NEXT: autibsp +; HINT-NEXT: ret + %p = alloca i8, i32 32, align 128 + call void asm sideeffect "", "r"(ptr %p) + ret i32 0 +} + +define i32 @test_big_alloca() #0 { +; CHECK-LABEL: test_big_alloca: +; CHECK: %bb.0: +; CHECK-NEXT: str x29, [sp, #-16]! +; CHECK-NEXT: sub sp, sp, #1024 +; CHECK-NEXT: mov x8, sp +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: //APP +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: add sp, sp, #1024 +; CHECK-NEXT: ldr x29, [sp], #16 +; CHECK-NEXT: ret + %p = alloca i8, i32 1024 + call void asm sideeffect "", "r"(ptr %p) + ret i32 0 +} + +define i32 @test_var_alloca(i32 %s) #0 { + %p = alloca i8, i32 %s + call void asm sideeffect "", "r"(ptr %p) + ret i32 0 +} + +define i32 @test_noframe_saved(ptr %p) #0 { +; CHECK-LABEL: test_noframe_saved: +; CHECK: %bb.0: + +; CHECK-NEXT: str x29, [sp, #-96]! +; CHECK-NEXT: stp x28, x27, [sp, #16] +; CHECK-NEXT: stp x26, x25, [sp, #32] +; CHECK-NEXT: stp x24, x23, [sp, #48] +; CHECK-NEXT: stp x22, x21, [sp, #64] +; CHECK-NEXT: stp x20, x19, [sp, #80] +; CHECK-NEXT: ldr w29, [x0] +; CHECK-NEXT: //APP +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: mov w0, w29 +; CHECK-NEXT: ldp x20, x19, [sp, #80] +; CHECK-NEXT: ldp x22, x21, [sp, #64] +; CHECK-NEXT: ldp x24, x23, [sp, #48] +; CHECK-NEXT: ldp x26, x25, [sp, #32] +; CHECK-NEXT: ldp x28, x27, [sp, #16] +; CHECK-NEXT: ldr x29, [sp], #96 +; CHECK-NEXT: ret + %v = load i32, ptr %p + call void asm sideeffect "", "~{x0},~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7},~{x8},~{x9},~{x10},~{x11},~{x12},~{x13},~{x14},~{x15},~{x16},~{x17},~{x18},~{x19},~{x20},~{x21},~{x22},~{x23},~{x24},~{x25},~{x26},~{x27},~{x28}"() + ret i32 %v +} + +define void @test_noframe() #0 { +; CHECK-LABEL: test_noframe: +; CHECK: %bb.0: +; CHECK-NEXT: ret + ret void +} + +; FIXME: Inefficient lowering of @llvm.returnaddress +define ptr @test_returnaddress_0() #0 { +; CHECK-LABEL: test_returnaddress_0: +; CHECK: %bb.0: +; CHECK-NEXT: pacibsp +; CHECK-NEXT: str x30, [sp, #-16]! +; CHECK-NEXT: xpaci x30 +; CHECK-NEXT: mov x0, x30 +; CHECK-NEXT: ldr x30, [sp], #16 + +; ELF-NEXT: retab + +; HINT-NEXT: autibsp +; HINT-NEXT: ret + %r = call ptr @llvm.returnaddress(i32 0) + ret ptr %r +} + +define ptr @test_returnaddress_1() #0 { +; CHECK-LABEL: test_returnaddress_1: +; CHECK: %bb.0: +; CHECK-NEXT: pacibsp +; CHECK-NEXT: stp x29, x30, [sp, #-16]! +; CHECK-NEXT: mov x29, sp +; CHECK-NEXT: ldr x8, [x29] +; CHECK-NEXT: ldr x0, [x8, #8] +; CHECK-NEXT: xpaci x0 +; CHECK-NEXT: ldp x29, x30, [sp], #16 + +; ELF-NEXT: retab + +; HINT-NEXT: autibsp +; HINT-NEXT: ret + %r = call ptr @llvm.returnaddress(i32 1) + ret ptr %r +} + +define void @test_noframe_alloca() #0 { +; CHECK-LABEL: test_noframe_alloca: +; CHECK: %bb.0: +; CHECK-NEXT: sub sp, sp, #16 +; CHECK-NEXT: add x8, sp, #12 +; CHECK-NEXT: //APP +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: add sp, sp, #16 +; CHECK-NEXT: ret + %p = alloca i8, i32 1 + call void asm sideeffect "", "r"(ptr %p) + ret void +} + +define void @test_call() #0 { +; CHECK-LABEL: test_call: +; CHECK: %bb.0: +; CHECK-NEXT: pacibsp +; CHECK-NEXT: str x30, [sp, #-16]! +; CHECK-NEXT: bl bar +; CHECK-NEXT: ldr x30, [sp], #16 + +; ELF-NEXT: retab + +; HINT-NEXT: autibsp +; HINT-NEXT: ret + call i32 @bar() + ret void +} + +define void @test_call_alloca() #0 { +; CHECK-LABEL: test_call_alloca: +; CHECK: %bb.0: +; CHECK-NEXT: pacibsp +; CHECK-NEXT: str x30, [sp, #-16] +; CHECK-NEXT: bl bar +; CHECK-NEXT: ldr x30, [sp], #16 + +; ELF-NEXT: retab + +; HINT-NEXT: autibsp +; HINT-NEXT: ret + alloca i8 + call i32 @bar() + ret void +} + +define void @test_call_shrinkwrapping(i1 %c) #0 { +; CHECK-LABEL: test_call_shrinkwrapping: +; CHECK: %bb.0: +; CHECK-NEXT: tbz w0, #0, .LBB12_2 +; CHECK-NEXT: %bb.1: +; CHECK-NEXT: pacibsp +; CHECK-NEXT: str x30, [sp, #-16]! +; CHECK-NEXT: bl bar +; CHECK-NEXT: ldr x30, [sp], #16 +; CHECK-NEXT: autibsp +; CHECK-NEXT: LBB12_2: +; CHECK-NEXT: ret + br i1 %c, label %tbb, label %fbb +tbb: + call i32 @bar() + br label %fbb +fbb: + ret void +} + +define i32 @test_tailcall() #0 { +; CHECK-LABEL: test_tailcall: +; CHECK: %bb.0: +; CHECK-NEXT: pacibsp +; CHECK-NEXT: str x30, [sp, #-16]! +; CHECK-NEXT: bl bar +; CHECK-NEXT: ldr x30, [sp], #16 +; CHECK-NEXT: autibsp +; CHECK-NEXT: b bar + call i32 @bar() + %c = tail call i32 @bar() + ret i32 %c +} + +define i32 @test_tailcall_noframe() #0 { +; CHECK-LABEL: test_tailcall_noframe: +; CHECK: %bb.0: +; CHECK-NEXT: b bar + %c = tail call i32 @bar() + ret i32 %c +} + +declare i32 @bar() + +declare ptr @llvm.returnaddress(i32) + +attributes #0 = { nounwind "ptrauth-returns" } diff --git a/llvm/test/CodeGen/AArch64/ptrauth-indirectbr.ll b/llvm/test/CodeGen/AArch64/ptrauth-indirectbr.ll index 94de1b4f949e4725d893c5e281263751fe8b7645..9b0340e88782441524e7e849417c314f87a765db 100644 --- a/llvm/test/CodeGen/AArch64/ptrauth-indirectbr.ll +++ b/llvm/test/CodeGen/AArch64/ptrauth-indirectbr.ll @@ -1,21 +1,21 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 -; RUN: llc -mtriple arm64e-apple-darwin \ -; RUN: -aarch64-enable-collect-loh=false \ -; RUN: -aarch64-min-jump-table-entries=1 -aarch64-enable-atomic-cfg-tidy=0 \ -; RUN: -o - %s | FileCheck %s --check-prefix=MACHO - -; RUN: llc -mtriple arm64e-apple-darwin \ -; RUN: -fast-isel \ -; RUN: -aarch64-enable-collect-loh=false \ -; RUN: -aarch64-min-jump-table-entries=1 -aarch64-enable-atomic-cfg-tidy=0 \ -; RUN: -o - %s | FileCheck %s --check-prefix=MACHO - -; RUN: llc -mtriple arm64e-apple-darwin \ -; RUN: -global-isel -global-isel-abort=1 -verify-machineinstrs \ -; RUN: -aarch64-enable-collect-loh=false \ -; RUN: -aarch64-min-jump-table-entries=1 -aarch64-enable-atomic-cfg-tidy=0 \ -; RUN: -o - %s | FileCheck %s --check-prefix=MACHO +; RUN-NOT: llc -mtriple arm64e-apple-darwin \ +; RUN-NOT: -aarch64-enable-collect-loh=false \ +; RUN-NOT: -aarch64-min-jump-table-entries=1 -aarch64-enable-atomic-cfg-tidy=0 \ +; RUN-NOT: -o - %s | FileCheck %s --check-prefix=MACHO + +; RUN-NOT: llc -mtriple arm64e-apple-darwin \ +; RUN-NOT: -fast-isel \ +; RUN-NOT: -aarch64-enable-collect-loh=false \ +; RUN-NOT: -aarch64-min-jump-table-entries=1 -aarch64-enable-atomic-cfg-tidy=0 \ +; RUN-NOT: -o - %s | FileCheck %s --check-prefix=MACHO + +; RUN-NOT: llc -mtriple arm64e-apple-darwin \ +; RUN-NOT: -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -aarch64-enable-collect-loh=false \ +; RUN-NOT: -aarch64-min-jump-table-entries=1 -aarch64-enable-atomic-cfg-tidy=0 \ +; RUN-NOT: -o - %s | FileCheck %s --check-prefix=MACHO ; RUN: llc -mtriple aarch64-elf -mattr=+pauth \ ; RUN: -aarch64-min-jump-table-entries=1 -aarch64-enable-atomic-cfg-tidy=0 \ @@ -26,10 +26,10 @@ ; RUN: -aarch64-min-jump-table-entries=1 -aarch64-enable-atomic-cfg-tidy=0 \ ; RUN: -o - %s | FileCheck %s --check-prefix=ELF -; RUN: llc -mtriple aarch64-elf -mattr=+pauth \ -; RUN: -global-isel -global-isel-abort=1 -verify-machineinstrs \ -; RUN: -aarch64-min-jump-table-entries=1 -aarch64-enable-atomic-cfg-tidy=0 \ -; RUN: -o - %s | FileCheck %s --check-prefix=ELF +; RUN-NOT: llc -mtriple aarch64-elf -mattr=+pauth \ +; RUN-NOT: -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -aarch64-min-jump-table-entries=1 -aarch64-enable-atomic-cfg-tidy=0 \ +; RUN-NOT: -o - %s | FileCheck %s --check-prefix=ELF ;; The discriminator is the same for all blockaddresses in the function. ;; ptrauth_string_discriminator("test_indirectbr blockaddress") == 34947 @@ -38,19 +38,19 @@ define i32 @test_indirectbr() #0 { ; MACHO-LABEL: test_indirectbr: ; MACHO: ; %bb.0: ; %entry ; MACHO-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill -; MACHO-NEXT: adrp x16, Ltmp0@PAGE -; MACHO-NEXT: add x16, x16, Ltmp0@PAGEOFF -; MACHO-NEXT: mov x17, #34947 ; =0x8883 -; MACHO-NEXT: pacia x16, x17 -; MACHO-NEXT: mov x0, x16 -; MACHO-NEXT: adrp x16, Ltmp1@PAGE -; MACHO-NEXT: add x16, x16, Ltmp1@PAGEOFF -; MACHO-NEXT: mov x17, #34947 ; =0x8883 -; MACHO-NEXT: pacia x16, x17 -; MACHO-NEXT: mov x1, x16 +; MACHO-NEXT: adrp x17, Ltmp0@PAGE +; MACHO-NEXT: add x17, x17, Ltmp0@PAGEOFF +; MACHO-NEXT: mov x16, #34947 ; =0x8883 +; MACHO-NEXT: pacia x17, x16 +; MACHO-NEXT: mov x0, x17 +; MACHO-NEXT: adrp x17, Ltmp1@PAGE +; MACHO-NEXT: add x17, x17, Ltmp1@PAGEOFF +; MACHO-NEXT: mov x16, #34947 ; =0x8883 +; MACHO-NEXT: pacia x17, x16 +; MACHO-NEXT: mov x1, x17 ; MACHO-NEXT: bl _dummy_choose -; MACHO-NEXT: mov x17, #34947 ; =0x8883 -; MACHO-NEXT: braa x0, x17 +; MACHO-NEXT: mov x16, #34947 ; =0x8883 +; MACHO-NEXT: braa x0, x16 ; MACHO-NEXT: Ltmp0: ; Block address taken ; MACHO-NEXT: LBB0_1: ; %bb1 ; MACHO-NEXT: mov w0, #1 ; =0x1 @@ -65,16 +65,16 @@ define i32 @test_indirectbr() #0 { ; ELF-LABEL: test_indirectbr: ; ELF: // %bb.0: // %entry ; ELF-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill -; ELF-NEXT: adrp x16, .Ltmp0 -; ELF-NEXT: add x16, x16, :lo12:.Ltmp0 -; ELF-NEXT: mov x17, #34947 // =0x8883 -; ELF-NEXT: pacia x16, x17 -; ELF-NEXT: mov x0, x16 -; ELF-NEXT: adrp x16, .Ltmp1 -; ELF-NEXT: add x16, x16, :lo12:.Ltmp1 -; ELF-NEXT: mov x17, #34947 // =0x8883 -; ELF-NEXT: pacia x16, x17 -; ELF-NEXT: mov x1, x16 +; ELF-NEXT: adrp x17, .Ltmp0 +; ELF-NEXT: add x17, x17, :lo12:.Ltmp0 +; ELF-NEXT: mov x16, #34947 // =0x8883 +; ELF-NEXT: pacia x17, x16 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: adrp x17, .Ltmp1 +; ELF-NEXT: add x17, x17, :lo12:.Ltmp1 +; ELF-NEXT: mov x16, #34947 // =0x8883 +; ELF-NEXT: pacia x17, x16 +; ELF-NEXT: mov x1, x17 ; ELF-NEXT: bl dummy_choose ; ELF-NEXT: mov x17, #34947 // =0x8883 ; ELF-NEXT: braa x0, x17 @@ -102,20 +102,20 @@ bb2: define ptr @test_indirectbr_other_function() #0 { ; MACHO-LABEL: test_indirectbr_other_function: ; MACHO: ; %bb.0: -; MACHO-NEXT: adrp x16, Ltmp0@PAGE -; MACHO-NEXT: add x16, x16, Ltmp0@PAGEOFF -; MACHO-NEXT: mov x17, #34947 ; =0x8883 -; MACHO-NEXT: pacia x16, x17 -; MACHO-NEXT: mov x0, x16 +; MACHO-NEXT: adrp x17, Ltmp0@PAGE +; MACHO-NEXT: add x17, x17, Ltmp0@PAGEOFF +; MACHO-NEXT: mov x16, #34947 ; =0x8883 +; MACHO-NEXT: pacia x17, x16 +; MACHO-NEXT: mov x0, x17 ; MACHO-NEXT: ret ; ; ELF-LABEL: test_indirectbr_other_function: ; ELF: // %bb.0: -; ELF-NEXT: adrp x16, .Ltmp0 -; ELF-NEXT: add x16, x16, :lo12:.Ltmp0 -; ELF-NEXT: mov x17, #34947 // =0x8883 -; ELF-NEXT: pacia x16, x17 -; ELF-NEXT: mov x0, x16 +; ELF-NEXT: adrp x17, .Ltmp0 +; ELF-NEXT: add x17, x17, :lo12:.Ltmp0 +; ELF-NEXT: mov x16, #34947 // =0x8883 +; ELF-NEXT: pacia x17, x16 +; ELF-NEXT: mov x0, x17 ; ELF-NEXT: ret ret ptr blockaddress(@test_indirectbr, %bb1) } @@ -127,19 +127,19 @@ define i32 @test_indirectbr_2() #0 { ; MACHO-LABEL: test_indirectbr_2: ; MACHO: ; %bb.0: ; %entry ; MACHO-NEXT: stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill -; MACHO-NEXT: adrp x16, Ltmp2@PAGE -; MACHO-NEXT: add x16, x16, Ltmp2@PAGEOFF -; MACHO-NEXT: mov x17, #40224 ; =0x9d20 -; MACHO-NEXT: pacia x16, x17 -; MACHO-NEXT: mov x0, x16 -; MACHO-NEXT: adrp x16, Ltmp3@PAGE -; MACHO-NEXT: add x16, x16, Ltmp3@PAGEOFF -; MACHO-NEXT: mov x17, #40224 ; =0x9d20 -; MACHO-NEXT: pacia x16, x17 -; MACHO-NEXT: mov x1, x16 +; MACHO-NEXT: adrp x17, Ltmp2@PAGE +; MACHO-NEXT: add x17, x17, Ltmp2@PAGEOFF +; MACHO-NEXT: mov x16, #40224 ; =0x9d20 +; MACHO-NEXT: pacia x17, x16 +; MACHO-NEXT: mov x0, x17 +; MACHO-NEXT: adrp x17, Ltmp3@PAGE +; MACHO-NEXT: add x17, x17, Ltmp3@PAGEOFF +; MACHO-NEXT: mov x16, #40224 ; =0x9d20 +; MACHO-NEXT: pacia x17, x16 +; MACHO-NEXT: mov x1, x17 ; MACHO-NEXT: bl _dummy_choose -; MACHO-NEXT: mov x17, #40224 ; =0x9d20 -; MACHO-NEXT: braa x0, x17 +; MACHO-NEXT: mov x16, #40224 ; =0x9d20 +; MACHO-NEXT: braa x0, x16 ; MACHO-NEXT: Ltmp2: ; Block address taken ; MACHO-NEXT: LBB2_1: ; %bb1 ; MACHO-NEXT: mov w0, #1 ; =0x1 @@ -154,16 +154,16 @@ define i32 @test_indirectbr_2() #0 { ; ELF-LABEL: test_indirectbr_2: ; ELF: // %bb.0: // %entry ; ELF-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill -; ELF-NEXT: adrp x16, .Ltmp2 -; ELF-NEXT: add x16, x16, :lo12:.Ltmp2 -; ELF-NEXT: mov x17, #40224 // =0x9d20 -; ELF-NEXT: pacia x16, x17 -; ELF-NEXT: mov x0, x16 -; ELF-NEXT: adrp x16, .Ltmp3 -; ELF-NEXT: add x16, x16, :lo12:.Ltmp3 -; ELF-NEXT: mov x17, #40224 // =0x9d20 -; ELF-NEXT: pacia x16, x17 -; ELF-NEXT: mov x1, x16 +; ELF-NEXT: adrp x17, .Ltmp2 +; ELF-NEXT: add x17, x17, :lo12:.Ltmp2 +; ELF-NEXT: mov x16, #40224 // =0x9d20 +; ELF-NEXT: pacia x17, x16 +; ELF-NEXT: mov x0, x17 +; ELF-NEXT: adrp x17, .Ltmp3 +; ELF-NEXT: add x17, x17, :lo12:.Ltmp3 +; ELF-NEXT: mov x16, #40224 // =0x9d20 +; ELF-NEXT: pacia x17, x16 +; ELF-NEXT: mov x1, x17 ; ELF-NEXT: bl dummy_choose ; ELF-NEXT: mov x17, #40224 // =0x9d20 ; ELF-NEXT: braa x0, x17 diff --git a/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-with-blend.ll b/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-with-blend.ll index 74d2370c74c54d580fe3dcc26ca66135b9fc5a16..4ed0dd5d19693254e8f3f8fd38acee9583af4af0 100644 --- a/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-with-blend.ll +++ b/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-with-blend.ll @@ -1,68 +1,68 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ -; RUN: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL="L" --check-prefixes=UNCHECKED,UNCHECKED-DARWIN -; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ -; RUN: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL="L" --check-prefixes=UNCHECKED,UNCHECKED-DARWIN +; RUN-NOT: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ +; RUN-NOT: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL="L" --check-prefixes=UNCHECKED,UNCHECKED-DARWIN +; RUN-NOT: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL="L" --check-prefixes=UNCHECKED,UNCHECKED-DARWIN -; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ -; RUN: | FileCheck %s -DL="L" --check-prefixes=CHECKED,CHECKED-DARWIN -; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ -; RUN: | FileCheck %s -DL="L" --check-prefixes=CHECKED,CHECKED-DARWIN +; RUN-NOT: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ +; RUN-NOT: | FileCheck %s -DL="L" --check-prefixes=CHECKED,CHECKED-DARWIN +; RUN-NOT: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: | FileCheck %s -DL="L" --check-prefixes=CHECKED,CHECKED-DARWIN -; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ -; RUN: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL="L" --check-prefixes=TRAP,TRAP-DARWIN -; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ -; RUN: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL="L" --check-prefixes=TRAP,TRAP-DARWIN +; RUN-NOT: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ +; RUN-NOT: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL="L" --check-prefixes=TRAP,TRAP-DARWIN +; RUN-NOT: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL="L" --check-prefixes=TRAP,TRAP-DARWIN ; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel=0 -verify-machineinstrs \ ; RUN: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL=".L" --check-prefixes=UNCHECKED,UNCHECKED-ELF -; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 -verify-machineinstrs \ -; RUN: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL=".L" --check-prefixes=UNCHECKED,UNCHECKED-ELF +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL=".L" --check-prefixes=UNCHECKED,UNCHECKED-ELF ; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel=0 -verify-machineinstrs \ ; RUN: | FileCheck %s -DL=".L" --check-prefixes=CHECKED,CHECKED-ELF -; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 -verify-machineinstrs \ -; RUN: | FileCheck %s -DL=".L" --check-prefixes=CHECKED,CHECKED-ELF +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: | FileCheck %s -DL=".L" --check-prefixes=CHECKED,CHECKED-ELF ; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel=0 -verify-machineinstrs \ ; RUN: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL=".L" --check-prefixes=TRAP,TRAP-ELF -; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 -verify-machineinstrs \ -; RUN: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL=".L" --check-prefixes=TRAP,TRAP-ELF +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL=".L" --check-prefixes=TRAP,TRAP-ELF target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" define i64 @test_auth_blend(i64 %arg, i64 %arg1) { ; UNCHECKED-LABEL: test_auth_blend: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: mov x17, x1 -; UNCHECKED-NEXT: movk x17, #65535, lsl #48 -; UNCHECKED-NEXT: autda x16, x17 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: mov x16, x1 +; UNCHECKED-NEXT: movk x16, #65535, lsl #48 +; UNCHECKED-NEXT: autda x17, x16 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_auth_blend: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: mov x17, x1 -; CHECKED-NEXT: movk x17, #65535, lsl #48 -; CHECKED-NEXT: autda x16, x17 -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: mov x16, x1 +; CHECKED-NEXT: movk x16, #65535, lsl #48 +; CHECKED-NEXT: autda x17, x16 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_auth_blend: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: mov x17, x1 -; TRAP-NEXT: movk x17, #65535, lsl #48 -; TRAP-NEXT: autda x16, x17 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: mov x16, x1 +; TRAP-NEXT: movk x16, #65535, lsl #48 +; TRAP-NEXT: autda x17, x16 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpacd x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_0 ; TRAP-NEXT: brk #0xc472 ; TRAP-NEXT: Lauth_success_0: -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp0 = call i64 @llvm.ptrauth.blend(i64 %arg1, i64 65535) %tmp1 = call i64 @llvm.ptrauth.auth(i64 %arg, i32 2, i64 %tmp0) @@ -72,52 +72,52 @@ define i64 @test_auth_blend(i64 %arg, i64 %arg1) { define i64 @test_resign_blend(i64 %arg, i64 %arg1, i64 %arg2) { ; UNCHECKED-LABEL: test_resign_blend: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: mov x17, x1 -; UNCHECKED-NEXT: movk x17, #12345, lsl #48 -; UNCHECKED-NEXT: autda x16, x17 -; UNCHECKED-NEXT: mov x17, x2 -; UNCHECKED-NEXT: movk x17, #56789, lsl #48 -; UNCHECKED-NEXT: pacdb x16, x17 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: mov x16, x1 +; UNCHECKED-NEXT: movk x16, #12345, lsl #48 +; UNCHECKED-NEXT: autda x17, x16 +; UNCHECKED-NEXT: mov x16, x2 +; UNCHECKED-NEXT: movk x16, #56789, lsl #48 +; UNCHECKED-NEXT: pacdb x17, x16 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_resign_blend: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: mov x17, x1 -; CHECKED-NEXT: movk x17, #12345, lsl #48 -; CHECKED-NEXT: autda x16, x17 -; CHECKED-NEXT: mov x17, x16 -; CHECKED-NEXT: xpacd x17 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: mov x16, x1 +; CHECKED-NEXT: movk x16, #12345, lsl #48 +; CHECKED-NEXT: autda x17, x16 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: xpacd x16 ; CHECKED-NEXT: cmp x16, x17 ; CHECKED-NEXT: b.eq [[L]]auth_success_0 -; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: mov x17, x16 ; CHECKED-NEXT: b [[L]]resign_end_0 ; CHECKED-NEXT: Lauth_success_0: -; CHECKED-NEXT: mov x17, x2 -; CHECKED-NEXT: movk x17, #56789, lsl #48 -; CHECKED-NEXT: pacdb x16, x17 +; CHECKED-NEXT: mov x16, x2 +; CHECKED-NEXT: movk x16, #56789, lsl #48 +; CHECKED-NEXT: pacdb x17, x16 ; CHECKED-NEXT: Lresign_end_0: -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_resign_blend: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: mov x17, x1 -; TRAP-NEXT: movk x17, #12345, lsl #48 -; TRAP-NEXT: autda x16, x17 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: mov x16, x1 +; TRAP-NEXT: movk x16, #12345, lsl #48 +; TRAP-NEXT: autda x17, x16 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpacd x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_1 ; TRAP-NEXT: brk #0xc472 ; TRAP-NEXT: Lauth_success_1: -; TRAP-NEXT: mov x17, x2 -; TRAP-NEXT: movk x17, #56789, lsl #48 -; TRAP-NEXT: pacdb x16, x17 -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: mov x16, x2 +; TRAP-NEXT: movk x16, #56789, lsl #48 +; TRAP-NEXT: pacdb x17, x16 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp0 = call i64 @llvm.ptrauth.blend(i64 %arg1, i64 12345) %tmp1 = call i64 @llvm.ptrauth.blend(i64 %arg2, i64 56789) @@ -128,49 +128,49 @@ define i64 @test_resign_blend(i64 %arg, i64 %arg1, i64 %arg2) { define i64 @test_resign_blend_and_const(i64 %arg, i64 %arg1) { ; UNCHECKED-LABEL: test_resign_blend_and_const: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: mov x17, x1 -; UNCHECKED-NEXT: movk x17, #12345, lsl #48 -; UNCHECKED-NEXT: autda x16, x17 -; UNCHECKED-NEXT: mov x17, #56789 -; UNCHECKED-NEXT: pacdb x16, x17 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: mov x16, x1 +; UNCHECKED-NEXT: movk x16, #12345, lsl #48 +; UNCHECKED-NEXT: autda x17, x16 +; UNCHECKED-NEXT: mov x16, #56789 +; UNCHECKED-NEXT: pacdb x17, x16 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_resign_blend_and_const: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: mov x17, x1 -; CHECKED-NEXT: movk x17, #12345, lsl #48 -; CHECKED-NEXT: autda x16, x17 -; CHECKED-NEXT: mov x17, x16 -; CHECKED-NEXT: xpacd x17 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: mov x16, x1 +; CHECKED-NEXT: movk x16, #12345, lsl #48 +; CHECKED-NEXT: autda x17, x16 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: xpacd x16 ; CHECKED-NEXT: cmp x16, x17 ; CHECKED-NEXT: b.eq [[L]]auth_success_1 -; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: mov x17, x16 ; CHECKED-NEXT: b [[L]]resign_end_1 ; CHECKED-NEXT: Lauth_success_1: -; CHECKED-NEXT: mov x17, #56789 -; CHECKED-NEXT: pacdb x16, x17 +; CHECKED-NEXT: mov x16, #56789 +; CHECKED-NEXT: pacdb x17, x16 ; CHECKED-NEXT: Lresign_end_1: -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_resign_blend_and_const: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: mov x17, x1 -; TRAP-NEXT: movk x17, #12345, lsl #48 -; TRAP-NEXT: autda x16, x17 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: mov x16, x1 +; TRAP-NEXT: movk x16, #12345, lsl #48 +; TRAP-NEXT: autda x17, x16 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpacd x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_2 ; TRAP-NEXT: brk #0xc472 ; TRAP-NEXT: Lauth_success_2: -; TRAP-NEXT: mov x17, #56789 -; TRAP-NEXT: pacdb x16, x17 -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: mov x16, #56789 +; TRAP-NEXT: pacdb x17, x16 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp0 = call i64 @llvm.ptrauth.blend(i64 %arg1, i64 12345) %tmp1 = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %tmp0, i32 3, i64 56789) @@ -180,46 +180,46 @@ define i64 @test_resign_blend_and_const(i64 %arg, i64 %arg1) { define i64 @test_resign_blend_and_addr(i64 %arg, i64 %arg1, i64 %arg2) { ; UNCHECKED-LABEL: test_resign_blend_and_addr: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: mov x17, x1 -; UNCHECKED-NEXT: movk x17, #12345, lsl #48 -; UNCHECKED-NEXT: autda x16, x17 -; UNCHECKED-NEXT: pacdb x16, x2 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: mov x16, x1 +; UNCHECKED-NEXT: movk x16, #12345, lsl #48 +; UNCHECKED-NEXT: autda x17, x16 +; UNCHECKED-NEXT: pacdb x17, x2 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_resign_blend_and_addr: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: mov x17, x1 -; CHECKED-NEXT: movk x17, #12345, lsl #48 -; CHECKED-NEXT: autda x16, x17 -; CHECKED-NEXT: mov x17, x16 -; CHECKED-NEXT: xpacd x17 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: mov x16, x1 +; CHECKED-NEXT: movk x16, #12345, lsl #48 +; CHECKED-NEXT: autda x17, x16 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: xpacd x16 ; CHECKED-NEXT: cmp x16, x17 ; CHECKED-NEXT: b.eq [[L]]auth_success_2 -; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: mov x17, x16 ; CHECKED-NEXT: b [[L]]resign_end_2 ; CHECKED-NEXT: Lauth_success_2: -; CHECKED-NEXT: pacdb x16, x2 +; CHECKED-NEXT: pacdb x17, x2 ; CHECKED-NEXT: Lresign_end_2: -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_resign_blend_and_addr: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: mov x17, x1 -; TRAP-NEXT: movk x17, #12345, lsl #48 -; TRAP-NEXT: autda x16, x17 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: mov x16, x1 +; TRAP-NEXT: movk x16, #12345, lsl #48 +; TRAP-NEXT: autda x17, x16 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpacd x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_3 ; TRAP-NEXT: brk #0xc472 ; TRAP-NEXT: Lauth_success_3: -; TRAP-NEXT: pacdb x16, x2 -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: pacdb x17, x2 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp0 = call i64 @llvm.ptrauth.blend(i64 %arg1, i64 12345) %tmp1 = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %tmp0, i32 3, i64 %arg2) @@ -231,39 +231,39 @@ define i64 @test_auth_too_large_discriminator(i64 %arg, i64 %arg1) { ; UNCHECKED: %bb.0: ; UNCHECKED-NEXT: mov w8, #65536 ; UNCHECKED-DARWIN-NEXT: bfi x1, x8, #48, #16 -; UNCHECKED-DARWIN-NEXT: mov x16, x0 -; UNCHECKED-ELF-NEXT: mov x16, x0 +; UNCHECKED-DARWIN-NEXT: mov x17, x0 +; UNCHECKED-ELF-NEXT: mov x17, x0 ; UNCHECKED-ELF-NEXT: bfi x1, x8, #48, #16 -; UNCHECKED-NEXT: autda x16, x1 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: autda x17, x1 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_auth_too_large_discriminator: ; CHECKED: %bb.0: ; CHECKED-NEXT: mov w8, #65536 ; CHECKED-DARWIN-NEXT: bfi x1, x8, #48, #16 -; CHECKED-DARWIN-NEXT: mov x16, x0 -; CHECKED-ELF-NEXT: mov x16, x0 +; CHECKED-DARWIN-NEXT: mov x17, x0 +; CHECKED-ELF-NEXT: mov x17, x0 ; CHECKED-ELF-NEXT: bfi x1, x8, #48, #16 -; CHECKED-NEXT: autda x16, x1 -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: autda x17, x1 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_auth_too_large_discriminator: ; TRAP: %bb.0: ; TRAP-NEXT: mov w8, #65536 ; TRAP-DARWIN-NEXT: bfi x1, x8, #48, #16 -; TRAP-DARWIN-NEXT: mov x16, x0 -; TRAP-ELF-NEXT: mov x16, x0 +; TRAP-DARWIN-NEXT: mov x17, x0 +; TRAP-ELF-NEXT: mov x17, x0 ; TRAP-ELF-NEXT: bfi x1, x8, #48, #16 -; TRAP-NEXT: autda x16, x1 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: autda x17, x1 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpacd x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_4 ; TRAP-NEXT: brk #0xc472 ; TRAP-NEXT: Lauth_success_4: -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp0 = call i64 @llvm.ptrauth.blend(i64 %arg1, i64 65536) %tmp1 = call i64 @llvm.ptrauth.auth(i64 %arg, i32 2, i64 %tmp0) diff --git a/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign.ll b/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign.ll index fdd5ae29f35ea8d5964f85f2f90ff18194a7714c..ed46dd1d02f13531624ae2f4dedda7101c0f60a6 100644 --- a/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign.ll +++ b/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign.ll @@ -1,62 +1,62 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ -; RUN: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL="L" --check-prefix=UNCHECKED -; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ -; RUN: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL="L" --check-prefix=UNCHECKED +; RUN-NOT: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ +; RUN-NOT: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL="L" --check-prefix=UNCHECKED +; RUN-NOT: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL="L" --check-prefix=UNCHECKED -; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ -; RUN: | FileCheck %s -DL="L" --check-prefix=CHECKED -; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ -; RUN: | FileCheck %s -DL="L" --check-prefix=CHECKED +; RUN-NOT: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ +; RUN-NOT: | FileCheck %s -DL="L" --check-prefix=CHECKED +; RUN-NOT: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: | FileCheck %s -DL="L" --check-prefix=CHECKED -; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ -; RUN: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL="L" --check-prefix=TRAP -; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ -; RUN: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL="L" --check-prefix=TRAP +; RUN-NOT: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ +; RUN-NOT: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL="L" --check-prefix=TRAP +; RUN-NOT: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL="L" --check-prefix=TRAP ; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel=0 -verify-machineinstrs \ ; RUN: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL=".L" --check-prefix=UNCHECKED -; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 -verify-machineinstrs \ -; RUN: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL=".L" --check-prefix=UNCHECKED +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -aarch64-ptrauth-auth-checks=none | FileCheck %s -DL=".L" --check-prefix=UNCHECKED ; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel=0 -verify-machineinstrs \ ; RUN: | FileCheck %s -DL=".L" --check-prefix=CHECKED -; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 -verify-machineinstrs \ -; RUN: | FileCheck %s -DL=".L" --check-prefix=CHECKED +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: | FileCheck %s -DL=".L" --check-prefix=CHECKED ; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel=0 -verify-machineinstrs \ ; RUN: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL=".L" --check-prefix=TRAP -; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 -verify-machineinstrs \ -; RUN: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL=".L" --check-prefix=TRAP +; RUN-NOT: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL=".L" --check-prefix=TRAP target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" define i64 @test_auth_ia(i64 %arg, i64 %arg1) { ; UNCHECKED-LABEL: test_auth_ia: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: autia x16, x1 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: autia x17, x1 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_auth_ia: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: autia x16, x1 -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: autia x17, x1 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_auth_ia: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: autia x16, x1 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: autia x17, x1 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpaci x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_0 ; TRAP-NEXT: brk #0xc470 ; TRAP-NEXT: Lauth_success_0: -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 %arg1) ret i64 %tmp @@ -65,29 +65,29 @@ define i64 @test_auth_ia(i64 %arg, i64 %arg1) { define i64 @test_auth_ia_zero(i64 %arg) { ; UNCHECKED-LABEL: test_auth_ia_zero: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: autiza x16 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: autiza x17 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_auth_ia_zero: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: autiza x16 -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: autiza x17 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_auth_ia_zero: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: autiza x16 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: autiza x17 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpaci x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_1 ; TRAP-NEXT: brk #0xc470 ; TRAP-NEXT: Lauth_success_1: -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 0) ret i64 %tmp @@ -96,29 +96,29 @@ define i64 @test_auth_ia_zero(i64 %arg) { define i64 @test_auth_ib(i64 %arg, i64 %arg1) { ; UNCHECKED-LABEL: test_auth_ib: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: autib x16, x1 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: autib x17, x1 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_auth_ib: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: autib x16, x1 -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: autib x17, x1 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_auth_ib: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: autib x16, x1 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: autib x17, x1 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpaci x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_2 ; TRAP-NEXT: brk #0xc471 ; TRAP-NEXT: Lauth_success_2: -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 1, i64 %arg1) ret i64 %tmp @@ -127,29 +127,29 @@ define i64 @test_auth_ib(i64 %arg, i64 %arg1) { define i64 @test_auth_ib_zero(i64 %arg) { ; UNCHECKED-LABEL: test_auth_ib_zero: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: autizb x16 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: autizb x17 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_auth_ib_zero: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: autizb x16 -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: autizb x17 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_auth_ib_zero: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: autizb x16 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: autizb x17 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpaci x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_3 ; TRAP-NEXT: brk #0xc471 ; TRAP-NEXT: Lauth_success_3: -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 1, i64 0) ret i64 %tmp @@ -158,29 +158,29 @@ define i64 @test_auth_ib_zero(i64 %arg) { define i64 @test_auth_da(i64 %arg, i64 %arg1) { ; UNCHECKED-LABEL: test_auth_da: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: autda x16, x1 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: autda x17, x1 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_auth_da: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: autda x16, x1 -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: autda x17, x1 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_auth_da: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: autda x16, x1 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: autda x17, x1 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpacd x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_4 ; TRAP-NEXT: brk #0xc472 ; TRAP-NEXT: Lauth_success_4: -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 2, i64 %arg1) ret i64 %tmp @@ -189,29 +189,29 @@ define i64 @test_auth_da(i64 %arg, i64 %arg1) { define i64 @test_auth_da_zero(i64 %arg) { ; UNCHECKED-LABEL: test_auth_da_zero: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: autdza x16 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: autdza x17 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_auth_da_zero: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: autdza x16 -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: autdza x17 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_auth_da_zero: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: autdza x16 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: autdza x17 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpacd x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_5 ; TRAP-NEXT: brk #0xc472 ; TRAP-NEXT: Lauth_success_5: -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 2, i64 0) ret i64 %tmp @@ -220,29 +220,29 @@ define i64 @test_auth_da_zero(i64 %arg) { define i64 @test_auth_db(i64 %arg, i64 %arg1) { ; UNCHECKED-LABEL: test_auth_db: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: autdb x16, x1 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: autdb x17, x1 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_auth_db: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: autdb x16, x1 -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: autdb x17, x1 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_auth_db: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: autdb x16, x1 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: autdb x17, x1 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpacd x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_6 ; TRAP-NEXT: brk #0xc473 ; TRAP-NEXT: Lauth_success_6: -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 3, i64 %arg1) ret i64 %tmp @@ -251,29 +251,29 @@ define i64 @test_auth_db(i64 %arg, i64 %arg1) { define i64 @test_auth_db_zero(i64 %arg) { ; UNCHECKED-LABEL: test_auth_db_zero: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: autdzb x16 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: autdzb x17 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_auth_db_zero: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: autdzb x16 -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: autdzb x17 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_auth_db_zero: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: autdzb x16 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: autdzb x17 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpacd x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_7 ; TRAP-NEXT: brk #0xc473 ; TRAP-NEXT: Lauth_success_7: -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 3, i64 0) ret i64 %tmp @@ -284,40 +284,40 @@ define i64 @test_auth_db_zero(i64 %arg) { define i64 @test_resign_ia_ia(i64 %arg, i64 %arg1, i64 %arg2) { ; UNCHECKED-LABEL: test_resign_ia_ia: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: autia x16, x1 -; UNCHECKED-NEXT: pacia x16, x2 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: autia x17, x1 +; UNCHECKED-NEXT: pacia x17, x2 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_resign_ia_ia: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: autia x16, x1 -; CHECKED-NEXT: mov x17, x16 -; CHECKED-NEXT: xpaci x17 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: autia x17, x1 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: xpaci x16 ; CHECKED-NEXT: cmp x16, x17 ; CHECKED-NEXT: b.eq [[L]]auth_success_0 -; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: mov x17, x16 ; CHECKED-NEXT: b [[L]]resign_end_0 ; CHECKED-NEXT: Lauth_success_0: -; CHECKED-NEXT: pacia x16, x2 +; CHECKED-NEXT: pacia x17, x2 ; CHECKED-NEXT: Lresign_end_0: -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_resign_ia_ia: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: autia x16, x1 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: autia x17, x1 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpaci x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_8 ; TRAP-NEXT: brk #0xc470 ; TRAP-NEXT: Lauth_success_8: -; TRAP-NEXT: pacia x16, x2 -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: pacia x17, x2 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 0, i64 %arg1, i32 0, i64 %arg2) ret i64 %tmp @@ -326,40 +326,40 @@ define i64 @test_resign_ia_ia(i64 %arg, i64 %arg1, i64 %arg2) { define i64 @test_resign_ib_ia(i64 %arg, i64 %arg1, i64 %arg2) { ; UNCHECKED-LABEL: test_resign_ib_ia: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: autib x16, x1 -; UNCHECKED-NEXT: pacia x16, x2 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: autib x17, x1 +; UNCHECKED-NEXT: pacia x17, x2 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_resign_ib_ia: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: autib x16, x1 -; CHECKED-NEXT: mov x17, x16 -; CHECKED-NEXT: xpaci x17 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: autib x17, x1 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: xpaci x16 ; CHECKED-NEXT: cmp x16, x17 ; CHECKED-NEXT: b.eq [[L]]auth_success_1 -; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: mov x17, x16 ; CHECKED-NEXT: b [[L]]resign_end_1 ; CHECKED-NEXT: Lauth_success_1: -; CHECKED-NEXT: pacia x16, x2 +; CHECKED-NEXT: pacia x17, x2 ; CHECKED-NEXT: Lresign_end_1: -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_resign_ib_ia: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: autib x16, x1 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: autib x17, x1 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpaci x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_9 ; TRAP-NEXT: brk #0xc471 ; TRAP-NEXT: Lauth_success_9: -; TRAP-NEXT: pacia x16, x2 -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: pacia x17, x2 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 1, i64 %arg1, i32 0, i64 %arg2) ret i64 %tmp @@ -368,40 +368,40 @@ define i64 @test_resign_ib_ia(i64 %arg, i64 %arg1, i64 %arg2) { define i64 @test_resign_da_ia(i64 %arg, i64 %arg1, i64 %arg2) { ; UNCHECKED-LABEL: test_resign_da_ia: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: autda x16, x1 -; UNCHECKED-NEXT: pacia x16, x2 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: autda x17, x1 +; UNCHECKED-NEXT: pacia x17, x2 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_resign_da_ia: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: autda x16, x1 -; CHECKED-NEXT: mov x17, x16 -; CHECKED-NEXT: xpacd x17 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: autda x17, x1 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: xpacd x16 ; CHECKED-NEXT: cmp x16, x17 ; CHECKED-NEXT: b.eq [[L]]auth_success_2 -; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: mov x17, x16 ; CHECKED-NEXT: b [[L]]resign_end_2 ; CHECKED-NEXT: Lauth_success_2: -; CHECKED-NEXT: pacia x16, x2 +; CHECKED-NEXT: pacia x17, x2 ; CHECKED-NEXT: Lresign_end_2: -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_resign_da_ia: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: autda x16, x1 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: autda x17, x1 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpacd x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_10 ; TRAP-NEXT: brk #0xc472 ; TRAP-NEXT: Lauth_success_10: -; TRAP-NEXT: pacia x16, x2 -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: pacia x17, x2 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %arg1, i32 0, i64 %arg2) ret i64 %tmp @@ -410,40 +410,40 @@ define i64 @test_resign_da_ia(i64 %arg, i64 %arg1, i64 %arg2) { define i64 @test_resign_db_da(i64 %arg, i64 %arg1, i64 %arg2) { ; UNCHECKED-LABEL: test_resign_db_da: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: autdb x16, x1 -; UNCHECKED-NEXT: pacda x16, x2 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: autdb x17, x1 +; UNCHECKED-NEXT: pacda x17, x2 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_resign_db_da: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: autdb x16, x1 -; CHECKED-NEXT: mov x17, x16 -; CHECKED-NEXT: xpacd x17 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: autdb x17, x1 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: xpacd x16 ; CHECKED-NEXT: cmp x16, x17 ; CHECKED-NEXT: b.eq [[L]]auth_success_3 -; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: mov x17, x16 ; CHECKED-NEXT: b [[L]]resign_end_3 ; CHECKED-NEXT: Lauth_success_3: -; CHECKED-NEXT: pacda x16, x2 +; CHECKED-NEXT: pacda x17, x2 ; CHECKED-NEXT: Lresign_end_3: -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_resign_db_da: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: autdb x16, x1 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: autdb x17, x1 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpacd x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_11 ; TRAP-NEXT: brk #0xc473 ; TRAP-NEXT: Lauth_success_11: -; TRAP-NEXT: pacda x16, x2 -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: pacda x17, x2 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 3, i64 %arg1, i32 2, i64 %arg2) ret i64 %tmp @@ -452,40 +452,40 @@ define i64 @test_resign_db_da(i64 %arg, i64 %arg1, i64 %arg2) { define i64 @test_resign_iza_db(i64 %arg, i64 %arg1, i64 %arg2) { ; UNCHECKED-LABEL: test_resign_iza_db: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: autiza x16 -; UNCHECKED-NEXT: pacdb x16, x2 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: autiza x17 +; UNCHECKED-NEXT: pacdb x17, x2 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_resign_iza_db: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: autiza x16 -; CHECKED-NEXT: mov x17, x16 -; CHECKED-NEXT: xpaci x17 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: autiza x17 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: xpaci x16 ; CHECKED-NEXT: cmp x16, x17 ; CHECKED-NEXT: b.eq [[L]]auth_success_4 -; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: mov x17, x16 ; CHECKED-NEXT: b [[L]]resign_end_4 ; CHECKED-NEXT: Lauth_success_4: -; CHECKED-NEXT: pacdb x16, x2 +; CHECKED-NEXT: pacdb x17, x2 ; CHECKED-NEXT: Lresign_end_4: -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_resign_iza_db: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: autiza x16 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: autiza x17 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpaci x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_12 ; TRAP-NEXT: brk #0xc470 ; TRAP-NEXT: Lauth_success_12: -; TRAP-NEXT: pacdb x16, x2 -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: pacdb x17, x2 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 0, i64 0, i32 3, i64 %arg2) ret i64 %tmp @@ -494,40 +494,40 @@ define i64 @test_resign_iza_db(i64 %arg, i64 %arg1, i64 %arg2) { define i64 @test_resign_da_dzb(i64 %arg, i64 %arg1, i64 %arg2) { ; UNCHECKED-LABEL: test_resign_da_dzb: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: autda x16, x1 -; UNCHECKED-NEXT: pacdzb x16 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: autda x17, x1 +; UNCHECKED-NEXT: pacdzb x17 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_resign_da_dzb: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: autda x16, x1 -; CHECKED-NEXT: mov x17, x16 -; CHECKED-NEXT: xpacd x17 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: autda x17, x1 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: xpacd x16 ; CHECKED-NEXT: cmp x16, x17 ; CHECKED-NEXT: b.eq [[L]]auth_success_5 -; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: mov x17, x16 ; CHECKED-NEXT: b [[L]]resign_end_5 ; CHECKED-NEXT: Lauth_success_5: -; CHECKED-NEXT: pacdzb x16 +; CHECKED-NEXT: pacdzb x17 ; CHECKED-NEXT: Lresign_end_5: -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_resign_da_dzb: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: autda x16, x1 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: autda x17, x1 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpacd x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_13 ; TRAP-NEXT: brk #0xc472 ; TRAP-NEXT: Lauth_success_13: -; TRAP-NEXT: pacdzb x16 -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: pacdzb x17 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %arg1, i32 3, i64 0) ret i64 %tmp @@ -536,35 +536,35 @@ define i64 @test_resign_da_dzb(i64 %arg, i64 %arg1, i64 %arg2) { define i64 @test_auth_trap_attribute(i64 %arg, i64 %arg1) "ptrauth-auth-traps" { ; UNCHECKED-LABEL: test_auth_trap_attribute: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: autia x16, x1 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: autia x17, x1 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_auth_trap_attribute: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: autia x16, x1 -; CHECKED-NEXT: mov x17, x16 -; CHECKED-NEXT: xpaci x17 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: autia x17, x1 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: xpaci x16 ; CHECKED-NEXT: cmp x16, x17 ; CHECKED-NEXT: b.eq [[L]]auth_success_6 ; CHECKED-NEXT: brk #0xc470 ; CHECKED-NEXT: Lauth_success_6: -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_auth_trap_attribute: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: autia x16, x1 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: autia x17, x1 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpaci x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_14 ; TRAP-NEXT: brk #0xc470 ; TRAP-NEXT: Lauth_success_14: -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 %arg1) ret i64 %tmp @@ -573,32 +573,32 @@ define i64 @test_auth_trap_attribute(i64 %arg, i64 %arg1) "ptrauth-auth-traps" { define i64 @test_auth_ia_constdisc(i64 %arg) { ; UNCHECKED-LABEL: test_auth_ia_constdisc: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: mov x17, #256 -; UNCHECKED-NEXT: autia x16, x17 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: mov x16, #256 +; UNCHECKED-NEXT: autia x17, x16 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_auth_ia_constdisc: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: mov x17, #256 -; CHECKED-NEXT: autia x16, x17 -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: mov x16, #256 +; CHECKED-NEXT: autia x17, x16 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_auth_ia_constdisc: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: mov x17, #256 -; TRAP-NEXT: autia x16, x17 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: mov x16, #256 +; TRAP-NEXT: autia x17, x16 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpaci x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_15 ; TRAP-NEXT: brk #0xc470 ; TRAP-NEXT: Lauth_success_15: -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 256) ret i64 %tmp @@ -607,43 +607,43 @@ define i64 @test_auth_ia_constdisc(i64 %arg) { define i64 @test_resign_da_constdisc(i64 %arg, i64 %arg1) { ; UNCHECKED-LABEL: test_resign_da_constdisc: ; UNCHECKED: %bb.0: -; UNCHECKED-NEXT: mov x16, x0 -; UNCHECKED-NEXT: autda x16, x1 -; UNCHECKED-NEXT: mov x17, #256 -; UNCHECKED-NEXT: pacda x16, x17 -; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: mov x17, x0 +; UNCHECKED-NEXT: autda x17, x1 +; UNCHECKED-NEXT: mov x16, #256 +; UNCHECKED-NEXT: pacda x17, x16 +; UNCHECKED-NEXT: mov x0, x17 ; UNCHECKED-NEXT: ret ; ; CHECKED-LABEL: test_resign_da_constdisc: ; CHECKED: %bb.0: -; CHECKED-NEXT: mov x16, x0 -; CHECKED-NEXT: autda x16, x1 -; CHECKED-NEXT: mov x17, x16 -; CHECKED-NEXT: xpacd x17 +; CHECKED-NEXT: mov x17, x0 +; CHECKED-NEXT: autda x17, x1 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: xpacd x16 ; CHECKED-NEXT: cmp x16, x17 ; CHECKED-NEXT: b.eq [[L]]auth_success_7 -; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: mov x17, x16 ; CHECKED-NEXT: b [[L]]resign_end_6 ; CHECKED-NEXT: Lauth_success_7: -; CHECKED-NEXT: mov x17, #256 -; CHECKED-NEXT: pacda x16, x17 +; CHECKED-NEXT: mov x16, #256 +; CHECKED-NEXT: pacda x17, x16 ; CHECKED-NEXT: Lresign_end_6: -; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: mov x0, x17 ; CHECKED-NEXT: ret ; ; TRAP-LABEL: test_resign_da_constdisc: ; TRAP: %bb.0: -; TRAP-NEXT: mov x16, x0 -; TRAP-NEXT: autda x16, x1 -; TRAP-NEXT: mov x17, x16 -; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: mov x17, x0 +; TRAP-NEXT: autda x17, x1 +; TRAP-NEXT: mov x16, x17 +; TRAP-NEXT: xpacd x16 ; TRAP-NEXT: cmp x16, x17 ; TRAP-NEXT: b.eq [[L]]auth_success_16 ; TRAP-NEXT: brk #0xc472 ; TRAP-NEXT: Lauth_success_16: -; TRAP-NEXT: mov x17, #256 -; TRAP-NEXT: pacda x16, x17 -; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: mov x16, #256 +; TRAP-NEXT: pacda x17, x16 +; TRAP-NEXT: mov x0, x17 ; TRAP-NEXT: ret %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %arg1, i32 2, i64 256) ret i64 %tmp diff --git a/llvm/test/CodeGen/AArch64/ptrauth-invoke.ll b/llvm/test/CodeGen/AArch64/ptrauth-invoke.ll index f6b3a88ca46779dc2403743da88bd35c39a80846..58548c0244dfa37e8349a07a8934b509f75d8f6e 100644 --- a/llvm/test/CodeGen/AArch64/ptrauth-invoke.ll +++ b/llvm/test/CodeGen/AArch64/ptrauth-invoke.ll @@ -1,16 +1,16 @@ -; RUN: llc -mtriple arm64e-apple-darwin -o - %s \ -; RUN: | FileCheck %s --check-prefixes=CHECK,DARWIN,DARWIN-SDAG +; RUN-NOT: llc -mtriple arm64e-apple-darwin -o - %s \ +; RUN-NOT: | FileCheck %s --check-prefixes=CHECK,DARWIN,DARWIN-SDAG ; RUN: llc -mtriple aarch64 -mattr=+pauth -o - %s \ ; RUN: | FileCheck %s --check-prefixes=CHECK,ELF,ELF-SDAG -; RUN: llc -mtriple arm64e-apple-darwin -o - %s \ -; RUN: -global-isel -global-isel-abort=1 -verify-machineinstrs \ -; RUN: | FileCheck %s --check-prefixes=CHECK,DARWIN,DARWIN-GISEL +; RUN-NOT: llc -mtriple arm64e-apple-darwin -o - %s \ +; RUN-NOT: -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: | FileCheck %s --check-prefixes=CHECK,DARWIN,DARWIN-GISEL -; RUN: llc -mtriple aarch64 -mattr=+pauth -o - %s \ -; RUN: -global-isel -global-isel-abort=1 -verify-machineinstrs \ -; RUN: | FileCheck %s --check-prefixes=CHECK,ELF,ELF-GISEL +; RUN-NOT: llc -mtriple aarch64 -mattr=+pauth -o - %s \ +; RUN-NOT: -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN-NOT: | FileCheck %s --check-prefixes=CHECK,ELF,ELF-GISEL ; DARWIN-LABEL: _test_invoke_ia_0: ; DARWIN-NEXT: [[FNBEGIN:L.*]]: @@ -404,25 +404,25 @@ continuebb: ; ELF-NEXT: .cfi_offset w30, -16 ; ELF-SDAG-NEXT: [[PRECALL:.L.*]]: -; ELF-SDAG-NEXT: adrp x16, :got:baz -; ELF-SDAG-NEXT: ldr x16, [x16, :got_lo12:baz] -; ELF-SDAG-NEXT: mov x17, #1234 -; ELF-SDAG-NEXT: pacia x16, x17 -; ELF-SDAG-NEXT: mov x8, x16 +; ELF-SDAG-NEXT: adrp x17, :got:baz +; ELF-SDAG-NEXT: ldr x17, [x17, :got_lo12:baz] +; ELF-SDAG-NEXT: mov x16, #1234 +; ELF-SDAG-NEXT: pacia x17, x16 +; ELF-SDAG-NEXT: mov x8, x17 ; ELF-SDAG-NEXT: mov x17, #2 ; ELF-SDAG-NEXT: blrab x8, x17 ; ELF-SDAG-NEXT: [[POSTCALL:.L.*]]: ; ELF-SDAG-NEXT: // %bb.1: ; ELF-SDAG-NEXT: mov w19, w0 -; ELF-GISEL-NEXT: adrp x16, :got:baz -; ELF-GISEL-NEXT: ldr x16, [x16, :got_lo12:baz] -; ELF-GISEL-NEXT: mov x17, #1234 -; ELF-GISEL-NEXT: pacia x16, x17 -; ELF-GISEL-NEXT: mov x8, x16 +; ELF-GISEL-NEXT: adrp x17, :got:baz +; ELF-GISEL-NEXT: ldr x17, [x17, :got_lo12:baz] +; ELF-GISEL-NEXT: mov x16, #1234 +; ELF-GISEL-NEXT: pacia x17, x16 +; ELF-GISEL-NEXT: mov x8, x17 ; ELF-GISEL-NEXT: [[PRECALL:.L.*]]: -; ELF-GISEL-NEXT: mov x17, #2 -; ELF-GISEL-NEXT: blrab x8, x17 +; ELF-GISEL-NEXT: mov x16, #2 +; ELF-GISEL-NEXT: blrab x8, x16 ; ELF-GISEL-NEXT: mov w19, w0 ; ELF-GISEL-NEXT: [[POSTCALL:.L.*]]: diff --git a/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll b/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll index b7304b957a00136c9f5416f2451d07ee968b5044..70e3270f69704de9dfd6089c5b1e4160bdb1bcf3 100644 --- a/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll +++ b/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll @@ -65,53 +65,53 @@ @g.ref.ib.0 = constant { i64, ptr, i64 } { i64 5, ptr ptrauth (ptr @g, i32 1, i64 0), i64 6 } -; CHECK-ELF-LABEL: .globl g.ref.da.42.addr +; CHECK-ELF-LABEL: .globl g.ref.ia.42.addr ; CHECK-ELF-NEXT: .p2align 3 -; CHECK-ELF-NEXT: g.ref.da.42.addr: -; CHECK-ELF-NEXT: .xword g@AUTH(da,42,addr) +; CHECK-ELF-NEXT: g.ref.ia.42.addr: +; CHECK-ELF-NEXT: .xword g@AUTH(ia,42,addr) -; CHECK-MACHO-LABEL: .globl _g.ref.da.42.addr +; CHECK-MACHO-LABEL: .globl _g.ref.ia.42.addr ; CHECK-MACHO-NEXT: .p2align 3 -; CHECK-MACHO-NEXT: _g.ref.da.42.addr: -; CHECK-MACHO-NEXT: .quad _g@AUTH(da,42,addr) +; CHECK-MACHO-NEXT: _g.ref.ia.42.addr: +; CHECK-MACHO-NEXT: .quad _g@AUTH(ia,42,addr) -@g.ref.da.42.addr = constant ptr ptrauth (ptr @g, i32 2, i64 42, ptr @g.ref.da.42.addr) +@g.ref.ia.42.addr = constant ptr ptrauth (ptr @g, i32 2, i64 42, ptr @g.ref.ia.42.addr) -; CHECK-ELF-LABEL: .globl g.offset.ref.da.0 +; CHECK-ELF-LABEL: .globl g.offset.ref.ia.0 ; CHECK-ELF-NEXT: .p2align 3 -; CHECK-ELF-NEXT: g.offset.ref.da.0: -; CHECK-ELF-NEXT: .xword (g+16)@AUTH(da,0) +; CHECK-ELF-NEXT: g.offset.ref.ia.0: +; CHECK-ELF-NEXT: .xword (g+16)@AUTH(ia,0) -; CHECK-MACHO-LABEL: .globl _g.offset.ref.da.0 +; CHECK-MACHO-LABEL: .globl _g.offset.ref.ia.0 ; CHECK-MACHO-NEXT: .p2align 3 -; CHECK-MACHO-NEXT: _g.offset.ref.da.0: -; CHECK-MACHO-NEXT: .quad (_g+16)@AUTH(da,0) +; CHECK-MACHO-NEXT: _g.offset.ref.ia.0: +; CHECK-MACHO-NEXT: .quad (_g+16)@AUTH(ia,0) -@g.offset.ref.da.0 = constant ptr ptrauth (i8* getelementptr (i8, ptr @g, i64 16), i32 2) +@g.offset.ref.ia.0 = constant ptr ptrauth (i8* getelementptr (i8, ptr @g, i64 16), i32 2) -; CHECK-ELF-LABEL: .globl g.big_offset.ref.da.0 +; CHECK-ELF-LABEL: .globl g.big_offset.ref.ia.0 ; CHECK-ELF-NEXT: .p2align 3 -; CHECK-ELF-NEXT: g.big_offset.ref.da.0: -; CHECK-ELF-NEXT: .xword (g+2147549185)@AUTH(da,0) +; CHECK-ELF-NEXT: g.big_offset.ref.ia.0: +; CHECK-ELF-NEXT: .xword (g+2147549185)@AUTH(ia,0) -; CHECK-MACHO-LABEL: .globl _g.big_offset.ref.da.0 +; CHECK-MACHO-LABEL: .globl _g.big_offset.ref.ia.0 ; CHECK-MACHO-NEXT: .p2align 3 -; CHECK-MACHO-NEXT: _g.big_offset.ref.da.0: -; CHECK-MACHO-NEXT: .quad (_g+2147549185)@AUTH(da,0) +; CHECK-MACHO-NEXT: _g.big_offset.ref.ia.0: +; CHECK-MACHO-NEXT: .quad (_g+2147549185)@AUTH(ia,0) -@g.big_offset.ref.da.0 = constant ptr ptrauth (i8* getelementptr (i8, ptr @g, i64 add (i64 2147483648, i64 65537)), i32 2) +@g.big_offset.ref.ia.0 = constant ptr ptrauth (i8* getelementptr (i8, ptr @g, i64 add (i64 2147483648, i64 65537)), i32 2) -; CHECK-ELF-LABEL: .globl g.weird_ref.da.0 +; CHECK-ELF-LABEL: .globl g.weird_ref.ia.0 ; CHECK-ELF-NEXT: .p2align 3 -; CHECK-ELF-NEXT: g.weird_ref.da.0: -; CHECK-ELF-NEXT: .xword (g+16)@AUTH(da,0) +; CHECK-ELF-NEXT: g.weird_ref.ia.0: +; CHECK-ELF-NEXT: .xword (g+16)@AUTH(ia,0) -; CHECK-MACHO-LABEL: .globl _g.weird_ref.da.0 +; CHECK-MACHO-LABEL: .globl _g.weird_ref.ia.0 ; CHECK-MACHO-NEXT: .p2align 3 -; CHECK-MACHO-NEXT: _g.weird_ref.da.0: -; CHECK-MACHO-NEXT: .quad (_g+16)@AUTH(da,0) +; CHECK-MACHO-NEXT: _g.weird_ref.ia.0: +; CHECK-MACHO-NEXT: .quad (_g+16)@AUTH(ia,0) -@g.weird_ref.da.0 = constant i64 ptrtoint (ptr inttoptr (i64 ptrtoint (ptr ptrauth (i8* getelementptr (i8, ptr @g, i64 16), i32 2) to i64) to ptr) to i64) +@g.weird_ref.ia.0 = constant i64 ptrtoint (ptr inttoptr (i64 ptrtoint (ptr ptrauth (i8* getelementptr (i8, ptr @g, i64 16), i32 2) to i64) to ptr) to i64) ; CHECK-ELF-LABEL: .globl g_weak.ref.ia.42 ; CHECK-ELF-NEXT: .p2align 3 @@ -125,17 +125,17 @@ @g_weak.ref.ia.42 = constant ptr ptrauth (ptr @g_weak, i32 0, i64 42) -; CHECK-ELF-LABEL: .globl g_strong_def.ref.da.0 +; CHECK-ELF-LABEL: .globl g_strong_def.ref.ia.0 ; CHECK-ELF-NEXT: .p2align 3 -; CHECK-ELF-NEXT: g_strong_def.ref.da.0: -; CHECK-ELF-NEXT: .xword g_strong_def@AUTH(da,0) +; CHECK-ELF-NEXT: g_strong_def.ref.ia.0: +; CHECK-ELF-NEXT: .xword g_strong_def@AUTH(ia,0) -; CHECK-MACHO-LABEL: .globl _g_strong_def.ref.da.0 +; CHECK-MACHO-LABEL: .globl _g_strong_def.ref.ia.0 ; CHECK-MACHO-NEXT: .p2align 3 -; CHECK-MACHO-NEXT: _g_strong_def.ref.da.0: -; CHECK-MACHO-NEXT: .quad _g_strong_def@AUTH(da,0) +; CHECK-MACHO-NEXT: _g_strong_def.ref.ia.0: +; CHECK-MACHO-NEXT: .quad _g_strong_def@AUTH(ia,0) -@g_strong_def.ref.da.0 = constant ptr ptrauth (ptr @g_strong_def, i32 2) +@g_strong_def.ref.ia.0 = constant ptr ptrauth (ptr @g_strong_def, i32 2) ;--- err-key.ll diff --git a/llvm/test/CodeGen/AArch64/ptrauth-type-info-vptr-discr.ll b/llvm/test/CodeGen/AArch64/ptrauth-type-info-vptr-discr.ll new file mode 100644 index 0000000000000000000000000000000000000000..f227a3e407f35a83f7e5f0a1f03168de767e40f1 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/ptrauth-type-info-vptr-discr.ll @@ -0,0 +1,21 @@ +; RUN: llc -mtriple aarch64-linux-gnu -mattr=+pauth -filetype=asm -o - %s | FileCheck --check-prefix=ELF %s +; RUN: llc -mtriple aarch64-apple-darwin -mattr=+pauth -filetype=asm -o - %s | FileCheck --check-prefix=MACHO %s + +; ELF-LABEL: _ZTI10Disc: +; ELF-NEXT: .xword (_ZTVN10__cxxabiv117__class_type_infoE+16)@AUTH(ia,45546,addr) +; ELF-LABEL: _ZTI10NoDisc: +; ELF-NEXT: .xword (_ZTVN10__cxxabiv117__class_type_infoE+16)@AUTH(ia,45546) + +; MACHO-LABEL: __ZTI10Disc: +; MACHO-NEXT: .quad (__ZTVN10__cxxabiv117__class_type_infoE+16)@AUTH(ia,45546,addr) +; MACHO-LABEL: __ZTI10NoDisc: +; MACHO-NEXT: .quad (__ZTVN10__cxxabiv117__class_type_infoE+16)@AUTH(ia,45546) + + +@_ZTI10Disc = constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2, i64 45546, ptr @_ZTI10Disc), ptr @_ZTS10Disc }, align 8 +@_ZTS10Disc = constant [4 x i8] c"Disc", align 1 + +@_ZTI10NoDisc = constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2, i64 45546), ptr @_ZTS10NoDisc }, align 8 +@_ZTS10NoDisc = constant [6 x i8] c"NoDisc", align 1 + +@_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr] diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp index 5ac13495662fafae9467de176a5b3d25b029d873..b681b23a95f04ddef8a608d2407ae1efb8936510 100644 --- a/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/llvm/tools/llvm-objdump/ELFDump.cpp @@ -290,6 +290,9 @@ template void ELFDumper::printProgramHeaders() { case ELF::PT_OPENBSD_MUTABLE: outs() << "OPENBSD_MUTABLE "; break; + case ELF::PT_OHOS_CFI_MODIFIER: + outs() << "OHOS_CFI_MODIFIER "; + break; case ELF::PT_OPENBSD_NOBTCFI: outs() << "OPENBSD_NOBTCFI "; break; diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index f0a22f1568bef223380791648bcbd5e07e7fb6b8..098c7332f9ff65a7cfc01f577753bd85ada6aa76 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -1496,6 +1496,7 @@ static StringRef segmentTypeToString(unsigned Arch, unsigned Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_NOBTCFI); LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_SYSCALLS); LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_BOOTDATA); + LLVM_READOBJ_ENUM_CASE(ELF, PT_OHOS_CFI_MODIFIER); default: return ""; }