[llvm] [CodeGen] Diagnose unsupported landingpad result types instead of asserting (PR #223205)
Akash Manna via llvm-commits
llvm-commits at lists.llvm.org
Sun Sep 27 03:58:54 PDT 2026
https://github.com/akash-manna-sky updated https://github.com/llvm/llvm-project/pull/223205
>From 9cb07c5489760cff387eb8032c7e9a72d605f758 Mon Sep 17 00:00:00 2001
From: Akash Manna <akash.manna.mymail at gmail.com>
Date: Sun, 13 Sep 2026 10:09:56 +0530
Subject: [PATCH 1/3] [CodeGen] Diagnose unsupported landingpad result types
instead of asserting
SelectionDAGBuilder::visitLandingPad assumed the landingpad result type
decomposes into exactly two values (exception pointer and selector) and
asserted otherwise. LangRef leaves that representation target specific
and the verifier does not check the shape, so `landingpad {}` is
well-formed IR that crashed the compiler.
Emit a DiagnosticInfoUnsupported error for other shapes and lower the
result to poison so compilation can continue. IRTranslator had the same
assertion behind an unchecked cast<StructType>; it now fails the
translation cleanly and falls back to SelectionDAG.
Fixes #220959
---
llvm/docs/ReleaseNotes.md | 5 ++
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 8 +++-
.../SelectionDAG/SelectionDAGBuilder.cpp | 15 +++++-
llvm/test/CodeGen/X86/pr220959.ll | 46 +++++++++++++++++++
4 files changed, 71 insertions(+), 3 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/pr220959.ll
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 985117034e2be..63756de3eef15 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -288,6 +288,11 @@ Makes programs 10x faster by doing Special New Thing.
compiling a function containing a static alloca of `(size_t)-1` bytes, whose
size collided with the sentinel value MachineFrameInfo used to mark dead
stack objects.
+* Fixed a crash
+ ([#220959](https://github.com/llvm/llvm-project/issues/220959)) when
+ compiling a `landingpad` whose result type does not consist of an exception
+ pointer and a selector (for example `{}`). Such a landingpad is now rejected
+ with a clean "unsupported" diagnostic instead of an assertion failure.
### Changes to the Metadata Info
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index d9e88f22ac2ca..185559ff29222 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -3977,6 +3977,11 @@ bool IRTranslatorImpl::translateLandingPad(const User &U,
if (LP.getType()->isTokenTy())
return true;
+ // Only the two-valued (exception pointer, selector) form can be translated.
+ auto *LPTy = dyn_cast<StructType>(LP.getType());
+ if (!LPTy || LPTy->getNumElements() != 2)
+ return false;
+
// Add a label to mark the beginning of the landing pad. Deletion of the
// landing pad can thus be detected via the MachineModuleInfo.
MIRBuilder.buildInstr(TargetOpcode::EH_LABEL)
@@ -3993,9 +3998,8 @@ bool IRTranslatorImpl::translateLandingPad(const User &U,
MIRBuilder.buildUndef(Undef);
SmallVector<LLT, 2> Tys;
- for (Type *Ty : cast<StructType>(LP.getType())->elements())
+ for (Type *Ty : LPTy->elements())
Tys.push_back(getLLTForType(*Ty, *DL));
- assert(Tys.size() == 2 && "Only two-valued landingpads are supported");
// Mark exception register as live in.
Register ExceptionReg =
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 065347d903033..18283db1136dc 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3655,7 +3655,20 @@ void SelectionDAGBuilder::visitLandingPad(const LandingPadInst &LP) {
SmallVector<EVT, 2> ValueVTs;
SDLoc dl = getCurSDLoc();
ComputeValueVTs(TLI, DAG.getDataLayout(), LP.getType(), ValueVTs);
- assert(ValueVTs.size() == 2 && "Only two-valued landingpads are supported");
+
+ // Only the two-valued (exception pointer, selector) form can be lowered.
+ // LangRef leaves the result type target-specific, so diagnose other shapes
+ // instead of asserting.
+ if (ValueVTs.size() != 2) {
+ DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
+ *LP.getFunction(),
+ "landingpad result type must consist of exactly two values, the "
+ "exception pointer and the selector",
+ dl.getDebugLoc()));
+ if (!ValueVTs.empty())
+ setValueToPoison(&LP, dl);
+ return;
+ }
// Get the two live-in registers as SDValues. The physregs have already been
// copied into virtual registers.
diff --git a/llvm/test/CodeGen/X86/pr220959.ll b/llvm/test/CodeGen/X86/pr220959.ll
new file mode 100644
index 0000000000000..ef03c662e9a59
--- /dev/null
+++ b/llvm/test/CodeGen/X86/pr220959.ll
@@ -0,0 +1,46 @@
+; RUN: not llc %s -mtriple=x86_64-unknown-linux-gnu -filetype=null 2>&1 | FileCheck %s
+; RUN: not llc %s -mtriple=x86_64-unknown-linux-gnu -O0 -filetype=null 2>&1 | FileCheck %s
+
+; A landingpad whose result type is not (exception pointer, selector) used to
+; trip an assertion in SelectionDAGBuilder::visitLandingPad. Expect a clean
+; diagnostic instead.
+
+; CHECK: error: {{.*}}in function main{{.*}}landingpad result type must consist of exactly two values, the exception pointer and the selector
+define i32 @main() personality ptr @__gxx_personality_v0 {
+ invoke void @g()
+ to label %cont unwind label %cleanup
+cont:
+ ret i32 0
+cleanup:
+ %lp = landingpad {}
+ cleanup
+ ret i32 1
+}
+
+; CHECK: error: {{.*}}in function scalar{{.*}}landingpad result type must consist of exactly two values, the exception pointer and the selector
+define i32 @scalar() personality ptr @__gxx_personality_v0 {
+ invoke void @g()
+ to label %cont unwind label %cleanup
+cont:
+ ret i32 0
+cleanup:
+ %lp = landingpad i32
+ cleanup
+ ret i32 %lp
+}
+
+; CHECK: error: {{.*}}in function three_values{{.*}}landingpad result type must consist of exactly two values, the exception pointer and the selector
+define i32 @three_values() personality ptr @__gxx_personality_v0 {
+ invoke void @g()
+ to label %cont unwind label %cleanup
+cont:
+ ret i32 0
+cleanup:
+ %lp = landingpad { ptr, i32, i32 }
+ cleanup
+ %sel = extractvalue { ptr, i32, i32 } %lp, 2
+ ret i32 %sel
+}
+
+declare void @g()
+declare i32 @__gxx_personality_v0(...)
>From 09563220c18969b4d6ca7e8af1db923049c2784c Mon Sep 17 00:00:00 2001
From: Akash Manna <akash.manna.mymail at gmail.com>
Date: Sun, 13 Sep 2026 15:16:59 +0530
Subject: [PATCH 2/3] [CodeGen] Check landingpad element types, not just the
value count
The previous check only mirrored the assertion condition, so a type
like { float, i32 } passed it and still crashed when the lowering tried
to truncate the register value to f32. Add isExceptionPointerAndSelectorType,
which checks the IR struct for a pointer-or-integer exception object and an
integer selector, and use it in both SelectionDAGBuilder and IRTranslator
before any value types are computed. Also make setValueToPoison tolerate
types with no values.
---
llvm/docs/ReleaseNotes.md | 7 ++---
llvm/include/llvm/CodeGen/Analysis.h | 4 +++
llvm/lib/CodeGen/Analysis.cpp | 9 +++++++
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 7 +++--
.../SelectionDAG/SelectionDAGBuilder.cpp | 23 ++++++++--------
llvm/test/CodeGen/X86/pr220959.ll | 27 ++++++++++++++-----
6 files changed, 52 insertions(+), 25 deletions(-)
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 63756de3eef15..d14d51c37b2b6 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -290,9 +290,10 @@ Makes programs 10x faster by doing Special New Thing.
stack objects.
* Fixed a crash
([#220959](https://github.com/llvm/llvm-project/issues/220959)) when
- compiling a `landingpad` whose result type does not consist of an exception
- pointer and a selector (for example `{}`). Such a landingpad is now rejected
- with a clean "unsupported" diagnostic instead of an assertion failure.
+ compiling a `landingpad` whose result type is not a struct of an exception
+ pointer and an integer selector (for example `{}`). Such a landingpad is now
+ rejected with a clean "unsupported" diagnostic instead of an assertion
+ failure.
### Changes to the Metadata Info
diff --git a/llvm/include/llvm/CodeGen/Analysis.h b/llvm/include/llvm/CodeGen/Analysis.h
index c2bcb93c649b4..a68dac6f6ee9d 100644
--- a/llvm/include/llvm/CodeGen/Analysis.h
+++ b/llvm/include/llvm/CodeGen/Analysis.h
@@ -98,6 +98,10 @@ LLVM_ABI void computeValueLLTs(const DataLayout &DL, Type &Ty,
/// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V.
LLVM_ABI GlobalValue *ExtractTypeInfo(Value *V);
+/// Return true if landingpad result type \p Ty is a struct of an exception
+/// pointer (pointer or integer) and an integer selector, the only lowerable form.
+LLVM_ABI bool isExceptionPointerAndSelectorType(Type *Ty);
+
/// getFCmpCondCode - Return the ISD condition code corresponding to
/// the given LLVM IR floating-point condition code. This includes
/// consideration of global floating-point math flags.
diff --git a/llvm/lib/CodeGen/Analysis.cpp b/llvm/lib/CodeGen/Analysis.cpp
index 9ece9f0c187a2..0e3807ebaf0ab 100644
--- a/llvm/lib/CodeGen/Analysis.cpp
+++ b/llvm/lib/CodeGen/Analysis.cpp
@@ -196,6 +196,15 @@ GlobalValue *llvm::ExtractTypeInfo(Value *V) {
return GV;
}
+bool llvm::isExceptionPointerAndSelectorType(Type *Ty) {
+ auto *STy = dyn_cast<StructType>(Ty);
+ if (!STy || STy->getNumElements() != 2)
+ return false;
+ Type *ExnTy = STy->getElementType(0);
+ return (ExnTy->isPointerTy() || ExnTy->isIntegerTy()) &&
+ STy->getElementType(1)->isIntegerTy();
+}
+
/// getFCmpCondCode - Return the ISD condition code corresponding to
/// the given LLVM IR floating-point condition code. This includes
/// consideration of global floating-point math flags.
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 185559ff29222..c2ca946ffa473 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -3977,9 +3977,7 @@ bool IRTranslatorImpl::translateLandingPad(const User &U,
if (LP.getType()->isTokenTy())
return true;
- // Only the two-valued (exception pointer, selector) form can be translated.
- auto *LPTy = dyn_cast<StructType>(LP.getType());
- if (!LPTy || LPTy->getNumElements() != 2)
+ if (!isExceptionPointerAndSelectorType(LP.getType()))
return false;
// Add a label to mark the beginning of the landing pad. Deletion of the
@@ -3998,8 +3996,9 @@ bool IRTranslatorImpl::translateLandingPad(const User &U,
MIRBuilder.buildUndef(Undef);
SmallVector<LLT, 2> Tys;
- for (Type *Ty : LPTy->elements())
+ for (Type *Ty : cast<StructType>(LP.getType())->elements())
Tys.push_back(getLLTForType(*Ty, *DL));
+ assert(Tys.size() == 2 && "Only two-valued landingpads are supported");
// Mark exception register as live in.
Register ExceptionReg =
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 18283db1136dc..e5d83ca77463c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -1821,6 +1821,8 @@ void SelectionDAGBuilder::setValueToPoison(const Value *V, const SDLoc &dl) {
SmallVector<EVT, 4> ValueVTs;
ComputeValueVTs(DAG.getTargetLoweringInfo(), DAG.getDataLayout(),
V->getType(), ValueVTs);
+ if (ValueVTs.empty())
+ return;
setValue(V, DAG.getErrorMergeValues(ValueVTs, SDValue(), dl));
}
@@ -3652,24 +3654,23 @@ void SelectionDAGBuilder::visitLandingPad(const LandingPadInst &LP) {
if (LP.getType()->isTokenTy())
return;
- SmallVector<EVT, 2> ValueVTs;
+ // LangRef leaves the result type target-specific, so diagnose types this
+ // lowering cannot represent instead of asserting.
SDLoc dl = getCurSDLoc();
- ComputeValueVTs(TLI, DAG.getDataLayout(), LP.getType(), ValueVTs);
-
- // Only the two-valued (exception pointer, selector) form can be lowered.
- // LangRef leaves the result type target-specific, so diagnose other shapes
- // instead of asserting.
- if (ValueVTs.size() != 2) {
+ if (!isExceptionPointerAndSelectorType(LP.getType())) {
DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
*LP.getFunction(),
- "landingpad result type must consist of exactly two values, the "
- "exception pointer and the selector",
+ "landingpad result type must be a struct of an exception pointer and "
+ "an integer selector",
dl.getDebugLoc()));
- if (!ValueVTs.empty())
- setValueToPoison(&LP, dl);
+ setValueToPoison(&LP, dl);
return;
}
+ SmallVector<EVT, 2> ValueVTs;
+ ComputeValueVTs(TLI, DAG.getDataLayout(), LP.getType(), ValueVTs);
+ assert(ValueVTs.size() == 2 && "Only two-valued landingpads are supported");
+
// Get the two live-in registers as SDValues. The physregs have already been
// copied into virtual registers.
SDValue Ops[2];
diff --git a/llvm/test/CodeGen/X86/pr220959.ll b/llvm/test/CodeGen/X86/pr220959.ll
index ef03c662e9a59..89e56037b9753 100644
--- a/llvm/test/CodeGen/X86/pr220959.ll
+++ b/llvm/test/CodeGen/X86/pr220959.ll
@@ -1,11 +1,10 @@
; RUN: not llc %s -mtriple=x86_64-unknown-linux-gnu -filetype=null 2>&1 | FileCheck %s
; RUN: not llc %s -mtriple=x86_64-unknown-linux-gnu -O0 -filetype=null 2>&1 | FileCheck %s
-; A landingpad whose result type is not (exception pointer, selector) used to
-; trip an assertion in SelectionDAGBuilder::visitLandingPad. Expect a clean
-; diagnostic instead.
+; Landingpad result types other than (exception pointer, integer selector) used
+; to trip an assertion in SelectionDAGBuilder::visitLandingPad.
-; CHECK: error: {{.*}}in function main{{.*}}landingpad result type must consist of exactly two values, the exception pointer and the selector
+; CHECK: error: {{.*}}in function main{{.*}}landingpad result type must be a struct of an exception pointer and an integer selector
define i32 @main() personality ptr @__gxx_personality_v0 {
invoke void @g()
to label %cont unwind label %cleanup
@@ -17,7 +16,7 @@ cleanup:
ret i32 1
}
-; CHECK: error: {{.*}}in function scalar{{.*}}landingpad result type must consist of exactly two values, the exception pointer and the selector
+; CHECK: error: {{.*}}in function scalar{{.*}}landingpad result type must be a struct of an exception pointer and an integer selector
define i32 @scalar() personality ptr @__gxx_personality_v0 {
invoke void @g()
to label %cont unwind label %cleanup
@@ -29,8 +28,8 @@ cleanup:
ret i32 %lp
}
-; CHECK: error: {{.*}}in function three_values{{.*}}landingpad result type must consist of exactly two values, the exception pointer and the selector
-define i32 @three_values() personality ptr @__gxx_personality_v0 {
+; CHECK: error: {{.*}}in function three_elements{{.*}}landingpad result type must be a struct of an exception pointer and an integer selector
+define i32 @three_elements() personality ptr @__gxx_personality_v0 {
invoke void @g()
to label %cont unwind label %cleanup
cont:
@@ -42,5 +41,19 @@ cleanup:
ret i32 %sel
}
+; Right element count, wrong element type.
+; CHECK: error: {{.*}}in function float_exception{{.*}}landingpad result type must be a struct of an exception pointer and an integer selector
+define float @float_exception() personality ptr @__gxx_personality_v0 {
+ invoke void @g()
+ to label %cont unwind label %cleanup
+cont:
+ ret float 0.0
+cleanup:
+ %lp = landingpad { float, i32 }
+ cleanup
+ %exn = extractvalue { float, i32 } %lp, 0
+ ret float %exn
+}
+
declare void @g()
declare i32 @__gxx_personality_v0(...)
>From 17f14e7cfba7a96d13ed9e5cc7da8cdf3a9e5c96 Mon Sep 17 00:00:00 2001
From: Akash Manna <akash.manna.mymail at gmail.com>
Date: Sun, 13 Sep 2026 15:24:27 +0530
Subject: [PATCH 3/3] Fix the formatting
---
llvm/include/llvm/CodeGen/Analysis.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/include/llvm/CodeGen/Analysis.h b/llvm/include/llvm/CodeGen/Analysis.h
index a68dac6f6ee9d..4ee4f39b5869e 100644
--- a/llvm/include/llvm/CodeGen/Analysis.h
+++ b/llvm/include/llvm/CodeGen/Analysis.h
@@ -99,7 +99,8 @@ LLVM_ABI void computeValueLLTs(const DataLayout &DL, Type &Ty,
LLVM_ABI GlobalValue *ExtractTypeInfo(Value *V);
/// Return true if landingpad result type \p Ty is a struct of an exception
-/// pointer (pointer or integer) and an integer selector, the only lowerable form.
+/// pointer (pointer or integer) and an integer selector, the only lowerable
+/// form.
LLVM_ABI bool isExceptionPointerAndSelectorType(Type *Ty);
/// getFCmpCondCode - Return the ISD condition code corresponding to
More information about the llvm-commits
mailing list