[llvm] [llubi] Implement ptrtoaddr (PR #203771)

Zhige Chen via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 14 07:30:32 PDT 2026


https://github.com/nofe1248 created https://github.com/llvm/llvm-project/pull/203771

This PR implements the `ptrtoaddr` instruction.

>From ef5a76f56578e18121f0330be7f7a8c39e063d21 Mon Sep 17 00:00:00 2001
From: Zhige Chen <zhigec_cpp at outlook.com>
Date: Sun, 14 Jun 2026 22:29:33 +0800
Subject: [PATCH] [llubi] Implement ptrtoaddr instruction

---
 llvm/test/tools/llubi/ptrtoaddr.ll            | 25 +++++++++++++++++++
 .../tools/llubi/ptrtoaddr_after_ptrtoint.ll   | 21 ++++++++++++++++
 llvm/test/tools/llubi/ptrtoaddr_no_expose.ll  | 20 +++++++++++++++
 llvm/tools/llubi/lib/Interpreter.cpp          | 11 ++++++--
 4 files changed, 75 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/tools/llubi/ptrtoaddr.ll
 create mode 100644 llvm/test/tools/llubi/ptrtoaddr_after_ptrtoint.ll
 create mode 100644 llvm/test/tools/llubi/ptrtoaddr_no_expose.ll

diff --git a/llvm/test/tools/llubi/ptrtoaddr.ll b/llvm/test/tools/llubi/ptrtoaddr.ll
new file mode 100644
index 0000000000000..6def7c3b2fa0e
--- /dev/null
+++ b/llvm/test/tools/llubi/ptrtoaddr.ll
@@ -0,0 +1,25 @@
+; RUN: llubi --verbose < %s 2>&1 | FileCheck %s
+
+target datalayout = "e-p:64:64:64-p1:64:64:64:32"
+
+define void @main() {
+  %wide1 = inttoptr i64 4294967301 to ptr addrspace(1)
+  %repr1 = ptrtoint ptr addrspace(1) %wide1 to i64
+  %addr1 = ptrtoaddr ptr addrspace(1) %wide1 to i32
+
+  %wide2 = inttoptr <2 x i64> <i64 4294967301, i64 4294967303> to <2 x ptr addrspace(1)>
+  %repr2 = ptrtoint <2 x ptr addrspace(1)> %wide2 to <2 x i64>
+  %addr2 = ptrtoaddr <2 x ptr addrspace(1)> %wide2 to <2 x i32>
+
+  ret void
+}
+
+; CHECK: Entering function: main
+; CHECK-NEXT:   %wide1 = inttoptr i64 4294967301 to ptr addrspace(1) => ptr 0x100000005 [nullary]
+; CHECK-NEXT:   %repr1 = ptrtoint ptr addrspace(1) %wide1 to i64 => i64 4294967301
+; CHECK-NEXT:   %addr1 = ptrtoaddr ptr addrspace(1) %wide1 to i32 => i32 5
+; CHECK-NEXT:   %wide2 = inttoptr <2 x i64> <i64 4294967301, i64 4294967303> to <2 x ptr addrspace(1)> => { ptr 0x100000005 [nullary], ptr 0x100000007 [nullary] }
+; CHECK-NEXT:   %repr2 = ptrtoint <2 x ptr addrspace(1)> %wide2 to <2 x i64> => { i64 4294967301, i64 4294967303 }
+; CHECK-NEXT:   %addr2 = ptrtoaddr <2 x ptr addrspace(1)> %wide2 to <2 x i32> => { i32 5, i32 7 }
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: Exiting function: main
diff --git a/llvm/test/tools/llubi/ptrtoaddr_after_ptrtoint.ll b/llvm/test/tools/llubi/ptrtoaddr_after_ptrtoint.ll
new file mode 100644
index 0000000000000..5cbf4818b8b56
--- /dev/null
+++ b/llvm/test/tools/llubi/ptrtoaddr_after_ptrtoint.ll
@@ -0,0 +1,21 @@
+; RUN: llubi --verbose < %s 2>&1 | FileCheck %s
+
+target datalayout = "e-p:64:64:64"
+
+define void @main() {
+  %p = alloca i32
+  %i = ptrtoint ptr %p to i64
+  %a = ptrtoaddr ptr %p to i64
+  %p2 = inttoptr i64 %a to ptr
+  store i32 0, ptr %p2
+  ret void
+}
+
+; CHECK: Entering function: main
+; CHECK-NEXT:   %p = alloca i32, align 4 => ptr 0x8 [p]
+; CHECK-NEXT:   %i = ptrtoint ptr %p to i64 => i64 8
+; CHECK-NEXT:   %a = ptrtoaddr ptr %p to i64 => i64 8
+; CHECK-NEXT:   %p2 = inttoptr i64 %a to ptr => ptr 0x8 [wildcard]
+; CHECK-NEXT:   store i32 0, ptr %p2, align 4
+; CHECK-NEXT:   ret void
+; CHECK-NEXT: Exiting function: main
diff --git a/llvm/test/tools/llubi/ptrtoaddr_no_expose.ll b/llvm/test/tools/llubi/ptrtoaddr_no_expose.ll
new file mode 100644
index 0000000000000..ccd75aeb77042
--- /dev/null
+++ b/llvm/test/tools/llubi/ptrtoaddr_no_expose.ll
@@ -0,0 +1,20 @@
+; RUN: not llubi --verbose < %s 2>&1 | FileCheck %s
+
+target datalayout = "e-p:64:64:64"
+
+define void @main() {
+  %alloc = alloca i32
+  %addr = ptrtoaddr ptr %alloc to i64
+  %cast = inttoptr i64 %addr to ptr
+  store i32 0, ptr %cast
+  ret void
+}
+
+; CHECK: Entering function: main
+; CHECK-NEXT:   %alloc = alloca i32, align 4 => ptr 0x8 [alloc]
+; CHECK-NEXT:   %addr = ptrtoaddr ptr %alloc to i64 => i64 8
+; CHECK-NEXT:   %cast = inttoptr i64 %addr to ptr => ptr 0x8 [nullary]
+; CHECK-NEXT: Stacktrace:
+; CHECK-NEXT: #0   store i32 0, ptr %cast, align 4 at @main {{.*}}
+; CHECK-NEXT: Immediate UB detected: Invalid memory access via a pointer with nullary provenance.
+; CHECK-NEXT: error: Execution of function 'main' failed.
diff --git a/llvm/tools/llubi/lib/Interpreter.cpp b/llvm/tools/llubi/lib/Interpreter.cpp
index 5769d0a4a9c4d..5f7c48794245d 100644
--- a/llvm/tools/llubi/lib/Interpreter.cpp
+++ b/llvm/tools/llubi/lib/Interpreter.cpp
@@ -2246,8 +2246,6 @@ class InstExecutor : public InstVisitor<InstExecutor, void>,
     });
   }
 
-  // TODO: Add support for ptrtoaddr, which exposes nothing.
-
   void visitIntToPtr(IntToPtrInst &I) {
     return visitUnOp(I, [&](const AnyValue &V) -> AnyValue {
       if (V.isPoison())
@@ -2260,6 +2258,15 @@ class InstExecutor : public InstVisitor<InstExecutor, void>,
     });
   }
 
+  void visitPtrToAddr(PtrToAddrInst &I) {
+    unsigned BitWidth = I.getType()->getScalarSizeInBits();
+    return visitUnOp(I, [&](const AnyValue &V) -> AnyValue {
+      if (V.isPoison())
+        return AnyValue::poison();
+      return V.asPointer().address().trunc(BitWidth);
+    });
+  }
+
   void visitLoadInst(LoadInst &LI) {
     auto RetVal = load(getValue(LI.getPointerOperand()), LI.getAlign(),
                        LI.getType(), LI.hasMetadata(LLVMContext::MD_noundef));



More information about the llvm-commits mailing list