[llvm-commits] [llvm-gcc-4.2] r50492 - in /llvm-gcc-4.2/branches/Apple/Tak/gcc: config/i386/llvm-i386-target.h config/i386/llvm-i386.cpp llvm-abi.h llvm-convert.cpp llvm-types.cpp
Bill Wendling
isanbard at gmail.com
Wed Apr 30 12:50:27 PDT 2008
Author: void
Date: Wed Apr 30 14:50:27 2008
New Revision: 50492
URL: http://llvm.org/viewvc/llvm-project?rev=50492&view=rev
Log:
Porting r50491 to Tak.
Modified:
llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386-target.h
llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386.cpp
llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-abi.h
llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-convert.cpp
llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-types.cpp
Modified: llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386-target.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386-target.h?rev=50492&r1=50491&r2=50492&view=diff
==============================================================================
--- llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386-target.h (original)
+++ llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386-target.h Wed Apr 30 14:50:27 2008
@@ -164,10 +164,20 @@
llvm_x86_32_should_pass_aggregate_in_mixed_regs(tree, const Type *Ty,
std::vector<const Type*>&);
-#define LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(T, TY, E) \
- (TARGET_64BIT ? \
- llvm_x86_64_should_pass_aggregate_in_mixed_regs((T), (TY), (E)) : \
+#define LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(T, TY, E) \
+ (TARGET_64BIT ? \
+ llvm_x86_64_should_pass_aggregate_in_mixed_regs((T), (TY), (E)) : \
llvm_x86_32_should_pass_aggregate_in_mixed_regs((T), (TY), (E)))
+
+extern
+bool llvm_x86_64_aggregate_partially_passed_in_regs(std::vector<const Type*>&,
+ std::vector<const Type*>&);
+
+#define LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(E, SE) \
+ (TARGET_64BIT ? \
+ llvm_x86_64_aggregate_partially_passed_in_regs((E), (SE)) : \
+ false)
+
#endif /* LLVM_ABI_H */
/* LLVM LOCAL end (ENTIRE FILE!) */
Modified: llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386.cpp?rev=50492&r1=50491&r2=50492&view=diff
==============================================================================
--- llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386.cpp (original)
+++ llvm-gcc-4.2/branches/Apple/Tak/gcc/config/i386/llvm-i386.cpp Wed Apr 30 14:50:27 2008
@@ -744,6 +744,82 @@
return llvm_x86_64_should_pass_aggregate_in_memory(TreeType, Mode);
}
+/* count_num_registers_uses - Return the number of GPRs and XMMs parameter
+ register used so far. */
+static void count_num_registers_uses(std::vector<const Type*> &ScalarElts,
+ unsigned &NumGPRs, unsigned &NumXMMs) {
+ NumGPRs = 0;
+ NumXMMs = 0;
+ for (unsigned i = 0, e = ScalarElts.size(); i != e; ++i) {
+ const Type *Ty = ScalarElts[i];
+ if (const VectorType *VTy = dyn_cast<VectorType>(Ty)) {
+ if (!TARGET_MACHO)
+ continue;
+ if (VTy->getNumElements() == 1)
+ // v1i64 is passed in GPRs on Darwin.
+ ++NumGPRs;
+ else
+ // All other vector scalar values are passed in XMM registers.
+ ++NumXMMs;
+ } else if (Ty->isInteger() || isa<PointerType>(Ty)) {
+ ++NumGPRs;
+ } else {
+ // Floating point scalar argument.
+ assert(Ty->isFloatingPoint() && Ty->isPrimitiveType() &&
+ "Expecting a floating point primitive type!");
+ if (Ty->getTypeID() == Type::FloatTyID
+ || Ty->getTypeID() == Type::DoubleTyID)
+ ++NumXMMs;
+ }
+ }
+}
+
+/* Target hook for llvm-abi.h. This is called when an aggregate is being passed
+ in registers. If there are only enough available parameter registers to pass
+ part of the aggregate, return true. That means the aggregate should instead
+ be passed in memory. */
+bool
+llvm_x86_64_aggregate_partially_passed_in_regs(std::vector<const Type*> &Elts,
+ std::vector<const Type*> &ScalarElts) {
+ // Counting number of GPRs and XMMs used so far. According to AMD64 ABI
+ // document: "If there are no registers available for any eightbyte of an
+ // argument, the whole argument is passed on the stack." X86-64 uses 6
+ // integer
+ // For example, if two GPRs are required but only one is available, then
+ // both parts will be in memory.
+ // FIXME: This is a temporary solution. To be removed when llvm has first
+ // class aggregate values.
+ unsigned NumGPRs = 0;
+ unsigned NumXMMs = 0;
+ count_num_registers_uses(ScalarElts, NumGPRs, NumXMMs);
+
+ unsigned NumGPRsNeeded = 0;
+ unsigned NumXMMsNeeded = 0;
+ count_num_registers_uses(Elts, NumGPRsNeeded, NumXMMsNeeded);
+
+ bool GPRsSatisfied = true;
+ if (NumGPRsNeeded) {
+ if (NumGPRs < 6) {
+ if ((NumGPRs + NumGPRsNeeded) > 6)
+ // Only partially satisfied.
+ return true;
+ } else
+ GPRsSatisfied = false;
+ }
+
+ bool XMMsSatisfied = true;
+ if (NumXMMsNeeded) {
+ if (NumXMMs < 8) {
+ if ((NumXMMs + NumXMMsNeeded) > 8)
+ // Only partially satisfied.
+ return true;
+ } else
+ XMMsSatisfied = false;
+ }
+
+ return !GPRsSatisfied || !XMMsSatisfied;
+}
+
/* Target hook for llvm-abi.h. It returns true if an aggregate of the
specified type should be passed in a number of registers of mixed types.
It also returns a vector of types that correspond to the registers used
@@ -792,17 +868,19 @@
Ty = STy->getElementType(0);
if (const VectorType *VTy = dyn_cast<VectorType>(Ty)) {
if (VTy->getNumElements() == 2) {
- if (VTy->getElementType()->isInteger())
+ if (VTy->getElementType()->isInteger()) {
Elts.push_back(VectorType::get(Type::Int64Ty, 2));
- else
+ } else {
Elts.push_back(VectorType::get(Type::DoubleTy, 2));
+ }
Bytes -= 8;
} else {
assert(VTy->getNumElements() == 4);
- if (VTy->getElementType()->isInteger())
+ if (VTy->getElementType()->isInteger()) {
Elts.push_back(VectorType::get(Type::Int32Ty, 4));
- else
+ } else {
Elts.push_back(VectorType::get(Type::FloatTy, 4));
+ }
Bytes -= 4;
}
} else if (llvm_x86_is_all_integer_types(Ty)) {
@@ -850,6 +928,7 @@
default: assert(0 && "Unexpected register class!");
}
}
+
return true;
}
Modified: llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-abi.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-abi.h?rev=50492&r1=50491&r2=50492&view=diff
==============================================================================
--- llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-abi.h (original)
+++ llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-abi.h Wed Apr 30 14:50:27 2008
@@ -247,6 +247,16 @@
false
#endif
+// LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS - Only called if
+// LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS returns true. This returns true if
+// there are only enough unused argument passing registers to pass a part of
+// the aggregate. Note, this routine should return false if none of the needed
+// registers are available.
+#ifndef LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS
+#define LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(E, SE) \
+ false
+#endif
+
// LLVM_BYVAL_ALIGNMENT - Returns the alignment of the type in bytes, if known,
// in the context of its use as a function parameter.
// Note that the alignment in the TYPE node is usually the alignment appropriate
@@ -387,23 +397,37 @@
/// argument and invokes methods on the client that indicate how its pieces
/// should be handled. This handles things like decimating structures into
/// their fields.
- void HandleArgument(tree type, ParameterAttributes *Attributes = NULL) {
+ void HandleArgument(tree type, std::vector<const Type*> &ScalarElts,
+ ParameterAttributes *Attributes = NULL) {
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.
std::vector<const Type*> Elts;
if (isPassedByInvisibleReference(type)) { // variable size -> by-ref.
- C.HandleByInvisibleReferenceArgument(PointerType::getUnqual(Ty), type);
+ const Type *PtrTy = PointerType::getUnqual(Ty);
+ C.HandleByInvisibleReferenceArgument(PtrTy, type);
+ ScalarElts.push_back(PtrTy);
} else if (Ty->getTypeID()==Type::VectorTyID) {
if (LLVM_SHOULD_PASS_VECTOR_IN_INTEGER_REGS(type)) {
- PassInIntegerRegisters(type, Ty);
+ PassInIntegerRegisters(type, Ty, ScalarElts);
} else {
C.HandleScalarArgument(Ty, type);
+ ScalarElts.push_back(Ty);
}
} else if (Ty->isFirstClassType()) {
C.HandleScalarArgument(Ty, type);
+ ScalarElts.push_back(Ty);
} else if (LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(type, Ty, Elts)) {
- PassInMixedRegisters(type, Ty, Elts);
+ if (!LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(Elts, ScalarElts))
+ PassInMixedRegisters(type, Ty, Elts, ScalarElts);
+ else {
+ C.HandleByValArgument(Ty, type);
+ if (Attributes) {
+ *Attributes |= ParamAttr::ByVal;
+ *Attributes |=
+ ParamAttr::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
+ }
+ }
} else if (LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(type, Ty)) {
C.HandleByValArgument(Ty, type);
if (Attributes) {
@@ -412,7 +436,7 @@
ParamAttr::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
}
} else if (LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(type)) {
- PassInIntegerRegisters(type, Ty);
+ PassInIntegerRegisters(type, Ty, ScalarElts);
} else if (isZeroSizedStructOrUnion(type)) {
// Zero sized struct or union, just drop it!
;
@@ -423,24 +447,24 @@
assert(FNo != ~0U && "Case not handled yet!");
C.EnterField(FNo, Ty);
- HandleArgument(getDeclaredType(Field));
+ HandleArgument(getDeclaredType(Field), ScalarElts);
C.ExitField();
}
} else if (TREE_CODE(type) == COMPLEX_TYPE) {
C.EnterField(0, Ty);
- HandleArgument(TREE_TYPE(type));
+ HandleArgument(TREE_TYPE(type), ScalarElts);
C.ExitField();
C.EnterField(1, Ty);
- HandleArgument(TREE_TYPE(type));
+ HandleArgument(TREE_TYPE(type), ScalarElts);
C.ExitField();
} else if ((TREE_CODE(type) == UNION_TYPE) ||
(TREE_CODE(type) == QUAL_UNION_TYPE)) {
- HandleUnion(type);
+ HandleUnion(type, ScalarElts);
} else if (TREE_CODE(type) == ARRAY_TYPE) {
const ArrayType *ATy = cast<ArrayType>(Ty);
for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) {
C.EnterField(i, Ty);
- HandleArgument(TREE_TYPE(type));
+ HandleArgument(TREE_TYPE(type), ScalarElts);
C.ExitField();
}
} else {
@@ -451,7 +475,7 @@
/// HandleUnion - Handle a UNION_TYPE or QUAL_UNION_TYPE tree.
///
- void HandleUnion(tree type) {
+ void HandleUnion(tree type, std::vector<const Type*> &ScalarElts) {
if (TYPE_TRANSPARENT_UNION(type)) {
tree Field = TYPE_FIELDS(type);
assert(Field && "Transparent union must have some elements!");
@@ -460,7 +484,7 @@
assert(Field && "Transparent union must have some elements!");
}
- HandleArgument(TREE_TYPE(Field));
+ HandleArgument(TREE_TYPE(Field), ScalarElts);
} else {
// Unions pass the largest element.
unsigned MaxSize = 0;
@@ -487,14 +511,15 @@
}
if (MaxElt)
- HandleArgument(TREE_TYPE(MaxElt));
+ HandleArgument(TREE_TYPE(MaxElt), ScalarElts);
}
}
/// 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.
- void PassInIntegerRegisters(tree type, const Type *Ty) {
+ void PassInIntegerRegisters(tree type, const Type *Ty,
+ std::vector<const Type*> &ScalarElts) {
unsigned Size = TREE_INT_CST_LOW(TYPE_SIZE(type))/8;
// FIXME: We should preserve all aggregate value alignment information.
@@ -543,6 +568,7 @@
for (unsigned j = 0; j < ArraySize; ++j) {
C.EnterField(j, ATy);
C.HandleScalarArgument(ArrayElementType, 0);
+ ScalarElts.push_back(ArrayElementType);
C.ExitField();
}
C.ExitField();
@@ -551,6 +577,7 @@
for (unsigned e = Elts.size(); i != e; ++i) {
C.EnterField(i, STy);
C.HandleScalarArgument(Elts[i], 0);
+ ScalarElts.push_back(Elts[i]);
C.ExitField();
}
}
@@ -559,11 +586,13 @@
/// mixed integer, floating point, and vector registers, convert it to a
/// structure containing the specified struct elements in.
void PassInMixedRegisters(tree type, const Type *Ty,
- std::vector<const Type*> &Elts) {
+ std::vector<const Type*> &Elts,
+ std::vector<const Type*> &ScalarElts) {
const StructType *STy = StructType::get(Elts, false);
for (unsigned i = 0, e = Elts.size(); i != e; ++i) {
C.EnterField(i, STy);
C.HandleScalarArgument(Elts[i], 0);
+ ScalarElts.push_back(Elts[i]);
C.ExitField();
}
}
Modified: llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-convert.cpp?rev=50492&r1=50491&r2=50492&view=diff
==============================================================================
--- llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-convert.cpp Wed Apr 30 14:50:27 2008
@@ -498,7 +498,7 @@
AI->setName(NameStack.back());
++AI;
}
-
+
void HandleByValArgument(const llvm::Type *LLVMTy, tree type) {
// Should not get here.
abort();
@@ -521,6 +521,22 @@
};
}
+// isPassedByVal - Return true if an aggregate of the specified type will be
+// passed in memory byval.
+static bool isPassedByVal(tree type, const Type *Ty,
+ std::vector<const Type*> &ScalarArgs) {
+ if (LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(type, Ty))
+ return true;
+
+ std::vector<const Type*> Args;
+ if (LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(type, Ty, Args) &&
+ LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(Args, ScalarArgs))
+ // We want to pass the whole aggregate in registers but only some of the
+ // registers are available.
+ return true;
+ return false;
+}
+
void TreeToLLVM::StartFunctionBody() {
const char *Name = "";
// Get the name of the function.
@@ -668,6 +684,8 @@
// Prepend the static chain (if any) to the list of arguments.
tree Args = static_chain ? static_chain : DECL_ARGUMENTS(FnDecl);
+ // Scalar arguments processed so far.
+ std::vector<const Type*> ScalarArgs;
while (Args) {
const char *Name = "unnamed_arg";
if (DECL_NAME(Args)) Name = IDENTIFIER_POINTER(DECL_NAME(Args));
@@ -676,7 +694,7 @@
bool isInvRef = isPassedByInvisibleReference(TREE_TYPE(Args));
if (isInvRef ||
(!ArgTy->isFirstClassType() &&
- LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(TREE_TYPE(Args), ArgTy))) {
+ isPassedByVal(TREE_TYPE(Args), ArgTy, ScalarArgs))) {
// If the value is passed by 'invisible reference' or 'byval reference',
// the l-value for the argument IS the argument itself.
AI->setName(Name);
@@ -710,7 +728,7 @@
Client.setName(Name);
Client.setLocation(Tmp);
- ABIConverter.HandleArgument(TREE_TYPE(Args));
+ ABIConverter.HandleArgument(TREE_TYPE(Args), ScalarArgs);
Client.clear();
}
@@ -2469,7 +2487,7 @@
// Perform any implicit type conversions.
if (CallOperands.size() < FTy->getNumParams()) {
- const Type *CalledTy = FTy->getParamType(CallOperands.size());
+ const Type *CalledTy= FTy->getParamType(CallOperands.size());
if (Loc->getType() != CalledTy) {
assert(type && "Inconsistent parameter types?");
bool isSigned = !TYPE_UNSIGNED(type);
@@ -2581,6 +2599,7 @@
CallOperands.push_back(Emit(TREE_OPERAND(exp, 2), 0));
// Loop over the arguments, expanding them and adding them to the op list.
+ std::vector<const Type*> ScalarArgs;
for (tree arg = TREE_OPERAND(exp, 1); arg; arg = TREE_CHAIN(arg)) {
const Type *ArgTy = ConvertType(TREE_TYPE(TREE_VALUE(arg)));
@@ -2596,7 +2615,8 @@
}
ParameterAttributes Attributes = ParamAttr::None;
- ABIConverter.HandleArgument(TREE_TYPE(TREE_VALUE(arg)), &Attributes);
+ ABIConverter.HandleArgument(TREE_TYPE(TREE_VALUE(arg)), ScalarArgs,
+ &Attributes);
if (Attributes != ParamAttr::None)
PAL = PAL.addAttr(CallOperands.size(), Attributes);
Modified: llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-types.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-types.cpp?rev=50492&r1=50491&r2=50492&view=diff
==============================================================================
--- llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-types.cpp (original)
+++ llvm-gcc-4.2/branches/Apple/Tak/gcc/llvm-types.cpp Wed Apr 30 14:50:27 2008
@@ -1068,9 +1068,10 @@
Attrs.push_back(ParamAttrsWithIndex::get(ArgTys.size(),
ParamAttr::StructRet | ParamAttr::NoAlias));
+ std::vector<const Type*> ScalarArgs;
if (static_chain) {
// Pass the static chain as the first parameter.
- ABIConverter.HandleArgument(TREE_TYPE(static_chain));
+ ABIConverter.HandleArgument(TREE_TYPE(static_chain), ScalarArgs);
// Mark it as the chain argument.
Attrs.push_back(ParamAttrsWithIndex::get(ArgTys.size(),
ParamAttr::Nest));
@@ -1082,7 +1083,7 @@
// Determine if there are any attributes for this param.
ParameterAttributes Attributes = ParamAttr::None;
- ABIConverter.HandleArgument(ArgTy, &Attributes);
+ ABIConverter.HandleArgument(ArgTy, ScalarArgs, &Attributes);
// Compute zext/sext attributes.
Attributes |= HandleArgumentExtension(ArgTy);
@@ -1165,9 +1166,10 @@
Attrs.push_back(ParamAttrsWithIndex::get(ArgTypes.size(),
ParamAttr::StructRet | ParamAttr::NoAlias));
+ std::vector<const Type*> ScalarArgs;
if (static_chain) {
// Pass the static chain as the first parameter.
- ABIConverter.HandleArgument(TREE_TYPE(static_chain));
+ ABIConverter.HandleArgument(TREE_TYPE(static_chain), ScalarArgs);
// Mark it as the chain argument.
Attrs.push_back(ParamAttrsWithIndex::get(ArgTypes.size(),
ParamAttr::Nest));
@@ -1207,7 +1209,7 @@
// Determine if there are any attributes for this param.
ParameterAttributes Attributes = ParamAttr::None;
- ABIConverter.HandleArgument(ArgTy, &Attributes);
+ ABIConverter.HandleArgument(ArgTy, ScalarArgs, &Attributes);
// Compute zext/sext attributes.
Attributes |= HandleArgumentExtension(ArgTy);
More information about the llvm-commits
mailing list