|
16 | 16 |
|
17 | 17 | #include "GenExistential.h"
|
18 | 18 |
|
19 |
| -#include "TypeLayout.h" |
20 | 19 | #include "swift/AST/ASTContext.h"
|
21 | 20 | #include "swift/AST/Decl.h"
|
22 | 21 | #include "swift/AST/ExistentialLayout.h"
|
|
29 | 28 | #include "llvm/IR/DerivedTypes.h"
|
30 | 29 | #include "llvm/IR/Function.h"
|
31 | 30 | #include "llvm/IR/Module.h"
|
32 |
| -#include "llvm/Support/ErrorHandling.h" |
33 | 31 | #include "llvm/Support/raw_ostream.h"
|
34 | 32 |
|
35 | 33 | #include "BitPatternBuilder.h"
|
@@ -663,60 +661,52 @@ namespace {
|
663 | 661 | return Super::getFixedExtraInhabitantMask(IGM); \
|
664 | 662 | } \
|
665 | 663 | }
|
666 |
| -#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \ |
667 |
| - class AddressOnly##Name##ClassExistentialTypeInfo final : \ |
668 |
| - public AddressOnlyClassExistentialTypeInfoBase< \ |
669 |
| - AddressOnly##Name##ClassExistentialTypeInfo, \ |
670 |
| - FixedTypeInfo> { \ |
671 |
| - bool IsOptional; \ |
672 |
| - public: \ |
673 |
| - AddressOnly##Name##ClassExistentialTypeInfo( \ |
674 |
| - ArrayRef<const ProtocolDecl *> protocols, \ |
675 |
| - llvm::Type *ty, \ |
676 |
| - SpareBitVector &&spareBits, \ |
677 |
| - Size size, Alignment align, \ |
678 |
| - ReferenceCounting refcounting, \ |
679 |
| - bool isOptional) \ |
680 |
| - : AddressOnlyClassExistentialTypeInfoBase(protocols, refcounting, \ |
681 |
| - ty, size, std::move(spareBits), \ |
682 |
| - align, IsNotPOD, \ |
683 |
| - IsNotBitwiseTakable, \ |
684 |
| - IsFixedSize), \ |
685 |
| - IsOptional(isOptional) {} \ |
686 |
| - TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM, \ |
687 |
| - SILType T) const override { \ |
688 |
| - ScalarKind kind; \ |
689 |
| - switch (Refcounting) { \ |
690 |
| - case ReferenceCounting::Native: kind = ScalarKind::NativeStrongReference; break; \ |
691 |
| - case ReferenceCounting::ObjC: kind = ScalarKind::ObjCReference; break; \ |
692 |
| - case ReferenceCounting::Block: kind = ScalarKind::BlockReference; break; \ |
693 |
| - case ReferenceCounting::Unknown: kind = ScalarKind::UnknownReference; break; \ |
694 |
| - case ReferenceCounting::Bridge: kind = ScalarKind::BridgeReference; break; \ |
695 |
| - case ReferenceCounting::Error: kind = ScalarKind::ErrorReference; break; \ |
696 |
| - } \ |
697 |
| - return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T, kind); \ |
698 |
| - } \ |
699 |
| - void emitValueAssignWithCopy(IRGenFunction &IGF, \ |
700 |
| - Address dest, Address src) const { \ |
701 |
| - IGF.emit##Name##CopyAssign(dest, src, Refcounting); \ |
702 |
| - } \ |
703 |
| - void emitValueInitializeWithCopy(IRGenFunction &IGF, \ |
704 |
| - Address dest, Address src) const { \ |
705 |
| - IGF.emit##Name##CopyInit(dest, src, Refcounting); \ |
706 |
| - } \ |
707 |
| - void emitValueAssignWithTake(IRGenFunction &IGF, \ |
708 |
| - Address dest, Address src) const { \ |
709 |
| - IGF.emit##Name##TakeAssign(dest, src, Refcounting); \ |
710 |
| - } \ |
711 |
| - void emitValueInitializeWithTake(IRGenFunction &IGF, \ |
712 |
| - Address dest, Address src) const { \ |
713 |
| - IGF.emit##Name##TakeInit(dest, src, Refcounting); \ |
714 |
| - } \ |
715 |
| - void emitValueDestroy(IRGenFunction &IGF, Address addr) const { \ |
716 |
| - IGF.emit##Name##Destroy(addr, Refcounting); \ |
717 |
| - } \ |
718 |
| - StringRef getStructNameSuffix() const { return "." #name "ref"; } \ |
719 |
| - REF_STORAGE_HELPER(Name, FixedTypeInfo) \ |
| 664 | +#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, name, ...) \ |
| 665 | + class AddressOnly##Name##ClassExistentialTypeInfo final \ |
| 666 | + : public AddressOnlyClassExistentialTypeInfoBase< \ |
| 667 | + AddressOnly##Name##ClassExistentialTypeInfo, FixedTypeInfo> { \ |
| 668 | + bool IsOptional; \ |
| 669 | + \ |
| 670 | + public: \ |
| 671 | + AddressOnly##Name##ClassExistentialTypeInfo( \ |
| 672 | + ArrayRef<const ProtocolDecl *> protocols, llvm::Type *ty, \ |
| 673 | + SpareBitVector &&spareBits, Size size, Alignment align, \ |
| 674 | + ReferenceCounting refcounting, bool isOptional) \ |
| 675 | + : AddressOnlyClassExistentialTypeInfoBase( \ |
| 676 | + protocols, refcounting, ty, size, std::move(spareBits), align, \ |
| 677 | + IsNotPOD, IsNotBitwiseTakable, IsFixedSize), \ |
| 678 | + IsOptional(isOptional) {} \ |
| 679 | + TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM, \ |
| 680 | + SILType T) const override { \ |
| 681 | + if (Refcounting == ReferenceCounting::Native) { \ |
| 682 | + return IGM.typeLayoutCache.getOrCreateScalarEntry( \ |
| 683 | + *this, T, ScalarKind::Native##Name##Reference); \ |
| 684 | + } else { \ |
| 685 | + return IGM.typeLayoutCache.getOrCreateScalarEntry( \ |
| 686 | + *this, T, ScalarKind::Unknown##Name##Reference); \ |
| 687 | + } \ |
| 688 | + } \ |
| 689 | + void emitValueAssignWithCopy(IRGenFunction &IGF, Address dest, \ |
| 690 | + Address src) const { \ |
| 691 | + IGF.emit##Name##CopyAssign(dest, src, Refcounting); \ |
| 692 | + } \ |
| 693 | + void emitValueInitializeWithCopy(IRGenFunction &IGF, Address dest, \ |
| 694 | + Address src) const { \ |
| 695 | + IGF.emit##Name##CopyInit(dest, src, Refcounting); \ |
| 696 | + } \ |
| 697 | + void emitValueAssignWithTake(IRGenFunction &IGF, Address dest, \ |
| 698 | + Address src) const { \ |
| 699 | + IGF.emit##Name##TakeAssign(dest, src, Refcounting); \ |
| 700 | + } \ |
| 701 | + void emitValueInitializeWithTake(IRGenFunction &IGF, Address dest, \ |
| 702 | + Address src) const { \ |
| 703 | + IGF.emit##Name##TakeInit(dest, src, Refcounting); \ |
| 704 | + } \ |
| 705 | + void emitValueDestroy(IRGenFunction &IGF, Address addr) const { \ |
| 706 | + IGF.emit##Name##Destroy(addr, Refcounting); \ |
| 707 | + } \ |
| 708 | + StringRef getStructNameSuffix() const { return "." #name "ref"; } \ |
| 709 | + REF_STORAGE_HELPER(Name, FixedTypeInfo) \ |
720 | 710 | };
|
721 | 711 | #define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
|
722 | 712 | class Loadable##Name##ClassExistentialTypeInfo final \
|
@@ -1016,21 +1006,31 @@ class ClassExistentialTypeInfo final
|
1016 | 1006 |
|
1017 | 1007 | TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
|
1018 | 1008 | SILType T) const override {
|
1019 |
| - ScalarKind kind; |
1020 |
| - switch (Refcounting) { |
1021 |
| - case ReferenceCounting::Native: |
1022 |
| - kind = ScalarKind::NativeStrongReference; |
1023 |
| - break; |
1024 |
| - case ReferenceCounting::ObjC: |
1025 |
| - kind = ScalarKind::ObjCReference; |
1026 |
| - break; |
1027 |
| - case ReferenceCounting::Unknown: |
1028 |
| - kind = ScalarKind::UnknownReference; |
1029 |
| - break; |
1030 |
| - default: |
1031 |
| - llvm_unreachable("Unsupported refcounting style"); |
| 1009 | + // We can't create an objc typeinfo by itself, so don't destructure if we |
| 1010 | + // have one |
| 1011 | + if (Refcounting == ReferenceCounting::ObjC) { |
| 1012 | + return IGM.typeLayoutCache.getOrCreateTypeInfoBasedEntry(*this, T); |
1032 | 1013 | }
|
1033 |
| - return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T, kind); |
| 1014 | + |
| 1015 | + /// The storage type of a class existential is a struct containing |
| 1016 | + /// a refcounted pointer to the class instance value followed by |
| 1017 | + /// witness table pointers for each conformed-to protocol. |
| 1018 | + std::vector<TypeLayoutEntry *> alignedGroup; |
| 1019 | + const TypeInfo &typeinfo = Refcounting == ReferenceCounting::Native |
| 1020 | + ? IGM.getNativeObjectTypeInfo() |
| 1021 | + : IGM.getUnknownObjectTypeInfo(); |
| 1022 | + |
| 1023 | + alignedGroup.push_back(IGM.typeLayoutCache.getOrCreateScalarEntry( |
| 1024 | + typeinfo, T, refcountingToScalarKind(Refcounting))); |
| 1025 | + for (unsigned i = 0; i < getNumStoredProtocols(); i++) { |
| 1026 | + alignedGroup.push_back(IGM.typeLayoutCache.getOrCreateScalarEntry( |
| 1027 | + IGM.getWitnessTablePtrTypeInfo(), |
| 1028 | + SILType::getBuiltinIntegerType(IGM.getPointerSize().getValue(), |
| 1029 | + IGM.Context), |
| 1030 | + ScalarKind::POD)); |
| 1031 | + } |
| 1032 | + |
| 1033 | + return IGM.typeLayoutCache.getOrCreateAlignedGroupEntry(alignedGroup, 0); |
1034 | 1034 | }
|
1035 | 1035 |
|
1036 | 1036 | /// Given an explosion with multiple pointer elements in them, pack them
|
|
0 commit comments