[PATCH] D21611: Fix small structures calling convention issue for some big endian architectures
Strahinja Petrovic via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 22 09:35:26 PDT 2016
spetrovic created this revision.
spetrovic added reviewers: rjmccall, john.brawn, dsanders, petarj.
spetrovic added subscribers: cfe-commits, rankov, ivanbaev.
Herald added a reviewer: vkalintiris.
Herald added a subscriber: aemerson.
This patch fixes problem with passing structures and unions smaller than register as argument in variadic functions
on big endian architectures.
For example passing 3 chars in a structure as argument of variadic function LLVM is passing those chars
left-adjusted in register and trying to read them like they are right-adjusted, and that makes the problem.
I have changed reading of those arguments. Now LLVM reads them properly (left-adjusted). I detected
this problem on ARM32 big endian, MIPS32 big endian and MIPS64 big endian.
http://reviews.llvm.org/D21611
Files:
lib/CodeGen/TargetInfo.cpp
test/CodeGen/struct-union-BE.c
Index: test/CodeGen/struct-union-BE.c
===================================================================
--- test/CodeGen/struct-union-BE.c
+++ test/CodeGen/struct-union-BE.c
@@ -0,0 +1,48 @@
+// RUN: %clang -O2 -target mips-linux-gnu -EB -S -emit-llvm %s -o - | FileCheck %s -check-prefix=MIPS
+// RUN: %clang -O2 -target mips64-linux-gnu -EB -S -emit-llvm %s -o - | FileCheck %s -check-prefix=MIPS64
+// RUN: %clang -O2 -target armeb-linux-gnueabihf -march=armv7a -EB -S -emit-llvm %s -o - | FileCheck %s -check-prefix=ARM
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+struct tiny {
+ char c;
+};
+
+union data {
+ char c;
+};
+
+void fstr(int n, ...) {
+ struct tiny x;
+ va_list ap;
+ va_start (ap,n);
+ x = va_arg (ap, struct tiny);
+ if (x.c != 10)
+ abort();
+ va_end (ap);
+// MIPS-NOT: %{{[0-9]+}} = getelementptr inbounds i8, i8* %argp.cur, i32 3
+// MIPS64-NOT: %{{[0-9]+}} = getelementptr inbounds i8, i8* %argp.cur, i64 7
+// ARM-NOT: %{{[0-9]+}} = getelementptr inbounds i8, i8* %argp.cur, i32 3
+}
+
+void funi(int n, ...) {
+ union data x;
+ va_list ap;
+ va_start (ap,n);
+ x = va_arg (ap, union data);
+ if (x.c != 10)
+ abort();
+ va_end (ap);
+// MIPS-NOT: %{{[0-9]+}} = getelementptr inbounds i8, i8* %argp.cur, i32 3
+// MIPS64-NOT: %{{[0-9]+}} = getelementptr inbounds i8, i8* %argp.cur, i64 7
+// ARM-NOT: %{{[0-9]+}} = getelementptr inbounds i8, i8* %argp.cur, i32 3
+}
+
+void foo() {
+ struct tiny x[3];
+ union data y;
+ x[0].c = 10;
+ fstr(1, x[0]);
+ funi(1, y);
+}
Index: lib/CodeGen/TargetInfo.cpp
===================================================================
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -272,7 +272,8 @@
// If the argument is smaller than a slot, and this is a big-endian
// target, the argument will be right-adjusted in its slot.
- if (DirectSize < SlotSize && CGF.CGM.getDataLayout().isBigEndian()) {
+ if (DirectSize < SlotSize && CGF.CGM.getDataLayout().isBigEndian() &&
+ !DirectTy->isStructTy()) {
Addr = CGF.Builder.CreateConstInBoundsByteGEP(Addr, SlotSize - DirectSize);
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D21611.61557.patch
Type: text/x-patch
Size: 2116 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160622/bbc2562f/attachment.bin>
More information about the cfe-commits
mailing list