This patch fixes problem with passing structures and unions

smaller than register as argument in variadic functions on
big endian architectures.
Differential Revision: http://reviews.llvm.org/D21611

llvm-svn: 273665
This commit is contained in:
Strahinja Petrovic
2016-06-24 12:12:41 +00:00
parent 034d2c92e8
commit 515a1eb44c
2 changed files with 50 additions and 1 deletions

View File

@@ -272,7 +272,8 @@ static Address emitVoidPtrDirectVAArg(CodeGenFunction &CGF,
// 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);
}

View File

@@ -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);
}