[llvm-commits] [llvm-gcc-4.2] r94390 - in /llvm-gcc-4.2/trunk/gcc: Makefile.in llvm-abi-default.cpp llvm-abi-linux-ppc.cpp llvm-abi.h

Rafael Espindola espindola at google.com
Sun Jan 24 15:48:58 PST 2010


The buildbots didn't like this, but the error message is very strange:

remoteFailed: [Failure instance: Traceback (failure with no frames):
<class 'twisted.internet.error.ConnectionLost'>: Connection to the
other side was lost in a non-clean fashion.
]

I will reboot and try to bootstrap on darwin. The message is from

http://google1.osuosl.org:8011/builders/llvm-gcc-x86_64-darwin10-selfhost/builds/1999

2010/1/24 Rafael Espindola <rafael.espindola at gmail.com>:
> Author: rafael
> Date: Sun Jan 24 16:57:22 2010
> New Revision: 94390
>
> URL: http://llvm.org/viewvc/llvm-project?rev=94390&view=rev
> Log:
> Move DefaultABI and the linux ppc one to .cpp files.
>
> Added:
>    llvm-gcc-4.2/trunk/gcc/llvm-abi-default.cpp
>    llvm-gcc-4.2/trunk/gcc/llvm-abi-linux-ppc.cpp
> Modified:
>    llvm-gcc-4.2/trunk/gcc/Makefile.in
>    llvm-gcc-4.2/trunk/gcc/llvm-abi.h
>
> Modified: llvm-gcc-4.2/trunk/gcc/Makefile.in
> URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/Makefile.in?rev=94390&r1=94389&r2=94390&view=diff
>
> ==============================================================================
> --- llvm-gcc-4.2/trunk/gcc/Makefile.in (original)
> +++ llvm-gcc-4.2/trunk/gcc/Makefile.in Sun Jan 24 16:57:22 2010
> @@ -1141,7 +1141,7 @@
>  OBJS = $(OBJS-common) $(out_object_file) $(OBJS-archive)
>  # LLVM LOCAL begin
>  ifneq ($(LLVMOBJDIR),)
> -OBJS-common += llvm-backend.o llvm-convert.o llvm-types.o llvm-debug.o llvm-linker-hack.o
> +OBJS-common += llvm-backend.o llvm-convert.o llvm-types.o llvm-debug.o llvm-linker-hack.o llvm-abi-default.o llvm-abi-linux-ppc.o
>  endif
>
>  ifneq ($(LLVMOBJDIR),)
> @@ -2956,6 +2956,8 @@
>             llvm.h llvm-internal.h llvm-file-ostream.h llvm-abi.h llvm-debug.h \
>             $(LLVM_HEADERS)
>  llvm-backend.o : llvm-backend.cpp $(ALL_HEADERS)
> +llvm-abi-linux-ppc.o : llvm-abi-linux-ppc.cpp $(ALL_HEADERS)
> +llvm-abi-default.o : llvm-abi-default.cpp $(ALL_HEADERS)
>  llvm-convert.o : llvm-convert.cpp $(ALL_HEADERS) \
>                  $(LLVMOBJDIR)/include/llvm/Intrinsics.gen
>  llvm-types.o : llvm-types.cpp $(ALL_HEADERS)
>
> Added: llvm-gcc-4.2/trunk/gcc/llvm-abi-default.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-abi-default.cpp?rev=94390&view=auto
>
> ==============================================================================
> --- llvm-gcc-4.2/trunk/gcc/llvm-abi-default.cpp (added)
> +++ llvm-gcc-4.2/trunk/gcc/llvm-abi-default.cpp Sun Jan 24 16:57:22 2010
> @@ -0,0 +1,338 @@
> +#include "llvm-abi.h"
> +
> +DefaultABI::DefaultABI(DefaultABIClient &c) : C(c) {}
> +
> +bool DefaultABI::isShadowReturn() const { return C.isShadowReturn(); }
> +
> +/// HandleReturnType - This is invoked by the target-independent code for the
> +/// return type. It potentially breaks down the argument and invokes methods
> +/// on the client that indicate how its pieces should be handled.  This
> +/// handles things like returning structures via hidden parameters.
> +void DefaultABI::HandleReturnType(tree type, tree fn, bool isBuiltin) {
> +  unsigned Offset = 0;
> +  const Type *Ty = ConvertType(type);
> +  if (isa<VectorType>(Ty)) {
> +    // Vector handling is weird on x86.  In particular builtin and
> +    // non-builtin function of the same return types can use different
> +    // calling conventions.
> +    tree ScalarType = LLVM_SHOULD_RETURN_VECTOR_AS_SCALAR(type, isBuiltin);
> +    if (ScalarType)
> +      C.HandleAggregateResultAsScalar(ConvertType(ScalarType));
> +    else if (LLVM_SHOULD_RETURN_VECTOR_AS_SHADOW(type, isBuiltin))
> +      C.HandleScalarShadowResult(Ty->getPointerTo(), false);
> +    else
> +      C.HandleScalarResult(Ty);
> +  } else if (Ty->isSingleValueType() || Ty->isVoidTy()) {
> +    // Return scalar values normally.
> +    C.HandleScalarResult(Ty);
> +  } 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 &&
> +       TREE_INT_CST_LOW(TYPE_SIZE_UNIT(type)) ==
> +       TREE_INT_CST_LOW(TYPE_SIZE_UNIT(SingleElt))) {
> +      C.HandleAggregateResultAsScalar(ConvertType(SingleElt));
> +    } 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,
> +                                  C.getCallingConv()))
> +       C.HandleAggregateResultAsAggregate(AggrTy);
> +      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();
> +      }
> +    }
> +  } else {
> +    // If the function is returning a struct or union, we pass the pointer to
> +    // the struct as the first argument to the function.
> +
> +    // FIXME: should return the hidden first argument for some targets
> +    // (e.g. ELF i386).
> +    C.HandleAggregateShadowResult(Ty->getPointerTo(), false);
> +  }
> +}
> +
> +/// HandleArgument - This is invoked by the target-independent code for each
> +/// argument type passed into the function.  It potentially breaks down the
> +/// 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 DefaultABI::HandleArgument(tree type, std::vector<const Type*> &ScalarElts,
> +                               Attributes *Attributes) {
> +  unsigned Size = 0;
> +  bool DontCheckAlignment = false;
> +  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 (Ty->isVoidTy()) {
> +    // Handle void explicitly as an opaque type.
> +    const Type *OpTy = OpaqueType::get(getGlobalContext());
> +    C.HandleScalarArgument(OpTy, type);
> +    ScalarElts.push_back(OpTy);
> +  } else if (isPassedByInvisibleReference(type)) { // variable size -> by-ref.
> +    const Type *PtrTy = Ty->getPointerTo();
> +    C.HandleByInvisibleReferenceArgument(PtrTy, type);
> +    ScalarElts.push_back(PtrTy);
> +  } else if (isa<VectorType>(Ty)) {
> +    if (LLVM_SHOULD_PASS_VECTOR_IN_INTEGER_REGS(type)) {
> +      PassInIntegerRegisters(type, ScalarElts, 0, false);
> +    } else if (LLVM_SHOULD_PASS_VECTOR_USING_BYVAL_ATTR(type)) {
> +      C.HandleByValArgument(Ty, type);
> +      if (Attributes) {
> +       *Attributes |= Attribute::ByVal;
> +       *Attributes |=
> +         Attribute::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
> +      }
> +    } else {
> +      C.HandleScalarArgument(Ty, type);
> +      ScalarElts.push_back(Ty);
> +    }
> +  } else if (Ty->isSingleValueType()) {
> +    C.HandleScalarArgument(Ty, type);
> +    ScalarElts.push_back(Ty);
> +  } else if (LLVM_SHOULD_PASS_AGGREGATE_AS_FCA(type, Ty)) {
> +    C.HandleFCAArgument(Ty, type);
> +  } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(type, Ty,
> +                                                     C.getCallingConv(),
> +                                                     Elts)) {
> +    if (!LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(Elts, ScalarElts,
> +                                                C.isShadowReturn(),
> +                                                C.getCallingConv()))
> +      PassInMixedRegisters(Ty, Elts, ScalarElts);
> +    else {
> +      C.HandleByValArgument(Ty, type);
> +      if (Attributes) {
> +       *Attributes |= Attribute::ByVal;
> +       *Attributes |=
> +         Attribute::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
> +      }
> +    }
> +  } else if (LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(type, Ty)) {
> +    C.HandleByValArgument(Ty, type);
> +    if (Attributes) {
> +      *Attributes |= Attribute::ByVal;
> +      *Attributes |=
> +       Attribute::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
> +    }
> +  } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(type, &Size,
> +                                                       &DontCheckAlignment)) {
> +    PassInIntegerRegisters(type, ScalarElts, Size, DontCheckAlignment);
> +  } else if (isZeroSizedStructOrUnion(type)) {
> +    // Zero sized struct or union, just drop it!
> +    ;
> +  } else if (TREE_CODE(type) == RECORD_TYPE) {
> +    for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field))
> +      if (TREE_CODE(Field) == FIELD_DECL) {
> +       const tree Ftype = getDeclaredType(Field);
> +       const Type *FTy = ConvertType(Ftype);
> +       unsigned FNo = GET_LLVM_FIELD_INDEX(Field);
> +       assert(FNo != ~0U && "Case not handled yet!");
> +
> +       // Currently, a bvyal type inside a non-byval struct is a zero-length
> +       // object inside a bigger object on x86-64.  This type should be
> +       // skipped (but only when it is inside a bigger object).
> +       // (We know there currently are no other such cases active because
> +       // they would hit the assert in FunctionPrologArgumentConversion::
> +       // HandleByValArgument.)
> +       if (!LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(Ftype, FTy)) {
> +         C.EnterField(FNo, Ty);
> +         HandleArgument(getDeclaredType(Field), ScalarElts);
> +         C.ExitField();
> +       }
> +      }
> +  } else if (TREE_CODE(type) == COMPLEX_TYPE) {
> +    C.EnterField(0, Ty);
> +    HandleArgument(TREE_TYPE(type), ScalarElts);
> +    C.ExitField();
> +    C.EnterField(1, Ty);
> +    HandleArgument(TREE_TYPE(type), ScalarElts);
> +    C.ExitField();
> +  } else if ((TREE_CODE(type) == UNION_TYPE) ||
> +            (TREE_CODE(type) == QUAL_UNION_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), ScalarElts);
> +      C.ExitField();
> +    }
> +  } else {
> +    assert(0 && "unknown aggregate type!");
> +    abort();
> +  }
> +}
> +
> +/// HandleUnion - Handle a UNION_TYPE or QUAL_UNION_TYPE tree.
> +void DefaultABI::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!");
> +    while (TREE_CODE(Field) != FIELD_DECL) {
> +      Field = TREE_CHAIN(Field);
> +      assert(Field && "Transparent union must have some elements!");
> +    }
> +
> +    HandleArgument(TREE_TYPE(Field), ScalarElts);
> +  } else {
> +    // Unions pass the largest element.
> +    unsigned MaxSize = 0;
> +    tree MaxElt = 0;
> +    for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
> +      if (TREE_CODE(Field) == FIELD_DECL) {
> +       // Skip fields that are known not to be present.
> +       if (TREE_CODE(type) == QUAL_UNION_TYPE &&
> +           integer_zerop(DECL_QUALIFIER(Field)))
> +         continue;
> +
> +       tree SizeTree = TYPE_SIZE(TREE_TYPE(Field));
> +       unsigned Size = ((unsigned)TREE_INT_CST_LOW(SizeTree)+7)/8;
> +       if (Size > MaxSize) {
> +         MaxSize = Size;
> +         MaxElt = Field;
> +       }
> +
> +       // Skip remaining fields if this one is known to be present.
> +       if (TREE_CODE(type) == QUAL_UNION_TYPE &&
> +           integer_onep(DECL_QUALIFIER(Field)))
> +         break;
> +      }
> +    }
> +
> +    if (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.  If Size is set we pass only that many bytes.
> +void DefaultABI::PassInIntegerRegisters(tree type,
> +                                       std::vector<const Type*> &ScalarElts,
> +                                       unsigned origSize,
> +                                       bool DontCheckAlignment) {
> +  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:
> +  // don't bitcast aggregate value to Int64 if its alignment is different
> +  // from Int64 alignment. ARM backend needs this.
> +  unsigned Align = TYPE_ALIGN(type)/8;
> +  unsigned Int64Align =
> +    getTargetData().getABITypeAlignment(Type::getInt64Ty(getGlobalContext()));
> +  bool UseInt64 = (getTargetData().isLegalInteger(64) &&
> +                  (DontCheckAlignment || Align >= Int64Align));
> +
> +  unsigned ElementSize = UseInt64 ? 8:4;
> +  unsigned ArraySize = Size / ElementSize;
> +
> +  // Put as much of the aggregate as possible into an array.
> +  const Type *ATy = NULL;
> +  const Type *ArrayElementType = NULL;
> +  if (ArraySize) {
> +    Size = Size % ElementSize;
> +    ArrayElementType = (UseInt64 ?
> +                       Type::getInt64Ty(getGlobalContext()) :
> +                       Type::getInt32Ty(getGlobalContext()));
> +    ATy = ArrayType::get(ArrayElementType, ArraySize);
> +  }
> +
> +  // Pass any leftover bytes as a separate element following the array.
> +  unsigned LastEltRealSize = 0;
> +  const llvm::Type *LastEltTy = 0;
> +  if (Size > 4) {
> +    LastEltTy = Type::getInt64Ty(getGlobalContext());
> +  } else if (Size > 2) {
> +    LastEltTy = Type::getInt32Ty(getGlobalContext());
> +  } else if (Size > 1) {
> +    LastEltTy = Type::getInt16Ty(getGlobalContext());
> +  } else if (Size > 0) {
> +    LastEltTy = Type::getInt8Ty(getGlobalContext());
> +  }
> +  if (LastEltTy) {
> +    if (Size != getTargetData().getTypeAllocSize(LastEltTy))
> +      LastEltRealSize = Size;
> +  }
> +
> +  std::vector<const Type*> Elts;
> +  if (ATy)
> +    Elts.push_back(ATy);
> +  if (LastEltTy)
> +    Elts.push_back(LastEltTy);
> +  const StructType *STy = StructType::get(getGlobalContext(), Elts, false);
> +
> +  unsigned i = 0;
> +  if (ArraySize) {
> +    C.EnterField(0, STy);
> +    for (unsigned j = 0; j < ArraySize; ++j) {
> +      C.EnterField(j, ATy);
> +      C.HandleScalarArgument(ArrayElementType, 0);
> +      ScalarElts.push_back(ArrayElementType);
> +      C.ExitField();
> +    }
> +    C.ExitField();
> +    ++i;
> +  }
> +  if (LastEltTy) {
> +    C.EnterField(i, STy);
> +    C.HandleScalarArgument(LastEltTy, 0, LastEltRealSize);
> +    ScalarElts.push_back(LastEltTy);
> +    C.ExitField();
> +  }
> +}
> +
> +/// PassInMixedRegisters - Given an aggregate value that should be passed in
> +/// mixed integer, floating point, and vector registers, convert it to a
> +/// structure containing the specified struct elements in.
> +void DefaultABI::PassInMixedRegisters(const Type *Ty,
> +                                     std::vector<const Type*> &OrigElts,
> +                                     std::vector<const Type*> &ScalarElts) {
> +  // We use VoidTy in OrigElts to mean "this is a word in the aggregate
> +  // that occupies storage but has no useful information, and is not passed
> +  // anywhere".  Happens on x86-64.
> +  std::vector<const Type*> Elts(OrigElts);
> +  const Type* wordType = getTargetData().getPointerSize() == 4 ?
> +    Type::getInt32Ty(getGlobalContext()) : Type::getInt64Ty(getGlobalContext());
> +  for (unsigned i=0, e=Elts.size(); i!=e; ++i)
> +    if (OrigElts[i]->isVoidTy())
> +      Elts[i] = wordType;
> +
> +  const StructType *STy = StructType::get(getGlobalContext(), Elts, false);
> +
> +  unsigned Size = getTargetData().getTypeAllocSize(STy);
> +  const StructType *InSTy = dyn_cast<StructType>(Ty);
> +  unsigned InSize = 0;
> +  // If Ty and STy size does not match then last element is accessing
> +  // extra bits.
> +  unsigned LastEltSizeDiff = 0;
> +  if (InSTy) {
> +    InSize = getTargetData().getTypeAllocSize(InSTy);
> +    if (InSize < Size) {
> +      unsigned N = STy->getNumElements();
> +      const llvm::Type *LastEltTy = STy->getElementType(N-1);
> +      if (LastEltTy->isInteger())
> +       LastEltSizeDiff =
> +         getTargetData().getTypeAllocSize(LastEltTy) - (Size - InSize);
> +    }
> +  }
> +  for (unsigned i = 0, e = Elts.size(); i != e; ++i) {
> +    if (!OrigElts[i]->isVoidTy()) {
> +      C.EnterField(i, STy);
> +      unsigned RealSize = 0;
> +      if (LastEltSizeDiff && i == (e - 1))
> +       RealSize = LastEltSizeDiff;
> +      C.HandleScalarArgument(Elts[i], 0, RealSize);
> +      ScalarElts.push_back(Elts[i]);
> +      C.ExitField();
> +    }
> +  }
> +}
>
> Added: llvm-gcc-4.2/trunk/gcc/llvm-abi-linux-ppc.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-abi-linux-ppc.cpp?rev=94390&view=auto
>
> ==============================================================================
> --- llvm-gcc-4.2/trunk/gcc/llvm-abi-linux-ppc.cpp (added)
> +++ llvm-gcc-4.2/trunk/gcc/llvm-abi-linux-ppc.cpp Sun Jan 24 16:57:22 2010
> @@ -0,0 +1,420 @@
> +#include "llvm-abi.h"
> +
> +SVR4ABI::SVR4ABI(DefaultABIClient &c) : NumGPR(0), C(c) {}
> +
> +bool SVR4ABI::isShadowReturn() const { return C.isShadowReturn(); }
> +
> +/// HandleReturnType - This is invoked by the target-independent code for the
> +/// return type. It potentially breaks down the argument and invokes methods
> +/// on the client that indicate how its pieces should be handled.  This
> +/// handles things like returning structures via hidden parameters.
> +void SVR4ABI::HandleReturnType(tree type, tree fn, bool isBuiltin) {
> +  unsigned Offset = 0;
> +  const Type *Ty = ConvertType(type);
> +  if (isa<VectorType>(Ty)) {
> +    // Vector handling is weird on x86.  In particular builtin and
> +    // non-builtin function of the same return types can use different
> +    // calling conventions.
> +    tree ScalarType = LLVM_SHOULD_RETURN_VECTOR_AS_SCALAR(type, isBuiltin);
> +    if (ScalarType)
> +      C.HandleAggregateResultAsScalar(ConvertType(ScalarType));
> +    else if (LLVM_SHOULD_RETURN_VECTOR_AS_SHADOW(type, isBuiltin))
> +      C.HandleScalarShadowResult(Ty->getPointerTo(), false);
> +    else
> +      C.HandleScalarResult(Ty);
> +  } else if (Ty->isSingleValueType() || Ty->isVoidTy()) {
> +    // Return scalar values normally.
> +    C.HandleScalarResult(Ty);
> +  } 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 &&
> +       TREE_INT_CST_LOW(TYPE_SIZE_UNIT(type)) ==
> +       TREE_INT_CST_LOW(TYPE_SIZE_UNIT(SingleElt))) {
> +      C.HandleAggregateResultAsScalar(ConvertType(SingleElt));
> +    } 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,
> +                                  C.getCallingConv()))
> +       C.HandleAggregateResultAsAggregate(AggrTy);
> +      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();
> +      }
> +    }
> +  } else {
> +    // If the function is returning a struct or union, we pass the pointer to
> +    // the struct as the first argument to the function.
> +
> +    // FIXME: should return the hidden first argument for some targets
> +    // (e.g. ELF i386).
> +    C.HandleAggregateShadowResult(Ty->getPointerTo(), false);
> +  }
> +}
> +
> +/// HandleArgument - This is invoked by the target-independent code for each
> +/// argument type passed into the function.  It potentially breaks down the
> +/// argument and invokes methods on the client that indicate how its pieces
> +/// should be handled.  This handles things like decimating structures into
> +/// their fields.
> +///
> +/// _Complex arguments are never split, thus their two scalars are either
> +/// passed both in argument registers or both on the stack. Also _Complex
> +/// arguments are always passed in general purpose registers, never in
> +/// Floating-point registers or vector registers. Arguments which should go
> +/// on the stack are marked with the inreg parameter attribute.
> +/// Giving inreg this target-dependent (and counter-intuitive) meaning
> +/// simplifies things, because functions calls are not always coming from the
> +/// frontend but are also created implicitly e.g. for libcalls. If inreg would
> +/// actually mean that the argument is passed in a register, then all places
> +/// which create function calls/function definitions implicitly would need to
> +/// be aware of this fact and would need to mark arguments accordingly. With
> +/// inreg meaning that the argument is passed on the stack, this is not an
> +/// issue, except for calls which involve _Complex types.
> +void SVR4ABI::HandleArgument(tree type, std::vector<const Type*> &ScalarElts,
> +                            Attributes *Attributes) {
> +  // Eight GPR's are availabe for parameter passing.
> +  const unsigned NumArgRegs = 8;
> +  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.
> +    const Type *PtrTy = Ty->getPointerTo();
> +    C.HandleByInvisibleReferenceArgument(PtrTy, type);
> +    ScalarElts.push_back(PtrTy);
> +
> +    unsigned Attr = Attribute::None;
> +
> +    if (NumGPR < NumArgRegs) {
> +      NumGPR++;
> +    } else {
> +      Attr |= Attribute::InReg;
> +    }
> +
> +    if (Attributes) {
> +      *Attributes |= Attr;
> +    }
> +  } else if (isa<VectorType>(Ty)) {
> +    if (LLVM_SHOULD_PASS_VECTOR_IN_INTEGER_REGS(type)) {
> +      PassInIntegerRegisters(type, ScalarElts, 0, false);
> +    } else if (LLVM_SHOULD_PASS_VECTOR_USING_BYVAL_ATTR(type)) {
> +      C.HandleByValArgument(Ty, type);
> +      if (Attributes) {
> +       *Attributes |= Attribute::ByVal;
> +       *Attributes |=
> +         Attribute::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
> +      }
> +    } else {
> +      C.HandleScalarArgument(Ty, type);
> +      ScalarElts.push_back(Ty);
> +    }
> +  } else if (Ty->isSingleValueType()) {
> +    C.HandleScalarArgument(Ty, type);
> +    ScalarElts.push_back(Ty);
> +
> +    unsigned Attr = Attribute::None;
> +
> +    if (Ty->isInteger()) {
> +      unsigned TypeSize = Ty->getPrimitiveSizeInBits();
> +
> +      // Determine how many general purpose registers are needed for the
> +      // argument.
> +      unsigned NumRegs = (TypeSize + 31) / 32;
> +
> +      // Make sure argument registers are aligned. 64-bit arguments are put in
> +      // a register pair which starts with an odd register number.
> +      if (TypeSize == 64 && (NumGPR % 2) == 1) {
> +       NumGPR++;
> +      }
> +
> +      if (NumGPR <= (NumArgRegs - NumRegs)) {
> +       NumGPR += NumRegs;
> +      } else {
> +       Attr |= Attribute::InReg;
> +       NumGPR = NumArgRegs;
> +      }
> +    } else if (isa<PointerType>(Ty)) {
> +      if (NumGPR < NumArgRegs) {
> +       NumGPR++;
> +      } else {
> +       Attr |= Attribute::InReg;
> +      }
> +      // We don't care about arguments passed in Floating-point or vector
> +      // registers.
> +    } else if (!(Ty->isFloatingPoint() || isa<VectorType>(Ty))) {
> +      abort();
> +    }
> +
> +    if (Attributes) {
> +      *Attributes |= Attr;
> +    }
> +  } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(type, Ty,
> +                                                     C.getCallingConv(),
> +                                                     Elts)) {
> +    HOST_WIDE_INT SrcSize = int_size_in_bytes(type);
> +
> +    // With the SVR4 ABI, the only aggregates which are passed in registers
> +    // are _Complex aggregates.
> +    assert(TREE_CODE(type) == COMPLEX_TYPE && "Not a _Complex type!");
> +
> +    unsigned Attr = Attribute::None;
> +
> +    switch (SrcSize) {
> +    default:
> +      abort();
> +      break;
> +    case 32:
> +      // _Complex long double
> +      if (NumGPR == 0) {
> +       NumGPR += NumArgRegs;
> +      } else {
> +       Attr |= Attribute::InReg;
> +       NumGPR = NumArgRegs;
> +      }
> +      break;
> +    case 16:
> +      // _Complex long long
> +      // _Complex double
> +      if (NumGPR <= (NumArgRegs - 4)) {
> +       NumGPR += 4;
> +      } else {
> +       Attr |= Attribute::InReg;
> +       NumGPR = NumArgRegs;
> +      }
> +      break;
> +    case 8:
> +      // _Complex int
> +      // _Complex long
> +      // _Complex float
> +
> +      // Make sure argument registers are aligned. 64-bit arguments are put in
> +      // a register pair which starts with an odd register number.
> +      if (NumGPR % 2 == 1) {
> +       NumGPR++;
> +      }
> +
> +      if (NumGPR <= (NumArgRegs - 2)) {
> +       NumGPR += 2;
> +      } else {
> +       Attr |= Attribute::InReg;
> +       NumGPR = NumArgRegs;
> +      }
> +      break;
> +    case 4:
> +    case 2:
> +      // _Complex short
> +      // _Complex char
> +      if (NumGPR < NumArgRegs) {
> +       NumGPR++;
> +      } else {
> +       Attr |= Attribute::InReg;
> +      }
> +      break;
> +    }
> +
> +    if (Attributes) {
> +      *Attributes |= Attr;
> +    }
> +
> +    PassInMixedRegisters(Ty, Elts, ScalarElts);
> +  } else if (LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(type, Ty)) {
> +    C.HandleByValArgument(Ty, type);
> +    if (Attributes) {
> +      *Attributes |= Attribute::ByVal;
> +      *Attributes |=
> +       Attribute::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
> +    }
> +
> +    unsigned Attr = Attribute::None;
> +
> +    if (NumGPR < NumArgRegs) {
> +      NumGPR++;
> +    } else {
> +      Attr |= Attribute::InReg;
> +    }
> +
> +    if (Attributes) {
> +      *Attributes |= Attr;
> +    }
> +  } else if (isZeroSizedStructOrUnion(type)) {
> +    // Zero sized struct or union, just drop it!
> +    ;
> +  } else {
> +    assert(0 && "unknown aggregate type!");
> +    abort();
> +  }
> +}
> +
> +/// HandleUnion - Handle a UNION_TYPE or QUAL_UNION_TYPE tree.
> +void SVR4ABI::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!");
> +    while (TREE_CODE(Field) != FIELD_DECL) {
> +      Field = TREE_CHAIN(Field);
> +      assert(Field && "Transparent union must have some elements!");
> +    }
> +
> +    HandleArgument(TREE_TYPE(Field), ScalarElts);
> +  } else {
> +    // Unions pass the largest element.
> +    unsigned MaxSize = 0;
> +    tree MaxElt = 0;
> +    for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
> +      if (TREE_CODE(Field) == FIELD_DECL) {
> +       // Skip fields that are known not to be present.
> +       if (TREE_CODE(type) == QUAL_UNION_TYPE &&
> +           integer_zerop(DECL_QUALIFIER(Field)))
> +         continue;
> +
> +       tree SizeTree = TYPE_SIZE(TREE_TYPE(Field));
> +       unsigned Size = ((unsigned)TREE_INT_CST_LOW(SizeTree)+7)/8;
> +       if (Size > MaxSize) {
> +         MaxSize = Size;
> +         MaxElt = Field;
> +       }
> +
> +       // Skip remaining fields if this one is known to be present.
> +       if (TREE_CODE(type) == QUAL_UNION_TYPE &&
> +           integer_onep(DECL_QUALIFIER(Field)))
> +         break;
> +      }
> +    }
> +
> +    if (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.  If Size is set we pass only that many bytes.
> +void SVR4ABI::PassInIntegerRegisters(tree type,
> +                                    std::vector<const Type*> &ScalarElts,
> +                                    unsigned origSize,
> +                                    bool DontCheckAlignment) {
> +  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:
> +  // don't bitcast aggregate value to Int64 if its alignment is different
> +  // from Int64 alignment. ARM backend needs this.
> +  unsigned Align = TYPE_ALIGN(type)/8;
> +  unsigned Int64Align =
> +    getTargetData().getABITypeAlignment(Type::getInt64Ty(getGlobalContext()));
> +  bool UseInt64 = (getTargetData().isLegalInteger(64) &&
> +                  (DontCheckAlignment || Align >= Int64Align));
> +
> +  unsigned ElementSize = UseInt64 ? 8:4;
> +  unsigned ArraySize = Size / ElementSize;
> +
> +  // Put as much of the aggregate as possible into an array.
> +  const Type *ATy = NULL;
> +  const Type *ArrayElementType = NULL;
> +  if (ArraySize) {
> +    Size = Size % ElementSize;
> +    ArrayElementType = (UseInt64 ?
> +                       Type::getInt64Ty(getGlobalContext()) :
> +                       Type::getInt32Ty(getGlobalContext()));
> +    ATy = ArrayType::get(ArrayElementType, ArraySize);
> +  }
> +
> +  // Pass any leftover bytes as a separate element following the array.
> +  unsigned LastEltRealSize = 0;
> +  const llvm::Type *LastEltTy = 0;
> +  if (Size > 4) {
> +    LastEltTy = Type::getInt64Ty(getGlobalContext());
> +  } else if (Size > 2) {
> +    LastEltTy = Type::getInt32Ty(getGlobalContext());
> +  } else if (Size > 1) {
> +    LastEltTy = Type::getInt16Ty(getGlobalContext());
> +  } else if (Size > 0) {
> +    LastEltTy = Type::getInt8Ty(getGlobalContext());
> +  }
> +  if (LastEltTy) {
> +    if (Size != getTargetData().getTypeAllocSize(LastEltTy))
> +      LastEltRealSize = Size;
> +  }
> +
> +  std::vector<const Type*> Elts;
> +  if (ATy)
> +    Elts.push_back(ATy);
> +  if (LastEltTy)
> +    Elts.push_back(LastEltTy);
> +  const StructType *STy = StructType::get(getGlobalContext(), Elts, false);
> +
> +  unsigned i = 0;
> +  if (ArraySize) {
> +    C.EnterField(0, STy);
> +    for (unsigned j = 0; j < ArraySize; ++j) {
> +      C.EnterField(j, ATy);
> +      C.HandleScalarArgument(ArrayElementType, 0);
> +      ScalarElts.push_back(ArrayElementType);
> +      C.ExitField();
> +    }
> +    C.ExitField();
> +    ++i;
> +  }
> +  if (LastEltTy) {
> +    C.EnterField(i, STy);
> +    C.HandleScalarArgument(LastEltTy, 0, LastEltRealSize);
> +    ScalarElts.push_back(LastEltTy);
> +    C.ExitField();
> +  }
> +}
> +
> +/// PassInMixedRegisters - Given an aggregate value that should be passed in
> +/// mixed integer, floating point, and vector registers, convert it to a
> +/// structure containing the specified struct elements in.
> +void SVR4ABI::PassInMixedRegisters(const Type *Ty,
> +                                  std::vector<const Type*> &OrigElts,
> +                                  std::vector<const Type*> &ScalarElts) {
> +  // We use VoidTy in OrigElts to mean "this is a word in the aggregate
> +  // that occupies storage but has no useful information, and is not passed
> +  // anywhere".  Happens on x86-64.
> +  std::vector<const Type*> Elts(OrigElts);
> +  const Type* wordType = getTargetData().getPointerSize() == 4 ?
> +    Type::getInt32Ty(getGlobalContext()) : Type::getInt64Ty(getGlobalContext());
> +  for (unsigned i=0, e=Elts.size(); i!=e; ++i)
> +    if (OrigElts[i]->isVoidTy())
> +      Elts[i] = wordType;
> +
> +  const StructType *STy = StructType::get(getGlobalContext(), Elts, false);
> +
> +  unsigned Size = getTargetData().getTypeAllocSize(STy);
> +  const StructType *InSTy = dyn_cast<StructType>(Ty);
> +  unsigned InSize = 0;
> +  // If Ty and STy size does not match then last element is accessing
> +  // extra bits.
> +  unsigned LastEltSizeDiff = 0;
> +  if (InSTy) {
> +    InSize = getTargetData().getTypeAllocSize(InSTy);
> +    if (InSize < Size) {
> +      unsigned N = STy->getNumElements();
> +      const llvm::Type *LastEltTy = STy->getElementType(N-1);
> +      if (LastEltTy->isInteger())
> +       LastEltSizeDiff =
> +         getTargetData().getTypeAllocSize(LastEltTy) - (Size - InSize);
> +    }
> +  }
> +  for (unsigned i = 0, e = Elts.size(); i != e; ++i) {
> +    if (!OrigElts[i]->isVoidTy()) {
> +      C.EnterField(i, STy);
> +      unsigned RealSize = 0;
> +      if (LastEltSizeDiff && i == (e - 1))
> +       RealSize = LastEltSizeDiff;
> +      C.HandleScalarArgument(Elts[i], 0, RealSize);
> +      ScalarElts.push_back(Elts[i]);
> +      C.ExitField();
> +    }
> +  }
> +}
>
> 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=94390&r1=94389&r2=94390&view=diff
>
> ==============================================================================
> --- llvm-gcc-4.2/trunk/gcc/llvm-abi.h (original)
> +++ llvm-gcc-4.2/trunk/gcc/llvm-abi.h Sun Jan 24 16:57:22 2010
> @@ -383,340 +383,61 @@
>  protected:
>   DefaultABIClient &C;
>  public:
> -  DefaultABI(DefaultABIClient &c) : C(c) {}
> +  DefaultABI(DefaultABIClient &c);
> +
> +  bool isShadowReturn() const;
>
> -  bool isShadowReturn() const { return C.isShadowReturn(); }
> -
>   /// HandleReturnType - This is invoked by the target-independent code for the
>   /// return type. It potentially breaks down the argument and invokes methods
>   /// 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 (isa<VectorType>(Ty)) {
> -      // Vector handling is weird on x86.  In particular builtin and
> -      // non-builtin function of the same return types can use different
> -      // calling conventions.
> -      tree ScalarType = LLVM_SHOULD_RETURN_VECTOR_AS_SCALAR(type, isBuiltin);
> -      if (ScalarType)
> -        C.HandleAggregateResultAsScalar(ConvertType(ScalarType));
> -      else if (LLVM_SHOULD_RETURN_VECTOR_AS_SHADOW(type, isBuiltin))
> -        C.HandleScalarShadowResult(Ty->getPointerTo(), false);
> -      else
> -        C.HandleScalarResult(Ty);
> -    } else if (Ty->isSingleValueType() || Ty->isVoidTy()) {
> -      // Return scalar values normally.
> -      C.HandleScalarResult(Ty);
> -    } 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 &&
> -          TREE_INT_CST_LOW(TYPE_SIZE_UNIT(type)) ==
> -            TREE_INT_CST_LOW(TYPE_SIZE_UNIT(SingleElt))) {
> -        C.HandleAggregateResultAsScalar(ConvertType(SingleElt));
> -      } 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,
> -                                    C.getCallingConv()))
> -          C.HandleAggregateResultAsAggregate(AggrTy);
> -        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();
> -        }
> -      }
> -    } else {
> -      // If the function is returning a struct or union, we pass the pointer to
> -      // the struct as the first argument to the function.
> -
> -      // FIXME: should return the hidden first argument for some targets
> -      // (e.g. ELF i386).
> -      C.HandleAggregateShadowResult(Ty->getPointerTo(), false);
> -    }
> -  }
> -
> +  void HandleReturnType(tree type, tree fn, bool isBuiltin);
> +
>   /// HandleArgument - This is invoked by the target-independent code for each
>   /// argument type passed into the function.  It potentially breaks down the
>   /// 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, std::vector<const Type*> &ScalarElts,
> -                      Attributes *Attributes = NULL) {
> -    unsigned Size = 0;
> -    bool DontCheckAlignment = false;
> -    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 (Ty->isVoidTy()) {
> -      // Handle void explicitly as an opaque type.
> -      const Type *OpTy = OpaqueType::get(getGlobalContext());
> -      C.HandleScalarArgument(OpTy, type);
> -      ScalarElts.push_back(OpTy);
> -    } else if (isPassedByInvisibleReference(type)) { // variable size -> by-ref.
> -      const Type *PtrTy = Ty->getPointerTo();
> -      C.HandleByInvisibleReferenceArgument(PtrTy, type);
> -      ScalarElts.push_back(PtrTy);
> -    } else if (isa<VectorType>(Ty)) {
> -      if (LLVM_SHOULD_PASS_VECTOR_IN_INTEGER_REGS(type)) {
> -        PassInIntegerRegisters(type, ScalarElts, 0, false);
> -      } else if (LLVM_SHOULD_PASS_VECTOR_USING_BYVAL_ATTR(type)) {
> -        C.HandleByValArgument(Ty, type);
> -        if (Attributes) {
> -          *Attributes |= Attribute::ByVal;
> -          *Attributes |=
> -            Attribute::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
> -        }
> -      } else {
> -        C.HandleScalarArgument(Ty, type);
> -        ScalarElts.push_back(Ty);
> -      }
> -    } else if (Ty->isSingleValueType()) {
> -      C.HandleScalarArgument(Ty, type);
> -      ScalarElts.push_back(Ty);
> -    } else if (LLVM_SHOULD_PASS_AGGREGATE_AS_FCA(type, Ty)) {
> -      C.HandleFCAArgument(Ty, type);
> -    } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(type, Ty,
> -                                                        C.getCallingConv(),
> -                                                        Elts)) {
> -      if (!LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(Elts, ScalarElts,
> -                                                   C.isShadowReturn(),
> -                                                   C.getCallingConv()))
> -        PassInMixedRegisters(Ty, Elts, ScalarElts);
> -      else {
> -        C.HandleByValArgument(Ty, type);
> -        if (Attributes) {
> -          *Attributes |= Attribute::ByVal;
> -          *Attributes |=
> -            Attribute::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
> -        }
> -      }
> -    } else if (LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(type, Ty)) {
> -      C.HandleByValArgument(Ty, type);
> -      if (Attributes) {
> -        *Attributes |= Attribute::ByVal;
> -        *Attributes |=
> -          Attribute::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
> -      }
> -    } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(type, &Size,
> -                                                     &DontCheckAlignment)) {
> -      PassInIntegerRegisters(type, ScalarElts, Size, DontCheckAlignment);
> -    } else if (isZeroSizedStructOrUnion(type)) {
> -      // Zero sized struct or union, just drop it!
> -      ;
> -    } else if (TREE_CODE(type) == RECORD_TYPE) {
> -      for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field))
> -        if (TREE_CODE(Field) == FIELD_DECL) {
> -          const tree Ftype = getDeclaredType(Field);
> -          const Type *FTy = ConvertType(Ftype);
> -          unsigned FNo = GET_LLVM_FIELD_INDEX(Field);
> -          assert(FNo != ~0U && "Case not handled yet!");
> -
> -          // Currently, a bvyal type inside a non-byval struct is a zero-length
> -          // object inside a bigger object on x86-64.  This type should be
> -          // skipped (but only when it is inside a bigger object).
> -          // (We know there currently are no other such cases active because
> -          // they would hit the assert in FunctionPrologArgumentConversion::
> -          // HandleByValArgument.)
> -          if (!LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(Ftype, FTy)) {
> -            C.EnterField(FNo, Ty);
> -            HandleArgument(getDeclaredType(Field), ScalarElts);
> -            C.ExitField();
> -          }
> -        }
> -    } else if (TREE_CODE(type) == COMPLEX_TYPE) {
> -      C.EnterField(0, Ty);
> -      HandleArgument(TREE_TYPE(type), ScalarElts);
> -      C.ExitField();
> -      C.EnterField(1, Ty);
> -      HandleArgument(TREE_TYPE(type), ScalarElts);
> -      C.ExitField();
> -    } else if ((TREE_CODE(type) == UNION_TYPE) ||
> -               (TREE_CODE(type) == QUAL_UNION_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), ScalarElts);
> -        C.ExitField();
> -      }
> -    } else {
> -      assert(0 && "unknown aggregate type!");
> -      abort();
> -    }
> -  }
> +                      Attributes *Attributes = NULL);
>
>   /// HandleUnion - Handle a UNION_TYPE or QUAL_UNION_TYPE tree.
>   ///
> -  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!");
> -      while (TREE_CODE(Field) != FIELD_DECL) {
> -        Field = TREE_CHAIN(Field);
> -        assert(Field && "Transparent union must have some elements!");
> -      }
> -
> -      HandleArgument(TREE_TYPE(Field), ScalarElts);
> -    } else {
> -      // Unions pass the largest element.
> -      unsigned MaxSize = 0;
> -      tree MaxElt = 0;
> -      for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
> -        if (TREE_CODE(Field) == FIELD_DECL) {
> -          // Skip fields that are known not to be present.
> -          if (TREE_CODE(type) == QUAL_UNION_TYPE &&
> -              integer_zerop(DECL_QUALIFIER(Field)))
> -              continue;
> -
> -          tree SizeTree = TYPE_SIZE(TREE_TYPE(Field));
> -          unsigned Size = ((unsigned)TREE_INT_CST_LOW(SizeTree)+7)/8;
> -          if (Size > MaxSize) {
> -            MaxSize = Size;
> -            MaxElt = Field;
> -          }
> -
> -          // Skip remaining fields if this one is known to be present.
> -          if (TREE_CODE(type) == QUAL_UNION_TYPE &&
> -              integer_onep(DECL_QUALIFIER(Field)))
> -              break;
> -        }
> -      }
> -
> -      if (MaxElt)
> -        HandleArgument(TREE_TYPE(MaxElt), ScalarElts);
> -    }
> -  }
> -
> +  void HandleUnion(tree type, std::vector<const Type*> &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.  If Size is set we pass only that many bytes.
>   void PassInIntegerRegisters(tree type, std::vector<const Type*> &ScalarElts,
> -                              unsigned origSize, bool DontCheckAlignment) {
> -    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:
> -    // don't bitcast aggregate value to Int64 if its alignment is different
> -    // from Int64 alignment. ARM backend needs this.
> -    unsigned Align = TYPE_ALIGN(type)/8;
> -    unsigned Int64Align =
> -      getTargetData().getABITypeAlignment(Type::getInt64Ty(getGlobalContext()));
> -    bool UseInt64 = (getTargetData().isLegalInteger(64) &&
> -                     (DontCheckAlignment || Align >= Int64Align));
> -
> -    unsigned ElementSize = UseInt64 ? 8:4;
> -    unsigned ArraySize = Size / ElementSize;
> -
> -    // Put as much of the aggregate as possible into an array.
> -    const Type *ATy = NULL;
> -    const Type *ArrayElementType = NULL;
> -    if (ArraySize) {
> -      Size = Size % ElementSize;
> -      ArrayElementType = (UseInt64 ?
> -                          Type::getInt64Ty(getGlobalContext()) :
> -                          Type::getInt32Ty(getGlobalContext()));
> -      ATy = ArrayType::get(ArrayElementType, ArraySize);
> -    }
> -
> -    // Pass any leftover bytes as a separate element following the array.
> -    unsigned LastEltRealSize = 0;
> -    const llvm::Type *LastEltTy = 0;
> -    if (Size > 4) {
> -      LastEltTy = Type::getInt64Ty(getGlobalContext());
> -    } else if (Size > 2) {
> -      LastEltTy = Type::getInt32Ty(getGlobalContext());
> -    } else if (Size > 1) {
> -      LastEltTy = Type::getInt16Ty(getGlobalContext());
> -    } else if (Size > 0) {
> -      LastEltTy = Type::getInt8Ty(getGlobalContext());
> -    }
> -    if (LastEltTy) {
> -      if (Size != getTargetData().getTypeAllocSize(LastEltTy))
> -        LastEltRealSize = Size;
> -    }
> -
> -    std::vector<const Type*> Elts;
> -    if (ATy)
> -      Elts.push_back(ATy);
> -    if (LastEltTy)
> -      Elts.push_back(LastEltTy);
> -    const StructType *STy = StructType::get(getGlobalContext(), Elts, false);
> -
> -    unsigned i = 0;
> -    if (ArraySize) {
> -      C.EnterField(0, STy);
> -      for (unsigned j = 0; j < ArraySize; ++j) {
> -        C.EnterField(j, ATy);
> -        C.HandleScalarArgument(ArrayElementType, 0);
> -        ScalarElts.push_back(ArrayElementType);
> -        C.ExitField();
> -      }
> -      C.ExitField();
> -      ++i;
> -    }
> -    if (LastEltTy) {
> -      C.EnterField(i, STy);
> -      C.HandleScalarArgument(LastEltTy, 0, LastEltRealSize);
> -      ScalarElts.push_back(LastEltTy);
> -      C.ExitField();
> -    }
> -  }
> +                              unsigned origSize, bool DontCheckAlignment);
>
>   /// PassInMixedRegisters - Given an aggregate value that should be passed in
>   /// mixed integer, floating point, and vector registers, convert it to a
>   /// structure containing the specified struct elements in.
>   void PassInMixedRegisters(const Type *Ty, std::vector<const Type*> &OrigElts,
> -                            std::vector<const Type*> &ScalarElts) {
> -    // We use VoidTy in OrigElts to mean "this is a word in the aggregate
> -    // that occupies storage but has no useful information, and is not passed
> -    // anywhere".  Happens on x86-64.
> -    std::vector<const Type*> Elts(OrigElts);
> -    const Type* wordType = getTargetData().getPointerSize() == 4 ?
> -        Type::getInt32Ty(getGlobalContext()) : Type::getInt64Ty(getGlobalContext());
> -    for (unsigned i=0, e=Elts.size(); i!=e; ++i)
> -      if (OrigElts[i]->isVoidTy())
> -        Elts[i] = wordType;
> -
> -    const StructType *STy = StructType::get(getGlobalContext(), Elts, false);
> -
> -    unsigned Size = getTargetData().getTypeAllocSize(STy);
> -    const StructType *InSTy = dyn_cast<StructType>(Ty);
> -    unsigned InSize = 0;
> -    // If Ty and STy size does not match then last element is accessing
> -    // extra bits.
> -    unsigned LastEltSizeDiff = 0;
> -    if (InSTy) {
> -      InSize = getTargetData().getTypeAllocSize(InSTy);
> -      if (InSize < Size) {
> -        unsigned N = STy->getNumElements();
> -        const llvm::Type *LastEltTy = STy->getElementType(N-1);
> -        if (LastEltTy->isInteger())
> -          LastEltSizeDiff =
> -            getTargetData().getTypeAllocSize(LastEltTy) - (Size - InSize);
> -      }
> -    }
> -    for (unsigned i = 0, e = Elts.size(); i != e; ++i) {
> -      if (!OrigElts[i]->isVoidTy()) {
> -        C.EnterField(i, STy);
> -        unsigned RealSize = 0;
> -        if (LastEltSizeDiff && i == (e - 1))
> -          RealSize = LastEltSizeDiff;
> -        C.HandleScalarArgument(Elts[i], 0, RealSize);
> -        ScalarElts.push_back(Elts[i]);
> -        C.ExitField();
> -      }
> -    }
> -  }
> +                            std::vector<const Type*> &ScalarElts);
> +};
> +
> +// Similar to DefaultABI but for linux ppc 32 bits
> +class SVR4ABI{
> +  // Number of general purpose argument registers which have already been
> +  // assigned.
> +protected:
> +  unsigned NumGPR;
> +  DefaultABIClient &C;
> +public:
> +  SVR4ABI(DefaultABIClient &c);
> +
> +  bool isShadowReturn() const;
> +  void HandleReturnType(tree type, tree fn, bool isBuiltin);
> +  void HandleArgument(tree type, std::vector<const Type*> &ScalarElts,
> +                      Attributes *Attributes = NULL);
> +  void HandleUnion(tree type, std::vector<const Type*> &ScalarElts);
> +  void PassInIntegerRegisters(tree type, std::vector<const Type*> &ScalarElts,
> +                              unsigned origSize, bool DontCheckAlignment);
> +  void PassInMixedRegisters(const Type *Ty, std::vector<const Type*> &OrigElts,
> +                            std::vector<const Type*> &ScalarElts);
> +
>  };
>
>  // Make sure the SVR4 ABI is used on 32-bit PowerPC Linux.
> @@ -731,442 +452,5 @@
>  #define TheLLVMABI DefaultABI
>  #endif
>
> -/// SVR4ABI - This class implements the System V Release 4 ABI for PowerPC. The
> -/// SVR4 ABI is the ABI used on 32-bit PowerPC Linux.
> -///
> -class SVR4ABI {
> -  // Number of general purpose argument registers which have already been
> -  // assigned.
> -  unsigned NumGPR;
> -protected:
> -  DefaultABIClient &C;
> -public:
> -  SVR4ABI(DefaultABIClient &c) : NumGPR(0), C(c) {}
> -
> -  bool isShadowReturn() const { return C.isShadowReturn(); }
> -
> -  /// HandleReturnType - This is invoked by the target-independent code for the
> -  /// return type. It potentially breaks down the argument and invokes methods
> -  /// on the client that indicate how its pieces should be handled.  This
> -  /// handles things like returning structures via hidden parameters.
> -  ///
> -  /// This is the default implementation which was copied from DefaultABI.
> -  void HandleReturnType(tree type, tree fn, bool isBuiltin) {
> -    unsigned Offset = 0;
> -    const Type *Ty = ConvertType(type);
> -    if (isa<VectorType>(Ty)) {
> -      // Vector handling is weird on x86.  In particular builtin and
> -      // non-builtin function of the same return types can use different
> -      // calling conventions.
> -      tree ScalarType = LLVM_SHOULD_RETURN_VECTOR_AS_SCALAR(type, isBuiltin);
> -      if (ScalarType)
> -        C.HandleAggregateResultAsScalar(ConvertType(ScalarType));
> -      else if (LLVM_SHOULD_RETURN_VECTOR_AS_SHADOW(type, isBuiltin))
> -        C.HandleScalarShadowResult(Ty->getPointerTo(), false);
> -      else
> -        C.HandleScalarResult(Ty);
> -    } else if (Ty->isSingleValueType() || Ty->isVoidTy()) {
> -      // Return scalar values normally.
> -      C.HandleScalarResult(Ty);
> -    } 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 &&
> -          TREE_INT_CST_LOW(TYPE_SIZE_UNIT(type)) ==
> -            TREE_INT_CST_LOW(TYPE_SIZE_UNIT(SingleElt))) {
> -        C.HandleAggregateResultAsScalar(ConvertType(SingleElt));
> -      } 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,
> -                                    C.getCallingConv()))
> -          C.HandleAggregateResultAsAggregate(AggrTy);
> -        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();
> -        }
> -      }
> -    } else {
> -      // If the function is returning a struct or union, we pass the pointer to
> -      // the struct as the first argument to the function.
> -
> -      // FIXME: should return the hidden first argument for some targets
> -      // (e.g. ELF i386).
> -      C.HandleAggregateShadowResult(Ty->getPointerTo(), false);
> -    }
> -  }
> -
> -  /// HandleArgument - This is invoked by the target-independent code for each
> -  /// argument type passed into the function.  It potentially breaks down the
> -  /// argument and invokes methods on the client that indicate how its pieces
> -  /// should be handled.  This handles things like decimating structures into
> -  /// their fields.
> -  ///
> -  /// _Complex arguments are never split, thus their two scalars are either
> -  /// passed both in argument registers or both on the stack. Also _Complex
> -  /// arguments are always passed in general purpose registers, never in
> -  /// Floating-point registers or vector registers. Arguments which should go
> -  /// on the stack are marked with the inreg parameter attribute.
> -  /// Giving inreg this target-dependent (and counter-intuitive) meaning
> -  /// simplifies things, because functions calls are not always coming from the
> -  /// frontend but are also created implicitly e.g. for libcalls. If inreg would
> -  /// actually mean that the argument is passed in a register, then all places
> -  /// which create function calls/function definitions implicitly would need to
> -  /// be aware of this fact and would need to mark arguments accordingly. With
> -  /// inreg meaning that the argument is passed on the stack, this is not an
> -  /// issue, except for calls which involve _Complex types.
> -  void HandleArgument(tree type, std::vector<const Type*> &ScalarElts,
> -                      Attributes *Attributes = NULL) {
> -    // Eight GPR's are availabe for parameter passing.
> -    const unsigned NumArgRegs = 8;
> -    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.
> -      const Type *PtrTy = Ty->getPointerTo();
> -      C.HandleByInvisibleReferenceArgument(PtrTy, type);
> -      ScalarElts.push_back(PtrTy);
> -
> -      unsigned Attr = Attribute::None;
> -
> -      if (NumGPR < NumArgRegs) {
> -        NumGPR++;
> -      } else {
> -        Attr |= Attribute::InReg;
> -      }
> -
> -      if (Attributes) {
> -        *Attributes |= Attr;
> -      }
> -    } else if (isa<VectorType>(Ty)) {
> -      if (LLVM_SHOULD_PASS_VECTOR_IN_INTEGER_REGS(type)) {
> -        PassInIntegerRegisters(type, ScalarElts, 0, false);
> -      } else if (LLVM_SHOULD_PASS_VECTOR_USING_BYVAL_ATTR(type)) {
> -        C.HandleByValArgument(Ty, type);
> -        if (Attributes) {
> -          *Attributes |= Attribute::ByVal;
> -          *Attributes |=
> -            Attribute::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
> -        }
> -      } else {
> -        C.HandleScalarArgument(Ty, type);
> -        ScalarElts.push_back(Ty);
> -      }
> -    } else if (Ty->isSingleValueType()) {
> -      C.HandleScalarArgument(Ty, type);
> -      ScalarElts.push_back(Ty);
> -
> -      unsigned Attr = Attribute::None;
> -
> -      if (Ty->isInteger()) {
> -        unsigned TypeSize = Ty->getPrimitiveSizeInBits();
> -
> -        // Determine how many general purpose registers are needed for the
> -        // argument.
> -        unsigned NumRegs = (TypeSize + 31) / 32;
> -
> -        // Make sure argument registers are aligned. 64-bit arguments are put in
> -        // a register pair which starts with an odd register number.
> -        if (TypeSize == 64 && (NumGPR % 2) == 1) {
> -          NumGPR++;
> -        }
> -
> -        if (NumGPR <= (NumArgRegs - NumRegs)) {
> -          NumGPR += NumRegs;
> -        } else {
> -          Attr |= Attribute::InReg;
> -          NumGPR = NumArgRegs;
> -        }
> -      } else if (isa<PointerType>(Ty)) {
> -        if (NumGPR < NumArgRegs) {
> -          NumGPR++;
> -        } else {
> -          Attr |= Attribute::InReg;
> -        }
> -      // We don't care about arguments passed in Floating-point or vector
> -      // registers.
> -      } else if (!(Ty->isFloatingPoint() || isa<VectorType>(Ty))) {
> -        abort();
> -      }
> -
> -      if (Attributes) {
> -        *Attributes |= Attr;
> -      }
> -    } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(type, Ty,
> -                                                        C.getCallingConv(),
> -                                                        Elts)) {
> -      HOST_WIDE_INT SrcSize = int_size_in_bytes(type);
> -
> -      // With the SVR4 ABI, the only aggregates which are passed in registers
> -      // are _Complex aggregates.
> -      assert(TREE_CODE(type) == COMPLEX_TYPE && "Not a _Complex type!");
> -
> -      unsigned Attr = Attribute::None;
> -
> -      switch (SrcSize) {
> -      default:
> -        abort();
> -        break;
> -      case 32:
> -        // _Complex long double
> -        if (NumGPR == 0) {
> -          NumGPR += NumArgRegs;
> -        } else {
> -          Attr |= Attribute::InReg;
> -          NumGPR = NumArgRegs;
> -        }
> -        break;
> -      case 16:
> -        // _Complex long long
> -        // _Complex double
> -        if (NumGPR <= (NumArgRegs - 4)) {
> -          NumGPR += 4;
> -        } else {
> -          Attr |= Attribute::InReg;
> -          NumGPR = NumArgRegs;
> -        }
> -        break;
> -      case 8:
> -        // _Complex int
> -        // _Complex long
> -        // _Complex float
> -
> -        // Make sure argument registers are aligned. 64-bit arguments are put in
> -        // a register pair which starts with an odd register number.
> -        if (NumGPR % 2 == 1) {
> -          NumGPR++;
> -        }
> -
> -        if (NumGPR <= (NumArgRegs - 2)) {
> -          NumGPR += 2;
> -        } else {
> -          Attr |= Attribute::InReg;
> -          NumGPR = NumArgRegs;
> -        }
> -        break;
> -      case 4:
> -      case 2:
> -        // _Complex short
> -        // _Complex char
> -        if (NumGPR < NumArgRegs) {
> -          NumGPR++;
> -        } else {
> -          Attr |= Attribute::InReg;
> -        }
> -        break;
> -      }
> -
> -      if (Attributes) {
> -        *Attributes |= Attr;
> -      }
> -
> -      PassInMixedRegisters(Ty, Elts, ScalarElts);
> -    } else if (LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(type, Ty)) {
> -      C.HandleByValArgument(Ty, type);
> -      if (Attributes) {
> -        *Attributes |= Attribute::ByVal;
> -        *Attributes |=
> -          Attribute::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type));
> -      }
> -
> -      unsigned Attr = Attribute::None;
> -
> -      if (NumGPR < NumArgRegs) {
> -        NumGPR++;
> -      } else {
> -        Attr |= Attribute::InReg;
> -      }
> -
> -      if (Attributes) {
> -        *Attributes |= Attr;
> -      }
> -    } else if (isZeroSizedStructOrUnion(type)) {
> -      // Zero sized struct or union, just drop it!
> -      ;
> -    } else {
> -      assert(0 && "unknown aggregate type!");
> -      abort();
> -    }
> -  }
> -
> -  /// HandleUnion - Handle a UNION_TYPE or QUAL_UNION_TYPE tree.
> -  ///
> -  /// This is the default implementation which was copied from DefaultABI.
> -  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!");
> -      while (TREE_CODE(Field) != FIELD_DECL) {
> -        Field = TREE_CHAIN(Field);
> -        assert(Field && "Transparent union must have some elements!");
> -      }
> -
> -      HandleArgument(TREE_TYPE(Field), ScalarElts);
> -    } else {
> -      // Unions pass the largest element.
> -      unsigned MaxSize = 0;
> -      tree MaxElt = 0;
> -      for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) {
> -        if (TREE_CODE(Field) == FIELD_DECL) {
> -          // Skip fields that are known not to be present.
> -          if (TREE_CODE(type) == QUAL_UNION_TYPE &&
> -              integer_zerop(DECL_QUALIFIER(Field)))
> -              continue;
> -
> -          tree SizeTree = TYPE_SIZE(TREE_TYPE(Field));
> -          unsigned Size = ((unsigned)TREE_INT_CST_LOW(SizeTree)+7)/8;
> -          if (Size > MaxSize) {
> -            MaxSize = Size;
> -            MaxElt = Field;
> -          }
> -
> -          // Skip remaining fields if this one is known to be present.
> -          if (TREE_CODE(type) == QUAL_UNION_TYPE &&
> -              integer_onep(DECL_QUALIFIER(Field)))
> -              break;
> -        }
> -      }
> -
> -      if (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.  If Size is set we pass only that many bytes.
> -  ///
> -  /// This is the default implementation which was copied from DefaultABI.
> -  void PassInIntegerRegisters(tree type, std::vector<const Type*> &ScalarElts,
> -                              unsigned origSize, bool DontCheckAlignment) {
> -    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:
> -    // don't bitcast aggregate value to Int64 if its alignment is different
> -    // from Int64 alignment. ARM backend needs this.
> -    unsigned Align = TYPE_ALIGN(type)/8;
> -    unsigned Int64Align =
> -      getTargetData().getABITypeAlignment(Type::getInt64Ty(getGlobalContext()));
> -    bool UseInt64 = (getTargetData().isLegalInteger(64) &&
> -                     (DontCheckAlignment || Align >= Int64Align));
> -
> -    // FIXME: In cases where we can, we should use the original struct.
> -    // Consider cases like { int, int } and {int, short} for example!  This will
> -    // produce far better LLVM code!
> -    std::vector<const Type*> Elts;
> -
> -    unsigned ElementSize = UseInt64 ? 8:4;
> -    unsigned ArraySize = Size / ElementSize;
> -
> -    // Put as much of the aggregate as possible into an array.
> -    const Type *ATy = NULL;
> -    const Type *ArrayElementType = NULL;
> -    if (ArraySize) {
> -      Size = Size % ElementSize;
> -      ArrayElementType = (UseInt64 ?
> -                          Type::getInt64Ty(getGlobalContext()) :
> -                          Type::getInt32Ty(getGlobalContext()));
> -      ATy = ArrayType::get(ArrayElementType, ArraySize);
> -      Elts.push_back(ATy);
> -    }
> -
> -    // Pass any leftover bytes as a separate element following the array.
> -    unsigned LastEltRealSize = 0;
> -    const llvm::Type *LastEltTy = 0;
> -    if (Size > 4) {
> -      LastEltTy = Type::getInt64Ty(getGlobalContext());
> -    } else if (Size > 2) {
> -      LastEltTy = Type::getInt32Ty(getGlobalContext());
> -    } else if (Size > 1) {
> -      LastEltTy = Type::getInt16Ty(getGlobalContext());
> -    } else if (Size > 0) {
> -      LastEltTy = Type::getInt8Ty(getGlobalContext());
> -    }
> -    if (LastEltTy) {
> -      Elts.push_back(LastEltTy);
> -      if (Size != getTargetData().getTypeAllocSize(LastEltTy))
> -        LastEltRealSize = Size;
> -    }
> -
> -    const StructType *STy = StructType::get(getGlobalContext(), Elts, false);
> -
> -    unsigned i = 0;
> -    if (ArraySize) {
> -      C.EnterField(0, STy);
> -      for (unsigned j = 0; j < ArraySize; ++j) {
> -        C.EnterField(j, ATy);
> -        C.HandleScalarArgument(ArrayElementType, 0);
> -        ScalarElts.push_back(ArrayElementType);
> -        C.ExitField();
> -      }
> -      C.ExitField();
> -      ++i;
> -    }
> -    if (LastEltTy) {
> -      C.EnterField(i, STy);
> -      C.HandleScalarArgument(LastEltTy, 0, LastEltRealSize);
> -      ScalarElts.push_back(LastEltTy);
> -      C.ExitField();
> -    }
> -  }
> -
> -  /// PassInMixedRegisters - Given an aggregate value that should be passed in
> -  /// mixed integer, floating point, and vector registers, convert it to a
> -  /// structure containing the specified struct elements in.
> -  ///
> -  /// This is the default implementation which was copied from DefaultABI.
> -  void PassInMixedRegisters(const Type *Ty, std::vector<const Type*> &OrigElts,
> -                            std::vector<const Type*> &ScalarElts) {
> -    // We use VoidTy in OrigElts to mean "this is a word in the aggregate
> -    // that occupies storage but has no useful information, and is not passed
> -    // anywhere".  Happens on x86-64.
> -    std::vector<const Type*> Elts(OrigElts);
> -    const Type* wordType = getTargetData().getPointerSize() == 4
> -      ? Type::getInt32Ty(getGlobalContext()) : Type::getInt64Ty(getGlobalContext());
> -    for (unsigned i=0, e=Elts.size(); i!=e; ++i)
> -      if (OrigElts[i]->isVoidTy())
> -        Elts[i] = wordType;
> -
> -    const StructType *STy = StructType::get(getGlobalContext(), Elts, false);
> -
> -    unsigned Size = getTargetData().getTypeAllocSize(STy);
> -    const StructType *InSTy = dyn_cast<StructType>(Ty);
> -    unsigned InSize = 0;
> -    // If Ty and STy size does not match then last element is accessing
> -    // extra bits.
> -    unsigned LastEltSizeDiff = 0;
> -    if (InSTy) {
> -      InSize = getTargetData().getTypeAllocSize(InSTy);
> -      if (InSize < Size) {
> -        unsigned N = STy->getNumElements();
> -        const llvm::Type *LastEltTy = STy->getElementType(N-1);
> -        if (LastEltTy->isInteger())
> -          LastEltSizeDiff =
> -            getTargetData().getTypeAllocSize(LastEltTy) - (Size - InSize);
> -      }
> -    }
> -    for (unsigned i = 0, e = Elts.size(); i != e; ++i) {
> -      if (!OrigElts[i]->isVoidTy()) {
> -        C.EnterField(i, STy);
> -        unsigned RealSize = 0;
> -        if (LastEltSizeDiff && i == (e - 1))
> -          RealSize = LastEltSizeDiff;
> -        C.HandleScalarArgument(Elts[i], 0, RealSize);
> -        ScalarElts.push_back(Elts[i]);
> -        C.ExitField();
> -      }
> -    }
> -  }
> -};
> -
>  #endif /* LLVM_ABI_H */
>  /* LLVM LOCAL end (ENTIRE FILE!)  */
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>



-- 
Rafael Ávila de Espíndola




More information about the llvm-commits mailing list