[llvm-commits] [llvm-gcc-4.2] r52436 - in /llvm-gcc-4.2/trunk/gcc: config/i386/llvm-i386-target.h config/i386/llvm-i386.cpp llvm-abi.h llvm-convert.cpp llvm-internal.h llvm-types.cpp
Dale Johannesen
dalej at apple.com
Tue Jun 17 16:39:43 PDT 2008
Author: johannes
Date: Tue Jun 17 18:39:43 2008
New Revision: 52436
URL: http://llvm.org/viewvc/llvm-project?rev=52436&view=rev
Log:
X86-64 ABI. Handle returning structs like
{ struct {}x[4]; double y; }
where the 1st word is allocated but not returned.
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
llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
llvm-gcc-4.2/trunk/gcc/llvm-internal.h
llvm-gcc-4.2/trunk/gcc/llvm-types.cpp
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=52436&r1=52435&r2=52436&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 Tue Jun 17 18:39:43 2008
@@ -116,10 +116,11 @@
/* LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN - Return LLVM Type if X can be
returned as a scalar, otherwise return NULL. */
-#define LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN(X) \
- llvm_x86_scalar_type_for_struct_return(X)
+#define LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN(X, Y) \
+ llvm_x86_scalar_type_for_struct_return((X), (Y))
-extern const Type *llvm_x86_scalar_type_for_struct_return(tree type);
+extern const Type *llvm_x86_scalar_type_for_struct_return(tree type,
+ unsigned *Offset);
/* LLVM_AGGR_TYPE_FOR_STRUCT_RETURN - Return LLVM Type if X can be
returned as an aggregate, otherwise return NULL. */
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=52436&r1=52435&r2=52436&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 Tue Jun 17 18:39:43 2008
@@ -941,17 +941,6 @@
if (llvm_x86_should_not_return_complex_in_memory(TreeType))
return true;
- // FIXME: llvm x86-64 code generator is not able to handle return {i8, float}
- bool foundInt = false;
- unsigned STyElements = STy->getNumElements();
- for (unsigned i = 0; i < STyElements; ++i) {
- const Type *ETy = STy->getElementType(i);
- if (const ArrayType *ATy = dyn_cast<ArrayType>(ETy))
- ETy = ATy->getElementType();
- if (ETy->isInteger())
- foundInt = true;
- }
-
// Let gcc specific routine answer the question.
enum x86_64_reg_class Class[MAX_CLASSES];
enum machine_mode Mode = ix86_getNaturalModeForType(TreeType);
@@ -959,12 +948,15 @@
if (NumClasses == 0)
return false;
- if (NumClasses == 1 && foundInt)
- return false;
-
if (NumClasses == 1 &&
(Class[0] == X86_64_INTEGERSI_CLASS || Class[0] == X86_64_INTEGER_CLASS))
- // This will fit in one i32 register.
+ // This will fit in one i64 register.
+ return false;
+
+ if (NumClasses == 2 &&
+ (Class[0] == X86_64_NO_CLASS || Class[1] == X86_64_NO_CLASS))
+ // One word is padding which is not passed at all; treat this as returning
+ // the scalar type of the other word.
return false;
// Otherwise, use of multiple value return is OK.
@@ -973,7 +965,8 @@
// llvm_x86_scalar_type_for_struct_return - Return LLVM type if TYPE
// can be returned as a scalar, otherwise return NULL.
-const Type *llvm_x86_scalar_type_for_struct_return(tree type) {
+const Type *llvm_x86_scalar_type_for_struct_return(tree type, unsigned *Offset) {
+ *Offset = 0;
const Type *Ty = ConvertType(type);
unsigned Size = getTargetData().getABITypeSize(Ty);
if (Size == 0)
@@ -989,13 +982,67 @@
if (llvm_suitable_multiple_ret_value_type(Ty, type))
return NULL;
- if (Size <= 8)
- return Type::Int64Ty;
- else if (Size <= 16)
- return IntegerType::get(128);
- else if (Size <= 32)
- return IntegerType::get(256);
+ if (TARGET_64BIT) {
+ // This logic relies on llvm_suitable_multiple_ret_value_type to have
+ // removed anything not expected here.
+ 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 == 0)
+ return Type::Int64Ty;
+ if (NumClasses == 1) {
+ if (Class[0] == X86_64_INTEGERSI_CLASS ||
+ Class[0] == X86_64_INTEGER_CLASS) {
+ // one int register
+ HOST_WIDE_INT Bytes =
+ (Mode == BLKmode) ? int_size_in_bytes(type) :
+ (int) GET_MODE_SIZE(Mode);
+ if (Bytes>4)
+ return Type::Int64Ty;
+ else if (Bytes>2)
+ return Type::Int32Ty;
+ else if (Bytes>1)
+ return Type::Int16Ty;
+ else
+ return Type::Int8Ty;
+ }
+ assert(0 && "Unexpected type!");
+ }
+ if (NumClasses == 2) {
+ if (Class[1] == X86_64_NO_CLASS) {
+ if (Class[0] == X86_64_INTEGER_CLASS ||
+ Class[0] == X86_64_NO_CLASS ||
+ Class[0] == X86_64_INTEGERSI_CLASS)
+ return Type::Int64Ty;
+ else if (Class[0] == X86_64_SSE_CLASS || Class[0] == X86_64_SSEDF_CLASS)
+ return Type::DoubleTy;
+ else if (Class[0] == X86_64_SSESF_CLASS)
+ return Type::FloatTy;
+ assert(0 && "Unexpected type!");
+ }
+ if (Class[0] == X86_64_NO_CLASS) {
+ *Offset = 8;
+ if (Class[1] == X86_64_INTEGERSI_CLASS ||
+ Class[1] == X86_64_INTEGER_CLASS)
+ return Type::Int64Ty;
+ else if (Class[1] == X86_64_SSE_CLASS || Class[1] == X86_64_SSEDF_CLASS)
+ return Type::DoubleTy;
+ else if (Class[1] == X86_64_SSESF_CLASS)
+ return Type::FloatTy;
+ assert(0 && "Unexpected type!");
+ }
+ assert(0 && "Unexpected type!");
+ }
+ assert(0 && "Unexpected type!");
+ } else {
+ if (Size <= 8)
+ return Type::Int64Ty;
+ else if (Size <= 16)
+ return IntegerType::get(128);
+ else if (Size <= 32)
+ return IntegerType::get(256);
+ }
return NULL;
}
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=52436&r1=52435&r2=52436&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-abi.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-abi.h Tue Jun 17 18:39:43 2008
@@ -57,8 +57,10 @@
/// HandleAggregateResultAsScalar - This callback is invoked if the function
/// returns an aggregate value by bit converting it to the specified scalar
- /// type and returning that.
- void HandleAggregateResultAsScalar(const Type *ScalarTy) {}
+ /// type and returning that. The bit conversion should start at byte Offset
+ /// within the struct, and ScalarTy is not necessarily big enough to cover
+ /// the entire struct.
+ void HandleAggregateResultAsScalar(const Type *ScalarTy, unsigned Offset=0) {}
/// HandleAggregateResultAsAggregate - This callback is invoked if the function
/// returns an aggregate value using multiple return values.
@@ -197,9 +199,10 @@
// getLLVMScalarTypeForStructReturn - Return LLVM Type if TY can be
// returned as a scalar, otherwise return NULL. This is the default
// target independent implementation.
-static const Type* getLLVMScalarTypeForStructReturn(tree type) {
+static const Type* getLLVMScalarTypeForStructReturn(tree type, unsigned *Offset) {
const Type *Ty = ConvertType(type);
unsigned Size = getTargetData().getABITypeSize(Ty);
+ *Offset = 0;
if (Size == 0)
return Type::VoidTy;
else if (Size == 1)
@@ -309,8 +312,8 @@
// LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN - Return LLVM Type if X can be
// returned as a scalar, otherwise return NULL.
#ifndef LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN
-#define LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN(X) \
- getLLVMScalarTypeForStructReturn(X)
+#define LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN(X, Y) \
+ getLLVMScalarTypeForStructReturn((X), (Y))
#endif
// LLVM_AGGR_TYPE_FOR_STRUCT_RETURN - Return LLVM Type if X can be
@@ -351,6 +354,7 @@
/// on the client that indicate how its pieces should be handled. This
/// handles things like returning structures via hidden parameters.
void HandleReturnType(tree type, tree fn, bool isBuiltin) {
+ unsigned Offset = 0;
const Type *Ty = ConvertType(type);
if (Ty->getTypeID() == Type::VectorTyID) {
// Vector handling is weird on x86. In particular builtin and
@@ -378,8 +382,9 @@
// aggregate.
if (const Type *AggrTy = LLVM_AGGR_TYPE_FOR_STRUCT_RETURN(type))
C.HandleAggregateResultAsAggregate(AggrTy);
- else if (const Type* ScalarTy = LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN(type))
- C.HandleAggregateResultAsScalar(ScalarTy);
+ else if (const Type* ScalarTy =
+ LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN(type, &Offset))
+ C.HandleAggregateResultAsScalar(ScalarTy, Offset);
else {
assert(0 && "Unable to determine how to return this aggregate!");
abort();
Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=52436&r1=52435&r2=52436&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Tue Jun 17 18:39:43 2008
@@ -350,6 +350,7 @@
FnDecl = fndecl;
Fn = 0;
ReturnBB = UnwindBB = 0;
+ ReturnOffset = 0;
if (TheDebugInfo) {
expanded_location Location = expand_location(DECL_SOURCE_LOCATION (fndecl));
@@ -427,10 +428,11 @@
IRBuilder Builder;
std::vector<Value*> LocStack;
std::vector<std::string> NameStack;
+ unsigned Offset;
FunctionPrologArgumentConversion(tree FnDecl,
Function::arg_iterator &ai,
const IRBuilder &B)
- : FunctionDecl(FnDecl), AI(ai), Builder(B) {}
+ : FunctionDecl(FnDecl), AI(ai), Builder(B), Offset(0) {}
void setName(const std::string &Name) {
NameStack.push_back(Name);
@@ -520,6 +522,10 @@
abort();
}
+ void HandleAggregateResultAsScalar(const Type *ScalarTy, unsigned Offset=0) {
+ this->Offset = Offset;
+ }
+
void EnterField(unsigned FieldNo, const llvm::Type *StructTy) {
NameStack.push_back(NameStack.back()+"."+utostr(FieldNo));
@@ -696,6 +702,8 @@
// Handle the DECL_RESULT.
ABIConverter.HandleReturnType(TREE_TYPE(TREE_TYPE(FnDecl)), FnDecl,
DECL_BUILT_IN(FnDecl));
+ // Remember this for use by FinishFunctionBody.
+ TheTreeToLLVM->ReturnOffset = Client.Offset;
// Prepend the static chain (if any) to the list of arguments.
tree Args = static_chain ? static_chain : DECL_ARGUMENTS(FnDecl);
@@ -805,10 +813,16 @@
RetVals.push_back(E);
}
} else {
- // Otherwise, this aggregate result must be something that is returned in
- // a scalar register for this target. We must bit convert the aggregate
- // to the specified scalar type, which we do by casting the pointer and
- // loading.
+ // Otherwise, this aggregate result must be something that is returned
+ // in a scalar register for this target. We must bit convert the
+ // aggregate to the specified scalar type, which we do by casting the
+ // pointer and loading. The load does not necessarily start at the
+ // beginning of the aggregate (x86-64).
+ if (ReturnOffset) {
+ RetVal = BitCastToType(RetVal, PointerType::getUnqual(Type::Int8Ty));
+ RetVal = Builder.CreateGEP(RetVal,
+ ConstantInt::get(TD.getIntPtrType(), ReturnOffset), "tmp");
+ }
RetVal = BitCastToType(RetVal,
PointerType::getUnqual(Fn->getReturnType()));
RetVal = Builder.CreateLoad(RetVal, "retval");
@@ -2383,6 +2397,7 @@
MemRef RetBuf;
bool isShadowRet;
bool isAggrRet;
+ unsigned Offset;
FunctionCallArgumentConversion(SmallVector<Value*, 16> &ops,
const FunctionType *FnTy,
@@ -2391,7 +2406,7 @@
IRBuilder &b)
: CallOperands(ops), FTy(FnTy), DestLoc(destloc),
useReturnSlot(ReturnSlotOpt), Builder(b), isShadowRet(false),
- isAggrRet(false) { }
+ isAggrRet(false), Offset(0) { }
// Push the address of an argument.
void pushAddress(Value *Loc) {
@@ -2472,12 +2487,13 @@
/// HandleAggregateResultAsScalar - This callback is invoked if the function
/// returns an aggregate value by bit converting it to the specified scalar
/// type and returning that.
- void HandleAggregateResultAsScalar(const Type *ScalarTy) {
- // There is nothing to do here.
+ void HandleAggregateResultAsScalar(const Type *ScalarTy,
+ unsigned Offset = 0) {
+ this->Offset = Offset;
}
- /// HandleAggregateResultAsAggregate - This callback is invoked if the function
- /// returns an aggregate value using multiple return values.
+ /// HandleAggregateResultAsAggregate - This callback is invoked if the
+ /// function returns an aggregate value using multiple return values.
void HandleAggregateResultAsAggregate(const Type *AggrTy) {
// There is nothing to do here.
isAggrRet = true;
@@ -2734,12 +2750,18 @@
// the current target specifies that the aggregate be returned in scalar
// registers even though it is an aggregate. We must bitconvert the scalar
// to the destination aggregate type. We do this by casting the DestLoc
- // pointer and storing into it.
+ // pointer and storing into it. The store does not necessarily start at the
+ // beginning of the aggregate (x86-64).
if (!DestLoc)
return Call; // Normal scalar return.
- Value *Ptr = BitCastToType(DestLoc->Ptr,
- PointerType::getUnqual(Call->getType()));
+ Value *Ptr = DestLoc->Ptr;
+ if (Client.Offset) {
+ Ptr = BitCastToType(Ptr, PointerType::getUnqual(Type::Int8Ty));
+ Ptr = Builder.CreateGEP(Ptr,
+ ConstantInt::get(TD.getIntPtrType(), Client.Offset), "tmp");
+ }
+ Ptr = BitCastToType(Ptr, PointerType::getUnqual(Call->getType()));
StoreInst *St = Builder.CreateStore(Call, Ptr, DestLoc->Volatile);
St->setAlignment(DestLoc->Alignment);
return 0;
Modified: llvm-gcc-4.2/trunk/gcc/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-internal.h?rev=52436&r1=52435&r2=52436&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Tue Jun 17 18:39:43 2008
@@ -274,6 +274,7 @@
Function *Fn;
BasicBlock *ReturnBB;
BasicBlock *UnwindBB;
+ unsigned ReturnOffset;
// State that changes as the function is emitted.
Modified: llvm-gcc-4.2/trunk/gcc/llvm-types.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-types.cpp?rev=52436&r1=52435&r2=52436&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-types.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-types.cpp Tue Jun 17 18:39:43 2008
@@ -936,10 +936,11 @@
unsigned &CallingConv;
bool isShadowRet;
bool KNRPromotion;
+ unsigned Offset;
public:
FunctionTypeConversion(PATypeHolder &retty, std::vector<PATypeHolder> &AT,
unsigned &CC, bool KNR)
- : RetTy(retty), ArgTypes(AT), CallingConv(CC), KNRPromotion(KNR) {
+ : RetTy(retty), ArgTypes(AT), CallingConv(CC), KNRPromotion(KNR), Offset(0) {
CallingConv = CallingConv::C;
isShadowRet = false;
}
@@ -955,8 +956,9 @@
/// HandleAggregateResultAsScalar - This callback is invoked if the function
/// returns an aggregate value by bit converting it to the specified scalar
/// type and returning that.
- void HandleAggregateResultAsScalar(const Type *ScalarTy) {
+ void HandleAggregateResultAsScalar(const Type *ScalarTy, unsigned Offset=0) {
RetTy = ScalarTy;
+ this->Offset = Offset;
}
/// HandleAggregateResultAsAggregate - This callback is invoked if the function
More information about the llvm-commits
mailing list