aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@mips.com>2012-05-11 21:56:58 +0000
committerAkira Hatanaka <ahatanaka@mips.com>2012-05-11 21:56:58 +0000
commit91338cf4129cfdb85af7e9ef396ab09621da10ec (patch)
treeacd7e5f25e2840ef1415bc8a9ce0ba06295ed4e5 /lib/CodeGen
parentdf8755884e039d3f313ee0fea42b955257b5e240 (diff)
Coerce byval aggregate arguments to integers whose size matches the integer
register size of the target architecture. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156650 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/TargetInfo.cpp79
1 files changed, 44 insertions, 35 deletions
diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp
index 9016d8c93a..3ee6c785d6 100644
--- a/lib/CodeGen/TargetInfo.cpp
+++ b/lib/CodeGen/TargetInfo.cpp
@@ -3156,7 +3156,8 @@ namespace {
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 @@ public:
};
}
+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 @@ llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty) const {
// 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 @@ llvm::Type* MipsABIInfo::HandleAggregates(QualType Ty) const {
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::HandleAggregates(QualType Ty) const {
}
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);
+
+ if ((Align - 1) & Offset)
+ return llvm::IntegerType::get(getVMContext(), MinABIStackAlignInBytes * 8);
- assert(Align <= 16 && "Alignment larger than 16 not handled.");
- return (Align == 16 && Offset & 0xf) ?
- llvm::IntegerType::get(getVMContext(), 64) : 0;
+ 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 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const {
// 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 @@ void MipsABIInfo::computeInfo(CGFunctionInfo &FI) const {
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)