[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)
Longsheng Mou via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 1 21:52:28 PDT 2024
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/86075
>From 355f540288d87ca35a8e5790e4eaff383d619201 Mon Sep 17 00:00:00 2001
From: Longsheng Mou <moulongsheng at huawei.com>
Date: Thu, 21 Mar 2024 11:23:56 +0800
Subject: [PATCH] [X86_32] Teach X86_32 va_arg to ignore empty structs.
Empty structs are ignored for parameter passing purposes, but va_arg was
incrementing the pointer anyway for that the size of empty struct in c++
is 1 byte, which could lead to va_list getting out of sync.
---
clang/lib/CodeGen/Targets/X86.cpp | 6 ++++++
clang/test/CodeGenCXX/x86_32-vaarg.cpp | 20 ++++++++++++++++++++
2 files changed, 26 insertions(+)
create mode 100644 clang/test/CodeGenCXX/x86_32-vaarg.cpp
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 1146a851a7715d..c831777699f627 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF,
auto TypeInfo = getContext().getTypeInfoInChars(Ty);
+ CCState State(*const_cast<CGFunctionInfo *>(CGF.CurFnInfo));
+ ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0);
+ // Empty records are ignored for parameter passing purposes.
+ if (AI.isIgnore())
+ return CGF.CreateMemTemp(Ty);
+
// x86-32 changes the alignment of certain arguments on the stack.
//
// Just messing with TypeInfo like this works because we never pass
diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
new file mode 100644
index 00000000000000..23eac1164118c6
--- /dev/null
+++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
@@ -0,0 +1,20 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -x c -o - %s | FileCheck %s
+
+typedef struct {} empty;
+
+// CHECK-LABEL: @{{.*}}empty_record_test
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[LIST:%.*]] = alloca ptr, align 4
+// CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
+// CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
+// CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT: call void @llvm.va_start(ptr [[LIST]])
+empty empty_record_test(int z, ...) {
+ __builtin_va_list list;
+ __builtin_va_start(list, z);
+ return __builtin_va_arg(list, empty);
+}
More information about the cfe-commits
mailing list