Author: evancheng Date: Sat Jan 12 03:22:43 2008 New Revision: 45907 URL: http://llvm.org/viewvc/llvm-project?rev=45907&view=rev Log: Add support for aggregate parameter passing by reference. At the llvm level they look like passing by address but with the ByVal parameter attribute. Code generator will lower them to confirm target ABI's. e.g. X86-32 passes aggregates on stack.
Modified: 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-types.cpp 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=45907&r1=45906&r2=45907&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-abi.h (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-abi.h Sat Jan 12 03:22:43 2008 @@ -32,6 +32,7 @@ #include "llvm-internal.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" +#include "llvm/ParameterAttributes.h" #include "llvm/Target/TargetData.h" namespace llvm { @@ -126,7 +127,15 @@ // would often be 64-bits). #ifndef LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS #define LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(X) \ - !isSingleElementStructOrArray(type) + !isSingleElementStructOrArray(X) +#endif + +// LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR - Return true if this aggregate +// value should be passed by reference by passing its address with the byval +// attribute bit set. The default is false. +#ifndef LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(X) +#define LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(X) \ + false #endif /// DefaultABI - This class implements the default LLVM ABI where structures are @@ -192,13 +201,17 @@ /// 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) { + void HandleArgument(tree type, uint16_t *Attributes = NULL) { const Type *Ty = ConvertType(type); if (isPassedByInvisibleReference(type)) { // variable size -> by-ref. C.HandleScalarArgument(PointerType::getUnqual(Ty), type); } else if (Ty->isFirstClassType()) { C.HandleScalarArgument(Ty, type); + } else if (LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(type)) { + C.HandleByValArgument(Ty, type); + if (Attributes) + *Attributes |= ParamAttr::ByVal; } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(type)) { PassInIntegerRegisters(type, Ty); } else if (TREE_CODE(type) == RECORD_TYPE) { 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=45907&r1=45906&r2=45907&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Sat Jan 12 03:22:43 2008 @@ -493,6 +493,11 @@ ++AI; } + void HandleByValArgument(const llvm::Type *LLVMTy, tree type) { + // Should not get here. + abort(); + } + void EnterField(unsigned FieldNo, const llvm::Type *StructTy) { NameStack.push_back(NameStack.back()+"."+utostr(FieldNo)); @@ -663,9 +668,12 @@ const char *Name = "unnamed_arg"; if (DECL_NAME(Args)) Name = IDENTIFIER_POINTER(DECL_NAME(Args)); - if (isPassedByInvisibleReference(TREE_TYPE(Args))) { - // If the value is passed by 'invisible reference', the l-value for the - // argument IS the argument itself. + const Type *ArgTy = ConvertType(TREE_TYPE(Args)); + if (isPassedByInvisibleReference(TREE_TYPE(Args)) || + (!ArgTy->isFirstClassType() && + LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(TREE_TYPE(Args)))) { + // If the value is passed by 'invisible reference' or 'byval reference', + // the l-value for the argument IS the argument itself. SET_DECL_LLVM(Args, AI); AI->setName(Name); ++AI; @@ -673,7 +681,6 @@ // Otherwise, we create an alloca to hold the argument value and provide // an l-value. On entry to the function, we copy formal argument values // into the alloca. - const Type *ArgTy = ConvertType(TREE_TYPE(Args)); Value *Tmp = CreateTemporary(ArgTy); Tmp->setName(std::string(Name)+"_addr"); SET_DECL_LLVM(Args, Tmp); @@ -2372,6 +2379,16 @@ CallOperands.push_back(Builder.CreateLoad(Loc, "tmp")); } + /// HandleByValArgument - This callback is invoked if the aggregate function + /// argument is passed by value. It is lowered to a parameter passed by + /// reference with an additional parameter attribute "ByVal". + void HandleByValArgument(const llvm::Type *LLVMTy, tree type) { + assert(!LocStack.empty()); + Value *Loc = LocStack.back(); + assert(PointerType::getUnqual(LLVMTy) == Loc->getType()); + CallOperands.push_back(Loc); + } + void EnterField(unsigned FieldNo, const llvm::Type *StructTy) { Constant *Zero = Constant::getNullValue(Type::Int32Ty); Constant *FIdx = ConstantInt::get(Type::Int32Ty, FieldNo); @@ -2477,7 +2494,10 @@ LValue LV = EmitLV(TREE_VALUE(arg)); assert(!LV.isBitfield() && "Bitfields are first-class types!"); Client.setLocation(LV.Ptr); - ABIConverter.HandleArgument(TREE_TYPE(TREE_VALUE(arg))); + uint16_t Attributes = ParamAttr::None; + ABIConverter.HandleArgument(TREE_TYPE(TREE_VALUE(arg)), &Attributes); + if (Attributes != ParamAttr::None) + PAL= ParamAttrsList::includeAttrs(PAL, CallOperands.size(), Attributes); } } 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=45907&r1=45906&r2=45907&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-types.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-types.cpp Sat Jan 12 03:22:43 2008 @@ -999,6 +999,13 @@ } ArgTypes.push_back(LLVMTy); } + + /// HandleByValArgument - This callback is invoked if the aggregate function + /// argument is passed by value. It is lowered to a parameter passed by + /// reference with an additional parameter attribute "ByVal". + void HandleByValArgument(const llvm::Type *LLVMTy, tree type) { + HandleScalarArgument(PointerType::getUnqual(LLVMTy), type); + } }; } @@ -1057,11 +1064,12 @@ for (; Args && TREE_TYPE(Args) != void_type_node; Args = TREE_CHAIN(Args)) { tree ArgTy = TREE_TYPE(Args); - ABIConverter.HandleArgument(ArgTy); // Determine if there are any attributes for this param. uint16_t Attributes = ParamAttr::None; + ABIConverter.HandleArgument(ArgTy, &Attributes); + // Compute zext/sext attributes. Attributes |= HandleArgumentExtension(ArgTy); @@ -1174,11 +1182,11 @@ break; } - ABIConverter.HandleArgument(ArgTy); - // Determine if there are any attributes for this param. uint16_t Attributes = ParamAttr::None; + ABIConverter.HandleArgument(ArgTy, &Attributes); + // Compute zext/sext attributes. Attributes |= HandleArgumentExtension(ArgTy); _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits