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);
76 if (!arrayType)
return;
78 QualType eltType = arrayType->getElementType();
80 for (uint64_t i = 0, e = arrayType->getSize().getZExtValue(); i != e; ++i) {
86 auto eltType = complexType->getElementType();
90 addTypedData(eltLLVMType, begin + eltSize, begin + 2 * eltSize);
114 for (
auto field : record->
fields()) {
115 if (field->isBitField()) {
116 addBitFieldData(field, begin, 0);
137 for (
auto &baseSpecifier : cxxRecord->bases()) {
138 if (baseSpecifier.isVirtual())
continue;
140 auto baseRecord = baseSpecifier.getType()->getAsCXXRecordDecl();
151 for (
auto field : record->
fields()) {
152 auto fieldOffsetInBits = layout.
getFieldOffset(field->getFieldIndex());
153 if (field->isBitField()) {
154 addBitFieldData(field, begin, fieldOffsetInBits);
164 for (
auto &vbaseSpecifier : cxxRecord->vbases()) {
165 auto baseRecord = vbaseSpecifier.getType()->getAsCXXRecordDecl();
171 void SwiftAggLowering::addBitFieldData(
const FieldDecl *bitfield,
173 uint64_t bitfieldBitBegin) {
179 if (width == 0)
return;
182 CharUnits bitfieldByteBegin = ctx.toCharUnitsFromBits(bitfieldBitBegin);
187 uint64_t bitfieldBitLast = bitfieldBitBegin + width - 1;
191 recordBegin + bitfieldByteEnd);
195 assert(type &&
"didn't provide type for typed data");
201 assert(type &&
"didn't provide type for typed data");
205 if (
auto vecTy = dyn_cast<llvm::VectorType>(type)) {
208 assert(componentTys.size() >= 1);
211 for (
size_t i = 0, e = componentTys.size(); i != e - 1; ++i) {
214 assert(componentSize < end - begin);
215 addLegalTypedData(componentTy, begin, begin + componentSize);
216 begin += componentSize;
219 return addLegalTypedData(componentTys.back(), begin, end);
223 if (
auto intTy = dyn_cast<llvm::IntegerType>(type)) {
229 return addLegalTypedData(type, begin, end);
238 if (
auto vecTy = dyn_cast<llvm::VectorType>(type)) {
240 auto eltTy = split.first;
241 auto numElts = split.second;
243 auto eltSize = (end - begin) / numElts;
245 for (
size_t i = 0, e = numElts; i != e; ++i) {
246 addLegalTypedData(eltTy, begin, begin + eltSize);
249 assert(begin == end);
256 addEntry(type, begin, end);
259 void SwiftAggLowering::addEntry(
llvm::Type *type,
262 (!isa<llvm::StructType>(type) && !isa<llvm::ArrayType>(type))) &&
263 "cannot add aggregate-typed data");
267 if (Entries.empty() || Entries.back().End <= begin) {
268 Entries.push_back({begin, end, type});
274 size_t index = Entries.size() - 1;
276 if (Entries[index - 1].
End <= begin)
break;
282 if (Entries[index].
Begin >= end) {
286 Entries.insert(Entries.begin() + index, {begin, end, type});
295 if (Entries[index].
Begin == begin && Entries[index].
End == end) {
297 if (Entries[index].
Type == type)
return;
300 if (Entries[index].
Type ==
nullptr) {
302 }
else if (type ==
nullptr) {
303 Entries[index].Type =
nullptr;
310 Entries[index].Type = entryType;
315 Entries[index].Type =
nullptr;
322 if (
auto vecTy = dyn_cast_or_null<llvm::VectorType>(type)) {
323 auto eltTy = vecTy->getElementType();
324 CharUnits eltSize = (end - begin) / vecTy->getNumElements();
326 for (
unsigned i = 0, e = vecTy->getNumElements(); i != e; ++i) {
327 addEntry(eltTy, begin, begin + eltSize);
330 assert(begin == end);
335 if (Entries[index].
Type && Entries[index].
Type->isVectorTy()) {
336 splitVectorEntry(index);
337 goto restartAfterSplit;
342 Entries[index].Type =
nullptr;
345 if (begin < Entries[index].
Begin) {
346 Entries[index].Begin = begin;
347 assert(index == 0 || begin >= Entries[index - 1].
End);
352 while (end > Entries[index].
End) {
353 assert(Entries[index].
Type ==
nullptr);
356 if (index == Entries.size() - 1 || end <= Entries[index + 1].Begin) {
357 Entries[index].End = end;
362 Entries[index].End = Entries[index + 1].Begin;
368 if (Entries[index].
Type ==
nullptr)
372 if (Entries[index].
Type->isVectorTy() &&
373 end < Entries[index].End) {
374 splitVectorEntry(index);
378 Entries[index].Type =
nullptr;
384 void SwiftAggLowering::splitVectorEntry(
unsigned index) {
385 auto vecTy = cast<llvm::VectorType>(Entries[index].Type);
388 auto eltTy = split.first;
390 auto numElts = split.second;
391 Entries.insert(Entries.begin() + index + 1, numElts - 1, StorageEntry());
394 for (
unsigned i = 0; i != numElts; ++i) {
395 Entries[index].Type = eltTy;
396 Entries[index].Begin = begin;
397 Entries[index].End = begin + eltSize;
419 if (Entries.empty()) {
430 bool hasOpaqueEntries = (Entries[0].Type ==
nullptr);
431 for (
size_t i = 1, e = Entries.size(); i != e; ++i) {
433 Entries[i].Begin, chunkSize)) {
434 Entries[i - 1].Type =
nullptr;
435 Entries[i].Type =
nullptr;
436 Entries[i - 1].End = Entries[i].Begin;
437 hasOpaqueEntries =
true;
439 }
else if (Entries[i].
Type ==
nullptr) {
440 hasOpaqueEntries =
true;
446 if (!hasOpaqueEntries) {
452 auto orig = std::move(Entries);
453 assert(Entries.empty());
455 for (
size_t i = 0, e = orig.size(); i != e; ++i) {
457 if (orig[i].
Type !=
nullptr) {
458 Entries.push_back(orig[i]);
465 auto begin = orig[i].Begin;
466 auto end = orig[i].End;
468 orig[i + 1].
Type ==
nullptr &&
469 end == orig[i + 1].Begin) {
470 end = orig[i + 1].End;
481 CharUnits chunkEnd = chunkBegin + chunkSize;
487 for (; ; unitSize *= 2) {
488 assert(unitSize <= chunkSize);
490 unitEnd = unitBegin + unitSize;
491 if (unitEnd >= localEnd)
break;
498 Entries.push_back({unitBegin, unitEnd, entryTy});
502 }
while (begin != end);
510 assert(Finished &&
"haven't yet finished lowering");
512 for (
auto &entry : Entries) {
513 callback(entry.Begin, entry.End, entry.Type);
517 std::pair<llvm::StructType*, llvm::Type*>
519 assert(Finished &&
"haven't yet finished lowering");
523 if (Entries.empty()) {
524 auto type = llvm::StructType::get(ctx);
525 return {
type, type };
530 bool hasPadding =
false;
532 for (
auto &entry : Entries) {
533 if (entry.Begin != lastEnd) {
534 auto paddingSize = entry.Begin - lastEnd;
535 assert(!paddingSize.isNegative());
537 auto padding = llvm::ArrayType::get(llvm::Type::getInt8Ty(ctx),
538 paddingSize.getQuantity());
539 elts.push_back(padding);
543 if (!packed && !entry.Begin.isMultipleOf(
548 elts.push_back(entry.Type);
551 assert(entry.End <= lastEnd);
556 auto coercionType = llvm::StructType::get(ctx, elts, packed);
561 for (
auto &entry : Entries) {
562 elts.push_back(entry.Type);
564 if (elts.size() == 1) {
565 unpaddedType = elts[0];
567 unpaddedType = llvm::StructType::get(ctx, elts,
false);
569 }
else if (Entries.size() == 1) {
570 unpaddedType = Entries[0].Type;
573 return { coercionType, unpaddedType };
577 assert(Finished &&
"haven't yet finished lowering");
580 if (Entries.empty())
return false;
582 CharUnits totalSize = Entries.back().End;
585 if (Entries.size() == 1) {
592 componentTys.reserve(Entries.size());
593 for (
auto &entry : Entries) {
594 componentTys.push_back(entry.Type);
612 size = 1ULL << (llvm::findLastSet(size, llvm::ZB_Undefined) + 1);
614 assert(size >= CGM.
getDataLayout().getABITypeAlignment(type));
619 llvm::IntegerType *intTy) {
620 auto size = intTy->getBitWidth();
639 llvm::VectorType *vectorTy) {
641 vectorTy->getNumElements());
646 assert(numElts > 1 &&
"illegal vector length");
651 std::pair<llvm::Type*, unsigned>
653 llvm::VectorType *vectorTy) {
654 auto numElts = vectorTy->getNumElements();
655 auto eltTy = vectorTy->getElementType();
660 return {llvm::VectorType::get(eltTy, numElts / 2), 2};
663 return {eltTy, numElts};
667 llvm::VectorType *origVectorTy,
671 components.push_back(origVectorTy);
676 auto numElts = origVectorTy->getNumElements();
677 auto eltTy = origVectorTy->getElementType();
678 assert(numElts != 1);
682 unsigned logCandidateNumElts = llvm::findLastSet(numElts, llvm::ZB_Undefined);
683 unsigned candidateNumElts = 1U << logCandidateNumElts;
684 assert(candidateNumElts <= numElts && candidateNumElts * 2 > numElts);
687 if (candidateNumElts == numElts) {
688 logCandidateNumElts--;
689 candidateNumElts >>= 1;
692 CharUnits eltSize = (origVectorSize / numElts);
693 CharUnits candidateSize = eltSize * candidateNumElts;
698 while (logCandidateNumElts > 0) {
699 assert(candidateNumElts == 1U << logCandidateNumElts);
700 assert(candidateNumElts <= numElts);
701 assert(candidateSize == eltSize * candidateNumElts);
705 logCandidateNumElts--;
706 candidateNumElts /= 2;
712 auto numVecs = numElts >> logCandidateNumElts;
713 components.append(numVecs, llvm::VectorType::get(eltTy, candidateNumElts));
714 numElts -= (numVecs << logCandidateNumElts);
716 if (numElts == 0)
return;
723 components.push_back(llvm::VectorType::get(eltTy, numElts));
729 logCandidateNumElts--;
730 candidateNumElts /= 2;
732 }
while (candidateNumElts > numElts);
736 components.append(numElts, eltTy);
749 for (
auto ctor : record->
ctors()) {
750 if (ctor->isCopyOrMoveConstructor() && !ctor->isDeleted() &&
762 if (lowering.
empty()) {
774 if (
auto recordType = dyn_cast<RecordType>(type)) {
775 auto record = recordType->getDecl();
778 if (
auto cxxRecord = dyn_cast<CXXRecordDecl>(record)) {
792 if (isa<ComplexType>(type)) {
797 if (isa<VectorType>(type)) {
811 if (type->isVoidType()) {
832 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.
static CharUnits getTypeAllocSize(CodeGenModule &CGM, llvm::Type *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
llvm::function_ref< void(CharUnits offset, CharUnits end, llvm::Type *type)> EnumerationCallback
ABIArgInfo - Helper class to encapsulate information about how a specific C type should be passed to ...
virtual bool isSwiftErrorInRegister() const =0
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)
bool isSwiftErrorLoweredInRegister(CodeGenModule &CGM)
Is swifterror lowered to a register by the target ABI.
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.
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)