[llvm-commits] [llvm-gcc-4.2] r85539 - in /llvm-gcc-4.2/trunk/gcc: config/arm/llvm-arm-target.h config/arm/llvm-arm.cpp config/i386/llvm-i386-target.h llvm-abi.h llvm-types.cpp

Sandeep Patel deeppatel1987 at gmail.com
Thu Oct 29 16:49:05 PDT 2009


Oh, hey, thanks. I was planning to sort out your earlier requests, but
haven't had solid time in a few days to do so.

deep

On Thu, Oct 29, 2009 at 11:35 PM, Bob Wilson <bob.wilson at apple.com> wrote:
> Author: bwilson
> Date: Thu Oct 29 18:35:11 2009
> New Revision: 85539
>
> URL: http://llvm.org/viewvc/llvm-project?rev=85539&view=rev
> Log:
> Fix ARM AAPCS-VFP return of homogeneous aggregates.  Patch by Sandeep Patel.
>
> Modified:
>    llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm-target.h
>    llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm.cpp
>    llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h
>    llvm-gcc-4.2/trunk/gcc/llvm-abi.h
>    llvm-gcc-4.2/trunk/gcc/llvm-types.cpp
>
> Modified: llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm-target.h
> URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm-target.h?rev=85539&r1=85538&r2=85539&view=diff
>
> ==============================================================================
> --- llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm-target.h (original)
> +++ llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm-target.h Thu Oct 29 18:35:11 2009
> @@ -25,17 +25,17 @@
>    specification says that varargs functions must use the base standard
>    instead of the VFP hard float variant. We check for that with
>    (isVoid || hasArgList). */
> -#define TARGET_ADJUST_LLVM_CC(CC, type)                                \
> -  {                                                            \
> -    if (TARGET_AAPCS_BASED)                                    \
> -      CC = ((TARGET_VFP && TARGET_HARD_FLOAT_ABI &&            \
> -             ((TYPE_ARG_TYPES(type) == 0) ||                   \
> -              (TREE_VALUE(tree_last(TYPE_ARG_TYPES(type))) ==  \
> -               void_type_node))) ?                             \
> -           CallingConv::ARM_AAPCS_VFP :                        \
> -           CallingConv::ARM_AAPCS);                            \
> -    else                                                       \
> -      CC = CallingConv::ARM_APCS;                              \
> +#define TARGET_ADJUST_LLVM_CC(CC, type)                       \
> +  {                                                           \
> +    if (TARGET_AAPCS_BASED)                                   \
> +      CC = ((TARGET_VFP && TARGET_HARD_FLOAT_ABI &&           \
> +             ((TYPE_ARG_TYPES(type) == 0) ||                  \
> +              (TREE_VALUE(tree_last(TYPE_ARG_TYPES(type))) == \
> +               void_type_node))) ?                            \
> +      CallingConv::ARM_AAPCS_VFP :                            \
> +      CallingConv::ARM_AAPCS);                                \
> +    else                                                      \
> +      CC = CallingConv::ARM_APCS;                             \
>   }
>
>  #ifdef LLVM_ABI_H
> @@ -45,7 +45,7 @@
>                                              CallingConv::ID&,
>                                              std::vector<const Type*>&);
>
> -#define LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(T, TY, CC, E)         \
> +#define LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(T, TY, CC, E)    \
>    llvm_arm_should_pass_aggregate_in_mixed_regs((T), (TY), (CC), (E))
>
>  extern
> @@ -53,9 +53,35 @@
>                                                  std::vector<const Type*>&,
>                                                  bool, CallingConv::ID&);
>
> -#define LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(E, SE, ISR, CC)                \
> +#define LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(E, SE, ISR, CC)   \
>    llvm_arm_aggregate_partially_passed_in_regs((E), (SE), (ISR), (CC))
>
> +extern const Type *llvm_arm_aggr_type_for_struct_return(tree type,
> +                                                        CallingConv::ID &CC);
> +
> +/* LLVM_AGGR_TYPE_FOR_STRUCT_RETURN - Return LLVM Type if X can be
> +  returned as an aggregate, otherwise return NULL. */
> +#define LLVM_AGGR_TYPE_FOR_STRUCT_RETURN(X, CC) \
> +    llvm_arm_aggr_type_for_struct_return((X), (CC))
> +
> +extern void llvm_arm_extract_multiple_return_value(Value *Src, Value *Dest,
> +                                                   bool isVolatile,
> +                                                   LLVMBuilder &B);
> +
> +/* LLVM_EXTRACT_MULTIPLE_RETURN_VALUE - Extract multiple return value from
> +  SRC and assign it to DEST. */
> +#define LLVM_EXTRACT_MULTIPLE_RETURN_VALUE(Src,Dest,V,B)       \
> +    llvm_arm_extract_multiple_return_value((Src),(Dest),(V),(B))
> +
> +extern
> +bool llvm_arm_should_pass_or_return_aggregate_in_regs(tree TreeType,
> +                                                      CallingConv::ID &CC);
> +
> +/* LLVM_SHOULD_NOT_USE_SHADOW_RETURN = Return true is the given type should
> +  not be returned via a shadow parameter with the given calling conventions. */
> +#define LLVM_SHOULD_NOT_USE_SHADOW_RETURN(X, CC) \
> +    llvm_arm_should_pass_or_return_aggregate_in_regs((X), (CC))
> +
>  #endif /* LLVM_ABI_H */
>  #endif /* ENABLE_LLVM */
>  /* LLVM LOCAL end (ENTIRE FILE!)  */
>
> Modified: llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm.cpp?rev=85539&r1=85538&r2=85539&view=diff
>
> ==============================================================================
> --- llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm.cpp (original)
> +++ llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm.cpp Thu Oct 29 18:35:11 2009
> @@ -2524,24 +2524,14 @@
>  llvm_arm_should_pass_aggregate_in_mixed_regs(tree TreeType, const Type *Ty,
>                                              CallingConv::ID &CC,
>                                              std::vector<const Type*> &Elts) {
> -  // Homogeneous aggregates are an AAPCS-VFP feature.
> -  if ((CC != CallingConv::ARM_AAPCS_VFP) ||
> -      !(TARGET_AAPCS_BASED && TARGET_VFP && TARGET_HARD_FLOAT_ABI))
> +  if (!llvm_arm_should_pass_or_return_aggregate_in_regs(TreeType, CC))
>     return false;
>
> -  // Alas, we can't use LLVM Types to figure this out because we need to
> -  // examine unions closely.  We'll have to walk the GCC TreeType.
> -  int fdt_counts[ARM_FDT_MAX] = { 0 };
> -  bool result = false;
> -  result = vfp_arg_homogeneous_aggregate_p(TYPE_MODE(TreeType), TreeType,
> -                                           fdt_counts);
> -
>   // Walk Ty and push LLVM types corresponding to register types onto
>   // Elts.
> -  if (result)
> -    push_elts(Ty, Elts);
> +  push_elts(Ty, Elts);
>
> -  return result;
> +  return true;
>  }
>
>  static bool alloc_next_spr(bool *SPRs)
> @@ -2645,4 +2635,124 @@
>   return false;                            // it all fit in registers!
>  }
>
> +// Return LLVM Type if TYPE can be returned as an aggregate,
> +// otherwise return NULL.
> +const Type *llvm_arm_aggr_type_for_struct_return(tree TreeType,
> +                                                 CallingConv::ID &CC) {
> +  if (!llvm_arm_should_pass_or_return_aggregate_in_regs(TreeType, CC))
> +    return NULL;
> +
> +  // Walk Ty and push LLVM types corresponding to register types onto
> +  // Elts.
> +  std::vector<const Type*> Elts;
> +  const Type *Ty = ConvertType(TreeType);
> +  push_elts(Ty, Elts);
> +
> +  return StructType::get(Context, Elts, false);
> +}
> +
> +// llvm_arm_extract_mrv_array_element - Helper function that helps extract
> +// an array element from multiple return value.
> +//
> +// Here, SRC is returning multiple values. DEST's DESTFIELDNO field is an array.
> +// Extract SRCFIELDNO's ELEMENO value and store it in DEST's FIELDNO field's
> +// ELEMENTNO.
> +//
> +static void llvm_arm_extract_mrv_array_element(Value *Src, Value *Dest,
> +                                               unsigned SrcFieldNo,
> +                                               unsigned SrcElemNo,
> +                                               unsigned DestFieldNo,
> +                                               unsigned DestElemNo,
> +                                               LLVMBuilder &Builder,
> +                                               bool isVolatile) {
> +  Value *EVI = Builder.CreateExtractValue(Src, SrcFieldNo, "mrv_gr");
> +  const StructType *STy = cast<StructType>(Src->getType());
> +  llvm::Value *Idxs[3];
> +  Idxs[0] = ConstantInt::get(llvm::Type::getInt32Ty(Context), 0);
> +  Idxs[1] = ConstantInt::get(llvm::Type::getInt32Ty(Context), DestFieldNo);
> +  Idxs[2] = ConstantInt::get(llvm::Type::getInt32Ty(Context), DestElemNo);
> +  Value *GEP = Builder.CreateGEP(Dest, Idxs, Idxs+3, "mrv_gep");
> +  if (isa<VectorType>(STy->getElementType(SrcFieldNo))) {
> +    Value *ElemIndex = ConstantInt::get(Type::getInt32Ty(Context), SrcElemNo);
> +    Value *EVIElem = Builder.CreateExtractElement(EVI, ElemIndex, "mrv");
> +    Builder.CreateStore(EVIElem, GEP, isVolatile);
> +  } else {
> +    Builder.CreateStore(EVI, GEP, isVolatile);
> +  }
> +}
> +
> +// llvm_arm_extract_multiple_return_value - Extract multiple values returned
> +// by SRC and store them in DEST. It is expected that SRC and
> +// DEST types are StructType, but they may not match.
> +void llvm_arm_extract_multiple_return_value(Value *Src, Value *Dest,
> +                                            bool isVolatile,
> +                                            LLVMBuilder &Builder) {
> +
> +  const StructType *STy = cast<StructType>(Src->getType());
> +  unsigned NumElements = STy->getNumElements();
> +
> +  const PointerType *PTy = cast<PointerType>(Dest->getType());
> +  const StructType *DestTy = cast<StructType>(PTy->getElementType());
> +
> +  unsigned SNO = 0;
> +  unsigned DNO = 0;
> +
> +  while (SNO < NumElements) {
> +
> +    const Type *DestElemType = DestTy->getElementType(DNO);
> +
> +    // Directly access first class values.
> +    if (DestElemType->isSingleValueType()) {
> +      Value *GEP = Builder.CreateStructGEP(Dest, DNO, "mrv_gep");
> +      Value *EVI = Builder.CreateExtractValue(Src, SNO, "mrv_gr");
> +      Builder.CreateStore(EVI, GEP, isVolatile);
> +      ++DNO; ++SNO;
> +      continue;
> +    }
> +
> +    // Access array elements individually. Note, Src and Dest type may
> +    // not match. For example { <2 x float>, float } and { float[3]; }
> +    const ArrayType *ATy = cast<ArrayType>(DestElemType);
> +    unsigned ArraySize = ATy->getNumElements();
> +    unsigned DElemNo = 0; // DestTy's DNO field's element number
> +    while (DElemNo < ArraySize) {
> +      unsigned i = 0;
> +      unsigned Size = 1;
> +
> +      if (const VectorType *SElemTy =
> +          dyn_cast<VectorType>(STy->getElementType(SNO))) {
> +        Size = SElemTy->getNumElements();
> +      }
> +      while (i < Size) {
> +        llvm_arm_extract_mrv_array_element(Src, Dest, SNO, i++,
> +                                           DNO, DElemNo++,
> +                                           Builder, isVolatile);
> +      }
> +      // Consumed this src field. Try next one.
> +      ++SNO;
> +    }
> +    // Finished building current dest field.
> +    ++DNO;
> +  }
> +}
> +
> +// Target hook for llvm-abi.h for LLVM_SHOULD_NOT_USE_SHADOW_RETURN and is
> +// also a utility function used for other target hooks in this file. Returns
> +// true if the aggregate should be passed or returned in registers.
> +bool llvm_arm_should_pass_or_return_aggregate_in_regs(tree TreeType,
> +                                                      CallingConv::ID &CC) {
> +  // Homogeneous aggregates are an AAPCS-VFP feature.
> +  if ((CC != CallingConv::ARM_AAPCS_VFP) ||
> +      !(TARGET_AAPCS_BASED && TARGET_VFP && TARGET_HARD_FLOAT_ABI))
> +    return false;
> +
> +  // Alas, we can't use LLVM Types to figure this out because we need to
> +  // examine unions closely.  We'll have to walk the GCC TreeType.
> +  int fdt_counts[ARM_FDT_MAX] = { 0 };
> +  bool result = false;
> +  result = vfp_arg_homogeneous_aggregate_p(TYPE_MODE(TreeType), TreeType,
> +                                           fdt_counts);
> +  return result;
> +}
> +
>  /* LLVM LOCAL end (ENTIRE FILE!)  */
>
> 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=85539&r1=85538&r2=85539&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 Oct 29 18:35:11 2009
> @@ -139,7 +139,7 @@
>
>  /* LLVM_AGGR_TYPE_FOR_STRUCT_RETURN - Return LLVM Type if X can be
>    returned as an aggregate, otherwise return NULL. */
> -#define LLVM_AGGR_TYPE_FOR_STRUCT_RETURN(X) \
> +#define LLVM_AGGR_TYPE_FOR_STRUCT_RETURN(X, CC) \
>   llvm_x86_aggr_type_for_struct_return(X)
>
>  extern void llvm_x86_extract_multiple_return_value(Value *Src, Value *Dest,
>
> 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=85539&r1=85538&r2=85539&view=diff
>
> ==============================================================================
> --- llvm-gcc-4.2/trunk/gcc/llvm-abi.h (original)
> +++ llvm-gcc-4.2/trunk/gcc/llvm-abi.h Thu Oct 29 18:35:11 2009
> @@ -126,15 +126,24 @@
>  false
>  #endif
>
> +// LLVM_SHOULD_NOT_USE_SHADOW_RETURN - A hook to allow aggregates to be
> +// returned in registers.
> +#ifndef LLVM_SHOULD_NOT_USE_SHADOW_RETURN
> +#define LLVM_SHOULD_NOT_USE_SHADOW_RETURN(X, CC) \
> + false
> +#endif
> +
>  // doNotUseShadowReturn - Return true if the specified GCC type
>  // should not be returned using a pointer to struct parameter.
> -static inline bool doNotUseShadowReturn(tree type, tree fndecl) {
> +static inline bool doNotUseShadowReturn(tree type, tree fndecl,
> +                                        CallingConv::ID CC) {
>   if (!TYPE_SIZE(type))
>     return false;
>   if (TREE_CODE(TYPE_SIZE(type)) != INTEGER_CST)
>     return false;
>   // LLVM says do not use shadow argument.
> -  if (LLVM_SHOULD_NOT_RETURN_COMPLEX_IN_MEMORY(type))
> +  if (LLVM_SHOULD_NOT_RETURN_COMPLEX_IN_MEMORY(type) ||
> +     LLVM_SHOULD_NOT_USE_SHADOW_RETURN(type, CC))
>     return true;
>   // GCC says use shadow argument.
>   if (aggregate_value_p(type, fndecl))
> @@ -396,7 +405,7 @@
>     } else if (Ty->isSingleValueType() || Ty->isVoidTy()) {
>       // Return scalar values normally.
>       C.HandleScalarResult(Ty);
> -    } else if (doNotUseShadowReturn(type, fn)) {
> +    } else if (doNotUseShadowReturn(type, fn, C.getCallingConv())) {
>       tree SingleElt = LLVM_SHOULD_RETURN_SELT_STRUCT_AS_SCALAR(type);
>       if (SingleElt && TYPE_SIZE(SingleElt) &&
>           TREE_CODE(TYPE_SIZE(SingleElt)) == INTEGER_CST &&
> @@ -406,7 +415,8 @@
>       } else {
>         // Otherwise return as an integer value large enough to hold the entire
>         // aggregate.
> -        if (const Type *AggrTy = LLVM_AGGR_TYPE_FOR_STRUCT_RETURN(type))
> +        if (const Type *AggrTy = LLVM_AGGR_TYPE_FOR_STRUCT_RETURN(type,
> +                                    C.getCallingConv()))
>           C.HandleAggregateResultAsAggregate(AggrTy);
>         else if (const Type* ScalarTy =
>                     LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN(type, &Offset))
> @@ -752,7 +762,7 @@
>     } else if (Ty->isSingleValueType() || Ty->isVoidTy()) {
>       // Return scalar values normally.
>       C.HandleScalarResult(Ty);
> -    } else if (doNotUseShadowReturn(type, fn)) {
> +    } else if (doNotUseShadowReturn(type, fn, C.getCallingConv())) {
>       tree SingleElt = LLVM_SHOULD_RETURN_SELT_STRUCT_AS_SCALAR(type);
>       if (SingleElt && TYPE_SIZE(SingleElt) &&
>           TREE_CODE(TYPE_SIZE(SingleElt)) == INTEGER_CST &&
> @@ -762,7 +772,8 @@
>       } else {
>         // Otherwise return as an integer value large enough to hold the entire
>         // aggregate.
> -        if (const Type *AggrTy = LLVM_AGGR_TYPE_FOR_STRUCT_RETURN(type))
> +        if (const Type *AggrTy = LLVM_AGGR_TYPE_FOR_STRUCT_RETURN(type,
> +                                    C.getCallingConv()))
>           C.HandleAggregateResultAsAggregate(AggrTy);
>         else if (const Type* ScalarTy =
>                     LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN(type, &Offset))
>
> 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=85539&r1=85538&r2=85539&view=diff
>
> ==============================================================================
> --- llvm-gcc-4.2/trunk/gcc/llvm-types.cpp (original)
> +++ llvm-gcc-4.2/trunk/gcc/llvm-types.cpp Thu Oct 29 18:35:11 2009
> @@ -1052,16 +1052,16 @@
>   tree ReturnType = TREE_TYPE(type);
>   std::vector<PATypeHolder> ArgTys;
>   PATypeHolder RetTy(Type::getVoidTy(Context));
> -
> +
>   FunctionTypeConversion Client(RetTy, ArgTys, CallingConv, true /*K&R*/);
>   TheLLVMABI<FunctionTypeConversion> ABIConverter(Client);
> -
> -  // Builtins are always prototyped, so this isn't one.
> -  ABIConverter.HandleReturnType(ReturnType, current_function_decl, false);
>
>  #ifdef TARGET_ADJUST_LLVM_CC
> -    TARGET_ADJUST_LLVM_CC(CallingConv, type);
> +  TARGET_ADJUST_LLVM_CC(CallingConv, type);
>  #endif
> +
> +  // Builtins are always prototyped, so this isn't one.
> +  ABIConverter.HandleReturnType(ReturnType, current_function_decl, false);
>
>   SmallVector<AttributeWithIndex, 8> Attrs;
>
> @@ -1118,15 +1118,15 @@
>   bool isVarArg = false;
>   FunctionTypeConversion Client(RetTy, ArgTypes, CallingConv, false/*not K&R*/);
>   TheLLVMABI<FunctionTypeConversion> ABIConverter(Client);
> -
> -  ABIConverter.HandleReturnType(TREE_TYPE(type), current_function_decl,
> -                                decl ? DECL_BUILT_IN(decl) : false);
> -
> +
>   // Allow the target to set the CC for things like fastcall etc.
>  #ifdef TARGET_ADJUST_LLVM_CC
>   TARGET_ADJUST_LLVM_CC(CallingConv, type);
>  #endif
>
> +  ABIConverter.HandleReturnType(TREE_TYPE(type), current_function_decl,
> +                                decl ? DECL_BUILT_IN(decl) : false);
> +
>   // Compute attributes for return type (and function attributes).
>   SmallVector<AttributeWithIndex, 8> Attrs;
>   Attributes FnAttributes = Attribute::None;
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>




More information about the llvm-commits mailing list