[llvm] [SelectionDAG][GlobalISel] Diagnose va_arg with an aggregate type (PR #225091)

via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 21 07:01:55 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: Timur Baidusenov (bai-tim)

<details>
<summary>Changes</summary>

The code generator does not support va_arg with an aggregate type on any target, as LangRef notes, but instead of saying so it crashed. SelectionDAG asked for the value type of the aggregate and hit "Unknown type!" in MVT::getVT(), and the IRTranslator asked for the single vreg to define and hit "attempt to get single VReg for aggregate or void". Report the construct as unsupported in SelectionDAG, and have the IRTranslator give up on it so that the fallback to SelectionDAG reports it too.

Fixes #<!-- -->162900.

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


4 Files Affected:

- (modified) llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp (+5) 
- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (+11) 
- (added) llvm/test/CodeGen/AArch64/GlobalISel/vaarg-aggregate-fallback.ll (+14) 
- (added) llvm/test/CodeGen/X86/vaarg-aggregate.ll (+24) 


``````````diff
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index d9e88f22ac2ca..a00f5aeaede2e 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -4086,6 +4086,11 @@ bool IRTranslatorImpl::translateAlloca(const User &U,
 
 bool IRTranslatorImpl::translateVAArg(const User &U,
                                       MachineIRBuilder &MIRBuilder) {
+  // The code generator does not support va_arg with an aggregate type, and an
+  // aggregate has no single vreg to define here.
+  if (U.getType()->isAggregateType())
+    return false;
+
   // FIXME: We may need more info about the type. Because of how LLT works,
   // we're completely discarding the i64/double distinction here (amongst
   // others). Fortunately the ABIs I know of where that matters don't use va_arg
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 065347d903033..8f03010256755 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -10905,6 +10905,17 @@ void SelectionDAGBuilder::visitVAStart(const CallInst &I) {
 }
 
 void SelectionDAGBuilder::visitVAArg(const VAArgInst &I) {
+  // The code generator does not support va_arg with an aggregate type on any
+  // target, and such a type has no value type to lower it to.
+  if (I.getType()->isAggregateType()) {
+    SDLoc sdl = getCurSDLoc();
+    DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
+        *I.getFunction(), "va_arg with an aggregate type is not supported",
+        sdl.getDebugLoc()));
+    setValueToPoison(&I, sdl);
+    return;
+  }
+
   const TargetLowering &TLI = DAG.getTargetLoweringInfo();
   const DataLayout &DL = DAG.getDataLayout();
   SDValue V = DAG.getVAArg(
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/vaarg-aggregate-fallback.ll b/llvm/test/CodeGen/AArch64/GlobalISel/vaarg-aggregate-fallback.ll
new file mode 100644
index 0000000000000..b9f753881fd45
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/vaarg-aggregate-fallback.ll
@@ -0,0 +1,14 @@
+; RUN: not llc %s -mtriple=aarch64-- -O0 -global-isel -global-isel-abort=2 \
+; RUN:   -pass-remarks-missed='gisel*' -filetype=null 2>&1 | FileCheck %s
+
+; The code generator does not support va_arg with an aggregate type. The
+; IRTranslator gives up on it, so that the fallback to SelectionDAG reports it
+; instead of crashing (see issue #162900).
+
+; CHECK: remark: {{.*}}unable to translate instruction: va_arg:{{.*}}(in function: struct)
+; CHECK: warning: Instruction selection used fallback path for struct
+; CHECK: error: {{.*}}in function struct {{.*}}: va_arg with an aggregate type is not supported
+define { i32, i64 } @struct(ptr %ap) {
+  %v = va_arg ptr %ap, { i32, i64 }
+  ret { i32, i64 } %v
+}
diff --git a/llvm/test/CodeGen/X86/vaarg-aggregate.ll b/llvm/test/CodeGen/X86/vaarg-aggregate.ll
new file mode 100644
index 0000000000000..083d65e242cdf
--- /dev/null
+++ b/llvm/test/CodeGen/X86/vaarg-aggregate.ll
@@ -0,0 +1,24 @@
+; RUN: not llc %s -mtriple=x86_64-- -filetype=null 2>&1 | FileCheck %s
+; RUN: not llc %s -mtriple=x86_64-- -O0 -filetype=null 2>&1 | FileCheck %s
+; RUN: not llc %s -mtriple=i686-- -filetype=null 2>&1 | FileCheck %s
+
+; The code generator does not support va_arg with an aggregate type on any
+; target. Emit a clean diagnostic instead of crashing (see issue #162900).
+
+; CHECK: error: {{.*}}in function packed_struct {{.*}}: va_arg with an aggregate type is not supported
+define <{ i32 }> @packed_struct(ptr %ap) {
+  %v = va_arg ptr %ap, <{ i32 }>
+  ret <{ i32 }> %v
+}
+
+; CHECK: error: {{.*}}in function struct {{.*}}: va_arg with an aggregate type is not supported
+define { i32, i64 } @struct(ptr %ap) {
+  %v = va_arg ptr %ap, { i32, i64 }
+  ret { i32, i64 } %v
+}
+
+; CHECK: error: {{.*}}in function array {{.*}}: va_arg with an aggregate type is not supported
+define [2 x i32] @array(ptr %ap) {
+  %v = va_arg ptr %ap, [2 x i32]
+  ret [2 x i32] %v
+}

``````````

</details>


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


More information about the llvm-commits mailing list