[llvm] 5f1bb62 - [AArch64][PAC] Lower ptrauth constants in code for MachO. (#97665)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 10 15:03:21 PDT 2024


Author: Ahmed Bougacha
Date: 2024-07-10T15:03:17-07:00
New Revision: 5f1bb62c6bb83b9a46e3c6a45999d4468edb11e0

URL: https://github.com/llvm/llvm-project/commit/5f1bb62c6bb83b9a46e3c6a45999d4468edb11e0
DIFF: https://github.com/llvm/llvm-project/commit/5f1bb62c6bb83b9a46e3c6a45999d4468edb11e0.diff

LOG: [AArch64][PAC] Lower ptrauth constants in code for MachO. (#97665)

This also adds support for auth stubs on MachO using __DATA,__auth_ptr.

Some of the machinery for auth stubs is already implemented;  this
generalizes that a bit to support MachO, and moves some of the shared
logic into MMIImpls.

In particular, this originally had an AuthStubInfo struct, but we no
longer need it beyond a single MCExpr.  So this provides variants of
the symbol stub helper type declarations and functions for "expr
stubs", where a stub points at an arbitrary MCExpr, rather than
a simple MCSymbol (and a bit).

Added: 
    

Modified: 
    llvm/include/llvm/CodeGen/MachineModuleInfo.h
    llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h
    llvm/lib/CodeGen/MachineModuleInfoImpls.cpp
    llvm/lib/MC/MCMachOStreamer.cpp
    llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
    llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
    llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
    llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
    llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
    llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll
    llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/MachineModuleInfo.h b/llvm/include/llvm/CodeGen/MachineModuleInfo.h
index 92ea3c902ce95..97b439c726b0a 100644
--- a/llvm/include/llvm/CodeGen/MachineModuleInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineModuleInfo.h
@@ -58,12 +58,20 @@ class MachineModuleInfoImpl {
   using StubValueTy = PointerIntPair<MCSymbol *, 1, bool>;
   using SymbolListTy = std::vector<std::pair<MCSymbol *, StubValueTy>>;
 
+  /// A variant of SymbolListTy where the stub is a generalized MCExpr.
+  using ExprStubListTy = std::vector<std::pair<MCSymbol *, const MCExpr *>>;
+
   virtual ~MachineModuleInfoImpl();
 
 protected:
   /// Return the entries from a DenseMap in a deterministic sorted orer.
   /// Clears the map.
   static SymbolListTy getSortedStubs(DenseMap<MCSymbol*, StubValueTy>&);
+
+  /// Return the entries from a DenseMap in a deterministic sorted orer.
+  /// Clears the map.
+  static ExprStubListTy
+  getSortedExprStubs(DenseMap<MCSymbol *, const MCExpr *> &);
 };
 
 //===----------------------------------------------------------------------===//

diff  --git a/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h b/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h
index 64d841d86c7c4..c1ae3d2d966df 100644
--- a/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h
+++ b/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h
@@ -36,6 +36,11 @@ class MachineModuleInfoMachO : public MachineModuleInfoImpl {
   /// bit is true if this GV is external.
   DenseMap<MCSymbol *, StubValueTy> ThreadLocalGVStubs;
 
+  /// Darwin '$auth_ptr' stubs.  The key is the stub symbol, like
+  /// "Lfoo$auth_ptr$ib$12".  The value is the MCExpr representing that
+  /// signed pointer, something like "_foo at AUTH(ib, 12)".
+  DenseMap<MCSymbol *, const MCExpr *> AuthPtrStubs;
+
   virtual void anchor(); // Out of line virtual method.
 
 public:
@@ -51,29 +56,32 @@ class MachineModuleInfoMachO : public MachineModuleInfoImpl {
     return ThreadLocalGVStubs[Sym];
   }
 
+  const MCExpr *&getAuthPtrStubEntry(MCSymbol *Sym) {
+    assert(Sym && "Key cannot be null");
+    return AuthPtrStubs[Sym];
+  }
+
   /// Accessor methods to return the set of stubs in sorted order.
   SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); }
   SymbolListTy GetThreadLocalGVStubList() {
     return getSortedStubs(ThreadLocalGVStubs);
   }
+
+  ExprStubListTy getAuthGVStubList() {
+    return getSortedExprStubs(AuthPtrStubs);
+  }
 };
 
 /// MachineModuleInfoELF - This is a MachineModuleInfoImpl implementation
 /// for ELF targets.
 class MachineModuleInfoELF : public MachineModuleInfoImpl {
-public:
-  struct AuthStubInfo {
-    const MCExpr *AuthPtrRef;
-  };
-
-private:
   /// GVStubs - These stubs are used to materialize global addresses in PIC
   /// mode.
   DenseMap<MCSymbol *, StubValueTy> GVStubs;
 
   /// AuthPtrStubs - These stubs are used to materialize signed addresses for
   /// extern_weak symbols.
-  DenseMap<MCSymbol *, AuthStubInfo> AuthPtrStubs;
+  DenseMap<MCSymbol *, const MCExpr *> AuthPtrStubs;
 
   virtual void anchor(); // Out of line virtual method.
 
@@ -85,7 +93,7 @@ class MachineModuleInfoELF : public MachineModuleInfoImpl {
     return GVStubs[Sym];
   }
 
-  AuthStubInfo &getAuthPtrStubEntry(MCSymbol *Sym) {
+  const MCExpr *&getAuthPtrStubEntry(MCSymbol *Sym) {
     assert(Sym && "Key cannot be null");
     return AuthPtrStubs[Sym];
   }
@@ -94,10 +102,9 @@ class MachineModuleInfoELF : public MachineModuleInfoImpl {
 
   SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); }
 
-  using AuthStubPairTy = std::pair<MCSymbol *, AuthStubInfo>;
-  typedef std::vector<AuthStubPairTy> AuthStubListTy;
-
-  AuthStubListTy getAuthGVStubList();
+  ExprStubListTy getAuthGVStubList() {
+    return getSortedExprStubs(AuthPtrStubs);
+  }
 };
 
 /// MachineModuleInfoCOFF - This is a MachineModuleInfoImpl implementation

diff  --git a/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp b/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp
index f114f1ecc0bae..956317510dc73 100644
--- a/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp
+++ b/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp
@@ -43,24 +43,19 @@ MachineModuleInfoImpl::SymbolListTy MachineModuleInfoImpl::getSortedStubs(
   return List;
 }
 
-template <typename MachineModuleInfoTarget>
-static typename MachineModuleInfoTarget::AuthStubListTy getAuthGVStubListHelper(
-    DenseMap<MCSymbol *, typename MachineModuleInfoTarget::AuthStubInfo>
-        &AuthPtrStubs) {
-  typename MachineModuleInfoTarget::AuthStubListTy List(AuthPtrStubs.begin(),
-                                                        AuthPtrStubs.end());
+using ExprStubPairTy = std::pair<MCSymbol *, const MCExpr *>;
+static int SortAuthStubPair(const ExprStubPairTy *LHS,
+                            const ExprStubPairTy *RHS) {
+  return LHS->first->getName().compare(RHS->first->getName());
+}
 
-  if (!List.empty())
-    llvm::sort(List.begin(), List.end(),
-               [](const typename MachineModuleInfoTarget::AuthStubPairTy &LHS,
-                  const typename MachineModuleInfoTarget::AuthStubPairTy &RHS) {
-                 return LHS.first->getName() < RHS.first->getName();
-               });
+MachineModuleInfoImpl::ExprStubListTy MachineModuleInfoImpl::getSortedExprStubs(
+    DenseMap<MCSymbol *, const MCExpr *> &ExprStubs) {
+  MachineModuleInfoImpl::ExprStubListTy List(ExprStubs.begin(),
+                                             ExprStubs.end());
 
-  AuthPtrStubs.clear();
-  return List;
-}
+  array_pod_sort(List.begin(), List.end(), SortAuthStubPair);
 
-MachineModuleInfoELF::AuthStubListTy MachineModuleInfoELF::getAuthGVStubList() {
-  return getAuthGVStubListHelper<MachineModuleInfoELF>(AuthPtrStubs);
+  ExprStubs.clear();
+  return List;
 }

diff  --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp
index 90e0fcd6ac6dd..c8bc819129850 100644
--- a/llvm/lib/MC/MCMachOStreamer.cpp
+++ b/llvm/lib/MC/MCMachOStreamer.cpp
@@ -167,6 +167,10 @@ static bool canGoAfterDWARF(const MCSectionMachO &MSec) {
     return true;
   if (SegName == "__LLVM" && (SecName == "__cg_profile"))
     return true;
+
+  if (SegName == "__DATA" && SecName == "__auth_ptr")
+    return true;
+
   return false;
 }
 

diff  --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index a966e1c1f618e..6f6b551993b6d 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -848,13 +848,12 @@ void AArch64AsmPrinter::emitHwasanMemaccessSymbols(Module &M) {
   }
 }
 
-template <typename MachineModuleInfoTarget>
-static void emitAuthenticatedPointer(
-    MCStreamer &OutStreamer, MCSymbol *StubLabel,
-    const typename MachineModuleInfoTarget::AuthStubInfo &StubInfo) {
+static void emitAuthenticatedPointer(MCStreamer &OutStreamer,
+                                     MCSymbol *StubLabel,
+                                     const MCExpr *StubAuthPtrRef) {
   // sym$auth_ptr$key$disc:
   OutStreamer.emitLabel(StubLabel);
-  OutStreamer.emitValue(StubInfo.AuthPtrRef, /*size=*/8);
+  OutStreamer.emitValue(StubAuthPtrRef, /*size=*/8);
 }
 
 void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) {
@@ -862,6 +861,25 @@ void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) {
 
   const Triple &TT = TM.getTargetTriple();
   if (TT.isOSBinFormatMachO()) {
+    // Output authenticated pointers as indirect symbols, if we have any.
+    MachineModuleInfoMachO &MMIMacho =
+        MMI->getObjFileInfo<MachineModuleInfoMachO>();
+
+    auto Stubs = MMIMacho.getAuthGVStubList();
+
+    if (!Stubs.empty()) {
+      // Switch to the "__auth_ptr" section.
+      OutStreamer->switchSection(
+          OutContext.getMachOSection("__DATA", "__auth_ptr", MachO::S_REGULAR,
+                                     SectionKind::getMetadata()));
+      emitAlignment(Align(8));
+
+      for (const auto &Stub : Stubs)
+        emitAuthenticatedPointer(*OutStreamer, Stub.first, Stub.second);
+
+      OutStreamer->addBlankLine();
+    }
+
     // Funny Darwin hack: This flag tells the linker that no global symbols
     // contain code that falls through to other global symbols (e.g. the obvious
     // implementation of multiple entry points).  If this doesn't occur, the
@@ -882,8 +900,7 @@ void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) {
       emitAlignment(Align(8));
 
       for (const auto &Stub : Stubs)
-        emitAuthenticatedPointer<MachineModuleInfoELF>(*OutStreamer, Stub.first,
-                                                       Stub.second);
+        emitAuthenticatedPointer(*OutStreamer, Stub.first, Stub.second);
 
       OutStreamer->addBlankLine();
     }
@@ -1676,16 +1693,29 @@ void AArch64AsmPrinter::LowerLOADauthptrstatic(const MachineInstr &MI) {
   //
   // Where the $auth_ptr$ symbol is the stub slot containing the signed pointer
   // to symbol.
-  assert(TM.getTargetTriple().isOSBinFormatELF() &&
-         "LOADauthptrstatic is implemented only for ELF");
-  const auto &TLOF =
-      static_cast<const AArch64_ELFTargetObjectFile &>(getObjFileLowering());
-
-  assert(GAOp.getOffset() == 0 &&
-         "non-zero offset for $auth_ptr$ stub slots is not supported");
-  const MCSymbol *GASym = TM.getSymbol(GAOp.getGlobal());
-  MCSymbol *AuthPtrStubSym =
-      TLOF.getAuthPtrSlotSymbol(TM, &MF->getMMI(), GASym, Key, Disc);
+  MCSymbol *AuthPtrStubSym;
+  if (TM.getTargetTriple().isOSBinFormatELF()) {
+    const auto &TLOF =
+        static_cast<const AArch64_ELFTargetObjectFile &>(getObjFileLowering());
+
+    assert(GAOp.getOffset() == 0 &&
+           "non-zero offset for $auth_ptr$ stub slots is not supported");
+    const MCSymbol *GASym = TM.getSymbol(GAOp.getGlobal());
+    AuthPtrStubSym =
+        TLOF.getAuthPtrSlotSymbol(TM, &MF->getMMI(), GASym, Key, Disc);
+  } else {
+    assert(TM.getTargetTriple().isOSBinFormatMachO() &&
+           "LOADauthptrstatic is implemented only for MachO/ELF");
+
+    const auto &TLOF = static_cast<const AArch64_MachoTargetObjectFile &>(
+        getObjFileLowering());
+
+    assert(GAOp.getOffset() == 0 &&
+           "non-zero offset for $auth_ptr$ stub slots is not supported");
+    const MCSymbol *GASym = TM.getSymbol(GAOp.getGlobal());
+    AuthPtrStubSym =
+        TLOF.getAuthPtrSlotSymbol(TM, &MF->getMMI(), GASym, Key, Disc);
+  }
 
   MachineOperand StubMOHi =
       MachineOperand::CreateMCSymbol(AuthPtrStubSym, AArch64II::MO_PAGE);

diff  --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index e5d5c6b6832af..aa73db16d1d85 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -9545,8 +9545,7 @@ SDValue AArch64TargetLowering::LowerGlobalTLSAddress(SDValue Op,
 //   Load a signed pointer for symbol 'sym' from a stub slot named
 //   'sym$auth_ptr$key$disc' filled by dynamic linker during relocation
 //   resolving. This usually lowers to adrp+ldr, but also emits an entry into
-//   .data with an
-//   @AUTH relocation. See LowerLOADauthptrstatic.
+//   .data with an @AUTH relocation. See LowerLOADauthptrstatic.
 //
 // All 3 are pseudos that are expand late to longer sequences: this lets us
 // provide integrity guarantees on the to-be-signed intermediate values.
@@ -9599,8 +9598,8 @@ AArch64TargetLowering::LowerPtrAuthGlobalAddress(SDValue Op,
         "constant discriminator in ptrauth global out of range [0, 0xffff]");
 
   // Choosing between 3 lowering alternatives is target-specific.
-  if (!Subtarget->isTargetELF())
-    report_fatal_error("ptrauth global lowering is only implemented for ELF");
+  if (!Subtarget->isTargetELF() && !Subtarget->isTargetMachO())
+    report_fatal_error("ptrauth global lowering only supported on MachO/ELF");
 
   int64_t PtrOffsetC = 0;
   if (Ptr.getOpcode() == ISD::ADD) {

diff  --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
index 3c0facd586732..d916f644de9b5 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp
@@ -105,15 +105,14 @@ static MCSymbol *getAuthPtrSlotSymbolHelper(
       Twine("$auth_ptr$") + AArch64PACKeyIDToString(Key) + Twine('$') +
       Twine(Discriminator));
 
-  typename MachineModuleInfoTarget::AuthStubInfo &StubInfo =
-      TargetMMI.getAuthPtrStubEntry(StubSym);
+  const MCExpr *&StubAuthPtrRef = TargetMMI.getAuthPtrStubEntry(StubSym);
 
-  if (StubInfo.AuthPtrRef)
+  if (StubAuthPtrRef)
     return StubSym;
 
   const MCExpr *Sym = MCSymbolRefExpr::create(RawSym, Ctx);
 
-  StubInfo.AuthPtrRef =
+  StubAuthPtrRef =
       AArch64AuthMCExpr::create(Sym, Discriminator, Key,
                                 /*HasAddressDiversity=*/false, Ctx);
   return StubSym;
@@ -126,3 +125,11 @@ MCSymbol *AArch64_ELFTargetObjectFile::getAuthPtrSlotSymbol(
   return getAuthPtrSlotSymbolHelper(getContext(), TM, MMI, ELFMMI, RawSym, Key,
                                     Discriminator);
 }
+
+MCSymbol *AArch64_MachoTargetObjectFile::getAuthPtrSlotSymbol(
+    const TargetMachine &TM, MachineModuleInfo *MMI, const MCSymbol *RawSym,
+    AArch64PACKey::ID Key, uint16_t Discriminator) const {
+  auto &MachOMMI = MMI->getObjFileInfo<MachineModuleInfoMachO>();
+  return getAuthPtrSlotSymbolHelper(getContext(), TM, MMI, MachOMMI, RawSym,
+                                    Key, Discriminator);
+}

diff  --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
index c5ebf03c39c77..2ef8bda2988d4 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
+++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h
@@ -60,6 +60,11 @@ class AArch64_MachoTargetObjectFile : public TargetLoweringObjectFileMachO {
 
   void getNameWithPrefix(SmallVectorImpl<char> &OutName, const GlobalValue *GV,
                          const TargetMachine &TM) const override;
+
+  MCSymbol *getAuthPtrSlotSymbol(const TargetMachine &TM,
+                                 MachineModuleInfo *MMI, const MCSymbol *RawSym,
+                                 AArch64PACKey::ID Key,
+                                 uint16_t Discriminator) const;
 };
 
 /// This implementation is used for AArch64 COFF targets.

diff  --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 1ff8a7e32a156..517d0bd3047ca 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -6636,8 +6636,8 @@ bool AArch64InstructionSelector::selectPtrAuthGlobalValue(
         "constant discriminator in ptrauth global out of range [0, 0xffff]");
 
   // Choosing between 3 lowering alternatives is target-specific.
-  if (!STI.isTargetELF())
-    report_fatal_error("ptrauth global lowering is only implemented for ELF");
+  if (!STI.isTargetELF() && !STI.isTargetMachO())
+    report_fatal_error("ptrauth global lowering only supported on MachO/ELF");
 
   if (!MRI.hasOneDef(Addr))
     return false;

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 7b85b12bb8952..12a3448111fcb 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/ptrauth-constant-in-code.ll
@@ -5,6 +5,9 @@
 ; RUN: not --crash llc < err1.ll -mtriple aarch64-elf -mattr=+pauth \
 ; RUN:   -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \
 ; RUN:   FileCheck --check-prefix=ERR1 %s
+; RUN: not --crash llc < err1.ll -mtriple arm64-apple-ios -mattr=+pauth \
+; RUN:   -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \
+; RUN:   FileCheck --check-prefix=ERR1 %s
 
 @g = external global i32
 
@@ -18,6 +21,9 @@ define ptr @foo() {
 ; RUN: not --crash llc < err2.ll -mtriple aarch64-elf -mattr=+pauth \
 ; RUN:   -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \
 ; RUN:   FileCheck --check-prefix=ERR2 %s
+; RUN: not --crash llc < err2.ll -mtriple arm64-apple-ios -mattr=+pauth \
+; RUN:   -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \
+; RUN:   FileCheck --check-prefix=ERR2 %s
 
 @g = external global i32
 
@@ -31,6 +37,9 @@ define ptr @foo() {
 ; RUN: not --crash llc < err3.ll -mtriple aarch64-elf -mattr=+pauth \
 ; RUN:   -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \
 ; RUN:   FileCheck --check-prefix=ERR3 %s
+; RUN: not --crash llc < err3.ll -mtriple arm64-apple-ios -mattr=+pauth \
+; RUN:   -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \
+; RUN:   FileCheck --check-prefix=ERR3 %s
 
 @g_weak = extern_weak global i32
 
@@ -44,6 +53,9 @@ define ptr @foo() {
 ; RUN: not --crash llc < err4.ll -mtriple aarch64-elf -mattr=+pauth \
 ; RUN:   -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \
 ; RUN:   FileCheck --check-prefix=ERR4 %s
+; RUN: not --crash llc < err4.ll -mtriple arm64-apple-ios -mattr=+pauth \
+; RUN:   -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \
+; RUN:   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)
@@ -55,21 +67,28 @@ define ptr @foo() {
 
 ;--- err5.ll
 
-; RUN: not --crash llc < err5.ll -mtriple arm64-apple-darwin -mattr=+pauth \
+; RUN: not --crash llc < err5.ll -mtriple aarch64-windows -mattr=+pauth \
 ; RUN:   -global-isel=1 -verify-machineinstrs -global-isel-abort=1 2>&1 | \
 ; RUN:   FileCheck --check-prefix=ERR5 %s
 
 @g = external global i32
 
 define ptr @foo() {
-; ERR5: LLVM ERROR: ptrauth global lowering is only implemented for ELF
+; 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=1 \
-; RUN:   -verify-machineinstrs -global-isel-abort=1 | FileCheck %s
+; RUN:   -verify-machineinstrs -global-isel-abort=1 | \
+; RUN:   FileCheck %s --check-prefix=ELF
+; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=1 \
+; RUN:   -verify-machineinstrs -global-isel-abort=1 -filetype=obj
+
+; RUN: llc < ok.ll -mtriple arm64-apple-ios -mattr=+pauth -global-isel=1 \
+; RUN:   -verify-machineinstrs -global-isel-abort=1 | \
+; RUN:   FileCheck %s --check-prefix=MACHO
 ; RUN: llc < ok.ll -mtriple aarch64-elf -mattr=+pauth -global-isel=1 \
 ; RUN:   -verify-machineinstrs -global-isel-abort=1 -filetype=obj
 
@@ -78,100 +97,171 @@ define ptr @foo() {
 @g_strong_def = dso_local constant i32 42
 
 define ptr @test_global_zero_disc() {
-; CHECK-LABEL: test_global_zero_disc:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, :got:g
-; CHECK-NEXT:    ldr     x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    paciza  x16
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
+; 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:      ret
+
+; MACHO-LABEL: _test_global_zero_disc:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr     x16, [x16, _g at GOTPAGEOFF]
+; MACHO-NEXT:    paciza  x16
+; MACHO-NEXT:    mov     x0, x16
+; MACHO-NEXT:    ret
 
   ret ptr ptrauth (ptr @g, i32 0)
 }
 
 define ptr @test_global_offset_zero_disc() {
-; CHECK-LABEL: test_global_offset_zero_disc:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, :got:g
-; CHECK-NEXT:    ldr     x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    add     x16, x16, #16
-; CHECK-NEXT:    pacdza  x16
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
+; 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:    ret
+
+; MACHO-LABEL: _test_global_offset_zero_disc:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr     x16, [x16, _g at GOTPAGEOFF]
+; MACHO-NEXT:    add     x16, x16, #16
+; MACHO-NEXT:    pacdza  x16
+; MACHO-NEXT:    mov     x0, x16
+; MACHO-NEXT:    ret
 
   ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 16), i32 2)
 }
 
 define ptr @test_global_neg_offset_zero_disc() {
-; CHECK-LABEL: test_global_neg_offset_zero_disc:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, :got:g
-; CHECK-NEXT:    ldr     x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    sub     x16, x16, #576
-; CHECK-NEXT:    sub     x16, x16, #30, lsl #12
-; CHECK-NEXT:    pacdza  x16
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
+; 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:    ret
+
+; MACHO-LABEL: _test_global_neg_offset_zero_disc:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr     x16, [x16, _g at 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:    ret
 
   ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456), i32 2)
 }
 
 define ptr @test_global_big_offset_zero_disc() {
-; CHECK-LABEL: test_global_big_offset_zero_disc:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, :got:g
-; CHECK-NEXT:    ldr     x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    mov     x17, #1
-; CHECK-NEXT:    movk    x17, #32769, lsl #16
-; CHECK-NEXT:    add     x16, x16, x17
-; CHECK-NEXT:    pacdza  x16
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
+; 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:    ret
+
+; MACHO-LABEL: _test_global_big_offset_zero_disc:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr     x16, [x16, _g at 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:    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() {
-; CHECK-LABEL: test_global_big_neg_offset_zero_disc:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, :got:g
-; CHECK-NEXT:    ldr     x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    mov     x17, #-52501
-; CHECK-NEXT:    movk    x17, #63652, lsl #16
-; CHECK-NEXT:    add     x16, x16, x17
-; CHECK-NEXT:    pacdza  x16
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
+; 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:    ret
+
+; MACHO-LABEL: _test_global_big_neg_offset_zero_disc:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr     x16, [x16, _g at 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:    ret
 
   ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456789), i32 2)
 }
 
 define ptr @test_global_huge_neg_offset_zero_disc() {
-; CHECK-LABEL: test_global_huge_neg_offset_zero_disc:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, :got:g
-; CHECK-NEXT:    ldr     x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    mov     x17, #-65536
-; CHECK-NEXT:    movk    x17, #0, lsl #16
-; CHECK-NEXT:    movk    x17, #0, lsl #32
-; CHECK-NEXT:    movk    x17, #32768, lsl #48
-; CHECK-NEXT:    add     x16, x16, x17
-; CHECK-NEXT:    pacdza  x16
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
+; 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:    ret
+
+; MACHO-LABEL: _test_global_huge_neg_offset_zero_disc:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr     x16, [x16, _g at 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:    ret
 
   ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -9223372036854775808), i32 2)
 }
 
 define ptr @test_global_disc() {
-; CHECK-LABEL: test_global_disc:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, :got:g
-; CHECK-NEXT:    ldr     x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    mov     x17, #42 // =0x2a
-; CHECK-NEXT:    pacia   x16, x17
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
+; 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:    ret
+
+; MACHO-LABEL: _test_global_disc:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr     x16, [x16, _g at GOTPAGEOFF]
+; MACHO-NEXT:    mov     x17, #42 ; =0x2a
+; MACHO-NEXT:    pacia   x16, x17
+; MACHO-NEXT:    mov     x0, x16
+; MACHO-NEXT:    ret
 
   ret ptr ptrauth (ptr @g, i32 0, i64 42)
 }
@@ -179,57 +269,123 @@ define ptr @test_global_disc() {
 @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() {
-; CHECK-LABEL: test_global_addr_disc:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp x8, g.ref.da.42.addr
-; CHECK-NEXT:    add x8, x8, :lo12:g.ref.da.42.addr
-; CHECK-NEXT:    adrp x16, :got:g
-; CHECK-NEXT:    ldr x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    mov x17, x8
-; CHECK-NEXT:    movk x17, #42, lsl #48
-; CHECK-NEXT:    pacda x16, x17
-; CHECK-NEXT:    mov x0, x16
-; CHECK-NEXT:    ret
+; 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 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:    ret
+
+; MACHO-LABEL: _test_global_addr_disc:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:   Lloh{{.*}}:
+; MACHO-NEXT:    adrp x8, _g.ref.da.42.addr at PAGE
+; MACHO-NEXT:   Lloh{{.*}}:
+; MACHO-NEXT:    add x8, x8, _g.ref.da.42.addr at PAGEOFF
+; MACHO-NEXT:    adrp x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr x16, [x16, _g at 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:    ret
 
   ret ptr ptrauth (ptr @g, i32 2, i64 42, ptr @g.ref.da.42.addr)
 }
 
 define ptr @test_global_process_specific() {
-; CHECK-LABEL: test_global_process_specific:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, :got:g
-; CHECK-NEXT:    ldr     x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    pacizb  x16
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
+; 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:    ret
+
+; MACHO-LABEL: _test_global_process_specific:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr     x16, [x16, _g at GOTPAGEOFF]
+; MACHO-NEXT:    pacizb  x16
+; MACHO-NEXT:    mov     x0, x16
+; MACHO-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    x16, g_strong_def
+; ELF-NEXT:    add     x16, x16, :lo12:g_strong_def
+; ELF-NEXT:    pacdza  x16
+; ELF-NEXT:    mov     x0, x16
+; ELF-NEXT:    ret
+
+; MACHO-LABEL: _test_global_strong_def:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g_strong_def at PAGE
+; MACHO-NEXT:    add     x16, x16, _g_strong_def at PAGEOFF
+; MACHO-NEXT:    pacdza  x16
+; MACHO-NEXT:    mov     x0, x16
+; MACHO-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() {
-; CHECK-LABEL: test_global_weak:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x0, g_weak$auth_ptr$ia$42
-; CHECK-NEXT:    ldr     x0, [x0, :lo12:g_weak$auth_ptr$ia$42]
-; CHECK-NEXT:    ret
+; 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
+
+; MACHO-LABEL: _test_global_weak:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x0, l_g_weak$auth_ptr$ia$42 at PAGE
+; MACHO-NEXT:    ldr     x0, [x0, l_g_weak$auth_ptr$ia$42 at PAGEOFF]
+; MACHO-NEXT:    ret
+
   ret ptr ptrauth (ptr @g_weak, i32 0, i64 42)
 }
 
-; Non-external symbols don't need to be accessed through the GOT.
+; Test another weak symbol to check that stubs are emitted in a stable order.
 
-define ptr @test_global_strong_def() {
-; CHECK-LABEL: test_global_strong_def:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, g_strong_def
-; CHECK-NEXT:    add     x16, x16, :lo12:g_strong_def
-; CHECK-NEXT:    pacdza  x16
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
-  ret ptr ptrauth (ptr @g_strong_def, i32 2)
+ at 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
+
+; MACHO-LABEL: _test_global_weak_2:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x0, l_g_weak_2$auth_ptr$ia$42 at PAGE
+; MACHO-NEXT:    ldr     x0, [x0, l_g_weak_2$auth_ptr$ia$42 at PAGEOFF]
+; MACHO-NEXT:    ret
+
+  ret ptr ptrauth (ptr @g_weak_2, i32 0, i64 42)
 }
 
-; CHECK-LABEL: g_weak$auth_ptr$ia$42:
-; CHECK-NEXT:    .xword  g_weak at AUTH(ia,42)
+; ELF-LABEL: g_weak$auth_ptr$ia$42:
+; ELF-NEXT:    .xword  g_weak at AUTH(ia,42)
+; ELF-LABEL: g_weak_2$auth_ptr$ia$42:
+; ELF-NEXT:    .xword  g_weak_2 at AUTH(ia,42)
+
+; MACHO-LABEL: l_g_weak$auth_ptr$ia$42:
+; MACHO-NEXT:    .quad  _g_weak at AUTH(ia,42)
+; MACHO-LABEL: l_g_weak_2$auth_ptr$ia$42:
+; MACHO-NEXT:    .quad  _g_weak_2 at AUTH(ia,42)

diff  --git a/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll b/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll
index 73993fa87bf27..76339a7cc5791 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-constant-in-code.ll
@@ -4,6 +4,8 @@
 
 ; 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 arm64-apple-ios -mattr=+pauth \
+; RUN:   -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR1 %s
 
 @g = external global i32
 
@@ -16,6 +18,8 @@ define ptr @foo() {
 
 ; 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 arm64-apple-ios -mattr=+pauth \
+; RUN:   -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR2 %s
 
 @g = external global i32
 
@@ -28,6 +32,8 @@ define ptr @foo() {
 
 ; 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 arm64-apple-ios -mattr=+pauth \
+; RUN:   -global-isel=0 -verify-machineinstrs 2>&1 | FileCheck --check-prefix=ERR3 %s
 
 @g_weak = extern_weak global i32
 
@@ -40,6 +46,8 @@ define ptr @foo() {
 
 ; 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 arm64-apple-ios -mattr=+pauth \
+; 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)
@@ -51,122 +59,198 @@ define ptr @foo() {
 
 ;--- err5.ll
 
-; RUN: not --crash llc < err5.ll -mtriple arm64-apple-darwin -mattr=+pauth \
+; RUN: not --crash llc < err5.ll -mtriple aarch64-windows -mattr=+pauth \
 ; 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 is only implemented for ELF
+; 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
+; 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 arm64-apple-ios -mattr=+pauth -global-isel=0 \
+; RUN:   -verify-machineinstrs | FileCheck %s --check-prefix=MACHO
+; RUN: llc < ok.ll -mtriple arm64-apple-ios -mattr=+pauth -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() {
-; CHECK-LABEL: test_global_zero_disc:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, :got:g
-; CHECK-NEXT:    ldr     x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    paciza  x16
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
+; 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:      ret
+
+; MACHO-LABEL: _test_global_zero_disc:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr     x16, [x16, _g at GOTPAGEOFF]
+; MACHO-NEXT:    paciza  x16
+; MACHO-NEXT:    mov     x0, x16
+; MACHO-NEXT:    ret
 
   ret ptr ptrauth (ptr @g, i32 0)
 }
 
 define ptr @test_global_offset_zero_disc() {
-; CHECK-LABEL: test_global_offset_zero_disc:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, :got:g
-; CHECK-NEXT:    ldr     x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    add     x16, x16, #16
-; CHECK-NEXT:    pacdza  x16
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
+; 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:    ret
+
+; MACHO-LABEL: _test_global_offset_zero_disc:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr     x16, [x16, _g at GOTPAGEOFF]
+; MACHO-NEXT:    add     x16, x16, #16
+; MACHO-NEXT:    pacdza  x16
+; MACHO-NEXT:    mov     x0, x16
+; MACHO-NEXT:    ret
 
   ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 16), i32 2)
 }
 
 define ptr @test_global_neg_offset_zero_disc() {
-; CHECK-LABEL: test_global_neg_offset_zero_disc:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, :got:g
-; CHECK-NEXT:    ldr     x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    sub     x16, x16, #576
-; CHECK-NEXT:    sub     x16, x16, #30, lsl #12
-; CHECK-NEXT:    pacdza  x16
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
+; 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:    ret
+
+; MACHO-LABEL: _test_global_neg_offset_zero_disc:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr     x16, [x16, _g at 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:    ret
 
   ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456), i32 2)
 }
 
 define ptr @test_global_big_offset_zero_disc() {
-; CHECK-LABEL: test_global_big_offset_zero_disc:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, :got:g
-; CHECK-NEXT:    ldr     x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    mov     x17, #1
-; CHECK-NEXT:    movk    x17, #32769, lsl #16
-; CHECK-NEXT:    add     x16, x16, x17
-; CHECK-NEXT:    pacdza  x16
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
+; 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:    ret
+
+; MACHO-LABEL: _test_global_big_offset_zero_disc:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr     x16, [x16, _g at 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:    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() {
-; CHECK-LABEL: test_global_big_neg_offset_zero_disc:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, :got:g
-; CHECK-NEXT:    ldr     x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    mov     x17, #-52501
-; CHECK-NEXT:    movk    x17, #63652, lsl #16
-; CHECK-NEXT:    add     x16, x16, x17
-; CHECK-NEXT:    pacdza  x16
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
+; 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:    ret
+
+; MACHO-LABEL: _test_global_big_neg_offset_zero_disc:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr     x16, [x16, _g at 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:    ret
 
   ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -123456789), i32 2)
 }
 
 define ptr @test_global_huge_neg_offset_zero_disc() {
-; CHECK-LABEL: test_global_huge_neg_offset_zero_disc:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, :got:g
-; CHECK-NEXT:    ldr     x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    mov     x17, #-65536
-; CHECK-NEXT:    movk    x17, #0, lsl #16
-; CHECK-NEXT:    movk    x17, #0, lsl #32
-; CHECK-NEXT:    movk    x17, #32768, lsl #48
-; CHECK-NEXT:    add     x16, x16, x17
-; CHECK-NEXT:    pacdza  x16
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
+; 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:    ret
+
+; MACHO-LABEL: _test_global_huge_neg_offset_zero_disc:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr     x16, [x16, _g at 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:    ret
 
   ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 -9223372036854775808), i32 2)
 }
 
 define ptr @test_global_disc() {
-; CHECK-LABEL: test_global_disc:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, :got:g
-; CHECK-NEXT:    ldr     x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    mov     x17, #42 // =0x2a
-; CHECK-NEXT:    pacia   x16, x17
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
+; 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:    ret
+
+; MACHO-LABEL: _test_global_disc:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr     x16, [x16, _g at GOTPAGEOFF]
+; MACHO-NEXT:    mov     x17, #42 ; =0x2a
+; MACHO-NEXT:    pacia   x16, x17
+; MACHO-NEXT:    mov     x0, x16
+; MACHO-NEXT:    ret
 
   ret ptr ptrauth (ptr @g, i32 0, i64 42)
 }
@@ -174,57 +258,123 @@ define ptr @test_global_disc() {
 @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() {
-; CHECK-LABEL: test_global_addr_disc:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp x8, g.ref.da.42.addr
-; CHECK-NEXT:    add x8, x8, :lo12:g.ref.da.42.addr
-; CHECK-NEXT:    adrp x16, :got:g
-; CHECK-NEXT:    ldr x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    mov x17, x8
-; CHECK-NEXT:    movk x17, #42, lsl #48
-; CHECK-NEXT:    pacda x16, x17
-; CHECK-NEXT:    mov x0, x16
-; CHECK-NEXT:    ret
+; 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 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:    ret
+
+; MACHO-LABEL: _test_global_addr_disc:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:   Lloh{{.*}}:
+; MACHO-NEXT:    adrp x8, _g.ref.da.42.addr at PAGE
+; MACHO-NEXT:   Lloh{{.*}}:
+; MACHO-NEXT:    add x8, x8, _g.ref.da.42.addr at PAGEOFF
+; MACHO-NEXT:    adrp x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr x16, [x16, _g at 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:    ret
 
   ret ptr ptrauth (ptr @g, i32 2, i64 42, ptr @g.ref.da.42.addr)
 }
 
 define ptr @test_global_process_specific() {
-; CHECK-LABEL: test_global_process_specific:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, :got:g
-; CHECK-NEXT:    ldr     x16, [x16, :got_lo12:g]
-; CHECK-NEXT:    pacizb  x16
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
+; 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:    ret
+
+; MACHO-LABEL: _test_global_process_specific:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g at GOTPAGE
+; MACHO-NEXT:    ldr     x16, [x16, _g at GOTPAGEOFF]
+; MACHO-NEXT:    pacizb  x16
+; MACHO-NEXT:    mov     x0, x16
+; MACHO-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    x16, g_strong_def
+; ELF-NEXT:    add     x16, x16, :lo12:g_strong_def
+; ELF-NEXT:    pacdza  x16
+; ELF-NEXT:    mov     x0, x16
+; ELF-NEXT:    ret
+
+; MACHO-LABEL: _test_global_strong_def:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x16, _g_strong_def at PAGE
+; MACHO-NEXT:    add     x16, x16, _g_strong_def at PAGEOFF
+; MACHO-NEXT:    pacdza  x16
+; MACHO-NEXT:    mov     x0, x16
+; MACHO-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() {
-; CHECK-LABEL: test_global_weak:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x0, g_weak$auth_ptr$ia$42
-; CHECK-NEXT:    ldr     x0, [x0, :lo12:g_weak$auth_ptr$ia$42]
-; CHECK-NEXT:    ret
+; 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
+
+; MACHO-LABEL: _test_global_weak:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x0, l_g_weak$auth_ptr$ia$42 at PAGE
+; MACHO-NEXT:    ldr     x0, [x0, l_g_weak$auth_ptr$ia$42 at PAGEOFF]
+; MACHO-NEXT:    ret
+
   ret ptr ptrauth (ptr @g_weak, i32 0, i64 42)
 }
 
-; Non-external symbols don't need to be accessed through the GOT.
+; Test another weak symbol to check that stubs are emitted in a stable order.
 
-define ptr @test_global_strong_def() {
-; CHECK-LABEL: test_global_strong_def:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    adrp    x16, g_strong_def
-; CHECK-NEXT:    add     x16, x16, :lo12:g_strong_def
-; CHECK-NEXT:    pacdza  x16
-; CHECK-NEXT:    mov     x0, x16
-; CHECK-NEXT:    ret
-  ret ptr ptrauth (ptr @g_strong_def, i32 2)
+ at 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
+
+; MACHO-LABEL: _test_global_weak_2:
+; MACHO:       ; %bb.0:
+; MACHO-NEXT:    adrp    x0, l_g_weak_2$auth_ptr$ia$42 at PAGE
+; MACHO-NEXT:    ldr     x0, [x0, l_g_weak_2$auth_ptr$ia$42 at PAGEOFF]
+; MACHO-NEXT:    ret
+
+  ret ptr ptrauth (ptr @g_weak_2, i32 0, i64 42)
 }
 
-; CHECK-LABEL: g_weak$auth_ptr$ia$42:
-; CHECK-NEXT:    .xword  g_weak at AUTH(ia,42)
+; ELF-LABEL: g_weak$auth_ptr$ia$42:
+; ELF-NEXT:    .xword  g_weak at AUTH(ia,42)
+; ELF-LABEL: g_weak_2$auth_ptr$ia$42:
+; ELF-NEXT:    .xword  g_weak_2 at AUTH(ia,42)
+
+; MACHO-LABEL: l_g_weak$auth_ptr$ia$42:
+; MACHO-NEXT:    .quad  _g_weak at AUTH(ia,42)
+; MACHO-LABEL: l_g_weak_2$auth_ptr$ia$42:
+; MACHO-NEXT:    .quad  _g_weak_2 at AUTH(ia,42)


        


More information about the llvm-commits mailing list