[llvm] [X86] Avoid invalid ret for EH_RETURN with SHSTK (PR #219322)

via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 7 11:36:41 PDT 2026


https://github.com/linisha15 updated https://github.com/llvm/llvm-project/pull/219322

>From c2c6691e7420d5b988769a7edcc750902bc4ba16 Mon Sep 17 00:00:00 2001
From: linisha <linisha232 at gmail.com>
Date: Fri, 28 Aug 2026 04:19:59 +0530
Subject: [PATCH 1/5] [X86] Avoid invalid ret for EH_RETURN with SHSTK

---
 llvm/lib/Target/X86/X86ExpandPseudo.cpp  | 12 ++++++++++++
 llvm/test/CodeGen/X86/eh-return-shstk.ll | 19 +++++++++++++++++++
 2 files changed, 31 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/eh-return-shstk.ll

diff --git a/llvm/lib/Target/X86/X86ExpandPseudo.cpp b/llvm/lib/Target/X86/X86ExpandPseudo.cpp
index 612d90361a44e..b8195e9cefc98 100644
--- a/llvm/lib/Target/X86/X86ExpandPseudo.cpp
+++ b/llvm/lib/Target/X86/X86ExpandPseudo.cpp
@@ -402,6 +402,18 @@ bool X86ExpandPseudoImpl::expandMI(MachineBasicBlock &MBB,
     BuildMI(MBB, MBBI, DL,
             TII->get(Uses64BitFramePtr ? X86::MOV64rr : X86::MOV32rr), StackPtr)
         .addReg(DestAddr.getReg());
+    if (STI->hasSHSTK()) {
+      unsigned PopOpcode = Uses64BitFramePtr ? X86::POP64r : X86::POP32r;
+      unsigned JumpOpcode = X86::JMP32r;
+      if (Uses64BitFramePtr)
+        JumpOpcode = STI->isTargetWin64() || STI->isTargetUEFI64()
+                         ? X86::JMP64r_REX
+                         : X86::JMP64r;
+      BuildMI(MBB, MBBI, DL, TII->get(PopOpcode))
+          .addReg(DestAddr.getReg(), RegState::Define);
+      BuildMI(MBB, MBBI, DL, TII->get(JumpOpcode)).addReg(DestAddr.getReg());
+      MBB.erase(MBBI);
+    }
     // The EH_RETURN pseudo is really removed during the MC Lowering.
     return true;
   }
diff --git a/llvm/test/CodeGen/X86/eh-return-shstk.ll b/llvm/test/CodeGen/X86/eh-return-shstk.ll
new file mode 100644
index 0000000000000..5f2c5d194824f
--- /dev/null
+++ b/llvm/test/CodeGen/X86/eh-return-shstk.ll
@@ -0,0 +1,19 @@
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=RET
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=+shstk -verify-machineinstrs < %s | FileCheck %s --check-prefix=SHSTK
+
+define void @test(i64 %offset, ptr %handler) {
+entry:
+  call void @llvm.eh.return.i64(i64 %offset, ptr %handler)
+  unreachable
+}
+
+; RET-LABEL: test:
+; RET:       movq %rcx, %rsp
+; RET-NEXT:  retq
+
+; SHSTK-LABEL: test:
+; SHSTK:      movq %rcx, %rsp
+; SHSTK-NEXT: popq %rcx
+; SHSTK-NEXT: jmpq *%rcx
+
+declare void @llvm.eh.return.i64(i64, ptr)

>From 504047b3a47f730de05010f7887dd95dc8816418 Mon Sep 17 00:00:00 2001
From: Linisha <linisha232 at gmail.com>
Date: Mon, 7 Sep 2026 23:07:18 +0530
Subject: [PATCH 2/5] Update llvm/lib/Target/X86/X86ExpandPseudo.cpp

Co-authored-by: Phoebe Wang <phoebe.wang at intel.com>
---
 llvm/lib/Target/X86/X86ExpandPseudo.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/X86/X86ExpandPseudo.cpp b/llvm/lib/Target/X86/X86ExpandPseudo.cpp
index b8195e9cefc98..bb7b7092fd8bf 100644
--- a/llvm/lib/Target/X86/X86ExpandPseudo.cpp
+++ b/llvm/lib/Target/X86/X86ExpandPseudo.cpp
@@ -403,7 +403,7 @@ bool X86ExpandPseudoImpl::expandMI(MachineBasicBlock &MBB,
             TII->get(Uses64BitFramePtr ? X86::MOV64rr : X86::MOV32rr), StackPtr)
         .addReg(DestAddr.getReg());
     if (STI->hasSHSTK()) {
-      unsigned PopOpcode = Uses64BitFramePtr ? X86::POP64r : X86::POP32r;
+      unsigned PopOpcode = STI->is64Bit() ? X86::POP64r : X86::POP32r;
       unsigned JumpOpcode = X86::JMP32r;
       if (Uses64BitFramePtr)
         JumpOpcode = STI->isTargetWin64() || STI->isTargetUEFI64()

>From 5aaf37a12788a1d059a6f359f0649578a899c6b4 Mon Sep 17 00:00:00 2001
From: linisha <linisha232 at gmail.com>
Date: Mon, 7 Sep 2026 23:33:35 +0530
Subject: [PATCH 3/5] [X86] Add EH_RETURN SHSTK target tests

---
 llvm/test/CodeGen/X86/eh-return-shstk.ll | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/llvm/test/CodeGen/X86/eh-return-shstk.ll b/llvm/test/CodeGen/X86/eh-return-shstk.ll
index 5f2c5d194824f..7281085ee9c72 100644
--- a/llvm/test/CodeGen/X86/eh-return-shstk.ll
+++ b/llvm/test/CodeGen/X86/eh-return-shstk.ll
@@ -1,5 +1,7 @@
 ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=RET
 ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=+shstk -verify-machineinstrs < %s | FileCheck %s --check-prefix=SHSTK
+; RUN: llc -mtriple=x86_64-pc-windows-msvc -mattr=+shstk -verify-machineinstrs < %s | FileCheck %s --check-prefix=WIN64
+; RUN: llc -mtriple=x86_64-uefi -mattr=+shstk -verify-machineinstrs < %s | FileCheck %s --check-prefix=UEFI64
 
 define void @test(i64 %offset, ptr %handler) {
 entry:
@@ -16,4 +18,14 @@ entry:
 ; SHSTK-NEXT: popq %rcx
 ; SHSTK-NEXT: jmpq *%rcx
 
+; WIN64-LABEL: test:
+; WIN64:       movq %rcx, %rsp
+; WIN64-NEXT:  popq %rcx
+; WIN64-NEXT:  rex64 jmpq *%rcx
+
+; UEFI64-LABEL: test:
+; UEFI64:       movq %rcx, %rsp
+; UEFI64-NEXT:  popq %rcx
+; UEFI64-NEXT:  rex64 jmpq *%rcx
+
 declare void @llvm.eh.return.i64(i64, ptr)

>From fcaeb0bbc101565cdf5c4cf9a6d4158e3118e64e Mon Sep 17 00:00:00 2001
From: linisha <linisha232 at gmail.com>
Date: Mon, 7 Sep 2026 23:49:58 +0530
Subject: [PATCH 4/5] [X86] Add 32-bit EH_return-shstk test

---
 llvm/test/CodeGen/X86/eh-return-shstk-32.ll | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/eh-return-shstk-32.ll

diff --git a/llvm/test/CodeGen/X86/eh-return-shstk-32.ll b/llvm/test/CodeGen/X86/eh-return-shstk-32.ll
new file mode 100644
index 0000000000000..5f9e65669424c
--- /dev/null
+++ b/llvm/test/CodeGen/X86/eh-return-shstk-32.ll
@@ -0,0 +1,17 @@
+; RUN: llc -mtriple=i386-pc-linux -mattr=+shstk -verify-machineinstrs < %s | FileCheck %s
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"
+target triple = "i386-pc-linux"
+
+define void @test(i32 %offset, ptr %handler) {
+entry:
+  call void @llvm.eh.return.i32(i32 %offset, ptr %handler)
+  unreachable
+}
+
+; CHECK-LABEL: test:
+; CHECK:       movl %ecx, %esp
+; CHECK-NEXT:  popl %ecx
+; CHECK-NEXT:  jmpl *%ecx
+
+declare void @llvm.eh.return.i32(i32, ptr)
\ No newline at end of file

>From 7690e9ab46f7b66a05f99c0ee9b5575ee03c813a Mon Sep 17 00:00:00 2001
From: linisha <linisha232 at gmail.com>
Date: Tue, 8 Sep 2026 00:06:17 +0530
Subject: [PATCH 5/5] [X86] Generate EH_RETURN SHSTK test checks

---
 llvm/test/CodeGen/X86/eh-return-shstk-32.ll | 27 +++++--
 llvm/test/CodeGen/X86/eh-return-shstk.ll    | 82 ++++++++++++++++-----
 2 files changed, 84 insertions(+), 25 deletions(-)

diff --git a/llvm/test/CodeGen/X86/eh-return-shstk-32.ll b/llvm/test/CodeGen/X86/eh-return-shstk-32.ll
index 5f9e65669424c..5748c78c9e3d9 100644
--- a/llvm/test/CodeGen/X86/eh-return-shstk-32.ll
+++ b/llvm/test/CodeGen/X86/eh-return-shstk-32.ll
@@ -1,17 +1,32 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
 ; RUN: llc -mtriple=i386-pc-linux -mattr=+shstk -verify-machineinstrs < %s | FileCheck %s
 
 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"
 target triple = "i386-pc-linux"
 
 define void @test(i32 %offset, ptr %handler) {
+; CHECK-LABEL: test:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    pushl %ebp
+; CHECK-NEXT:    .cfi_def_cfa_offset 8
+; CHECK-NEXT:    .cfi_offset %ebp, -8
+; CHECK-NEXT:    movl %esp, %ebp
+; CHECK-NEXT:    .cfi_def_cfa_register %ebp
+; CHECK-NEXT:    pushl %eax
+; CHECK-NEXT:    .cfi_offset %eax, -12
+; CHECK-NEXT:    movl 12(%ebp), %ecx
+; CHECK-NEXT:    movl 8(%ebp), %eax
+; CHECK-NEXT:    movl %ecx, 4(%ebp,%eax)
+; CHECK-NEXT:    leal 4(%ebp,%eax), %ecx
+; CHECK-NEXT:    popl %eax
+; CHECK-NEXT:    popl %ebp
+; CHECK-NEXT:    .cfi_def_cfa %esp, 4
+; CHECK-NEXT:    movl %ecx, %esp
+; CHECK-NEXT:    popl %ecx
+; CHECK-NEXT:    jmpl *%ecx
 entry:
   call void @llvm.eh.return.i32(i32 %offset, ptr %handler)
   unreachable
 }
 
-; CHECK-LABEL: test:
-; CHECK:       movl %ecx, %esp
-; CHECK-NEXT:  popl %ecx
-; CHECK-NEXT:  jmpl *%ecx
-
-declare void @llvm.eh.return.i32(i32, ptr)
\ No newline at end of file
+declare void @llvm.eh.return.i32(i32, ptr)
diff --git a/llvm/test/CodeGen/X86/eh-return-shstk.ll b/llvm/test/CodeGen/X86/eh-return-shstk.ll
index 7281085ee9c72..63897e5b765b2 100644
--- a/llvm/test/CodeGen/X86/eh-return-shstk.ll
+++ b/llvm/test/CodeGen/X86/eh-return-shstk.ll
@@ -1,31 +1,75 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
 ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=RET
 ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=+shstk -verify-machineinstrs < %s | FileCheck %s --check-prefix=SHSTK
 ; RUN: llc -mtriple=x86_64-pc-windows-msvc -mattr=+shstk -verify-machineinstrs < %s | FileCheck %s --check-prefix=WIN64
 ; RUN: llc -mtriple=x86_64-uefi -mattr=+shstk -verify-machineinstrs < %s | FileCheck %s --check-prefix=UEFI64
 
 define void @test(i64 %offset, ptr %handler) {
-entry:
-  call void @llvm.eh.return.i64(i64 %offset, ptr %handler)
-  unreachable
-}
-
 ; RET-LABEL: test:
-; RET:       movq %rcx, %rsp
-; RET-NEXT:  retq
-
+; RET:       # %bb.0: # %entry
+; RET-NEXT:    pushq %rbp
+; RET-NEXT:    .cfi_def_cfa_offset 16
+; RET-NEXT:    .cfi_offset %rbp, -16
+; RET-NEXT:    movq %rsp, %rbp
+; RET-NEXT:    .cfi_def_cfa_register %rbp
+; RET-NEXT:    movq %rsi, 8(%rbp,%rdi)
+; RET-NEXT:    leaq 8(%rbp,%rdi), %rcx
+; RET-NEXT:    popq %rbp
+; RET-NEXT:    .cfi_def_cfa %rsp, 8
+; RET-NEXT:    movq %rcx, %rsp
+; RET-NEXT:    retq # eh_return, addr: %rcx
+;
 ; SHSTK-LABEL: test:
-; SHSTK:      movq %rcx, %rsp
-; SHSTK-NEXT: popq %rcx
-; SHSTK-NEXT: jmpq *%rcx
-
+; SHSTK:       # %bb.0: # %entry
+; SHSTK-NEXT:    pushq %rbp
+; SHSTK-NEXT:    .cfi_def_cfa_offset 16
+; SHSTK-NEXT:    .cfi_offset %rbp, -16
+; SHSTK-NEXT:    movq %rsp, %rbp
+; SHSTK-NEXT:    .cfi_def_cfa_register %rbp
+; SHSTK-NEXT:    movq %rsi, 8(%rbp,%rdi)
+; SHSTK-NEXT:    leaq 8(%rbp,%rdi), %rcx
+; SHSTK-NEXT:    popq %rbp
+; SHSTK-NEXT:    .cfi_def_cfa %rsp, 8
+; SHSTK-NEXT:    movq %rcx, %rsp
+; SHSTK-NEXT:    popq %rcx
+; SHSTK-NEXT:    jmpq *%rcx
+;
 ; WIN64-LABEL: test:
-; WIN64:       movq %rcx, %rsp
-; WIN64-NEXT:  popq %rcx
-; WIN64-NEXT:  rex64 jmpq *%rcx
-
+; WIN64:       # %bb.0: # %entry
+; WIN64-NEXT:    pushq %rbp
+; WIN64-NEXT:    .seh_pushreg %rbp
+; WIN64-NEXT:    movq %rsp, %rbp
+; WIN64-NEXT:    .seh_setframe %rbp, 0
+; WIN64-NEXT:    .seh_endprologue
+; WIN64-NEXT:    movq %rdx, 8(%rbp,%rcx)
+; WIN64-NEXT:    leaq 8(%rbp,%rcx), %rcx
+; WIN64-NEXT:    .seh_startepilogue
+; WIN64-NEXT:    popq %rbp
+; WIN64-NEXT:    .seh_endepilogue
+; WIN64-NEXT:    movq %rcx, %rsp
+; WIN64-NEXT:    popq %rcx
+; WIN64-NEXT:    rex64 jmpq *%rcx
+; WIN64-NEXT:    .seh_endproc
+;
 ; UEFI64-LABEL: test:
-; UEFI64:       movq %rcx, %rsp
-; UEFI64-NEXT:  popq %rcx
-; UEFI64-NEXT:  rex64 jmpq *%rcx
+; UEFI64:       # %bb.0: # %entry
+; UEFI64-NEXT:    pushq %rbp
+; UEFI64-NEXT:    .seh_pushreg %rbp
+; UEFI64-NEXT:    movq %rsp, %rbp
+; UEFI64-NEXT:    .seh_setframe %rbp, 0
+; UEFI64-NEXT:    .seh_endprologue
+; UEFI64-NEXT:    movq %rdx, 8(%rbp,%rcx)
+; UEFI64-NEXT:    leaq 8(%rbp,%rcx), %rcx
+; UEFI64-NEXT:    .seh_startepilogue
+; UEFI64-NEXT:    popq %rbp
+; UEFI64-NEXT:    .seh_endepilogue
+; UEFI64-NEXT:    movq %rcx, %rsp
+; UEFI64-NEXT:    popq %rcx
+; UEFI64-NEXT:    rex64 jmpq *%rcx
+; UEFI64-NEXT:    .seh_endproc
+entry:
+  call void @llvm.eh.return.i64(i64 %offset, ptr %handler)
+  unreachable
+}
 
 declare void @llvm.eh.return.i64(i64, ptr)



More information about the llvm-commits mailing list