19 using namespace clang;
20 using namespace CodeGen;
21 using namespace swiftcall;
33 assert(first != second);
36 if (first->isIntegerTy()) {
37 if (second->isPointerTy())
return first;
38 }
else if (first->isPointerTy()) {
39 if (second->isIntegerTy())
return second;
40 if (second->isPointerTy())
return first;
44 }
else if (
auto firstVecTy = dyn_cast<llvm::VectorType>(first)) {
45 if (
auto secondVecTy = dyn_cast<llvm::VectorType>(second)) {
46 if (
auto commonTy =
getCommonType(firstVecTy->getElementType(),
47 secondVecTy->getElementType())) {
48 return (commonTy == firstVecTy->getElementType() ? first : second);
72 if (!arrayType)
return;
74 QualType eltType = arrayType->getElementType();
76 for (uint64_t i = 0, e = arrayType->getSize().getZExtValue(); i != e; ++i) {
82 auto eltType = complexType->getElementType();
86 addTypedData(eltLLVMType, begin + eltSize, begin + 2 * eltSize);
110 for (
auto field : record->
fields()) {
111 if (field->isBitField()) {
112 addBitFieldData(field, begin, 0);
133 for (
auto &baseSpecifier : cxxRecord->bases()) {
134 if (baseSpecifier.isVirtual())
continue;
136 auto baseRecord = baseSpecifier.getType()->getAsCXXRecordDecl();
147 for (
auto field : record->
fields()) {
148 auto fieldOffsetInBits = layout.
getFieldOffset(field->getFieldIndex());
149 if (field->isBitField()) {
150 addBitFieldData(field, begin, fieldOffsetInBits);
160 for (
auto &vbaseSpecifier : cxxRecord->vbases()) {
161 auto baseRecord = vbaseSpecifier.getType()->getAsCXXRecordDecl();
167 void SwiftAggLowering::addBitFieldData(
const FieldDecl *bitfield,
169 uint64_t bitfieldBitBegin) {
175 if (width == 0)
return;
178 CharUnits bitfieldByteBegin = ctx.toCharUnitsFromBits(bitfieldBitBegin);
183 uint64_t bitfieldBitLast = bitfieldBitBegin + width - 1;
187 recordBegin + bitfieldByteEnd);
191 assert(type &&
"didn't provide type for typed data");
197 assert(type &&
"didn't provide type for typed data");
201 if (
auto vecTy = dyn_cast<llvm::VectorType>(type)) {
204 assert(componentTys.size() >= 1);
207 for (
size_t i = 0, e = componentTys.size(); i != e - 1; ++i) {
210 assert(componentSize < end - begin);
211 addLegalTypedData(componentTy, begin, begin + componentSize);
212 begin += componentSize;
215 return addLegalTypedData(componentTys.back(),
begin,
end);
219 if (
auto intTy = dyn_cast<llvm::IntegerType>(type)) {
225 return addLegalTypedData(type, begin, end);
234 if (
auto vecTy = dyn_cast<llvm::VectorType>(type)) {
236 auto eltTy = split.first;
237 auto numElts = split.second;
239 auto eltSize = (end -
begin) / numElts;
241 for (
size_t i = 0, e = numElts; i != e; ++i) {
242 addLegalTypedData(eltTy, begin, begin + eltSize);
245 assert(begin == end);
252 addEntry(type, begin, end);
255 void SwiftAggLowering::addEntry(
llvm::Type *type,
258 (!isa<llvm::StructType>(type) && !isa<llvm::ArrayType>(type))) &&
259 "cannot add aggregate-typed data");
263 if (Entries.empty() || Entries.back().End <=
begin) {
264 Entries.push_back({
begin,
end, type});
270 size_t index = Entries.size() - 1;
272 if (Entries[index - 1].
End <= begin)
break;
278 if (Entries[index].Begin >= end) {
282 Entries.insert(Entries.begin() + index, {
begin,
end, type});
291 if (Entries[index].Begin == begin && Entries[index].
End == end) {
293 if (Entries[index].
Type == type)
return;
296 if (Entries[index].
Type ==
nullptr) {
298 }
else if (type ==
nullptr) {
299 Entries[index].Type =
nullptr;
306 Entries[index].Type = entryType;
311 Entries[index].Type =
nullptr;
318 if (
auto vecTy = dyn_cast_or_null<llvm::VectorType>(type)) {
319 auto eltTy = vecTy->getElementType();
322 for (
unsigned i = 0, e = vecTy->getNumElements(); i != e; ++i) {
323 addEntry(eltTy, begin, begin + eltSize);
326 assert(begin == end);
331 if (Entries[index].
Type && Entries[index].
Type->isVectorTy()) {
332 splitVectorEntry(index);
333 goto restartAfterSplit;
338 Entries[index].Type =
nullptr;
341 if (begin < Entries[index].Begin) {
342 Entries[index].Begin =
begin;
343 assert(index == 0 || begin >= Entries[index - 1].
End);
348 while (end > Entries[index].
End) {
349 assert(Entries[index].
Type ==
nullptr);
352 if (index == Entries.size() - 1 || end <= Entries[index + 1].Begin) {
353 Entries[index].End =
end;
358 Entries[index].End = Entries[index + 1].Begin;
364 if (Entries[index].
Type ==
nullptr)
368 if (Entries[index].
Type->isVectorTy() &&
369 end < Entries[index].End) {
370 splitVectorEntry(index);
374 Entries[index].Type =
nullptr;
380 void SwiftAggLowering::splitVectorEntry(
unsigned index) {
381 auto vecTy = cast<llvm::VectorType>(Entries[index].Type);
384 auto eltTy = split.first;
386 auto numElts = split.second;
387 Entries.insert(&Entries[index + 1], numElts - 1, StorageEntry());
390 for (
unsigned i = 0; i != numElts; ++i) {
391 Entries[index].Type = eltTy;
392 Entries[index].Begin =
begin;
393 Entries[index].End = begin + eltSize;
415 if (Entries.empty()) {
426 bool hasOpaqueEntries = (Entries[0].Type ==
nullptr);
427 for (
size_t i = 1, e = Entries.size(); i != e; ++i) {
429 Entries[i].Begin, chunkSize)) {
430 Entries[i - 1].Type =
nullptr;
431 Entries[i].Type =
nullptr;
432 Entries[i - 1].End = Entries[i].Begin;
433 hasOpaqueEntries =
true;
435 }
else if (Entries[i].
Type ==
nullptr) {
436 hasOpaqueEntries =
true;
442 if (!hasOpaqueEntries) {
448 auto orig = std::move(Entries);
449 assert(Entries.empty());
451 for (
size_t i = 0, e = orig.size(); i != e; ++i) {
453 if (orig[i].
Type !=
nullptr) {
454 Entries.push_back(orig[i]);
461 auto begin = orig[i].Begin;
462 auto end = orig[i].End;
464 orig[i + 1].
Type ==
nullptr &&
465 end == orig[i + 1].Begin) {
466 end = orig[i + 1].End;
477 CharUnits chunkEnd = chunkBegin + chunkSize;
483 for (; ; unitSize *= 2) {
484 assert(unitSize <= chunkSize);
486 unitEnd = unitBegin + unitSize;
487 if (unitEnd >= localEnd)
break;
494 Entries.push_back({unitBegin, unitEnd, entryTy});
498 }
while (begin != end);
506 assert(Finished &&
"haven't yet finished lowering");
508 for (
auto &entry : Entries) {
509 callback(entry.Begin, entry.Type);
513 std::pair<llvm::StructType*, llvm::Type*>
515 assert(Finished &&
"haven't yet finished lowering");
519 if (Entries.empty()) {
520 auto type = llvm::StructType::get(ctx);
521 return {
type, type };
526 bool hasPadding =
false;
528 for (
auto &entry : Entries) {
529 if (entry.Begin != lastEnd) {
530 auto paddingSize = entry.Begin - lastEnd;
531 assert(!paddingSize.isNegative());
533 auto padding = llvm::ArrayType::get(llvm::Type::getInt8Ty(ctx),
534 paddingSize.getQuantity());
535 elts.push_back(padding);
539 if (!packed && !entry.Begin.isMultipleOf(
544 elts.push_back(entry.Type);
550 auto coercionType = llvm::StructType::get(ctx, elts, packed);
555 for (
auto &entry : Entries) {
556 elts.push_back(entry.Type);
558 if (elts.size() == 1) {
559 unpaddedType = elts[0];
561 unpaddedType = llvm::StructType::get(ctx, elts,
false);
563 }
else if (Entries.size() == 1) {
564 unpaddedType = Entries[0].Type;
567 return { coercionType, unpaddedType };
571 assert(Finished &&
"haven't yet finished lowering");
574 if (Entries.empty())
return false;
576 CharUnits totalSize = Entries.back().End;
579 if (Entries.size() == 1) {
586 componentTys.reserve(Entries.size());
587 for (
auto &entry : Entries) {
588 componentTys.push_back(entry.Type);
606 size = 1ULL << (llvm::findLastSet(size, llvm::ZB_Undefined) + 1);
608 assert(size >= CGM.
getDataLayout().getABITypeAlignment(type));
613 llvm::IntegerType *intTy) {
614 auto size = intTy->getBitWidth();
633 llvm::VectorType *vectorTy) {
635 vectorTy->getNumElements());
640 assert(numElts > 1 &&
"illegal vector length");
645 std::pair<llvm::Type*, unsigned>
647 llvm::VectorType *vectorTy) {
648 auto numElts = vectorTy->getNumElements();
649 auto eltTy = vectorTy->getElementType();
654 return {llvm::VectorType::get(eltTy, numElts / 2), 2};
657 return {eltTy, numElts};
661 llvm::VectorType *origVectorTy,
665 components.push_back(origVectorTy);
670 auto numElts = origVectorTy->getNumElements();
671 auto eltTy = origVectorTy->getElementType();
672 assert(numElts != 1);
676 unsigned logCandidateNumElts = llvm::findLastSet(numElts, llvm::ZB_Undefined);
677 unsigned candidateNumElts = 1U << logCandidateNumElts;
678 assert(candidateNumElts <= numElts && candidateNumElts * 2 > numElts);
681 if (candidateNumElts == numElts) {
682 logCandidateNumElts--;
683 candidateNumElts >>= 1;
686 CharUnits eltSize = (origVectorSize / numElts);
687 CharUnits candidateSize = eltSize * candidateNumElts;
692 while (logCandidateNumElts > 0) {
693 assert(candidateNumElts == 1U << logCandidateNumElts);
694 assert(candidateNumElts <= numElts);
695 assert(candidateSize == eltSize * candidateNumElts);
699 logCandidateNumElts--;
700 candidateNumElts /= 2;
706 auto numVecs = numElts >> logCandidateNumElts;
707 components.append(numVecs, llvm::VectorType::get(eltTy, candidateNumElts));
708 numElts -= (numVecs << logCandidateNumElts);
710 if (numElts == 0)
return;
717 components.push_back(llvm::VectorType::get(eltTy, numElts));
723 logCandidateNumElts--;
724 candidateNumElts /= 2;
726 }
while (candidateNumElts > numElts);
730 components.append(numElts, eltTy);
743 for (
auto ctor : record->
ctors()) {
744 if (ctor->isCopyOrMoveConstructor() && !ctor->isDeleted() &&
756 if (lowering.
empty()) {
768 if (
auto recordType = dyn_cast<RecordType>(type)) {
769 auto record = recordType->getDecl();
772 if (
auto cxxRecord = dyn_cast<CXXRecordDecl>(record)) {
786 if (isa<ComplexType>(type)) {
791 if (isa<VectorType>(type)) {
805 if (type->isVoidType()) {
826 for (
unsigned i = 0, e = FI.
arg_size(); i != e; ++i) {
A (possibly-)qualified type.
const ABIInfo & getABIInfo() const
getABIInfo() - Returns ABI info helper for the target.
CodeGenTypes & getTypes()
bool empty() const
Does this lowering require passing any data?
CanQualType getReturnType() const
bool isBitField() const
Determines whether this field is a bitfield.
llvm::LLVMContext & getLLVMContext()
static ABIArgInfo classifyType(CodeGenModule &CGM, CanQualType type, bool forReturn)
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
bool hasNonTrivialDestructor() const
Determine whether this class has a non-trivial destructor (C++ [class.dtor]p3)
bool shouldPassIndirectly(bool asReturnValue) const
According to the target Swift ABI, should a value with this lowering be passed indirectly?
const llvm::DataLayout & getDataLayout() const
The base class of the type hierarchy.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
void enumerateComponents(EnumerationCallback callback) const
Enumerate the expanded components of this type.
std::pair< llvm::Type *, unsigned > splitLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, llvm::VectorType *vectorTy)
Minimally split a legal vector type.
static ABIArgInfo getIgnore()
virtual bool shouldPassIndirectlyForSwift(CharUnits totalSize, ArrayRef< llvm::Type * > types, bool asReturnValue) const =0
RecordDecl - Represents a struct/union/class.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type)
Classify the rules for how to pass a particular type.
FieldDecl - An instance of this class is created by Sema::ActOnField to represent a member of a struc...
static bool isPowerOf2(unsigned n)
ABIArgInfo classifyReturnType(CodeGenModule &CGM, CanQualType type)
Classify the rules for how to return a particular type.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
static ABIArgInfo getDirect(llvm::Type *T=nullptr, unsigned Offset=0, llvm::Type *Padding=nullptr, bool CanBeFlattened=true)
const TargetInfo & getTargetInfo() const
CharUnits - This is an opaque type for sizes expressed in character units.
field_range fields() const
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
static ABIArgInfo classifyExpandedType(SwiftAggLowering &lowering, bool forReturn, CharUnits alignmentForIndirect)
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
static ABIArgInfo getExpand()
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static bool areBytesInSameUnit(CharUnits first, CharUnits second, CharUnits chunkSize)
static CharUnits One()
One - Construct a CharUnits quantity of one.
static llvm::Type * getCommonType(llvm::Type *first, llvm::Type *second)
Given two types with the same size, try to find a common type.
const TargetCodeGenInfo & getTargetCodeGenInfo()
CharUnits getNaturalAlignment(CodeGenModule &CGM, llvm::Type *type)
Return the Swift CC's notion of the natural alignment of a type.
bool hasOwnVBPtr() const
hasOwnVBPtr - Does this class provide its own virtual-base table pointer, rather than inheriting one ...
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
void addOpaqueData(CharUnits begin, CharUnits end)
virtual bool isLegalVectorTypeForSwift(CharUnits totalSize, llvm::Type *eltTy, unsigned elts) const
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
ASTContext & getContext() const
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
char __ovld __cnfn min(char x, char y)
Returns y if y < x, otherwise it returns x.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CharUnits getVBPtrOffset() const
getVBPtrOffset - Get the offset for virtual base table pointer.
void legalizeVectorType(CodeGenModule &CGM, CharUnits vectorSize, llvm::VectorType *vectorTy, llvm::SmallVectorImpl< llvm::Type * > &types)
Turn a vector type in a sequence of legal component vector types.
The l-value was considered opaque, so the alignment was determined from a type.
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
void addTypedData(QualType type, CharUnits begin)
unsigned getBitWidthValue(const ASTContext &Ctx) const
static CharUnits getTypeStoreSize(CodeGenModule &CGM, llvm::Type *type)
void computeABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI)
Compute the ABI information of a swiftcall function.
const ConstantArrayType * getAsConstantArrayType(QualType T) const
bool isMultipleOf(CharUnits N) const
Test whether this is a multiple of the other value.
static const SwiftABIInfo & getSwiftABIInfo(CodeGenModule &CGM)
static CharUnits getOffsetAtStartOfUnit(CharUnits offset, CharUnits unitSize)
Given a power-of-two unit size, return the offset of the aligned unit of that size which contains the...
bool shouldPassCXXRecordIndirectly(CodeGenModule &CGM, const CXXRecordDecl *record)
Should a C++ record type be passed and returned indirectly?
CGFunctionInfo - Class to encapsulate the information about a function definition.
This class organizes the cross-function state that is used while generating LLVM code.
std::pair< llvm::StructType *, llvm::Type * > getCoerceAndExpandTypes() const
Return the types for a coerce-and-expand operation.
bool isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, llvm::VectorType *vectorTy)
Is the given vector type "legal" for Swift's perspective on the current platform?
A refining implementation of ABIInfo for targets that support swiftcall.
bool isZero() const
isZero - Test whether the quantity equals zero.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
A pointer to member type per C++ 8.3.3 - Pointers to members.
virtual bool hasInt128Type() const
Determine whether the __int128 type is supported on this target.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Complex values, per C99 6.2.5p11.
const T * getAs() const
Member-template getAs<specific type>'.
llvm::PointerType * Int8PtrTy
ABIArgInfo & getReturnInfo()
uint64_t getPointerWidth(unsigned AddrSpace) const
Return the width of pointers on this target, for the specified address space.
llvm::function_ref< void(CharUnits offset, llvm::Type *type)> EnumerationCallback
static ABIArgInfo getCoerceAndExpand(llvm::StructType *coerceToType, llvm::Type *unpaddedCoerceToType)
Represents a C++ struct/union/class.
bool isLegalIntegerType(CodeGenModule &CGM, llvm::IntegerType *type)
Is the given integer type "legal" for Swift's perspective on the current platform?
Defines the clang::TargetInfo interface.
const_arg_iterator arg_begin() const
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
unsigned arg_size() const
CharUnits getMaximumVoluntaryIntegerSize(CodeGenModule &CGM)
Return the maximum voluntary integer size for the current target.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal=true, bool Realign=false, llvm::Type *Padding=nullptr)