mirror of
https://github.com/intel/llvm.git
synced 2026-01-29 04:16:38 +08:00
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:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
48
clang/test/CodeGen/struct-union-BE.c
Normal file
48
clang/test/CodeGen/struct-union-BE.c
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user