[llvm-commits] [llvm-gcc-4.2] r51723 - in /llvm-gcc-4.2/trunk/gcc: config/i386/llvm-i386-target.h config/i386/llvm-i386.cpp config/rs6000/llvm-rs6000.cpp llvm-abi.h
Dale Johannesen
dalej at apple.com
Thu May 29 18:23:12 PDT 2008
Author: johannes
Date: Thu May 29 20:23:12 2008
New Revision: 51723
URL: http://llvm.org/viewvc/llvm-project?rev=51723&view=rev
Log:
X86-64 ABI fix. Revert isSingleElementStructOrArray
change in favor of a more general version which handles
the case where there's more than one element correctly.
Fixes gcc.dg/compat/struct-layout-1.exp/t003
and many more.
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/config/rs6000/llvm-rs6000.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=51723&r1=51722&r2=51723&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 Thu May 29 20:23:12 2008
@@ -95,17 +95,18 @@
considered as if they were the type of the data field. */
#ifndef LLVM_SHOULD_RETURN_SELT_STRUCT_AS_SCALAR
#define LLVM_SHOULD_RETURN_SELT_STRUCT_AS_SCALAR(X) \
- isSingleElementStructOrArray(X, true, false, false)
+ isSingleElementStructOrArray(X, true, false)
#endif
+extern bool llvm_x86_should_pass_aggregate_in_integer_regs(tree, unsigned*);
+
/* 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 single-int-element unions as the type of the
- field. */
-#define LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(X) \
- (TARGET_64BIT ? \
- !isSingleElementStructOrArray((X), true, true, true) : \
- !isSingleElementStructOrArray((X), false, true, false))
+ 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))
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=51723&r1=51722&r2=51723&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 Thu May 29 20:23:12 2008
@@ -1288,4 +1288,38 @@
return Loc;
}
+/// 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)
+{
+ *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);
+ if (NumClasses == 1 && (Class[0] == X86_64_INTEGERSI_CLASS ||
+ Class[0] == X86_64_INTEGER_CLASS)) {
+ /* 8 byte object, one int register */
+ 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)
+ /* 16 byte object, 2 int registers */
+ return true;
+ if (Class[1] == X86_64_NO_CLASS) {
+ /* 16 byte object, only 1st register has information */
+ *size = 8;
+ return true;
+ }
+ }
+ return false;
+ }
+ else
+ return !isSingleElementStructOrArray(type, false, true);
+}
+
/* LLVM LOCAL end (ENTIRE FILE!) */
Modified: llvm-gcc-4.2/trunk/gcc/config/rs6000/llvm-rs6000.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/rs6000/llvm-rs6000.cpp?rev=51723&r1=51722&r2=51723&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/config/rs6000/llvm-rs6000.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/config/rs6000/llvm-rs6000.cpp Thu May 29 20:23:12 2008
@@ -404,7 +404,7 @@
// some zero-length fields as well, must be passed as the field type.
// Note this does not apply to long double.
// This is required for ABI correctness.
- tree tType = isSingleElementStructOrArray(TreeType, true, false, false);
+ tree tType = isSingleElementStructOrArray(TreeType, true, false);
if (tType && int_size_in_bytes(tType)==Bytes && TYPE_MODE(tType)!=TFmode &&
(TREE_CODE(tType)!=VECTOR_TYPE || Bytes==16))
return false;
@@ -437,7 +437,7 @@
// Other single-element structs may be passed this way as well, but
// only if the type size matches the element's type size (structs that
// violate this can be created with __aligned__).
- tree tType = isSingleElementStructOrArray(TreeType, true, false, false);
+ tree tType = isSingleElementStructOrArray(TreeType, true, false);
if (tType && int_size_in_bytes(tType)==SrcSize && TYPE_MODE(tType)!=TFmode &&
(TREE_CODE(tType)!=VECTOR_TYPE || SrcSize==16)) {
Elts.push_back(ConvertType(tType));
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=51723&r1=51722&r2=51723&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-abi.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-abi.h Thu May 29 20:23:12 2008
@@ -138,21 +138,17 @@
/// rejectFatBitField, and the single element is a bitfield of a type that's
/// bigger than the struct, return null anyway.
static tree isSingleElementStructOrArray(tree type, bool ignoreZeroLength,
- bool rejectFatBitfield,
- bool acceptUnions) {
+ bool rejectFatBitfield) {
// Scalars are good.
if (!isAggregateTreeType(type)) return type;
tree FoundField = 0;
switch (TREE_CODE(type)) {
case QUAL_UNION_TYPE:
+ case UNION_TYPE: // Single element unions don't count.
case COMPLEX_TYPE: // Complex values are like 2-element records.
default:
return 0;
- case UNION_TYPE: // Single element unions don't count.
- if (!acceptUnions)
- return 0;
- // fall through
case RECORD_TYPE:
// If this record has variable length, reject it.
if (TREE_CODE(TYPE_SIZE(type)) != INTEGER_CST)
@@ -178,15 +174,13 @@
}
}
return FoundField ? isSingleElementStructOrArray(FoundField,
- ignoreZeroLength, false,
- false)
+ ignoreZeroLength, false)
: 0;
case ARRAY_TYPE:
const ArrayType *Ty = dyn_cast<ArrayType>(ConvertType(type));
if (!Ty || Ty->getNumElements() != 1)
return 0;
- return isSingleElementStructOrArray(TREE_TYPE(type), false, false,
- false);
+ return isSingleElementStructOrArray(TREE_TYPE(type), false, false);
}
}
@@ -283,8 +277,8 @@
// 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) \
- !isSingleElementStructOrArray(X, false, true, false)
+#define LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(X, Y) \
+ !isSingleElementStructOrArray((X), false, true)
#endif
// LLVM_SHOULD_RETURN_SELT_STRUCT_AS_SCALAR - Return a TYPE tree if this single
@@ -295,7 +289,7 @@
// by abusing the __aligned__ attribute.)
#ifndef LLVM_SHOULD_RETURN_SELT_STRUCT_AS_SCALAR
#define LLVM_SHOULD_RETURN_SELT_STRUCT_AS_SCALAR(X) \
- isSingleElementStructOrArray(X, false, false, false)
+ isSingleElementStructOrArray(X, false, false)
#endif
// LLVM_SHOULD_RETURN_VECTOR_AS_SCALAR - Return a TYPE tree if this vector type
@@ -408,6 +402,7 @@
/// their fields.
void HandleArgument(tree type, std::vector<const Type*> &ScalarElts,
ParameterAttributes *Attributes = NULL) {
+ unsigned Size = 0;
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.
@@ -418,7 +413,7 @@
ScalarElts.push_back(PtrTy);
} else if (Ty->getTypeID()==Type::VectorTyID) {
if (LLVM_SHOULD_PASS_VECTOR_IN_INTEGER_REGS(type)) {
- PassInIntegerRegisters(type, Ty, ScalarElts);
+ PassInIntegerRegisters(type, Ty, ScalarElts, 0);
} else {
C.HandleScalarArgument(Ty, type);
ScalarElts.push_back(Ty);
@@ -444,8 +439,8 @@
*Attributes |=
ParamAttr::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
}
- } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(type)) {
- PassInIntegerRegisters(type, Ty, ScalarElts);
+ } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(type, &Size)) {
+ PassInIntegerRegisters(type, Ty, ScalarElts, Size);
} else if (isZeroSizedStructOrUnion(type)) {
// Zero sized struct or union, just drop it!
;
@@ -526,10 +521,15 @@
/// PassInIntegerRegisters - Given an aggregate value that should be passed in
/// integer registers, convert it to a structure containing ints and pass all
- /// of the struct elements in.
+ /// 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 Size = TREE_INT_CST_LOW(TYPE_SIZE(type))/8;
+ std::vector<const Type*> &ScalarElts,
+ unsigned origSize) {
+ unsigned Size;
+ if (origSize)
+ Size = origSize;
+ else
+ Size = TREE_INT_CST_LOW(TYPE_SIZE(type))/8;
// FIXME: We should preserve all aggregate value alignment information.
// Work around to preserve some aggregate value alignment information:
@@ -568,7 +568,7 @@
Elts.push_back(Type::Int8Ty);
Size -= 1;
}
- assert(Size == 0 && "Didn't cover value?");
+ assert((origSize || Size == 0) && "Didn't cover value?");
const StructType *STy = StructType::get(Elts, false);
unsigned i = 0;
More information about the llvm-commits
mailing list