mirror of https://github.com/microsoft/clang.git
[mips] Handle transparent unions correctly.
Summary: This fixes MultiSource/Applications/lemon on big-endian N32 by correcting the handling of the argument to wait(). glibc defines it as a transparent union of void* and int*. Such unions are passed according to the rules of the first member so the argument must be passed as if it were a void* (sign extended from i32 to i64) and not as a union (shifted to the upper bits of an i64). wait() already behaves correctly on big-endian O32 and N64 since the union is already the same size as an argument slot. Reviewers: atanasyan Reviewed By: atanasyan Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D6963 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@225981 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6c1b926674
commit
e90c8e8c4e
|
@ -5693,6 +5693,8 @@ llvm::Type *MipsABIInfo::getPaddingType(uint64_t OrigOffset,
|
|||
|
||||
ABIArgInfo
|
||||
MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
|
||||
Ty = useFirstFieldIfTransparentUnion(Ty);
|
||||
|
||||
uint64_t OrigOffset = Offset;
|
||||
uint64_t TySize = getContext().getTypeSize(Ty);
|
||||
uint64_t Align = getContext().getTypeAlign(Ty) / 8;
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// RUN: %clang_cc1 -triple mips64-linux-gnu -S -o - -emit-llvm %s | FileCheck %s
|
||||
//
|
||||
// Transparent unions are passed according to the calling convention rules of
|
||||
// the first member. In this case, it is as if it were a void pointer so we
|
||||
// do not have the inreg attribute we would normally have for unions.
|
||||
//
|
||||
// This comes up in glibc's wait() function and matters for the big-endian N32
|
||||
// case where pointers are promoted to i64 and a non-transparent union would be
|
||||
// passed in the upper 32-bits of an i64.
|
||||
|
||||
union either_pointer {
|
||||
void *void_ptr;
|
||||
int *int_ptr;
|
||||
} __attribute__((transparent_union));
|
||||
|
||||
extern void foo(union either_pointer p);
|
||||
|
||||
int data;
|
||||
|
||||
void bar(void) {
|
||||
return foo(&data);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define void @bar()
|
||||
// CHECK: call void @foo(i8* %{{[0-9]+}})
|
||||
|
||||
// CHECK: declare void @foo(i8*)
|
Loading…
Reference in New Issue