112f23521SJohn McCall //===--- SwiftCallingConv.cpp - Lowering for the Swift calling convention -===//
212f23521SJohn McCall //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
612f23521SJohn McCall //
712f23521SJohn McCall //===----------------------------------------------------------------------===//
812f23521SJohn McCall //
912f23521SJohn McCall // Implementation of the abstract lowering for the Swift calling convention.
1012f23521SJohn McCall //
1112f23521SJohn McCall //===----------------------------------------------------------------------===//
1212f23521SJohn McCall 
1312f23521SJohn McCall #include "clang/CodeGen/SwiftCallingConv.h"
14*37502e04SSergei Barannikov #include "ABIInfo.h"
1512f23521SJohn McCall #include "CodeGenModule.h"
1612f23521SJohn McCall #include "TargetInfo.h"
17*37502e04SSergei Barannikov #include "clang/Basic/TargetInfo.h"
1812f23521SJohn McCall 
1912f23521SJohn McCall using namespace clang;
2012f23521SJohn McCall using namespace CodeGen;
2112f23521SJohn McCall using namespace swiftcall;
2212f23521SJohn McCall 
getSwiftABIInfo(CodeGenModule & CGM)2312f23521SJohn McCall static const SwiftABIInfo &getSwiftABIInfo(CodeGenModule &CGM) {
2412f23521SJohn McCall   return cast<SwiftABIInfo>(CGM.getTargetCodeGenInfo().getABIInfo());
2512f23521SJohn McCall }
2612f23521SJohn McCall 
isPowerOf2(unsigned n)2712f23521SJohn McCall static bool isPowerOf2(unsigned n) {
2812f23521SJohn McCall   return n == (n & -n);
2912f23521SJohn McCall }
3012f23521SJohn McCall 
3112f23521SJohn McCall /// Given two types with the same size, try to find a common type.
getCommonType(llvm::Type * first,llvm::Type * second)3212f23521SJohn McCall static llvm::Type *getCommonType(llvm::Type *first, llvm::Type *second) {
3312f23521SJohn McCall   assert(first != second);
3412f23521SJohn McCall 
3512f23521SJohn McCall   // Allow pointers to merge with integers, but prefer the integer type.
3612f23521SJohn McCall   if (first->isIntegerTy()) {
3712f23521SJohn McCall     if (second->isPointerTy()) return first;
3812f23521SJohn McCall   } else if (first->isPointerTy()) {
3912f23521SJohn McCall     if (second->isIntegerTy()) return second;
4012f23521SJohn McCall     if (second->isPointerTy()) return first;
4112f23521SJohn McCall 
4212f23521SJohn McCall   // Allow two vectors to be merged (given that they have the same size).
4312f23521SJohn McCall   // This assumes that we never have two different vector register sets.
4412f23521SJohn McCall   } else if (auto firstVecTy = dyn_cast<llvm::VectorType>(first)) {
4512f23521SJohn McCall     if (auto secondVecTy = dyn_cast<llvm::VectorType>(second)) {
4612f23521SJohn McCall       if (auto commonTy = getCommonType(firstVecTy->getElementType(),
4712f23521SJohn McCall                                         secondVecTy->getElementType())) {
4812f23521SJohn McCall         return (commonTy == firstVecTy->getElementType() ? first : second);
4912f23521SJohn McCall       }
5012f23521SJohn McCall     }
5112f23521SJohn McCall   }
5212f23521SJohn McCall 
5312f23521SJohn McCall   return nullptr;
5412f23521SJohn McCall }
5512f23521SJohn McCall 
getTypeStoreSize(CodeGenModule & CGM,llvm::Type * type)5612f23521SJohn McCall static CharUnits getTypeStoreSize(CodeGenModule &CGM, llvm::Type *type) {
5712f23521SJohn McCall   return CharUnits::fromQuantity(CGM.getDataLayout().getTypeStoreSize(type));
5812f23521SJohn McCall }
5912f23521SJohn McCall 
getTypeAllocSize(CodeGenModule & CGM,llvm::Type * type)607b871611SArnold Schwaighofer static CharUnits getTypeAllocSize(CodeGenModule &CGM, llvm::Type *type) {
617b871611SArnold Schwaighofer   return CharUnits::fromQuantity(CGM.getDataLayout().getTypeAllocSize(type));
627b871611SArnold Schwaighofer }
637b871611SArnold Schwaighofer 
addTypedData(QualType type,CharUnits begin)6412f23521SJohn McCall void SwiftAggLowering::addTypedData(QualType type, CharUnits begin) {
6512f23521SJohn McCall   // Deal with various aggregate types as special cases:
6612f23521SJohn McCall 
6712f23521SJohn McCall   // Record types.
6812f23521SJohn McCall   if (auto recType = type->getAs<RecordType>()) {
6912f23521SJohn McCall     addTypedData(recType->getDecl(), begin);
7012f23521SJohn McCall 
7112f23521SJohn McCall   // Array types.
7212f23521SJohn McCall   } else if (type->isArrayType()) {
7312f23521SJohn McCall     // Incomplete array types (flexible array members?) don't provide
7412f23521SJohn McCall     // data to lay out, and the other cases shouldn't be possible.
7512f23521SJohn McCall     auto arrayType = CGM.getContext().getAsConstantArrayType(type);
7612f23521SJohn McCall     if (!arrayType) return;
7712f23521SJohn McCall 
7812f23521SJohn McCall     QualType eltType = arrayType->getElementType();
7912f23521SJohn McCall     auto eltSize = CGM.getContext().getTypeSizeInChars(eltType);
8012f23521SJohn McCall     for (uint64_t i = 0, e = arrayType->getSize().getZExtValue(); i != e; ++i) {
8112f23521SJohn McCall       addTypedData(eltType, begin + i * eltSize);
8212f23521SJohn McCall     }
8312f23521SJohn McCall 
8412f23521SJohn McCall   // Complex types.
8512f23521SJohn McCall   } else if (auto complexType = type->getAs<ComplexType>()) {
8612f23521SJohn McCall     auto eltType = complexType->getElementType();
8712f23521SJohn McCall     auto eltSize = CGM.getContext().getTypeSizeInChars(eltType);
8812f23521SJohn McCall     auto eltLLVMType = CGM.getTypes().ConvertType(eltType);
8912f23521SJohn McCall     addTypedData(eltLLVMType, begin, begin + eltSize);
9012f23521SJohn McCall     addTypedData(eltLLVMType, begin + eltSize, begin + 2 * eltSize);
9112f23521SJohn McCall 
9212f23521SJohn McCall   // Member pointer types.
9312f23521SJohn McCall   } else if (type->getAs<MemberPointerType>()) {
9412f23521SJohn McCall     // Just add it all as opaque.
9512f23521SJohn McCall     addOpaqueData(begin, begin + CGM.getContext().getTypeSizeInChars(type));
9612f23521SJohn McCall 
9741634497SArnold Schwaighofer     // Atomic types.
9841634497SArnold Schwaighofer   } else if (const auto *atomicType = type->getAs<AtomicType>()) {
9941634497SArnold Schwaighofer     auto valueType = atomicType->getValueType();
10041634497SArnold Schwaighofer     auto atomicSize = CGM.getContext().getTypeSizeInChars(atomicType);
10141634497SArnold Schwaighofer     auto valueSize = CGM.getContext().getTypeSizeInChars(valueType);
10241634497SArnold Schwaighofer 
10341634497SArnold Schwaighofer     addTypedData(atomicType->getValueType(), begin);
10441634497SArnold Schwaighofer 
10541634497SArnold Schwaighofer     // Add atomic padding.
10641634497SArnold Schwaighofer     auto atomicPadding = atomicSize - valueSize;
10741634497SArnold Schwaighofer     if (atomicPadding > CharUnits::Zero())
10841634497SArnold Schwaighofer       addOpaqueData(begin + valueSize, begin + atomicSize);
10941634497SArnold Schwaighofer 
11012f23521SJohn McCall     // Everything else is scalar and should not convert as an LLVM aggregate.
11112f23521SJohn McCall   } else {
11212f23521SJohn McCall     // We intentionally convert as !ForMem because we want to preserve
11312f23521SJohn McCall     // that a type was an i1.
11441634497SArnold Schwaighofer     auto *llvmType = CGM.getTypes().ConvertType(type);
11512f23521SJohn McCall     addTypedData(llvmType, begin);
11612f23521SJohn McCall   }
11712f23521SJohn McCall }
11812f23521SJohn McCall 
addTypedData(const RecordDecl * record,CharUnits begin)11912f23521SJohn McCall void SwiftAggLowering::addTypedData(const RecordDecl *record, CharUnits begin) {
12012f23521SJohn McCall   addTypedData(record, begin, CGM.getContext().getASTRecordLayout(record));
12112f23521SJohn McCall }
12212f23521SJohn McCall 
addTypedData(const RecordDecl * record,CharUnits begin,const ASTRecordLayout & layout)12312f23521SJohn McCall void SwiftAggLowering::addTypedData(const RecordDecl *record, CharUnits begin,
12412f23521SJohn McCall                                     const ASTRecordLayout &layout) {
12512f23521SJohn McCall   // Unions are a special case.
12612f23521SJohn McCall   if (record->isUnion()) {
12712f23521SJohn McCall     for (auto field : record->fields()) {
12812f23521SJohn McCall       if (field->isBitField()) {
12912f23521SJohn McCall         addBitFieldData(field, begin, 0);
13012f23521SJohn McCall       } else {
13112f23521SJohn McCall         addTypedData(field->getType(), begin);
13212f23521SJohn McCall       }
13312f23521SJohn McCall     }
13412f23521SJohn McCall     return;
13512f23521SJohn McCall   }
13612f23521SJohn McCall 
13712f23521SJohn McCall   // Note that correctness does not rely on us adding things in
13812f23521SJohn McCall   // their actual order of layout; it's just somewhat more efficient
13912f23521SJohn McCall   // for the builder.
14012f23521SJohn McCall 
14112f23521SJohn McCall   // With that in mind, add "early" C++ data.
14212f23521SJohn McCall   auto cxxRecord = dyn_cast<CXXRecordDecl>(record);
14312f23521SJohn McCall   if (cxxRecord) {
14412f23521SJohn McCall     //   - a v-table pointer, if the class adds its own
14512f23521SJohn McCall     if (layout.hasOwnVFPtr()) {
14612f23521SJohn McCall       addTypedData(CGM.Int8PtrTy, begin);
14712f23521SJohn McCall     }
14812f23521SJohn McCall 
14912f23521SJohn McCall     //   - non-virtual bases
15012f23521SJohn McCall     for (auto &baseSpecifier : cxxRecord->bases()) {
15112f23521SJohn McCall       if (baseSpecifier.isVirtual()) continue;
15212f23521SJohn McCall 
15312f23521SJohn McCall       auto baseRecord = baseSpecifier.getType()->getAsCXXRecordDecl();
15412f23521SJohn McCall       addTypedData(baseRecord, begin + layout.getBaseClassOffset(baseRecord));
15512f23521SJohn McCall     }
15612f23521SJohn McCall 
15712f23521SJohn McCall     //   - a vbptr if the class adds its own
15812f23521SJohn McCall     if (layout.hasOwnVBPtr()) {
15912f23521SJohn McCall       addTypedData(CGM.Int8PtrTy, begin + layout.getVBPtrOffset());
16012f23521SJohn McCall     }
16112f23521SJohn McCall   }
16212f23521SJohn McCall 
16312f23521SJohn McCall   // Add fields.
16412f23521SJohn McCall   for (auto field : record->fields()) {
16512f23521SJohn McCall     auto fieldOffsetInBits = layout.getFieldOffset(field->getFieldIndex());
16612f23521SJohn McCall     if (field->isBitField()) {
16712f23521SJohn McCall       addBitFieldData(field, begin, fieldOffsetInBits);
16812f23521SJohn McCall     } else {
16912f23521SJohn McCall       addTypedData(field->getType(),
17012f23521SJohn McCall               begin + CGM.getContext().toCharUnitsFromBits(fieldOffsetInBits));
17112f23521SJohn McCall     }
17212f23521SJohn McCall   }
17312f23521SJohn McCall 
17412f23521SJohn McCall   // Add "late" C++ data:
17512f23521SJohn McCall   if (cxxRecord) {
17612f23521SJohn McCall     //   - virtual bases
17712f23521SJohn McCall     for (auto &vbaseSpecifier : cxxRecord->vbases()) {
17812f23521SJohn McCall       auto baseRecord = vbaseSpecifier.getType()->getAsCXXRecordDecl();
17912f23521SJohn McCall       addTypedData(baseRecord, begin + layout.getVBaseClassOffset(baseRecord));
18012f23521SJohn McCall     }
18112f23521SJohn McCall   }
18212f23521SJohn McCall }
18312f23521SJohn McCall 
addBitFieldData(const FieldDecl * bitfield,CharUnits recordBegin,uint64_t bitfieldBitBegin)18412f23521SJohn McCall void SwiftAggLowering::addBitFieldData(const FieldDecl *bitfield,
18512f23521SJohn McCall                                        CharUnits recordBegin,
18612f23521SJohn McCall                                        uint64_t bitfieldBitBegin) {
18712f23521SJohn McCall   assert(bitfield->isBitField());
18812f23521SJohn McCall   auto &ctx = CGM.getContext();
18912f23521SJohn McCall   auto width = bitfield->getBitWidthValue(ctx);
19012f23521SJohn McCall 
19112f23521SJohn McCall   // We can ignore zero-width bit-fields.
19212f23521SJohn McCall   if (width == 0) return;
19312f23521SJohn McCall 
19412f23521SJohn McCall   // toCharUnitsFromBits rounds down.
19512f23521SJohn McCall   CharUnits bitfieldByteBegin = ctx.toCharUnitsFromBits(bitfieldBitBegin);
19612f23521SJohn McCall 
19712f23521SJohn McCall   // Find the offset of the last byte that is partially occupied by the
19812f23521SJohn McCall   // bit-field; since we otherwise expect exclusive ends, the end is the
19912f23521SJohn McCall   // next byte.
20012f23521SJohn McCall   uint64_t bitfieldBitLast = bitfieldBitBegin + width - 1;
20112f23521SJohn McCall   CharUnits bitfieldByteEnd =
20212f23521SJohn McCall     ctx.toCharUnitsFromBits(bitfieldBitLast) + CharUnits::One();
20312f23521SJohn McCall   addOpaqueData(recordBegin + bitfieldByteBegin,
20412f23521SJohn McCall                 recordBegin + bitfieldByteEnd);
20512f23521SJohn McCall }
20612f23521SJohn McCall 
addTypedData(llvm::Type * type,CharUnits begin)20712f23521SJohn McCall void SwiftAggLowering::addTypedData(llvm::Type *type, CharUnits begin) {
20812f23521SJohn McCall   assert(type && "didn't provide type for typed data");
20912f23521SJohn McCall   addTypedData(type, begin, begin + getTypeStoreSize(CGM, type));
21012f23521SJohn McCall }
21112f23521SJohn McCall 
addTypedData(llvm::Type * type,CharUnits begin,CharUnits end)21212f23521SJohn McCall void SwiftAggLowering::addTypedData(llvm::Type *type,
21312f23521SJohn McCall                                     CharUnits begin, CharUnits end) {
21412f23521SJohn McCall   assert(type && "didn't provide type for typed data");
21512f23521SJohn McCall   assert(getTypeStoreSize(CGM, type) == end - begin);
21612f23521SJohn McCall 
21712f23521SJohn McCall   // Legalize vector types.
21812f23521SJohn McCall   if (auto vecTy = dyn_cast<llvm::VectorType>(type)) {
21912f23521SJohn McCall     SmallVector<llvm::Type*, 4> componentTys;
22012f23521SJohn McCall     legalizeVectorType(CGM, end - begin, vecTy, componentTys);
22112f23521SJohn McCall     assert(componentTys.size() >= 1);
22212f23521SJohn McCall 
22312f23521SJohn McCall     // Walk the initial components.
22412f23521SJohn McCall     for (size_t i = 0, e = componentTys.size(); i != e - 1; ++i) {
22512f23521SJohn McCall       llvm::Type *componentTy = componentTys[i];
22612f23521SJohn McCall       auto componentSize = getTypeStoreSize(CGM, componentTy);
22712f23521SJohn McCall       assert(componentSize < end - begin);
22812f23521SJohn McCall       addLegalTypedData(componentTy, begin, begin + componentSize);
22912f23521SJohn McCall       begin += componentSize;
23012f23521SJohn McCall     }
23112f23521SJohn McCall 
23212f23521SJohn McCall     return addLegalTypedData(componentTys.back(), begin, end);
23312f23521SJohn McCall   }
23412f23521SJohn McCall 
23512f23521SJohn McCall   // Legalize integer types.
23612f23521SJohn McCall   if (auto intTy = dyn_cast<llvm::IntegerType>(type)) {
23712f23521SJohn McCall     if (!isLegalIntegerType(CGM, intTy))
23812f23521SJohn McCall       return addOpaqueData(begin, end);
23912f23521SJohn McCall   }
24012f23521SJohn McCall 
24112f23521SJohn McCall   // All other types should be legal.
24212f23521SJohn McCall   return addLegalTypedData(type, begin, end);
24312f23521SJohn McCall }
24412f23521SJohn McCall 
addLegalTypedData(llvm::Type * type,CharUnits begin,CharUnits end)24512f23521SJohn McCall void SwiftAggLowering::addLegalTypedData(llvm::Type *type,
24612f23521SJohn McCall                                          CharUnits begin, CharUnits end) {
24712f23521SJohn McCall   // Require the type to be naturally aligned.
24812f23521SJohn McCall   if (!begin.isZero() && !begin.isMultipleOf(getNaturalAlignment(CGM, type))) {
24912f23521SJohn McCall 
25012f23521SJohn McCall     // Try splitting vector types.
25112f23521SJohn McCall     if (auto vecTy = dyn_cast<llvm::VectorType>(type)) {
25212f23521SJohn McCall       auto split = splitLegalVectorType(CGM, end - begin, vecTy);
25312f23521SJohn McCall       auto eltTy = split.first;
25412f23521SJohn McCall       auto numElts = split.second;
25512f23521SJohn McCall 
25612f23521SJohn McCall       auto eltSize = (end - begin) / numElts;
25712f23521SJohn McCall       assert(eltSize == getTypeStoreSize(CGM, eltTy));
25812f23521SJohn McCall       for (size_t i = 0, e = numElts; i != e; ++i) {
2598cde42c4SJohn McCall         addLegalTypedData(eltTy, begin, begin + eltSize);
26012f23521SJohn McCall         begin += eltSize;
26112f23521SJohn McCall       }
26212f23521SJohn McCall       assert(begin == end);
26312f23521SJohn McCall       return;
26412f23521SJohn McCall     }
26512f23521SJohn McCall 
26612f23521SJohn McCall     return addOpaqueData(begin, end);
26712f23521SJohn McCall   }
26812f23521SJohn McCall 
26912f23521SJohn McCall   addEntry(type, begin, end);
27012f23521SJohn McCall }
27112f23521SJohn McCall 
addEntry(llvm::Type * type,CharUnits begin,CharUnits end)27212f23521SJohn McCall void SwiftAggLowering::addEntry(llvm::Type *type,
27312f23521SJohn McCall                                 CharUnits begin, CharUnits end) {
274e6352150SJames Y Knight   assert((!type ||
275e6352150SJames Y Knight           (!isa<llvm::StructType>(type) && !isa<llvm::ArrayType>(type))) &&
27612f23521SJohn McCall          "cannot add aggregate-typed data");
27712f23521SJohn McCall   assert(!type || begin.isMultipleOf(getNaturalAlignment(CGM, type)));
27812f23521SJohn McCall 
27912f23521SJohn McCall   // Fast path: we can just add entries to the end.
28012f23521SJohn McCall   if (Entries.empty() || Entries.back().End <= begin) {
28112f23521SJohn McCall     Entries.push_back({begin, end, type});
28212f23521SJohn McCall     return;
28312f23521SJohn McCall   }
28412f23521SJohn McCall 
28512f23521SJohn McCall   // Find the first existing entry that ends after the start of the new data.
28612f23521SJohn McCall   // TODO: do a binary search if Entries is big enough for it to matter.
28712f23521SJohn McCall   size_t index = Entries.size() - 1;
28812f23521SJohn McCall   while (index != 0) {
28912f23521SJohn McCall     if (Entries[index - 1].End <= begin) break;
29012f23521SJohn McCall     --index;
29112f23521SJohn McCall   }
29212f23521SJohn McCall 
29312f23521SJohn McCall   // The entry ends after the start of the new data.
29412f23521SJohn McCall   // If the entry starts after the end of the new data, there's no conflict.
29512f23521SJohn McCall   if (Entries[index].Begin >= end) {
29612f23521SJohn McCall     // This insertion is potentially O(n), but the way we generally build
29712f23521SJohn McCall     // these layouts makes that unlikely to matter: we'd need a union of
29812f23521SJohn McCall     // several very large types.
29912f23521SJohn McCall     Entries.insert(Entries.begin() + index, {begin, end, type});
30012f23521SJohn McCall     return;
30112f23521SJohn McCall   }
30212f23521SJohn McCall 
30312f23521SJohn McCall   // Otherwise, the ranges overlap.  The new range might also overlap
30412f23521SJohn McCall   // with later ranges.
30512f23521SJohn McCall restartAfterSplit:
30612f23521SJohn McCall 
30712f23521SJohn McCall   // Simplest case: an exact overlap.
30812f23521SJohn McCall   if (Entries[index].Begin == begin && Entries[index].End == end) {
30912f23521SJohn McCall     // If the types match exactly, great.
31012f23521SJohn McCall     if (Entries[index].Type == type) return;
31112f23521SJohn McCall 
31212f23521SJohn McCall     // If either type is opaque, make the entry opaque and return.
31312f23521SJohn McCall     if (Entries[index].Type == nullptr) {
31412f23521SJohn McCall       return;
31512f23521SJohn McCall     } else if (type == nullptr) {
31612f23521SJohn McCall       Entries[index].Type = nullptr;
31712f23521SJohn McCall       return;
31812f23521SJohn McCall     }
31912f23521SJohn McCall 
32012f23521SJohn McCall     // If they disagree in an ABI-agnostic way, just resolve the conflict
32112f23521SJohn McCall     // arbitrarily.
32212f23521SJohn McCall     if (auto entryType = getCommonType(Entries[index].Type, type)) {
32312f23521SJohn McCall       Entries[index].Type = entryType;
32412f23521SJohn McCall       return;
32512f23521SJohn McCall     }
32612f23521SJohn McCall 
32712f23521SJohn McCall     // Otherwise, make the entry opaque.
32812f23521SJohn McCall     Entries[index].Type = nullptr;
32912f23521SJohn McCall     return;
33012f23521SJohn McCall   }
33112f23521SJohn McCall 
33212f23521SJohn McCall   // Okay, we have an overlapping conflict of some sort.
33312f23521SJohn McCall 
33412f23521SJohn McCall   // If we have a vector type, split it.
33512f23521SJohn McCall   if (auto vecTy = dyn_cast_or_null<llvm::VectorType>(type)) {
33612f23521SJohn McCall     auto eltTy = vecTy->getElementType();
33719e883fcSChristopher Tetreault     CharUnits eltSize =
33819e883fcSChristopher Tetreault         (end - begin) / cast<llvm::FixedVectorType>(vecTy)->getNumElements();
33912f23521SJohn McCall     assert(eltSize == getTypeStoreSize(CGM, eltTy));
34019e883fcSChristopher Tetreault     for (unsigned i = 0,
34119e883fcSChristopher Tetreault                   e = cast<llvm::FixedVectorType>(vecTy)->getNumElements();
34219e883fcSChristopher Tetreault          i != e; ++i) {
34312f23521SJohn McCall       addEntry(eltTy, begin, begin + eltSize);
34412f23521SJohn McCall       begin += eltSize;
34512f23521SJohn McCall     }
34612f23521SJohn McCall     assert(begin == end);
34712f23521SJohn McCall     return;
34812f23521SJohn McCall   }
34912f23521SJohn McCall 
35012f23521SJohn McCall   // If the entry is a vector type, split it and try again.
35112f23521SJohn McCall   if (Entries[index].Type && Entries[index].Type->isVectorTy()) {
35212f23521SJohn McCall     splitVectorEntry(index);
35312f23521SJohn McCall     goto restartAfterSplit;
35412f23521SJohn McCall   }
35512f23521SJohn McCall 
35612f23521SJohn McCall   // Okay, we have no choice but to make the existing entry opaque.
35712f23521SJohn McCall 
35812f23521SJohn McCall   Entries[index].Type = nullptr;
35912f23521SJohn McCall 
36012f23521SJohn McCall   // Stretch the start of the entry to the beginning of the range.
36112f23521SJohn McCall   if (begin < Entries[index].Begin) {
36212f23521SJohn McCall     Entries[index].Begin = begin;
36312f23521SJohn McCall     assert(index == 0 || begin >= Entries[index - 1].End);
36412f23521SJohn McCall   }
36512f23521SJohn McCall 
36612f23521SJohn McCall   // Stretch the end of the entry to the end of the range; but if we run
36712f23521SJohn McCall   // into the start of the next entry, just leave the range there and repeat.
36812f23521SJohn McCall   while (end > Entries[index].End) {
36912f23521SJohn McCall     assert(Entries[index].Type == nullptr);
37012f23521SJohn McCall 
37112f23521SJohn McCall     // If the range doesn't overlap the next entry, we're done.
37212f23521SJohn McCall     if (index == Entries.size() - 1 || end <= Entries[index + 1].Begin) {
37312f23521SJohn McCall       Entries[index].End = end;
37412f23521SJohn McCall       break;
37512f23521SJohn McCall     }
37612f23521SJohn McCall 
37712f23521SJohn McCall     // Otherwise, stretch to the start of the next entry.
37812f23521SJohn McCall     Entries[index].End = Entries[index + 1].Begin;
37912f23521SJohn McCall 
38012f23521SJohn McCall     // Continue with the next entry.
38112f23521SJohn McCall     index++;
38212f23521SJohn McCall 
38312f23521SJohn McCall     // This entry needs to be made opaque if it is not already.
38412f23521SJohn McCall     if (Entries[index].Type == nullptr)
38512f23521SJohn McCall       continue;
38612f23521SJohn McCall 
38712f23521SJohn McCall     // Split vector entries unless we completely subsume them.
38812f23521SJohn McCall     if (Entries[index].Type->isVectorTy() &&
38912f23521SJohn McCall         end < Entries[index].End) {
39012f23521SJohn McCall       splitVectorEntry(index);
39112f23521SJohn McCall     }
39212f23521SJohn McCall 
39312f23521SJohn McCall     // Make the entry opaque.
39412f23521SJohn McCall     Entries[index].Type = nullptr;
39512f23521SJohn McCall   }
39612f23521SJohn McCall }
39712f23521SJohn McCall 
39812f23521SJohn McCall /// Replace the entry of vector type at offset 'index' with a sequence
39912f23521SJohn McCall /// of its component vectors.
splitVectorEntry(unsigned index)40012f23521SJohn McCall void SwiftAggLowering::splitVectorEntry(unsigned index) {
40112f23521SJohn McCall   auto vecTy = cast<llvm::VectorType>(Entries[index].Type);
40212f23521SJohn McCall   auto split = splitLegalVectorType(CGM, Entries[index].getWidth(), vecTy);
40312f23521SJohn McCall 
40412f23521SJohn McCall   auto eltTy = split.first;
40512f23521SJohn McCall   CharUnits eltSize = getTypeStoreSize(CGM, eltTy);
40612f23521SJohn McCall   auto numElts = split.second;
4073d01ad11SArnold Schwaighofer   Entries.insert(Entries.begin() + index + 1, numElts - 1, StorageEntry());
40812f23521SJohn McCall 
40912f23521SJohn McCall   CharUnits begin = Entries[index].Begin;
41012f23521SJohn McCall   for (unsigned i = 0; i != numElts; ++i) {
41112f23521SJohn McCall     Entries[index].Type = eltTy;
41212f23521SJohn McCall     Entries[index].Begin = begin;
41312f23521SJohn McCall     Entries[index].End = begin + eltSize;
41412f23521SJohn McCall     begin += eltSize;
41512f23521SJohn McCall   }
41612f23521SJohn McCall }
41712f23521SJohn McCall 
41812f23521SJohn McCall /// Given a power-of-two unit size, return the offset of the aligned unit
41912f23521SJohn McCall /// of that size which contains the given offset.
42012f23521SJohn McCall ///
42112f23521SJohn McCall /// In other words, round down to the nearest multiple of the unit size.
getOffsetAtStartOfUnit(CharUnits offset,CharUnits unitSize)42212f23521SJohn McCall static CharUnits getOffsetAtStartOfUnit(CharUnits offset, CharUnits unitSize) {
42312f23521SJohn McCall   assert(isPowerOf2(unitSize.getQuantity()));
42412f23521SJohn McCall   auto unitMask = ~(unitSize.getQuantity() - 1);
42512f23521SJohn McCall   return CharUnits::fromQuantity(offset.getQuantity() & unitMask);
42612f23521SJohn McCall }
42712f23521SJohn McCall 
areBytesInSameUnit(CharUnits first,CharUnits second,CharUnits chunkSize)42812f23521SJohn McCall static bool areBytesInSameUnit(CharUnits first, CharUnits second,
42912f23521SJohn McCall                                CharUnits chunkSize) {
43012f23521SJohn McCall   return getOffsetAtStartOfUnit(first, chunkSize)
43112f23521SJohn McCall       == getOffsetAtStartOfUnit(second, chunkSize);
43212f23521SJohn McCall }
43312f23521SJohn McCall 
isMergeableEntryType(llvm::Type * type)434d2bfe4b7SJohn McCall static bool isMergeableEntryType(llvm::Type *type) {
435d2bfe4b7SJohn McCall   // Opaquely-typed memory is always mergeable.
436d2bfe4b7SJohn McCall   if (type == nullptr) return true;
437d2bfe4b7SJohn McCall 
438d2bfe4b7SJohn McCall   // Pointers and integers are always mergeable.  In theory we should not
439d2bfe4b7SJohn McCall   // merge pointers, but (1) it doesn't currently matter in practice because
440d2bfe4b7SJohn McCall   // the chunk size is never greater than the size of a pointer and (2)
441d2bfe4b7SJohn McCall   // Swift IRGen uses integer types for a lot of things that are "really"
442d2bfe4b7SJohn McCall   // just storing pointers (like Optional<SomePointer>).  If we ever have a
443d2bfe4b7SJohn McCall   // target that would otherwise combine pointers, we should put some effort
444d2bfe4b7SJohn McCall   // into fixing those cases in Swift IRGen and then call out pointer types
445d2bfe4b7SJohn McCall   // here.
446d2bfe4b7SJohn McCall 
447d2bfe4b7SJohn McCall   // Floating-point and vector types should never be merged.
448d2bfe4b7SJohn McCall   // Most such types are too large and highly-aligned to ever trigger merging
449d2bfe4b7SJohn McCall   // in practice, but it's important for the rule to cover at least 'half'
450d2bfe4b7SJohn McCall   // and 'float', as well as things like small vectors of 'i1' or 'i8'.
451d2bfe4b7SJohn McCall   return (!type->isFloatingPointTy() && !type->isVectorTy());
452d2bfe4b7SJohn McCall }
453d2bfe4b7SJohn McCall 
shouldMergeEntries(const StorageEntry & first,const StorageEntry & second,CharUnits chunkSize)454d2bfe4b7SJohn McCall bool SwiftAggLowering::shouldMergeEntries(const StorageEntry &first,
455d2bfe4b7SJohn McCall                                           const StorageEntry &second,
456d2bfe4b7SJohn McCall                                           CharUnits chunkSize) {
457d2bfe4b7SJohn McCall   // Only merge entries that overlap the same chunk.  We test this first
458d2bfe4b7SJohn McCall   // despite being a bit more expensive because this is the condition that
459d2bfe4b7SJohn McCall   // tends to prevent merging.
460d2bfe4b7SJohn McCall   if (!areBytesInSameUnit(first.End - CharUnits::One(), second.Begin,
461d2bfe4b7SJohn McCall                           chunkSize))
462d2bfe4b7SJohn McCall     return false;
463d2bfe4b7SJohn McCall 
464d2bfe4b7SJohn McCall   return (isMergeableEntryType(first.Type) &&
465d2bfe4b7SJohn McCall           isMergeableEntryType(second.Type));
466d2bfe4b7SJohn McCall }
467d2bfe4b7SJohn McCall 
finish()46812f23521SJohn McCall void SwiftAggLowering::finish() {
46912f23521SJohn McCall   if (Entries.empty()) {
47012f23521SJohn McCall     Finished = true;
47112f23521SJohn McCall     return;
47212f23521SJohn McCall   }
47312f23521SJohn McCall 
47412f23521SJohn McCall   // We logically split the layout down into a series of chunks of this size,
47512f23521SJohn McCall   // which is generally the size of a pointer.
47612f23521SJohn McCall   const CharUnits chunkSize = getMaximumVoluntaryIntegerSize(CGM);
47712f23521SJohn McCall 
478d2bfe4b7SJohn McCall   // First pass: if two entries should be merged, make them both opaque
47912f23521SJohn McCall   // and stretch one to meet the next.
480d2bfe4b7SJohn McCall   // Also, remember if there are any opaque entries.
48112f23521SJohn McCall   bool hasOpaqueEntries = (Entries[0].Type == nullptr);
48212f23521SJohn McCall   for (size_t i = 1, e = Entries.size(); i != e; ++i) {
483d2bfe4b7SJohn McCall     if (shouldMergeEntries(Entries[i - 1], Entries[i], chunkSize)) {
48412f23521SJohn McCall       Entries[i - 1].Type = nullptr;
48512f23521SJohn McCall       Entries[i].Type = nullptr;
48612f23521SJohn McCall       Entries[i - 1].End = Entries[i].Begin;
48712f23521SJohn McCall       hasOpaqueEntries = true;
48812f23521SJohn McCall 
48912f23521SJohn McCall     } else if (Entries[i].Type == nullptr) {
49012f23521SJohn McCall       hasOpaqueEntries = true;
49112f23521SJohn McCall     }
49212f23521SJohn McCall   }
49312f23521SJohn McCall 
49412f23521SJohn McCall   // The rest of the algorithm leaves non-opaque entries alone, so if we
49512f23521SJohn McCall   // have no opaque entries, we're done.
49612f23521SJohn McCall   if (!hasOpaqueEntries) {
49712f23521SJohn McCall     Finished = true;
49812f23521SJohn McCall     return;
49912f23521SJohn McCall   }
50012f23521SJohn McCall 
50112f23521SJohn McCall   // Okay, move the entries to a temporary and rebuild Entries.
50212f23521SJohn McCall   auto orig = std::move(Entries);
50312f23521SJohn McCall   assert(Entries.empty());
50412f23521SJohn McCall 
50512f23521SJohn McCall   for (size_t i = 0, e = orig.size(); i != e; ++i) {
50612f23521SJohn McCall     // Just copy over non-opaque entries.
50712f23521SJohn McCall     if (orig[i].Type != nullptr) {
50812f23521SJohn McCall       Entries.push_back(orig[i]);
50912f23521SJohn McCall       continue;
51012f23521SJohn McCall     }
51112f23521SJohn McCall 
51212f23521SJohn McCall     // Scan forward to determine the full extent of the next opaque range.
51312f23521SJohn McCall     // We know from the first pass that only contiguous ranges will overlap
51412f23521SJohn McCall     // the same aligned chunk.
51512f23521SJohn McCall     auto begin = orig[i].Begin;
51612f23521SJohn McCall     auto end = orig[i].End;
51712f23521SJohn McCall     while (i + 1 != e &&
51812f23521SJohn McCall            orig[i + 1].Type == nullptr &&
51912f23521SJohn McCall            end == orig[i + 1].Begin) {
52012f23521SJohn McCall       end = orig[i + 1].End;
52112f23521SJohn McCall       i++;
52212f23521SJohn McCall     }
52312f23521SJohn McCall 
52412f23521SJohn McCall     // Add an entry per intersected chunk.
52512f23521SJohn McCall     do {
52612f23521SJohn McCall       // Find the smallest aligned storage unit in the maximal aligned
52712f23521SJohn McCall       // storage unit containing 'begin' that contains all the bytes in
52812f23521SJohn McCall       // the intersection between the range and this chunk.
52912f23521SJohn McCall       CharUnits localBegin = begin;
53012f23521SJohn McCall       CharUnits chunkBegin = getOffsetAtStartOfUnit(localBegin, chunkSize);
53112f23521SJohn McCall       CharUnits chunkEnd = chunkBegin + chunkSize;
53212f23521SJohn McCall       CharUnits localEnd = std::min(end, chunkEnd);
53312f23521SJohn McCall 
53412f23521SJohn McCall       // Just do a simple loop over ever-increasing unit sizes.
53512f23521SJohn McCall       CharUnits unitSize = CharUnits::One();
53612f23521SJohn McCall       CharUnits unitBegin, unitEnd;
53712f23521SJohn McCall       for (; ; unitSize *= 2) {
53812f23521SJohn McCall         assert(unitSize <= chunkSize);
53912f23521SJohn McCall         unitBegin = getOffsetAtStartOfUnit(localBegin, unitSize);
54012f23521SJohn McCall         unitEnd = unitBegin + unitSize;
54112f23521SJohn McCall         if (unitEnd >= localEnd) break;
54212f23521SJohn McCall       }
54312f23521SJohn McCall 
54412f23521SJohn McCall       // Add an entry for this unit.
54512f23521SJohn McCall       auto entryTy =
54612f23521SJohn McCall         llvm::IntegerType::get(CGM.getLLVMContext(),
54712f23521SJohn McCall                                CGM.getContext().toBits(unitSize));
54812f23521SJohn McCall       Entries.push_back({unitBegin, unitEnd, entryTy});
54912f23521SJohn McCall 
55012f23521SJohn McCall       // The next chunk starts where this chunk left off.
55112f23521SJohn McCall       begin = localEnd;
55212f23521SJohn McCall     } while (begin != end);
55312f23521SJohn McCall   }
55412f23521SJohn McCall 
55512f23521SJohn McCall   // Okay, finally finished.
55612f23521SJohn McCall   Finished = true;
55712f23521SJohn McCall }
55812f23521SJohn McCall 
enumerateComponents(EnumerationCallback callback) const55912f23521SJohn McCall void SwiftAggLowering::enumerateComponents(EnumerationCallback callback) const {
56012f23521SJohn McCall   assert(Finished && "haven't yet finished lowering");
56112f23521SJohn McCall 
56212f23521SJohn McCall   for (auto &entry : Entries) {
5635d2c510cSArnold Schwaighofer     callback(entry.Begin, entry.End, entry.Type);
56412f23521SJohn McCall   }
56512f23521SJohn McCall }
56612f23521SJohn McCall 
56712f23521SJohn McCall std::pair<llvm::StructType*, llvm::Type*>
getCoerceAndExpandTypes() const56812f23521SJohn McCall SwiftAggLowering::getCoerceAndExpandTypes() const {
56912f23521SJohn McCall   assert(Finished && "haven't yet finished lowering");
57012f23521SJohn McCall 
57112f23521SJohn McCall   auto &ctx = CGM.getLLVMContext();
57212f23521SJohn McCall 
57312f23521SJohn McCall   if (Entries.empty()) {
57412f23521SJohn McCall     auto type = llvm::StructType::get(ctx);
57512f23521SJohn McCall     return { type, type };
57612f23521SJohn McCall   }
57712f23521SJohn McCall 
57812f23521SJohn McCall   SmallVector<llvm::Type*, 8> elts;
57912f23521SJohn McCall   CharUnits lastEnd = CharUnits::Zero();
58012f23521SJohn McCall   bool hasPadding = false;
58112f23521SJohn McCall   bool packed = false;
58212f23521SJohn McCall   for (auto &entry : Entries) {
58312f23521SJohn McCall     if (entry.Begin != lastEnd) {
58412f23521SJohn McCall       auto paddingSize = entry.Begin - lastEnd;
58512f23521SJohn McCall       assert(!paddingSize.isNegative());
58612f23521SJohn McCall 
58712f23521SJohn McCall       auto padding = llvm::ArrayType::get(llvm::Type::getInt8Ty(ctx),
58812f23521SJohn McCall                                           paddingSize.getQuantity());
58912f23521SJohn McCall       elts.push_back(padding);
59012f23521SJohn McCall       hasPadding = true;
59112f23521SJohn McCall     }
59212f23521SJohn McCall 
59312f23521SJohn McCall     if (!packed && !entry.Begin.isMultipleOf(
59412f23521SJohn McCall           CharUnits::fromQuantity(
59512f23521SJohn McCall             CGM.getDataLayout().getABITypeAlignment(entry.Type))))
59612f23521SJohn McCall       packed = true;
59712f23521SJohn McCall 
59812f23521SJohn McCall     elts.push_back(entry.Type);
5997b871611SArnold Schwaighofer 
6007b871611SArnold Schwaighofer     lastEnd = entry.Begin + getTypeAllocSize(CGM, entry.Type);
6017b871611SArnold Schwaighofer     assert(entry.End <= lastEnd);
60212f23521SJohn McCall   }
60312f23521SJohn McCall 
60412f23521SJohn McCall   // We don't need to adjust 'packed' to deal with possible tail padding
60512f23521SJohn McCall   // because we never do that kind of access through the coercion type.
60612f23521SJohn McCall   auto coercionType = llvm::StructType::get(ctx, elts, packed);
60712f23521SJohn McCall 
60812f23521SJohn McCall   llvm::Type *unpaddedType = coercionType;
60912f23521SJohn McCall   if (hasPadding) {
61012f23521SJohn McCall     elts.clear();
61112f23521SJohn McCall     for (auto &entry : Entries) {
61212f23521SJohn McCall       elts.push_back(entry.Type);
61312f23521SJohn McCall     }
61412f23521SJohn McCall     if (elts.size() == 1) {
61512f23521SJohn McCall       unpaddedType = elts[0];
61612f23521SJohn McCall     } else {
61712f23521SJohn McCall       unpaddedType = llvm::StructType::get(ctx, elts, /*packed*/ false);
61812f23521SJohn McCall     }
61912f23521SJohn McCall   } else if (Entries.size() == 1) {
62012f23521SJohn McCall     unpaddedType = Entries[0].Type;
62112f23521SJohn McCall   }
62212f23521SJohn McCall 
62312f23521SJohn McCall   return { coercionType, unpaddedType };
62412f23521SJohn McCall }
62512f23521SJohn McCall 
shouldPassIndirectly(bool asReturnValue) const62612f23521SJohn McCall bool SwiftAggLowering::shouldPassIndirectly(bool asReturnValue) const {
62712f23521SJohn McCall   assert(Finished && "haven't yet finished lowering");
62812f23521SJohn McCall 
62912f23521SJohn McCall   // Empty types don't need to be passed indirectly.
63012f23521SJohn McCall   if (Entries.empty()) return false;
63112f23521SJohn McCall 
63212f23521SJohn McCall   // Avoid copying the array of types when there's just a single element.
63312f23521SJohn McCall   if (Entries.size() == 1) {
63456331e28SJohn McCall     return getSwiftABIInfo(CGM).shouldPassIndirectlyForSwift(
63512f23521SJohn McCall                                                            Entries.back().Type,
63612f23521SJohn McCall                                                              asReturnValue);
63712f23521SJohn McCall   }
63812f23521SJohn McCall 
63912f23521SJohn McCall   SmallVector<llvm::Type*, 8> componentTys;
64012f23521SJohn McCall   componentTys.reserve(Entries.size());
64112f23521SJohn McCall   for (auto &entry : Entries) {
64212f23521SJohn McCall     componentTys.push_back(entry.Type);
64312f23521SJohn McCall   }
64456331e28SJohn McCall   return getSwiftABIInfo(CGM).shouldPassIndirectlyForSwift(componentTys,
64556331e28SJohn McCall                                                            asReturnValue);
64656331e28SJohn McCall }
64756331e28SJohn McCall 
shouldPassIndirectly(CodeGenModule & CGM,ArrayRef<llvm::Type * > componentTys,bool asReturnValue)64856331e28SJohn McCall bool swiftcall::shouldPassIndirectly(CodeGenModule &CGM,
64956331e28SJohn McCall                                      ArrayRef<llvm::Type*> componentTys,
65056331e28SJohn McCall                                      bool asReturnValue) {
65156331e28SJohn McCall   return getSwiftABIInfo(CGM).shouldPassIndirectlyForSwift(componentTys,
65212f23521SJohn McCall                                                            asReturnValue);
65312f23521SJohn McCall }
65412f23521SJohn McCall 
getMaximumVoluntaryIntegerSize(CodeGenModule & CGM)65512f23521SJohn McCall CharUnits swiftcall::getMaximumVoluntaryIntegerSize(CodeGenModule &CGM) {
65612f23521SJohn McCall   // Currently always the size of an ordinary pointer.
65712f23521SJohn McCall   return CGM.getContext().toCharUnitsFromBits(
65812f23521SJohn McCall            CGM.getContext().getTargetInfo().getPointerWidth(0));
65912f23521SJohn McCall }
66012f23521SJohn McCall 
getNaturalAlignment(CodeGenModule & CGM,llvm::Type * type)66112f23521SJohn McCall CharUnits swiftcall::getNaturalAlignment(CodeGenModule &CGM, llvm::Type *type) {
66212f23521SJohn McCall   // For Swift's purposes, this is always just the store size of the type
66312f23521SJohn McCall   // rounded up to a power of 2.
66412f23521SJohn McCall   auto size = (unsigned long long) getTypeStoreSize(CGM, type).getQuantity();
66512f23521SJohn McCall   if (!isPowerOf2(size)) {
666829b5d42SAaron Ballman     size = 1ULL << (llvm::findLastSet(size, llvm::ZB_Undefined) + 1);
66712f23521SJohn McCall   }
66812f23521SJohn McCall   assert(size >= CGM.getDataLayout().getABITypeAlignment(type));
66912f23521SJohn McCall   return CharUnits::fromQuantity(size);
67012f23521SJohn McCall }
67112f23521SJohn McCall 
isLegalIntegerType(CodeGenModule & CGM,llvm::IntegerType * intTy)67212f23521SJohn McCall bool swiftcall::isLegalIntegerType(CodeGenModule &CGM,
67312f23521SJohn McCall                                    llvm::IntegerType *intTy) {
67412f23521SJohn McCall   auto size = intTy->getBitWidth();
67512f23521SJohn McCall   switch (size) {
67612f23521SJohn McCall   case 1:
67712f23521SJohn McCall   case 8:
67812f23521SJohn McCall   case 16:
67912f23521SJohn McCall   case 32:
68012f23521SJohn McCall   case 64:
68112f23521SJohn McCall     // Just assume that the above are always legal.
68212f23521SJohn McCall     return true;
68312f23521SJohn McCall 
68412f23521SJohn McCall   case 128:
68512f23521SJohn McCall     return CGM.getContext().getTargetInfo().hasInt128Type();
68612f23521SJohn McCall 
68712f23521SJohn McCall   default:
68812f23521SJohn McCall     return false;
68912f23521SJohn McCall   }
69012f23521SJohn McCall }
69112f23521SJohn McCall 
isLegalVectorType(CodeGenModule & CGM,CharUnits vectorSize,llvm::VectorType * vectorTy)69212f23521SJohn McCall bool swiftcall::isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
69312f23521SJohn McCall                                   llvm::VectorType *vectorTy) {
69419e883fcSChristopher Tetreault   return isLegalVectorType(
69519e883fcSChristopher Tetreault       CGM, vectorSize, vectorTy->getElementType(),
69619e883fcSChristopher Tetreault       cast<llvm::FixedVectorType>(vectorTy)->getNumElements());
69712f23521SJohn McCall }
69812f23521SJohn McCall 
isLegalVectorType(CodeGenModule & CGM,CharUnits vectorSize,llvm::Type * eltTy,unsigned numElts)69912f23521SJohn McCall bool swiftcall::isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
70012f23521SJohn McCall                                   llvm::Type *eltTy, unsigned numElts) {
70112f23521SJohn McCall   assert(numElts > 1 && "illegal vector length");
70212f23521SJohn McCall   return getSwiftABIInfo(CGM)
70312f23521SJohn McCall            .isLegalVectorTypeForSwift(vectorSize, eltTy, numElts);
70412f23521SJohn McCall }
70512f23521SJohn McCall 
70612f23521SJohn McCall std::pair<llvm::Type*, unsigned>
splitLegalVectorType(CodeGenModule & CGM,CharUnits vectorSize,llvm::VectorType * vectorTy)70712f23521SJohn McCall swiftcall::splitLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
70812f23521SJohn McCall                                 llvm::VectorType *vectorTy) {
70919e883fcSChristopher Tetreault   auto numElts = cast<llvm::FixedVectorType>(vectorTy)->getNumElements();
71012f23521SJohn McCall   auto eltTy = vectorTy->getElementType();
71112f23521SJohn McCall 
71212f23521SJohn McCall   // Try to split the vector type in half.
71312f23521SJohn McCall   if (numElts >= 4 && isPowerOf2(numElts)) {
71412f23521SJohn McCall     if (isLegalVectorType(CGM, vectorSize / 2, eltTy, numElts / 2))
71579689817SChristopher Tetreault       return {llvm::FixedVectorType::get(eltTy, numElts / 2), 2};
71612f23521SJohn McCall   }
71712f23521SJohn McCall 
71812f23521SJohn McCall   return {eltTy, numElts};
71912f23521SJohn McCall }
72012f23521SJohn McCall 
legalizeVectorType(CodeGenModule & CGM,CharUnits origVectorSize,llvm::VectorType * origVectorTy,llvm::SmallVectorImpl<llvm::Type * > & components)72112f23521SJohn McCall void swiftcall::legalizeVectorType(CodeGenModule &CGM, CharUnits origVectorSize,
72212f23521SJohn McCall                                    llvm::VectorType *origVectorTy,
72312f23521SJohn McCall                              llvm::SmallVectorImpl<llvm::Type*> &components) {
72412f23521SJohn McCall   // If it's already a legal vector type, use it.
72512f23521SJohn McCall   if (isLegalVectorType(CGM, origVectorSize, origVectorTy)) {
72612f23521SJohn McCall     components.push_back(origVectorTy);
72712f23521SJohn McCall     return;
72812f23521SJohn McCall   }
72912f23521SJohn McCall 
73012f23521SJohn McCall   // Try to split the vector into legal subvectors.
73119e883fcSChristopher Tetreault   auto numElts = cast<llvm::FixedVectorType>(origVectorTy)->getNumElements();
73212f23521SJohn McCall   auto eltTy = origVectorTy->getElementType();
73312f23521SJohn McCall   assert(numElts != 1);
73412f23521SJohn McCall 
73512f23521SJohn McCall   // The largest size that we're still considering making subvectors of.
73612f23521SJohn McCall   // Always a power of 2.
73712f23521SJohn McCall   unsigned logCandidateNumElts = llvm::findLastSet(numElts, llvm::ZB_Undefined);
73812f23521SJohn McCall   unsigned candidateNumElts = 1U << logCandidateNumElts;
73912f23521SJohn McCall   assert(candidateNumElts <= numElts && candidateNumElts * 2 > numElts);
74012f23521SJohn McCall 
74112f23521SJohn McCall   // Minor optimization: don't check the legality of this exact size twice.
74212f23521SJohn McCall   if (candidateNumElts == numElts) {
74312f23521SJohn McCall     logCandidateNumElts--;
74412f23521SJohn McCall     candidateNumElts >>= 1;
74512f23521SJohn McCall   }
74612f23521SJohn McCall 
74712f23521SJohn McCall   CharUnits eltSize = (origVectorSize / numElts);
74812f23521SJohn McCall   CharUnits candidateSize = eltSize * candidateNumElts;
74912f23521SJohn McCall 
75012f23521SJohn McCall   // The sensibility of this algorithm relies on the fact that we never
75112f23521SJohn McCall   // have a legal non-power-of-2 vector size without having the power of 2
75212f23521SJohn McCall   // also be legal.
75312f23521SJohn McCall   while (logCandidateNumElts > 0) {
75412f23521SJohn McCall     assert(candidateNumElts == 1U << logCandidateNumElts);
75512f23521SJohn McCall     assert(candidateNumElts <= numElts);
75612f23521SJohn McCall     assert(candidateSize == eltSize * candidateNumElts);
75712f23521SJohn McCall 
75812f23521SJohn McCall     // Skip illegal vector sizes.
75912f23521SJohn McCall     if (!isLegalVectorType(CGM, candidateSize, eltTy, candidateNumElts)) {
76012f23521SJohn McCall       logCandidateNumElts--;
76112f23521SJohn McCall       candidateNumElts /= 2;
76212f23521SJohn McCall       candidateSize /= 2;
76312f23521SJohn McCall       continue;
76412f23521SJohn McCall     }
76512f23521SJohn McCall 
76612f23521SJohn McCall     // Add the right number of vectors of this size.
76712f23521SJohn McCall     auto numVecs = numElts >> logCandidateNumElts;
76879689817SChristopher Tetreault     components.append(numVecs,
76979689817SChristopher Tetreault                       llvm::FixedVectorType::get(eltTy, candidateNumElts));
77012f23521SJohn McCall     numElts -= (numVecs << logCandidateNumElts);
77112f23521SJohn McCall 
77212f23521SJohn McCall     if (numElts == 0) return;
77312f23521SJohn McCall 
77412f23521SJohn McCall     // It's possible that the number of elements remaining will be legal.
77512f23521SJohn McCall     // This can happen with e.g. <7 x float> when <3 x float> is legal.
77612f23521SJohn McCall     // This only needs to be separately checked if it's not a power of 2.
77712f23521SJohn McCall     if (numElts > 2 && !isPowerOf2(numElts) &&
77812f23521SJohn McCall         isLegalVectorType(CGM, eltSize * numElts, eltTy, numElts)) {
77979689817SChristopher Tetreault       components.push_back(llvm::FixedVectorType::get(eltTy, numElts));
78012f23521SJohn McCall       return;
78112f23521SJohn McCall     }
78212f23521SJohn McCall 
78312f23521SJohn McCall     // Bring vecSize down to something no larger than numElts.
78412f23521SJohn McCall     do {
78512f23521SJohn McCall       logCandidateNumElts--;
78612f23521SJohn McCall       candidateNumElts /= 2;
78712f23521SJohn McCall       candidateSize /= 2;
78812f23521SJohn McCall     } while (candidateNumElts > numElts);
78912f23521SJohn McCall   }
79012f23521SJohn McCall 
79112f23521SJohn McCall   // Otherwise, just append a bunch of individual elements.
79212f23521SJohn McCall   components.append(numElts, eltTy);
79312f23521SJohn McCall }
79412f23521SJohn McCall 
mustPassRecordIndirectly(CodeGenModule & CGM,const RecordDecl * record)795bfbc05e2SJohn McCall bool swiftcall::mustPassRecordIndirectly(CodeGenModule &CGM,
796bfbc05e2SJohn McCall                                          const RecordDecl *record) {
7974fcd9ef6SJohn McCall   // FIXME: should we not rely on the standard computation in Sema, just in
7984fcd9ef6SJohn McCall   // case we want to diverge from the platform ABI (e.g. on targets where
7994fcd9ef6SJohn McCall   // that uses the MSVC rule)?
8004fcd9ef6SJohn McCall   return !record->canPassInRegisters();
80112f23521SJohn McCall }
80212f23521SJohn McCall 
classifyExpandedType(SwiftAggLowering & lowering,bool forReturn,CharUnits alignmentForIndirect)80312f23521SJohn McCall static ABIArgInfo classifyExpandedType(SwiftAggLowering &lowering,
80412f23521SJohn McCall                                        bool forReturn,
80512f23521SJohn McCall                                        CharUnits alignmentForIndirect) {
80612f23521SJohn McCall   if (lowering.empty()) {
80712f23521SJohn McCall     return ABIArgInfo::getIgnore();
80812f23521SJohn McCall   } else if (lowering.shouldPassIndirectly(forReturn)) {
80912f23521SJohn McCall     return ABIArgInfo::getIndirect(alignmentForIndirect, /*byval*/ false);
81012f23521SJohn McCall   } else {
81112f23521SJohn McCall     auto types = lowering.getCoerceAndExpandTypes();
81212f23521SJohn McCall     return ABIArgInfo::getCoerceAndExpand(types.first, types.second);
81312f23521SJohn McCall   }
81412f23521SJohn McCall }
81512f23521SJohn McCall 
classifyType(CodeGenModule & CGM,CanQualType type,bool forReturn)81612f23521SJohn McCall static ABIArgInfo classifyType(CodeGenModule &CGM, CanQualType type,
81712f23521SJohn McCall                                bool forReturn) {
81812f23521SJohn McCall   if (auto recordType = dyn_cast<RecordType>(type)) {
81912f23521SJohn McCall     auto record = recordType->getDecl();
82012f23521SJohn McCall     auto &layout = CGM.getContext().getASTRecordLayout(record);
82112f23521SJohn McCall 
822bfbc05e2SJohn McCall     if (mustPassRecordIndirectly(CGM, record))
82312f23521SJohn McCall       return ABIArgInfo::getIndirect(layout.getAlignment(), /*byval*/ false);
82412f23521SJohn McCall 
82512f23521SJohn McCall     SwiftAggLowering lowering(CGM);
82612f23521SJohn McCall     lowering.addTypedData(recordType->getDecl(), CharUnits::Zero(), layout);
82712f23521SJohn McCall     lowering.finish();
82812f23521SJohn McCall 
82912f23521SJohn McCall     return classifyExpandedType(lowering, forReturn, layout.getAlignment());
83012f23521SJohn McCall   }
83112f23521SJohn McCall 
83212f23521SJohn McCall   // Just assume that all of our target ABIs can support returning at least
83312f23521SJohn McCall   // two integer or floating-point values.
83412f23521SJohn McCall   if (isa<ComplexType>(type)) {
83512f23521SJohn McCall     return (forReturn ? ABIArgInfo::getDirect() : ABIArgInfo::getExpand());
83612f23521SJohn McCall   }
83712f23521SJohn McCall 
83812f23521SJohn McCall   // Vector types may need to be legalized.
83912f23521SJohn McCall   if (isa<VectorType>(type)) {
84012f23521SJohn McCall     SwiftAggLowering lowering(CGM);
84112f23521SJohn McCall     lowering.addTypedData(type, CharUnits::Zero());
84212f23521SJohn McCall     lowering.finish();
84312f23521SJohn McCall 
84412f23521SJohn McCall     CharUnits alignment = CGM.getContext().getTypeAlignInChars(type);
84512f23521SJohn McCall     return classifyExpandedType(lowering, forReturn, alignment);
84612f23521SJohn McCall   }
84712f23521SJohn McCall 
84812f23521SJohn McCall   // Member pointer types need to be expanded, but it's a simple form of
84912f23521SJohn McCall   // expansion that 'Direct' can handle.  Note that CanBeFlattened should be
85012f23521SJohn McCall   // true for this to work.
85112f23521SJohn McCall 
85212f23521SJohn McCall   // 'void' needs to be ignored.
85312f23521SJohn McCall   if (type->isVoidType()) {
85412f23521SJohn McCall     return ABIArgInfo::getIgnore();
85512f23521SJohn McCall   }
85612f23521SJohn McCall 
85712f23521SJohn McCall   // Everything else can be passed directly.
85812f23521SJohn McCall   return ABIArgInfo::getDirect();
85912f23521SJohn McCall }
86012f23521SJohn McCall 
classifyReturnType(CodeGenModule & CGM,CanQualType type)86112f23521SJohn McCall ABIArgInfo swiftcall::classifyReturnType(CodeGenModule &CGM, CanQualType type) {
86212f23521SJohn McCall   return classifyType(CGM, type, /*forReturn*/ true);
86312f23521SJohn McCall }
86412f23521SJohn McCall 
classifyArgumentType(CodeGenModule & CGM,CanQualType type)86512f23521SJohn McCall ABIArgInfo swiftcall::classifyArgumentType(CodeGenModule &CGM,
86612f23521SJohn McCall                                            CanQualType type) {
86712f23521SJohn McCall   return classifyType(CGM, type, /*forReturn*/ false);
86812f23521SJohn McCall }
86912f23521SJohn McCall 
computeABIInfo(CodeGenModule & CGM,CGFunctionInfo & FI)87012f23521SJohn McCall void swiftcall::computeABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI) {
87112f23521SJohn McCall   auto &retInfo = FI.getReturnInfo();
87212f23521SJohn McCall   retInfo = classifyReturnType(CGM, FI.getReturnType());
87312f23521SJohn McCall 
87412f23521SJohn McCall   for (unsigned i = 0, e = FI.arg_size(); i != e; ++i) {
87512f23521SJohn McCall     auto &argInfo = FI.arg_begin()[i];
87612f23521SJohn McCall     argInfo.info = classifyArgumentType(CGM, argInfo.type);
87712f23521SJohn McCall   }
87812f23521SJohn McCall }
879b0f2c339SArnold Schwaighofer 
880b0f2c339SArnold Schwaighofer // Is swifterror lowered to a register by the target ABI.
isSwiftErrorLoweredInRegister(CodeGenModule & CGM)881b0f2c339SArnold Schwaighofer bool swiftcall::isSwiftErrorLoweredInRegister(CodeGenModule &CGM) {
882b0f2c339SArnold Schwaighofer   return getSwiftABIInfo(CGM).isSwiftErrorInRegister();
883b0f2c339SArnold Schwaighofer }
884