[llvm] [X86] Fix crash when calling through __ptr32 function pointer (PR #209078)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 12 21:30:34 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: Muhammed Shiyas N (Shiyas-N)

<details>
<summary>Changes</summary>

Fixes #<!-- -->56199 

Calling through a __ptr32 function pointer on x86-64 crashes during instruction selection
because LowerCall doesn't extend the 32-bit callee to 64-bit.
This patch sign-extends __sptr (addrspace 270) and zero-extends __uptr (addrspace 271)
callee pointers to i64 before building the CALL/TC_RETURN node.

---
Full diff: https://github.com/llvm/llvm-project/pull/209078.diff


2 Files Affected:

- (modified) llvm/lib/Target/X86/X86ISelLoweringCall.cpp (+11) 
- (added) llvm/test/CodeGen/X86/ptr32-call.ll (+62) 


``````````diff
diff --git a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
index 819e0a023c1c5..d81c12685560b 100644
--- a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
+++ b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp
@@ -2589,6 +2589,17 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
              Callee.getValueType() == MVT::i32) {
     // Zero-extend the 32-bit Callee address into a 64-bit according to x32 ABI
     Callee = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, Callee);
+  } else if (Is64Bit && Callee.getValueType() == MVT::i32) {
+    // On 64-bit targets, extend 32-bit MS __ptr32 callees before the call.
+    // Use sign-extension for __sptr (or when CallBase is null)
+    // and zero-extension for __uptr
+    ISD::NodeType ExtOpc = ISD::SIGN_EXTEND;
+    if (CB) {
+      unsigned AS = CB->getCalledOperand()->getType()->getPointerAddressSpace();
+      if (AS == X86AS::PTR32_UPTR)
+        ExtOpc = ISD::ZERO_EXTEND;
+    }
+    Callee = DAG.getNode(ExtOpc, dl, MVT::i64, Callee);
   } else if (Is64Bit && CB && isCFGuardCall(CB)) {
     // We'll use a specific psuedo instruction for tail calls to control flow
     // guard functions to guarantee the instruction used for the call. To do
diff --git a/llvm/test/CodeGen/X86/ptr32-call.ll b/llvm/test/CodeGen/X86/ptr32-call.ll
new file mode 100644
index 0000000000000..a88d7b8b466a9
--- /dev/null
+++ b/llvm/test/CodeGen/X86/ptr32-call.ll
@@ -0,0 +1,62 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
+
+; Tail call through addrspace(270) (__ptr32 __sptr) function pointer.
+; The callee should be sign-extended from i32 to i64.
+define i32 @tailcall_sptr(ptr addrspace(270) %fptr, i32 %arg) {
+; CHECK-LABEL: tailcall_sptr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movslq %edi, %rax
+; CHECK-NEXT:    movl %esi, %edi
+; CHECK-NEXT:    jmpq *%rax # TAILCALL
+entry:
+  %call = tail call addrspace(270) i32 %fptr(i32 %arg)
+  ret i32 %call
+}
+
+; Tail call through addrspace(271) (__ptr32 __uptr) function pointer.
+; The callee should be zero-extended from i32 to i64.
+define i32 @tailcall_uptr(ptr addrspace(271) %fptr, i32 %arg) {
+; CHECK-LABEL: tailcall_uptr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    movq %rdi, %rax
+; CHECK-NEXT:    movl %esi, %edi
+; CHECK-NEXT:    jmpq *%rax # TAILCALL
+entry:
+  %call = tail call addrspace(271) i32 %fptr(i32 %arg)
+  ret i32 %call
+}
+
+; Non-tail call through addrspace(270) (__ptr32 __sptr) function pointer.
+define i32 @call_sptr(ptr addrspace(270) %fptr, i32 %arg) {
+; CHECK-LABEL: call_sptr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pushq %rax
+; CHECK-NEXT:    .cfi_def_cfa_offset 16
+; CHECK-NEXT:    movslq %edi, %rax
+; CHECK-NEXT:    movl %esi, %edi
+; CHECK-NEXT:    callq *%rax
+; CHECK-NEXT:    popq %rcx
+; CHECK-NEXT:    .cfi_def_cfa_offset 8
+; CHECK-NEXT:    retq
+entry:
+  %call = call addrspace(270) i32 %fptr(i32 %arg)
+  ret i32 %call
+}
+
+; Non-tail call through addrspace(271) (__ptr32 __uptr) function pointer.
+define i32 @call_uptr(ptr addrspace(271) %fptr, i32 %arg) {
+; CHECK-LABEL: call_uptr:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pushq %rax
+; CHECK-NEXT:    .cfi_def_cfa_offset 16
+; CHECK-NEXT:    movq %rdi, %rax
+; CHECK-NEXT:    movl %esi, %edi
+; CHECK-NEXT:    callq *%rax
+; CHECK-NEXT:    popq %rcx
+; CHECK-NEXT:    .cfi_def_cfa_offset 8
+; CHECK-NEXT:    retq
+entry:
+  %call = call addrspace(271) i32 %fptr(i32 %arg)
+  ret i32 %call
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/209078


More information about the llvm-commits mailing list