[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