[llvm] [AArch64] Handle inttoptr+add+ptrtoint pattern in lowerConstantPtrAuth (PR #189474)
Oskar Wirga via llvm-commits
llvm-commits at lists.llvm.org
Sun Apr 5 16:56:03 PDT 2026
https://github.com/oskarwirga updated https://github.com/llvm/llvm-project/pull/189474
>From 7bbedfbbeaf2c6740b84fa546cfe88d38466017f Mon Sep 17 00:00:00 2001
From: Oskar Wirga <oskar.wirga at gmail.com>
Date: Thu, 26 Mar 2026 10:40:18 -0700
Subject: [PATCH 1/5] [AArch64] Handle inttoptr+add+ptrtoint pattern in
lowerConstantPtrAuth
Enable LookThroughIntToPtr on stripAndAccumulateConstantOffsets so
that Swift's inttoptr(add(ptrtoint(@global), offset)) pattern inside
ptrauth constants is handled correctly. Without this, the base global
is not resolved and the constant is emitted as a bare integer.
---
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 6 +++++-
llvm/test/CodeGen/AArch64/ptrauth-reloc.ll | 14 ++++++++++++++
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 2b8db27599d3c..47281791ff7a0 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -2680,9 +2680,13 @@ AArch64AsmPrinter::lowerConstantPtrAuth(const ConstantPtrAuth &CPA) {
MCContext &Ctx = OutContext;
// Figure out the base symbol and the addend, if any.
+ // LookThroughIntToPtr handles Swift patterns like:
+ // inttoptr (i64 add (i64 ptrtoint (ptr @global to i64), i64 2) to ptr)
APInt Offset(64, 0);
const Value *BaseGV = CPA.getPointer()->stripAndAccumulateConstantOffsets(
- getDataLayout(), Offset, /*AllowNonInbounds=*/true);
+ getDataLayout(), Offset, /*AllowNonInbounds=*/true,
+ /*AllowInvariantGroup=*/false, /*ExternalAnalysis=*/nullptr,
+ /*LookThroughIntToPtr=*/true);
auto *BaseGVB = dyn_cast<GlobalValue>(BaseGV);
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll b/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll
index 14f5571fc2deb..befb726bcdab8 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll
@@ -113,6 +113,20 @@
@g.weird_ref.da.0 = constant i64 ptrtoint (ptr inttoptr (i64 ptrtoint (ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 16), i32 2) to i64) to ptr) to i64)
+; Swift generates inttoptr(add(ptrtoint(@global), offset)) inside ptrauth.
+
+; CHECK-ELF-LABEL: .globl g.inttoptr_add.da.0
+; CHECK-ELF-NEXT: .p2align 3
+; CHECK-ELF-NEXT: g.inttoptr_add.da.0:
+; CHECK-ELF-NEXT: .xword (g+2)@AUTH(da,0)
+
+; CHECK-MACHO-LABEL: .globl _g.inttoptr_add.da.0
+; CHECK-MACHO-NEXT: .p2align 3
+; CHECK-MACHO-NEXT: _g.inttoptr_add.da.0:
+; CHECK-MACHO-NEXT: .quad (_g+2)@AUTH(da,0)
+
+ at g.inttoptr_add.da.0 = constant ptr ptrauth (ptr inttoptr (i64 add (i64 ptrtoint (ptr @g to i64), i64 2) to ptr), i32 2)
+
; CHECK-ELF-LABEL: .globl g_weak.ref.ia.42
; CHECK-ELF-NEXT: .p2align 3
; CHECK-ELF-NEXT: g_weak.ref.ia.42:
>From 4e4071b0b3dae4301de30711acddb943a1d5d884 Mon Sep 17 00:00:00 2001
From: Oskar Wirga <oskar.wirga at gmail.com>
Date: Thu, 26 Mar 2026 10:40:18 -0700
Subject: [PATCH 2/5] [AArch64] Handle inttoptr+add+ptrtoint pattern in
lowerConstantPtrAuth
Enable LookThroughIntToPtr on stripAndAccumulateConstantOffsets so
that Swift's inttoptr(add(ptrtoint(@global), offset)) pattern inside
ptrauth constants is handled correctly. Without this, the base global
is not resolved and the constant is miscompiled.
Also replace the silent fallback for unresolved base values with
reportFatalUsageError to catch future unsupported constant expression
forms.
---
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 8 ++++++--
llvm/test/CodeGen/AArch64/ptrauth-reloc.ll | 14 ++++++++++++++
2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 2b8db27599d3c..e6652ef374e73 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -2680,9 +2680,13 @@ AArch64AsmPrinter::lowerConstantPtrAuth(const ConstantPtrAuth &CPA) {
MCContext &Ctx = OutContext;
// Figure out the base symbol and the addend, if any.
+ // LookThroughIntToPtr handles Swift patterns like:
+ // inttoptr (i64 add (i64 ptrtoint (ptr @global to i64), i64 2) to ptr)
APInt Offset(64, 0);
const Value *BaseGV = CPA.getPointer()->stripAndAccumulateConstantOffsets(
- getDataLayout(), Offset, /*AllowNonInbounds=*/true);
+ getDataLayout(), Offset, /*AllowNonInbounds=*/true,
+ /*AllowInvariantGroup=*/false, /*ExternalAnalysis=*/nullptr,
+ /*LookThroughIntToPtr=*/true);
auto *BaseGVB = dyn_cast<GlobalValue>(BaseGV);
@@ -2697,7 +2701,7 @@ AArch64AsmPrinter::lowerConstantPtrAuth(const ConstantPtrAuth &CPA) {
Sym = MCBinaryExpr::createSub(
Sym, MCConstantExpr::create((-Offset).getSExtValue(), Ctx), Ctx);
} else {
- Sym = MCConstantExpr::create(Offset.getSExtValue(), Ctx);
+ reportFatalUsageError("unsupported constant expression in ptrauth pointer");
}
const MCExpr *DSExpr = nullptr;
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll b/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll
index 14f5571fc2deb..befb726bcdab8 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll
@@ -113,6 +113,20 @@
@g.weird_ref.da.0 = constant i64 ptrtoint (ptr inttoptr (i64 ptrtoint (ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 16), i32 2) to i64) to ptr) to i64)
+; Swift generates inttoptr(add(ptrtoint(@global), offset)) inside ptrauth.
+
+; CHECK-ELF-LABEL: .globl g.inttoptr_add.da.0
+; CHECK-ELF-NEXT: .p2align 3
+; CHECK-ELF-NEXT: g.inttoptr_add.da.0:
+; CHECK-ELF-NEXT: .xword (g+2)@AUTH(da,0)
+
+; CHECK-MACHO-LABEL: .globl _g.inttoptr_add.da.0
+; CHECK-MACHO-NEXT: .p2align 3
+; CHECK-MACHO-NEXT: _g.inttoptr_add.da.0:
+; CHECK-MACHO-NEXT: .quad (_g+2)@AUTH(da,0)
+
+ at g.inttoptr_add.da.0 = constant ptr ptrauth (ptr inttoptr (i64 add (i64 ptrtoint (ptr @g to i64), i64 2) to ptr), i32 2)
+
; CHECK-ELF-LABEL: .globl g_weak.ref.ia.42
; CHECK-ELF-NEXT: .p2align 3
; CHECK-ELF-NEXT: g_weak.ref.ia.42:
>From 9dfc2dad32f480e0eb59d6a91cc8e502b2876644 Mon Sep 17 00:00:00 2001
From: Oskar Wirga <oskar.wirga at gmail.com>
Date: Mon, 30 Mar 2026 14:55:49 -0700
Subject: [PATCH 3/5] Only error on unresolved ConstantExpr, not integer/null
constants
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
ptrauth(ptr null, ...) is legitimate — the base is a
ConstantPointerNull, not a failed resolution. Only fire
reportFatalUsageError when stripAndAccumulateConstantOffsets
leaves an unresolved ConstantExpr.
Fixes ptrauth-irelative.ll test failure.
---
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index e6652ef374e73..98d73466725c8 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -2700,8 +2700,10 @@ AArch64AsmPrinter::lowerConstantPtrAuth(const ConstantPtrAuth &CPA) {
else if (Offset.slt(0))
Sym = MCBinaryExpr::createSub(
Sym, MCConstantExpr::create((-Offset).getSExtValue(), Ctx), Ctx);
- } else {
+ } else if (isa<ConstantExpr>(BaseGV)) {
reportFatalUsageError("unsupported constant expression in ptrauth pointer");
+ } else {
+ Sym = MCConstantExpr::create(Offset.getSExtValue(), Ctx);
}
const MCExpr *DSExpr = nullptr;
>From 2a45dded9cda2b3e0b9afb0525b59464c2c5d0dc Mon Sep 17 00:00:00 2001
From: Oskar Wirga <oskar.wirga at gmail.com>
Date: Mon, 30 Mar 2026 16:03:32 -0700
Subject: [PATCH 4/5] Use allowlist instead of denylist for ptrauth constant
base check
Check for known-safe types (ConstantPointerNull) and error on
everything else, rather than checking for known-bad types
(ConstantExpr). This catches other unhandled forms like nested
ptrauth constants.
Adds test cases for null pointer ptrauth and unsupported base
expression error.
---
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 6 ++---
llvm/test/CodeGen/AArch64/ptrauth-reloc.ll | 26 +++++++++++++++++++
2 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 98d73466725c8..8f81b7bb023f2 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -2700,10 +2700,10 @@ AArch64AsmPrinter::lowerConstantPtrAuth(const ConstantPtrAuth &CPA) {
else if (Offset.slt(0))
Sym = MCBinaryExpr::createSub(
Sym, MCConstantExpr::create((-Offset).getSExtValue(), Ctx), Ctx);
- } else if (isa<ConstantExpr>(BaseGV)) {
- reportFatalUsageError("unsupported constant expression in ptrauth pointer");
- } else {
+ } else if (isa<ConstantPointerNull>(BaseGV)) {
Sym = MCConstantExpr::create(Offset.getSExtValue(), Ctx);
+ } else {
+ reportFatalUsageError("unsupported constant expression in ptrauth pointer");
}
const MCExpr *DSExpr = nullptr;
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll b/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll
index befb726bcdab8..755f94adf80d4 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll
@@ -127,6 +127,20 @@
@g.inttoptr_add.da.0 = constant ptr ptrauth (ptr inttoptr (i64 add (i64 ptrtoint (ptr @g to i64), i64 2) to ptr), i32 2)
+; Null pointer inside ptrauth is valid (e.g. ptrauth-irelative.ll).
+
+; CHECK-ELF-LABEL: .globl g.null_ref.da.0
+; CHECK-ELF-NEXT: .p2align 3
+; CHECK-ELF-NEXT: g.null_ref.da.0:
+; CHECK-ELF-NEXT: .xword (0)@AUTH(da,0)
+
+; CHECK-MACHO-LABEL: .globl _g.null_ref.da.0
+; CHECK-MACHO-NEXT: .p2align 3
+; CHECK-MACHO-NEXT: _g.null_ref.da.0:
+; CHECK-MACHO-NEXT: .quad (0)@AUTH(da,0)
+
+ at g.null_ref.da.0 = constant ptr ptrauth (ptr null, i32 2)
+
; CHECK-ELF-LABEL: .globl g_weak.ref.ia.42
; CHECK-ELF-NEXT: .p2align 3
; CHECK-ELF-NEXT: g_weak.ref.ia.42:
@@ -206,3 +220,15 @@
; CHECK-ERR-DISC-GNU: error: AArch64 PAC Discriminator '65538' out of range [0, 0xFFFF]
@g.ref.da.65538 = constant ptr ptrauth (ptr @g, i32 2, i64 65538, ptr null, ptr @ds)
+
+;--- err-unsupported-base.ll
+
+; RUN: not llc < err-unsupported-base.ll -mtriple arm64e-apple-darwin 2>&1 \
+; RUN: | FileCheck %s --check-prefix=CHECK-ERR-BASE
+; RUN: not llc < err-unsupported-base.ll -mtriple aarch64-elf -mattr=+pauth 2>&1 \
+; RUN: | FileCheck %s --check-prefix=CHECK-ERR-BASE
+
+; CHECK-ERR-BASE: unsupported constant expression in ptrauth pointer
+
+ at g = external global i32
+ at g.nested_ptrauth = constant ptr ptrauth (ptr ptrauth (ptr @g, i32 0), i32 2)
>From e26d3d5598a10d24cc38dabab5270a31040d8037 Mon Sep 17 00:00:00 2001
From: Oskar Wirga <oskar at wirga.com>
Date: Sun, 5 Apr 2026 19:39:38 -0400
Subject: [PATCH 5/5] Remove Swift attribution from comments
The inttoptr(add(ptrtoint)) pattern is not Swift-specific.
Drop the attribution and just describe the pattern.
---
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 2 +-
llvm/test/CodeGen/AArch64/ptrauth-reloc.ll | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 8f81b7bb023f2..e0befa75048bf 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -2680,7 +2680,7 @@ AArch64AsmPrinter::lowerConstantPtrAuth(const ConstantPtrAuth &CPA) {
MCContext &Ctx = OutContext;
// Figure out the base symbol and the addend, if any.
- // LookThroughIntToPtr handles Swift patterns like:
+ // LookThroughIntToPtr is needed to handle patterns like:
// inttoptr (i64 add (i64 ptrtoint (ptr @global to i64), i64 2) to ptr)
APInt Offset(64, 0);
const Value *BaseGV = CPA.getPointer()->stripAndAccumulateConstantOffsets(
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll b/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll
index 755f94adf80d4..ccee9bc2355f1 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll
@@ -113,7 +113,7 @@
@g.weird_ref.da.0 = constant i64 ptrtoint (ptr inttoptr (i64 ptrtoint (ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 16), i32 2) to i64) to ptr) to i64)
-; Swift generates inttoptr(add(ptrtoint(@global), offset)) inside ptrauth.
+; inttoptr(add(ptrtoint(@global), offset)) inside ptrauth.
; CHECK-ELF-LABEL: .globl g.inttoptr_add.da.0
; CHECK-ELF-NEXT: .p2align 3
More information about the llvm-commits
mailing list