[llvm] [PAC][CodeGen][ELF][AArch64] Support signed GOT with tiny code model (PR #114525)

Daniil Kovalev via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 1 02:30:21 PDT 2024


https://github.com/kovdan01 created https://github.com/llvm/llvm-project/pull/114525

Support the following relocations and assembly operators:

- `R_AARCH64_AUTH_GOT_ADR_PREL_LO21` (`:got_auth:` for `adr`)
- `R_AARCH64_AUTH_GOT_LD_PREL19` (`:got_auth:` for `ldr`)

`LOADgotAUTH` pseudo-instruction is expanded to actual instruction sequence like the following.

```
adr x16, :got_auth:sym
ldr x0, [x16]
autia x0, x16
```

Both SelectionDAG and GlobalISel are suppported. For FastISel, we fall back to SelectionDAG.

Tests starting with 'ptrauth-' have corresponding variants w/o this prefix.

>From 2bde6a50a2c168bed56874c2406115ea75102875 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev <dkovalev at accesssoftek.com>
Date: Sun, 27 Oct 2024 17:23:17 +0300
Subject: [PATCH] [PAC][CodeGen][ELF][AArch64] Support signed GOT with tiny
 code model

Support the following relocations and assembly operators:

- `R_AARCH64_AUTH_GOT_ADR_PREL_LO21` (`:got_auth:` for `adr`)
- `R_AARCH64_AUTH_GOT_LD_PREL19` (`:got_auth:` for `ldr`)

`LOADgotAUTH` pseudo-instruction is expanded to actual instruction
sequence like the following.

```
adr x16, :got_auth:sym
ldr x0, [x16]
autia x0, x16
```

Both SelectionDAG and GlobalISel are suppported. For FastISel, we fall
back to SelectionDAG.

Tests starting with 'ptrauth-' have corresponding variants w/o this prefix.
---
 llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp |  47 +++--
 .../AArch64/AsmParser/AArch64AsmParser.cpp    |   8 +-
 .../MCTargetDesc/AArch64ELFObjectWriter.cpp   |  18 ++
 .../CodeGen/AArch64/ptrauth-extern-weak.ll    |  42 ++++
 .../CodeGen/AArch64/ptrauth-tiny-model-pic.ll | 182 ++++++++++++++++++
 .../AArch64/ptrauth-tiny-model-static.ll      | 157 +++++++++++++++
 llvm/test/MC/AArch64/arm64-elf-relocs.s       |  13 ++
 llvm/test/MC/AArch64/ilp32-diagnostics.s      |   6 +
 8 files changed, 454 insertions(+), 19 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/ptrauth-tiny-model-pic.ll
 create mode 100644 llvm/test/CodeGen/AArch64/ptrauth-tiny-model-static.ll

diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index e79457f925db66..2a3161a5c6b704 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -2277,28 +2277,39 @@ void AArch64AsmPrinter::LowerLOADgotAUTH(const MachineInstr &MI) {
   const MachineOperand &GAMO = MI.getOperand(1);
   assert(GAMO.getOffset() == 0);
 
-  MachineOperand GAHiOp(GAMO);
-  MachineOperand GALoOp(GAMO);
-  GAHiOp.addTargetFlag(AArch64II::MO_PAGE);
-  GALoOp.addTargetFlag(AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
+  if (MI.getMF()->getTarget().getCodeModel() == CodeModel::Tiny) {
+    MCOperand GAMC;
+    MCInstLowering.lowerOperand(GAMO, GAMC);
+    EmitToStreamer(
+        MCInstBuilder(AArch64::ADR).addReg(AArch64::X17).addOperand(GAMC));
+    EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
+                       .addReg(AuthResultReg)
+                       .addReg(AArch64::X17)
+                       .addImm(0));
+  } else {
+    MachineOperand GAHiOp(GAMO);
+    MachineOperand GALoOp(GAMO);
+    GAHiOp.addTargetFlag(AArch64II::MO_PAGE);
+    GALoOp.addTargetFlag(AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
 
-  MCOperand GAMCHi, GAMCLo;
-  MCInstLowering.lowerOperand(GAHiOp, GAMCHi);
-  MCInstLowering.lowerOperand(GALoOp, GAMCLo);
+    MCOperand GAMCHi, GAMCLo;
+    MCInstLowering.lowerOperand(GAHiOp, GAMCHi);
+    MCInstLowering.lowerOperand(GALoOp, GAMCLo);
 
-  EmitToStreamer(
-      MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).addOperand(GAMCHi));
+    EmitToStreamer(
+        MCInstBuilder(AArch64::ADRP).addReg(AArch64::X17).addOperand(GAMCHi));
 
-  EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
-                     .addReg(AArch64::X17)
-                     .addReg(AArch64::X17)
-                     .addOperand(GAMCLo)
-                     .addImm(0));
+    EmitToStreamer(MCInstBuilder(AArch64::ADDXri)
+                       .addReg(AArch64::X17)
+                       .addReg(AArch64::X17)
+                       .addOperand(GAMCLo)
+                       .addImm(0));
 
-  EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
-                     .addReg(AuthResultReg)
-                     .addReg(AArch64::X17)
-                     .addImm(0));
+    EmitToStreamer(MCInstBuilder(AArch64::LDRXui)
+                       .addReg(AuthResultReg)
+                       .addReg(AArch64::X17)
+                       .addImm(0));
+  }
 
   assert(GAMO.isGlobal());
   MCSymbol *UndefWeakSym;
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 712f6de52941c9..4a792f7bddb220 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -3354,7 +3354,13 @@ ParseStatus AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
       // No modifier was specified at all; this is the syntax for an ELF basic
       // ADR relocation (unfortunately).
       Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS, getContext());
-    } else {
+    } else if (ELFRefKind != AArch64MCExpr::VK_GOT_AUTH_PAGE) {
+      // For tiny code model, we use :got_auth: operator to fill 21-bit imm of
+      // adr. It's not actually GOT entry page address but the GOT address
+      // itself - we just share the same variant kind with :got_auth: operator
+      // applied for adrp.
+      // TODO: can we somehow get current TargetMachine object to call
+      // getCodeModel() on it to ensure we are using tiny code model?
       return Error(S, "unexpected adr label");
     }
   }
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
index b5f5a58d96288e..04f90e21bb3b1f 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
@@ -147,6 +147,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
       }
       return ELF::R_AARCH64_PREL64;
     case AArch64::fixup_aarch64_pcrel_adr_imm21:
+      if (SymLoc == AArch64MCExpr::VK_GOT_AUTH) {
+        if (IsILP32) {
+          Ctx.reportError(Fixup.getLoc(),
+                          "ILP32 ADR AUTH relocation not supported "
+                          "(LP64 eqv: AUTH_GOT_ADR_PREL_LO21)");
+          return ELF::R_AARCH64_NONE;
+        }
+        return ELF::R_AARCH64_AUTH_GOT_ADR_PREL_LO21;
+      }
       if (SymLoc != AArch64MCExpr::VK_ABS)
         Ctx.reportError(Fixup.getLoc(),
                         "invalid symbol kind for ADR relocation");
@@ -190,6 +199,15 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
         return R_CLS(TLSIE_LD_GOTTPREL_PREL19);
       if (SymLoc == AArch64MCExpr::VK_GOT)
         return R_CLS(GOT_LD_PREL19);
+      if (SymLoc == AArch64MCExpr::VK_GOT_AUTH) {
+        if (IsILP32) {
+          Ctx.reportError(Fixup.getLoc(),
+                          "ILP32 LDR AUTH relocation not supported "
+                          "(LP64 eqv: AUTH_GOT_LD_PREL19)");
+          return ELF::R_AARCH64_NONE;
+        }
+        return ELF::R_AARCH64_AUTH_GOT_LD_PREL19;
+      }
       return R_CLS(LD_PREL_LO19);
     case AArch64::fixup_aarch64_pcrel_branch14:
       return R_CLS(TSTBR14);
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll b/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll
index 5d0a3f556c4c2e..141af917fa3e2c 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-extern-weak.ll
@@ -13,6 +13,11 @@
 ; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel=1 -global-isel-abort=1 -relocation-model=pic \
 ; RUN:   -mattr=+pauth              -o - %s | FileCheck --check-prefixes=CHECK,TRAP %s
 
+; RUN: llc -mtriple=aarch64-none-linux-gnu -code-model=tiny -mattr=+pauth -mattr=+fpac -o - %s | \
+; RUN:   FileCheck --check-prefixes=CHECK-TINY,NOTRAP-TINY %s
+; RUN: llc -mtriple=aarch64-none-linux-gnu -code-model=tiny -mattr=+pauth              -o - %s | \
+; RUN:   FileCheck --check-prefixes=CHECK-TINY,TRAP-TINY %s
+
 ;; Note: for FastISel, we fall back to SelectionDAG
 
 declare extern_weak dso_local i32 @var()
@@ -41,6 +46,24 @@ define ptr @foo() {
 ; TRAP-NEXT:   .Lauth_success_0:
 ; TRAP-NEXT:     mov   x0,  x16
 ; CHECK-NEXT:    ret
+
+; CHECK-TINY-LABEL: foo:
+; CHECK-TINY:         adr   x17, :got_auth:var
+; NOTRAP-TINY-NEXT:   ldr   x0,  [x17]
+; NOTRAP-TINY-NEXT:   cbz   x0,  .Lundef_weak0
+; NOTRAP-TINY-NEXT:   autia x0,  x17
+; TRAP-TINY-NEXT:     ldr   x16, [x17]
+; TRAP-TINY-NEXT:     cbz   x16, .Lundef_weak0
+; TRAP-TINY-NEXT:     autia x16, x17
+; CHECK-TINY-NEXT:  .Lundef_weak0:
+; TRAP-TINY-NEXT:     mov   x17, x16
+; TRAP-TINY-NEXT:     xpaci x17
+; TRAP-TINY-NEXT:     cmp   x16, x17
+; TRAP-TINY-NEXT:     b.eq  .Lauth_success_0
+; TRAP-TINY-NEXT:     brk   #0xc470
+; TRAP-TINY-NEXT:   .Lauth_success_0:
+; TRAP-TINY-NEXT:     mov   x0,  x16
+; CHECK-TINY-NEXT:    ret
 }
 
 @arr_var = extern_weak global [10 x i32]
@@ -68,6 +91,25 @@ define ptr @bar() {
 ; TRAP-NEXT:     mov   x8,  x16
 ; CHECK-NEXT:    add   x0,  x8, #20
 ; CHECK-NEXT:    ret
+
+; CHECK-TINY-LABEL: bar:
+; CHECK-TINY:         adr   x17, :got_auth:arr_var
+; NOTRAP-TINY-NEXT:   ldr   x8,  [x17]
+; NOTRAP-TINY-NEXT:   cbz   x8,  .Lundef_weak1
+; NOTRAP-TINY-NEXT:   autda x8,  x17
+; TRAP-TINY-NEXT:     ldr   x16, [x17]
+; TRAP-TINY-NEXT:     cbz   x16, .Lundef_weak1
+; TRAP-TINY-NEXT:     autda x16, x17
+; CHECK-TINY-NEXT:  .Lundef_weak1:
+; TRAP-TINY-NEXT:     mov   x17, x16
+; TRAP-TINY-NEXT:     xpacd x17
+; TRAP-TINY-NEXT:     cmp   x16, x17
+; TRAP-TINY-NEXT:     b.eq  .Lauth_success_1
+; TRAP-TINY-NEXT:     brk   #0xc472
+; TRAP-TINY-NEXT:   .Lauth_success_1:
+; TRAP-TINY-NEXT:     mov   x8,  x16
+; CHECK-TINY-NEXT:    add   x0,  x8, #20
+; CHECK-TINY-NEXT:    ret
 }
 
 !llvm.module.flags = !{!0}
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-pic.ll b/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-pic.ll
new file mode 100644
index 00000000000000..93b21c93418a64
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-pic.ll
@@ -0,0 +1,182 @@
+; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -mattr=+fpac -code-model=tiny \
+; RUN:   -relocation-model=pic < %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
+; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth              -code-model=tiny \
+; RUN:   -relocation-model=pic < %s | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -mattr=+fpac -code-model=tiny \
+; RUN:   -relocation-model=pic -fast-isel < %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
+; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth              -code-model=tiny \
+; RUN:   -relocation-model=pic -fast-isel < %s | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth -mattr=+fpac -code-model=tiny \
+; RUN:   -relocation-model=pic -global-isel -global-isel-abort=1 < %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
+; RUN: llc -verify-machineinstrs -mtriple=aarch64 -mattr=+pauth              -code-model=tiny \
+; RUN:   -relocation-model=pic -global-isel -global-isel-abort=1 < %s | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; Note: fast-isel tests here will fall back to isel
+
+ at src = external local_unnamed_addr global [65536 x i8], align 1
+ at dst = external global [65536 x i8], align 1
+ at ptr = external local_unnamed_addr global ptr, align 8
+
+define dso_preemptable void @foo1() {
+; CHECK-LABEL: foo1:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    adr   x17, :got_auth:src
+; 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:    ldrb  w8,  [x8]
+; CHECK-NEXT:    adr   x17, :got_auth:dst
+; NOTRAP-NEXT:   ldr   x9,  [x17]
+; NOTRAP-NEXT:   autda x9,  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   x9, x16
+; CHECK-NEXT:    strb  w8,  [x9]
+; CHECK-NEXT:    ret
+
+entry:
+  %0 = load i8, ptr @src, align 1
+  store i8 %0, ptr @dst, align 1
+  ret void
+}
+
+define dso_preemptable void @foo2() {
+; CHECK-LABEL: foo2:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    adr   x17, :got_auth:ptr
+; 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_2
+; TRAP-NEXT:     brk   #0xc472
+; TRAP-NEXT:   .Lauth_success_2:
+; TRAP-NEXT:     mov   x8, x16
+; CHECK-NEXT:    adr   x17, :got_auth:dst
+; NOTRAP-NEXT:   ldr   x9,  [x17]
+; NOTRAP-NEXT:   autda x9,  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_3
+; TRAP-NEXT:     brk   #0xc472
+; TRAP-NEXT:   .Lauth_success_3:
+; TRAP-NEXT:     mov   x9, x16
+; CHECK-NEXT:    str   x9,  [x8]
+; CHECK-NEXT:    ret
+
+entry:
+  store ptr @dst, ptr @ptr, align 8
+  ret void
+}
+
+define dso_preemptable void @foo3() {
+; CHECK-LABEL: foo3:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    adr   x17, :got_auth:src
+; 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_4
+; TRAP-NEXT:     brk   #0xc472
+; TRAP-NEXT:   .Lauth_success_4:
+; TRAP-NEXT:     mov   x8, x16
+; CHECK-NEXT:    ldrb  w8,  [x8]
+; CHECK-NEXT:    adr   x17, :got_auth:ptr
+; NOTRAP-NEXT:   ldr   x9,  [x17]
+; NOTRAP-NEXT:   autda x9,  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_5
+; TRAP-NEXT:     brk   #0xc472
+; TRAP-NEXT:   .Lauth_success_5:
+; TRAP-NEXT:     mov   x9, x16
+; CHECK-NEXT:    ldr   x9,  [x9]
+; CHECK-NEXT:    strb  w8,  [x9]
+; CHECK-NEXT:    ret
+
+entry:
+  %0 = load i8, ptr @src, align 1
+  %1 = load ptr, ptr @ptr, align 8
+  store i8 %0, ptr %1, align 1
+  ret void
+}
+
+ at lsrc = internal global i8 0, align 4
+ at ldst = internal global i8 0, align 4
+ at lptr = internal global ptr null, align 8
+
+declare void @func(...)
+
+define dso_preemptable ptr @externfuncaddr() {
+; CHECK-LABEL: externfuncaddr:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    adr   x17, :got_auth:func
+; NOTRAP-NEXT:   ldr   x0,  [x17]
+; NOTRAP-NEXT:   autia x0,  x17
+; TRAP-NEXT:     ldr   x16, [x17]
+; TRAP-NEXT:     autia x16, x17
+; TRAP-NEXT:     mov   x17, x16
+; TRAP-NEXT:     xpaci x17
+; TRAP-NEXT:     cmp   x16, x17
+; TRAP-NEXT:     b.eq  .Lauth_success_6
+; TRAP-NEXT:     brk   #0xc470
+; TRAP-NEXT:   .Lauth_success_6:
+; TRAP-NEXT:     mov   x0, x16
+; CHECK-NEXT:    ret
+
+entry:
+  ret ptr @func
+}
+
+define dso_preemptable ptr @localfuncaddr() {
+; CHECK-LABEL: localfuncaddr:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    adr   x17, :got_auth:externfuncaddr
+; NOTRAP-NEXT:   ldr   x0,  [x17]
+; NOTRAP-NEXT:   autia x0,  x17
+; TRAP-NEXT:     ldr   x16, [x17]
+; TRAP-NEXT:     autia x16, x17
+; TRAP-NEXT:     mov   x17, x16
+; TRAP-NEXT:     xpaci x17
+; TRAP-NEXT:     cmp   x16, x17
+; TRAP-NEXT:     b.eq  .Lauth_success_7
+; TRAP-NEXT:     brk   #0xc470
+; TRAP-NEXT:   .Lauth_success_7:
+; TRAP-NEXT:     mov   x0, x16
+; CHECK-NEXT:    ret
+
+entry:
+  ret ptr @externfuncaddr
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 8, !"ptrauth-elf-got", i32 1}
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-static.ll b/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-static.ll
new file mode 100644
index 00000000000000..2d098b70accccc
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ptrauth-tiny-model-static.ll
@@ -0,0 +1,157 @@
+; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth -mattr=+fpac \
+; RUN:   -code-model=tiny < %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
+; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth \
+; RUN:   -code-model=tiny < %s | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth -mattr=+fpac \
+; RUN:   -code-model=tiny -fast-isel < %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
+; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth \
+; RUN:   -code-model=tiny -fast-isel < %s | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth -mattr=+fpac \
+; RUN:   -code-model=tiny -global-isel -global-isel-abort=1 < %s | FileCheck --check-prefixes=CHECK,NOTRAP %s
+; RUN: llc -verify-machineinstrs -o - -mtriple=aarch64-none-linux-gnu -mattr=+pauth \
+; RUN:   -code-model=tiny -global-isel -global-isel-abort=1 < %s | FileCheck --check-prefixes=CHECK,TRAP %s
+
+; Note fast-isel tests here will fall back to isel
+
+ at src = external local_unnamed_addr global [65536 x i8], align 1
+ at dst = external global [65536 x i8], align 1
+ at ptr = external local_unnamed_addr global ptr, align 8
+
+define dso_local void @foo1() {
+; CHECK-LABEL: foo1:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    adr   x17, :got_auth:src
+; 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:    ldrb  w8,  [x8]
+; CHECK-NEXT:    adr   x17, :got_auth:dst
+; NOTRAP-NEXT:   ldr   x9,  [x17]
+; NOTRAP-NEXT:   autda x9,  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   x9,  x16
+; CHECK-NEXT:    strb  w8,  [x9]
+; CHECK-NEXT:    ret
+
+entry:
+  %0 = load i8, ptr @src, align 1
+  store i8 %0, ptr @dst, align 1
+  ret void
+}
+
+define dso_local void @foo2() {
+; CHECK-LABEL: foo2:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    adr   x17, :got_auth:ptr
+; 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_2
+; TRAP-NEXT:     brk   #0xc472
+; TRAP-NEXT:   .Lauth_success_2:
+; TRAP-NEXT:     mov   x8,  x16
+; CHECK-NEXT:    adr   x17, :got_auth:dst
+; NOTRAP-NEXT:   ldr   x9,  [x17]
+; NOTRAP-NEXT:   autda x9,  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_3
+; TRAP-NEXT:     brk   #0xc472
+; TRAP-NEXT:   .Lauth_success_3:
+; TRAP-NEXT:     mov   x9,  x16
+; CHECK-NEXT:    str   x9,  [x8]
+; CHECK-NEXT:    ret
+
+entry:
+  store ptr @dst, ptr @ptr, align 8
+  ret void
+}
+
+define dso_local void @foo3() {
+; CHECK-LABEL: foo3:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    adr   x17, :got_auth:src
+; 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_4
+; TRAP-NEXT:     brk   #0xc472
+; TRAP-NEXT:   .Lauth_success_4:
+; TRAP-NEXT:     mov   x8,  x16
+; CHECK-NEXT:    ldrb  w8,  [x8]
+; CHECK-NEXT:    adr   x17, :got_auth:ptr
+; NOTRAP-NEXT:   ldr   x9,  [x17]
+; NOTRAP-NEXT:   autda x9,  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_5
+; TRAP-NEXT:     brk   #0xc472
+; TRAP-NEXT:   .Lauth_success_5:
+; TRAP-NEXT:     mov   x9,  x16
+; CHECK-NEXT:    ldr   x9,  [x9]
+; CHECK-NEXT:    strb  w8,  [x9]
+; CHECK-NEXT:    ret
+
+entry:
+  %0 = load i8, ptr @src, align 1
+  %1 = load ptr, ptr @ptr, align 8
+  store i8 %0, ptr %1, align 1
+  ret void
+}
+
+declare void @func(...)
+
+define dso_local ptr @externfuncaddr() {
+; CHECK-LABEL: externfuncaddr:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    adr   x17, :got_auth:func
+; NOTRAP-NEXT:   ldr   x0,  [x17]
+; NOTRAP-NEXT:   autia x0,  x17
+; TRAP-NEXT:     ldr   x16, [x17]
+; TRAP-NEXT:     autia x16, x17
+; TRAP-NEXT:     mov   x17, x16
+; TRAP-NEXT:     xpaci x17
+; TRAP-NEXT:     cmp   x16, x17
+; TRAP-NEXT:     b.eq  .Lauth_success_6
+; TRAP-NEXT:     brk   #0xc470
+; TRAP-NEXT:   .Lauth_success_6:
+; TRAP-NEXT:     mov   x0,  x16
+; CHECK-NEXT:    ret
+
+entry:
+  ret ptr @func
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 8, !"ptrauth-elf-got", i32 1}
diff --git a/llvm/test/MC/AArch64/arm64-elf-relocs.s b/llvm/test/MC/AArch64/arm64-elf-relocs.s
index f679bb4c82827b..5c04e899a7b22e 100644
--- a/llvm/test/MC/AArch64/arm64-elf-relocs.s
+++ b/llvm/test/MC/AArch64/arm64-elf-relocs.s
@@ -331,6 +331,19 @@ trickQuestion:
 // CHECK-OBJ-LP64: R_AARCH64_GOT_LD_PREL19 sym
 // CHECK-OBJ-LP64: R_AARCH64_GOT_LD_PREL19 sym
 
+   adr x24, #:got_auth:sym
+   adr x24, :got_auth:sym
+   ldr x24, #:got_auth:sym
+   ldr x24, :got_auth:sym
+// CHECK: adr x24, :got_auth:sym
+// CHECK: adr x24, :got_auth:sym
+// CHECK: ldr x24, :got_auth:sym
+// CHECK: ldr x24, :got_auth:sym
+// CHECK-OBJ-LP64: R_AARCH64_AUTH_GOT_ADR_PREL_LO21 sym
+// CHECK-OBJ-LP64: R_AARCH64_AUTH_GOT_ADR_PREL_LO21 sym
+// CHECK-OBJ-LP64: R_AARCH64_AUTH_GOT_LD_PREL19 sym
+// CHECK-OBJ-LP64: R_AARCH64_AUTH_GOT_LD_PREL19 sym
+
 // GOT relocations referencing local symbols are not converted to reference
 // STT_SECTION symbols. https://github.com/llvm/llvm-project/issues/63418
   ldr x0, [x0, :got_lo12:local0]
diff --git a/llvm/test/MC/AArch64/ilp32-diagnostics.s b/llvm/test/MC/AArch64/ilp32-diagnostics.s
index 5d9c6e5626b2b3..cf50188ec8ae60 100644
--- a/llvm/test/MC/AArch64/ilp32-diagnostics.s
+++ b/llvm/test/MC/AArch64/ilp32-diagnostics.s
@@ -87,3 +87,9 @@ ldr x24, [x23, #:got_lo12:sym]
 
 ldr x24, [x23, :gottprel_lo12:sym]
 // ERROR: [[#@LINE-1]]:1: error: ILP32 64-bit load/store relocation not supported (LP64 eqv: TLSIE_LD64_GOTTPREL_LO12_NC)
+
+ldr x24, :got_auth:sym
+// ERROR: error: ILP32 LDR AUTH relocation not supported (LP64 eqv: AUTH_GOT_LD_PREL19)
+
+adr x24, :got_auth:sym
+// ERROR: error: ILP32 ADR AUTH relocation not supported (LP64 eqv: AUTH_GOT_ADR_PREL_LO21)



More information about the llvm-commits mailing list