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);
80 for (uint64_t i = 0, e =
arrayType->getSize().getZExtValue(); i != e; ++i) {
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);
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);
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)) {
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) {
const llvm::DataLayout & getDataLayout() const
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
A (possibly-)qualified type.
CodeGenTypes & getTypes()
llvm::LLVMContext & getLLVMContext()
static ABIArgInfo classifyType(CodeGenModule &CGM, CanQualType type, bool forReturn)
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
The base class of the type hierarchy.
const ABIInfo & getABIInfo() const
getABIInfo() - Returns ABI info helper for the target.
bool isZero() const
isZero - Test whether the quantity equals zero.
const TargetInfo & getTargetInfo() const
virtual bool shouldPassIndirectlyForSwift(CharUnits totalSize, ArrayRef< llvm::Type *> types, bool asReturnValue) const =0
const T * getAs() const
Member-template getAs<specific type>'.
bool hasOwnVFPtr() const
hasOwnVFPtr - Does this class provide its own virtual-function table pointer, rather than inheriting ...
std::pair< llvm::Type *, unsigned > splitLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize, llvm::VectorType *vectorTy)
Minimally split a legal vector type.
static ABIArgInfo getIgnore()
unsigned arg_size() const
const AstTypeMatcher< RecordType > recordType
Matches record types (e.g.
RecordDecl - Represents a struct/union/class.
uint64_t getPointerWidth(unsigned AddrSpace) const
Return the width of pointers on this target, for the specified address space.
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)
field_range fields() const
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.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
const AstTypeMatcher< ComplexType > complexType
Matches C99 complex types.
static ABIArgInfo getDirect(llvm::Type *T=nullptr, unsigned Offset=0, llvm::Type *Padding=nullptr, bool CanBeFlattened=true)
bool isBitField() const
Determines whether this field is a bitfield.
CharUnits - This is an opaque type for sizes expressed in character units.
const_arg_iterator arg_begin() 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)
unsigned getBitWidthValue(const ASTContext &Ctx) const
static ABIArgInfo getExpand()
static bool areBytesInSameUnit(CharUnits first, CharUnits second, CharUnits chunkSize)
CanQualType getReturnType() const
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.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
void addOpaqueData(CharUnits begin, CharUnits end)
std::pair< llvm::StructType *, llvm::Type * > getCoerceAndExpandTypes() const
Return the types for a coerce-and-expand operation.
bool isSwiftErrorLoweredInRegister(CodeGenModule &CGM)
Is swifterror lowered to a register by the target ABI.
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
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.
const AstTypeMatcher< ArrayType > arrayType
Matches all kinds of arrays.
bool hasNonTrivialDestructor() const
Determine whether this class has a non-trivial destructor (C++ [class.dtor]p3)
CharUnits getVBPtrOffset() const
getVBPtrOffset - Get the offset for virtual base table pointer.
ASTContext & getContext() const
The l-value was considered opaque, so the alignment was determined from a type.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
bool empty() const
Does this lowering require passing any data?
void addTypedData(QualType type, CharUnits begin)
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
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?
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.
CGFunctionInfo - Class to encapsulate the information about a function definition.
This class organizes the cross-function state that is used while generating LLVM code.
Dataflow Directional Tag Classes.
void enumerateComponents(EnumerationCallback callback) const
Enumerate the expanded components of this type.
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.
A pointer to member type per C++ 8.3.3 - Pointers to members.
virtual bool isLegalVectorTypeForSwift(CharUnits totalSize, llvm::Type *eltTy, unsigned elts) const
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.
llvm::PointerType * Int8PtrTy
virtual bool hasInt128Type() const
Determine whether the __int128 type is supported on this target.
ABIArgInfo & getReturnInfo()
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
bool isMultipleOf(CharUnits N) const
Test whether this is a multiple of the other value.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
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.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CharUnits getMaximumVoluntaryIntegerSize(CodeGenModule &CGM)
Return the maximum voluntary integer size for the current target.
bool hasOwnVBPtr() const
hasOwnVBPtr - Does this class provide its own virtual-base table pointer, rather than inheriting one ...
static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal=true, bool Realign=false, llvm::Type *Padding=nullptr)
bool shouldPassIndirectly(bool asReturnValue) const
According to the target Swift ABI, should a value with this lowering be passed indirectly?