[cfe-commits] r156650 - in /cfe/trunk: lib/CodeGen/TargetInfo.cpp test/CodeGen/mips-byval-arg.c test/CodeGen/mips64-class-return.cpp
Akira Hatanaka
ahatanaka at mips.com
Fri May 11 14:56:58 PDT 2012
Author: ahatanak
Date: Fri May 11 16:56:58 2012
New Revision: 156650
URL: http://llvm.org/viewvc/llvm-project?rev=156650&view=rev
Log:
Coerce byval aggregate arguments to integers whose size matches the integer
register size of the target architecture.
Added:
cfe/trunk/test/CodeGen/mips-byval-arg.c
Modified:
cfe/trunk/lib/CodeGen/TargetInfo.cpp
cfe/trunk/test/CodeGen/mips64-class-return.cpp
Modified: cfe/trunk/lib/CodeGen/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp?rev=156650&r1=156649&r2=156650&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/TargetInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/TargetInfo.cpp Fri May 11 16:56:58 2012
@@ -3156,7 +3156,8 @@
class MipsABIInfo : public ABIInfo {
bool IsO32;
unsigned MinABIStackAlignInBytes;
- llvm::Type* HandleAggregates(QualType Ty) const;
+ llvm::Type* CoerceToIntArgs(uint64_t TySize) const;
+ llvm::Type* HandleAggregates(QualType Ty, uint64_t TySize) const;
llvm::Type* returnAggregateInRegs(QualType RetTy, uint64_t Size) const;
llvm::Type* getPaddingType(uint64_t Align, uint64_t Offset) const;
public:
@@ -3190,11 +3191,29 @@
};
}
+llvm::Type* MipsABIInfo::CoerceToIntArgs(uint64_t TySize) const {
+ SmallVector<llvm::Type*, 8> ArgList;
+ llvm::IntegerType *IntTy = llvm::IntegerType::get(getVMContext(),
+ MinABIStackAlignInBytes * 8);
+
+ // Add (TySize / MinABIStackAlignInBytes) args of IntTy.
+ for (unsigned N = TySize / (MinABIStackAlignInBytes * 8); N; --N)
+ ArgList.push_back(IntTy);
+
+ // If necessary, add one more integer type to ArgList.
+ unsigned R = TySize % (MinABIStackAlignInBytes * 8);
+
+ if (R)
+ ArgList.push_back(llvm::IntegerType::get(getVMContext(), R));
+
+ return llvm::StructType::get(getVMContext(), ArgList);
+}
+
// In N32/64, an aligned double precision floating point field is passed in
// a register.
-llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty) const {
+llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty, uint64_t TySize) const {
if (IsO32)
- return 0;
+ return CoerceToIntArgs(TySize);
if (Ty->isComplexType())
return CGT.ConvertType(Ty);
@@ -3203,12 +3222,11 @@
// Unions are passed in integer registers.
if (!RT || !RT->isStructureOrClassType())
- return 0;
+ return CoerceToIntArgs(TySize);
const RecordDecl *RD = RT->getDecl();
const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
- uint64_t StructSize = getContext().getTypeSize(Ty);
- assert(!(StructSize % 8) && "Size of structure must be multiple of 8.");
+ assert(!(TySize % 8) && "Size of structure must be multiple of 8.");
uint64_t LastOffset = 0;
unsigned idx = 0;
@@ -3238,17 +3256,13 @@
LastOffset = Offset + 64;
}
- // This struct/class doesn't have an aligned double field.
- if (!LastOffset)
- return 0;
-
- // Add ((StructSize - LastOffset) / 64) args of type i64.
- for (unsigned N = (StructSize - LastOffset) / 64; N; --N)
+ // Add ((TySize - LastOffset) / 64) args of type i64.
+ for (unsigned N = (TySize - LastOffset) / 64; N; --N)
ArgList.push_back(I64);
// If the size of the remainder is not zero, add one more integer type to
// ArgList.
- unsigned R = (StructSize - LastOffset) % 64;
+ unsigned R = (TySize - LastOffset) % 64;
if (R)
ArgList.push_back(llvm::IntegerType::get(getVMContext(), R));
@@ -3256,23 +3270,23 @@
}
llvm::Type *MipsABIInfo::getPaddingType(uint64_t Align, uint64_t Offset) const {
- // Padding is inserted only for N32/64.
- if (IsO32)
- return 0;
+ assert((Offset % MinABIStackAlignInBytes) == 0);
- assert(Align <= 16 && "Alignment larger than 16 not handled.");
- return (Align == 16 && Offset & 0xf) ?
- llvm::IntegerType::get(getVMContext(), 64) : 0;
+ if ((Align - 1) & Offset)
+ return llvm::IntegerType::get(getVMContext(), MinABIStackAlignInBytes * 8);
+
+ return 0;
}
ABIArgInfo
MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
uint64_t OrigOffset = Offset;
- uint64_t TySize =
- llvm::RoundUpToAlignment(getContext().getTypeSize(Ty), 64) / 8;
+ uint64_t TySize = getContext().getTypeSize(Ty);
uint64_t Align = getContext().getTypeAlign(Ty) / 8;
- Offset = llvm::RoundUpToAlignment(Offset, std::max(Align, (uint64_t)8));
- Offset += TySize;
+
+ Align = std::max(Align, (uint64_t)MinABIStackAlignInBytes);
+ Offset = llvm::RoundUpToAlignment(Offset, Align);
+ Offset += llvm::RoundUpToAlignment(TySize, Align * 8) / 8;
if (isAggregateTypeForABI(Ty)) {
// Ignore empty aggregates.
@@ -3282,20 +3296,15 @@
// Records with non trivial destructors/constructors should not be passed
// by value.
if (isRecordWithNonTrivialDestructorOrCopyConstructor(Ty)) {
- Offset = OrigOffset + 8;
+ Offset = OrigOffset + MinABIStackAlignInBytes;
return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
}
- // If we have reached here, aggregates are passed either indirectly via a
- // byval pointer or directly by coercing to another structure type. In the
- // latter case, padding is inserted if the offset of the aggregate is
- // unaligned.
- llvm::Type *ResType = HandleAggregates(Ty);
-
- if (!ResType)
- return ABIArgInfo::getIndirect(0);
-
- return ABIArgInfo::getDirect(ResType, 0, getPaddingType(Align, OrigOffset));
+ // If we have reached here, aggregates are passed directly by coercing to
+ // another structure type. Padding is inserted if the offset of the
+ // aggregate is unaligned.
+ return ABIArgInfo::getDirect(HandleAggregates(Ty, TySize), 0,
+ getPaddingType(Align, OrigOffset));
}
// Treat an enum type as its underlying type.
@@ -3385,7 +3394,7 @@
RetInfo = classifyReturnType(FI.getReturnType());
// Check if a pointer to an aggregate is passed as a hidden argument.
- uint64_t Offset = RetInfo.isIndirect() ? 8 : 0;
+ uint64_t Offset = RetInfo.isIndirect() ? MinABIStackAlignInBytes : 0;
for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
it != ie; ++it)
Added: cfe/trunk/test/CodeGen/mips-byval-arg.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/mips-byval-arg.c?rev=156650&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/mips-byval-arg.c (added)
+++ cfe/trunk/test/CodeGen/mips-byval-arg.c Fri May 11 16:56:58 2012
@@ -0,0 +1,15 @@
+// RUN: %clang -target mipsel-unknown-linux -ccc-clang-archs mipsel -O3 -S -o - -emit-llvm %s | FileCheck %s -check-prefix=O32
+// RUN: %clang -target mips64el-unknown-linux -ccc-clang-archs mips64el -O3 -S -mabi=n64 -o - -emit-llvm %s | FileCheck %s -check-prefix=N64
+
+typedef struct {
+ float f[3];
+} S0;
+
+extern void foo2(S0);
+
+// O32: define void @foo1(i32 %a0.coerce0, i32 %a0.coerce1, i32 %a0.coerce2)
+// N64: define void @foo1(i64 %a0.coerce0, i32 %a0.coerce1)
+
+void foo1(S0 a0) {
+ foo2(a0);
+}
Modified: cfe/trunk/test/CodeGen/mips64-class-return.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/mips64-class-return.cpp?rev=156650&r1=156649&r2=156650&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/mips64-class-return.cpp (original)
+++ cfe/trunk/test/CodeGen/mips64-class-return.cpp Fri May 11 16:56:58 2012
@@ -39,7 +39,7 @@
gd2 = a0;
}
-// CHECK: define void @_Z4foo42D0(%class.D0* nocapture byval %a0)
+// CHECK: define void @_Z4foo42D0(i64 %a0.coerce0, i64 %a0.coerce1)
void foo4(D0 a0) {
gd0 = a0;
}
More information about the cfe-commits
mailing list