-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[X86_64] fix empty structure vaarg in c++ #77903
Conversation
@llvm/pr-subscribers-backend-x86 @llvm/pr-subscribers-clang-codegen Author: None (hstk30-hw) ChangesSizeInBytes of empty structure is 0 in C, while 1 in C++. And empty structure argument of the function is ignored in X86_64 backend.As a result, the value of variable arguments in C++ is incorrect. #77036 Full diff: https://github.com/llvm/llvm-project/pull/77903.diff 2 Files Affected:
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index d053f41ab168f5..fde76ed6709cef 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2989,6 +2989,11 @@ static Address EmitX86_64VAArgFromMemory(CodeGenFunction &CGF,
// an 8 byte boundary.
uint64_t SizeInBytes = (CGF.getContext().getTypeSize(Ty) + 7) / 8;
+
+ if (isEmptyRecord(CGF.getContext(), Ty, true)) {
+ SizeInBytes = 0;
+ }
+
llvm::Value *Offset =
llvm::ConstantInt::get(CGF.Int32Ty, (SizeInBytes + 7) & ~7);
overflow_arg_area = CGF.Builder.CreateGEP(CGF.Int8Ty, overflow_arg_area,
diff --git a/clang/test/CodeGen/X86/x86_64-vaarg.c b/clang/test/CodeGen/X86/x86_64-vaarg.c
new file mode 100644
index 00000000000000..ae201a2d3f3017
--- /dev/null
+++ b/clang/test/CodeGen/X86/x86_64-vaarg.c
@@ -0,0 +1,15 @@
+// RUN: %clang -xc++ -target x86_64-linux-gnu -emit-llvm -S -o - %s | FileCheck %s
+
+struct Empty {};
+
+struct Empty emptyvar;
+
+void take_args(int a, ...) {
+ // CHECK: %overflow_arg_area = load ptr, ptr %overflow_arg_area_p, align 8
+ // CHECK-NEXT: %overflow_arg_area.next = getelementptr i8, ptr %overflow_arg_area, i32 0
+ // CHECK-NEXT: store ptr %overflow_arg_area.next, ptr %overflow_arg_area_p, align 8
+ __builtin_va_list l;
+ __builtin_va_start(l, a);
+ emptyvar = __builtin_va_arg(l, struct Empty);
+ __builtin_va_end(l);
+}
|
You can test this locally with the following command:git-clang-format --diff 4d467215f162b487381e17b8cb59283af75ca50e 6891699009f796ec1c09fad268aa8ef51a1ada36 -- clang/test/CodeGen/X86/x86_64-vaarg.c clang/lib/CodeGen/Targets/X86.cpp View the diff from clang-format here.diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index c2c1128083..4f9e903b8f 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2991,7 +2991,7 @@ static Address EmitX86_64VAArgFromMemory(CodeGenFunction &CGF,
uint64_t SizeInBytes = (CGF.getContext().getTypeSize(Ty) + 7) / 8;
if (isEmptyRecord(CGF.getContext(), Ty, true)) {
- SizeInBytes = 0;
+ SizeInBytes = 0;
}
llvm::Value *Offset =
|
SizeInBytes of empty structure is 0 in C, while 1 in C++. And empty structure argument of the function is ignored in X86_64 backend.As a result, the value of variable arguments in C++ is incorrect.
SizeInBytes of empty structure is 0 in C, while 1 in C++. And empty structure argument of the function is ignored in X86_64 backend.As a result, the value of variable arguments in C++ is incorrect.
SizeInBytes of empty structure is 0 in C, while 1 in C++. And empty structure argument of the function is ignored in X86_64 backend.As a result, the value of variable arguments in C++ is incorrect. #77036