[llvm-commits] [llvm-gcc-4.2] r51799 - in /llvm-gcc-4.2/trunk/gcc: config/i386/llvm-i386-target.h config/i386/llvm-i386.cpp llvm-abi.h
Dale Johannesen
dalej at apple.com
Fri May 30 16:16:47 PDT 2008
Author: johannes
Date: Fri May 30 18:16:47 2008
New Revision: 51799
URL: http://llvm.org/viewvc/llvm-project?rev=51799&view=rev
Log:
More x86-64 ABI conformance. Handles struct parameters
shorter than 16 bytes and not multiple of size 8 the same
way as gcc (although arguably not correctly).
Modified:
llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h
llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp
llvm-gcc-4.2/trunk/gcc/llvm-abi.h
Modified: llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h?rev=51799&r1=51798&r2=51799&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h (original)
+++ llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h Fri May 30 18:16:47 2008
@@ -98,15 +98,16 @@
isSingleElementStructOrArray(X, true, false)
#endif
-extern bool llvm_x86_should_pass_aggregate_in_integer_regs(tree, unsigned*);
+extern bool llvm_x86_should_pass_aggregate_in_integer_regs(tree,
+ unsigned*, bool*);
/* LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS - Return true if this aggregate
value should be passed in integer registers. This differs from the usual
handling in that x86-64 passes 128-bit structs and unions which only
contain data in the first 64 bits, as 64-bit objects. (These can be
created by abusing __attribute__((aligned)). */
-#define LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(X, Y) \
- llvm_x86_should_pass_aggregate_in_integer_regs((X), (Y))
+#define LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(X, Y, Z) \
+ llvm_x86_should_pass_aggregate_in_integer_regs((X), (Y), (Z))
extern bool llvm_x86_should_pass_vector_in_integer_regs(tree);
Modified: llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp?rev=51799&r1=51798&r2=51799&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp Fri May 30 18:16:47 2008
@@ -1291,25 +1291,32 @@
/// llvm_x86_should_pass_aggregate_in_integer_regs - x86-32 is same as the
/// default. x86-64 detects the case where a type is 16 bytes long but
/// only 8 of them are passed, the rest being padding (*size is set to 8
-/// to identify this case).
-bool llvm_x86_should_pass_aggregate_in_integer_regs(tree type, unsigned *size)
+/// to identify this case). It also pads out the size to that of a full
+/// register. This means we'll be loading bytes off the end of the object
+/// in some cases. That's what gcc does, so it must be OK, right? Right?
+bool llvm_x86_should_pass_aggregate_in_integer_regs(tree type, unsigned *size,
+ bool *DontCheckAlignment)
{
*size = 0;
if (TARGET_64BIT) {
enum x86_64_reg_class Class[MAX_CLASSES];
enum machine_mode Mode = ix86_getNaturalModeForType(type);
int NumClasses = ix86_ClassifyArgument(Mode, type, Class, 0);
+ *DontCheckAlignment= true;
if (NumClasses == 1 && (Class[0] == X86_64_INTEGERSI_CLASS ||
Class[0] == X86_64_INTEGER_CLASS)) {
/* 8 byte object, one int register */
+ *size = 8;
return true;
}
if (NumClasses == 2 && (Class[0] == X86_64_INTEGERSI_CLASS ||
Class[0] == X86_64_INTEGER_CLASS)) {
if (Class[1] == X86_64_INTEGERSI_CLASS ||
- Class[1] == X86_64_INTEGER_CLASS)
+ Class[1] == X86_64_INTEGER_CLASS) {
/* 16 byte object, 2 int registers */
+ *size = 16;
return true;
+ }
if (Class[1] == X86_64_NO_CLASS) {
/* 16 byte object, only 1st register has information */
*size = 8;
Modified: llvm-gcc-4.2/trunk/gcc/llvm-abi.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-abi.h?rev=51799&r1=51798&r2=51799&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-abi.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-abi.h Fri May 30 18:16:47 2008
@@ -277,7 +277,7 @@
// single element is a bitfield of a type bigger than the struct; the code
// for field-by-field struct passing does not handle this one right.
#ifndef LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS
-#define LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(X, Y) \
+#define LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(X, Y, Z) \
!isSingleElementStructOrArray((X), false, true)
#endif
@@ -403,6 +403,7 @@
void HandleArgument(tree type, std::vector<const Type*> &ScalarElts,
ParameterAttributes *Attributes = NULL) {
unsigned Size = 0;
+ bool DontCheckAlignment = false;
const Type *Ty = ConvertType(type);
// Figure out if this field is zero bits wide, e.g. {} or [0 x int]. Do
// not include variable sized fields here.
@@ -413,7 +414,7 @@
ScalarElts.push_back(PtrTy);
} else if (Ty->getTypeID()==Type::VectorTyID) {
if (LLVM_SHOULD_PASS_VECTOR_IN_INTEGER_REGS(type)) {
- PassInIntegerRegisters(type, Ty, ScalarElts, 0);
+ PassInIntegerRegisters(type, Ty, ScalarElts, 0, false);
} else {
C.HandleScalarArgument(Ty, type);
ScalarElts.push_back(Ty);
@@ -439,8 +440,9 @@
*Attributes |=
ParamAttr::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
}
- } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(type, &Size)) {
- PassInIntegerRegisters(type, Ty, ScalarElts, Size);
+ } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(type, &Size,
+ &DontCheckAlignment)) {
+ PassInIntegerRegisters(type, Ty, ScalarElts, Size, DontCheckAlignment);
} else if (isZeroSizedStructOrUnion(type)) {
// Zero sized struct or union, just drop it!
;
@@ -524,7 +526,7 @@
/// of the struct elements in. If Size is set we pass only that many bytes.
void PassInIntegerRegisters(tree type, const Type *Ty,
std::vector<const Type*> &ScalarElts,
- unsigned origSize) {
+ unsigned origSize, bool DontCheckAlignment) {
unsigned Size;
if (origSize)
Size = origSize;
@@ -537,7 +539,7 @@
// from Int64 alignment. ARM backend needs this.
unsigned Align = TYPE_ALIGN(type)/8;
unsigned Int64Align = getTargetData().getABITypeAlignment(Type::Int64Ty);
- bool UseInt64 = (Align >= Int64Align);
+ bool UseInt64 = DontCheckAlignment ? true : (Align >= Int64Align);
// FIXME: In cases where we can, we should use the original struct.
// Consider cases like { int, int } and {int, short} for example! This will
More information about the llvm-commits
mailing list