@@ -53,6 +53,7 @@ enum class StructTypeInfoKind {
53
53
LoadableStructTypeInfo,
54
54
FixedStructTypeInfo,
55
55
LoadableClangRecordTypeInfo,
56
+ AddressOnlyClangRecordTypeInfo,
56
57
NonFixedStructTypeInfo,
57
58
ResilientStructTypeInfo
58
59
};
@@ -83,6 +84,12 @@ namespace {
83
84
// / A field-info implementation for fields of Clang types.
84
85
class ClangFieldInfo : public RecordField <ClangFieldInfo> {
85
86
public:
87
+ ClangFieldInfo (VarDecl *swiftField, const ElementLayout &layout,
88
+ const TypeInfo &typeInfo)
89
+ : RecordField(typeInfo), Field(swiftField) {
90
+ completeFrom (layout);
91
+ }
92
+
86
93
ClangFieldInfo (VarDecl *swiftField, const ElementLayout &layout,
87
94
unsigned explosionBegin, unsigned explosionEnd)
88
95
: RecordField(layout, explosionBegin, explosionEnd),
@@ -290,7 +297,7 @@ namespace {
290
297
}
291
298
}
292
299
};
293
-
300
+
294
301
// / A type implementation for loadable record types imported from Clang.
295
302
class LoadableClangRecordTypeInfo final :
296
303
public StructTypeInfoBase<LoadableClangRecordTypeInfo, LoadableTypeInfo,
@@ -339,6 +346,50 @@ namespace {
339
346
}
340
347
};
341
348
349
+ class AddressOnlyClangRecordTypeInfo final
350
+ : public StructTypeInfoBase<AddressOnlyClangRecordTypeInfo, FixedTypeInfo,
351
+ ClangFieldInfo> {
352
+ const clang::RecordDecl *ClangDecl;
353
+
354
+ public:
355
+ AddressOnlyClangRecordTypeInfo (ArrayRef<ClangFieldInfo> fields,
356
+ llvm::Type *storageType, Size size,
357
+ Alignment align,
358
+ const clang::RecordDecl *clangDecl)
359
+ : StructTypeInfoBase(StructTypeInfoKind::AddressOnlyClangRecordTypeInfo,
360
+ fields, storageType, size,
361
+ // We can't assume any spare bits in a C++ type
362
+ // with user-defined special member functions.
363
+ SpareBitVector (llvm::Optional<APInt>{
364
+ llvm::APInt (size.getValueInBits (), 0 )}),
365
+ align, IsPOD, IsNotBitwiseTakable, IsFixedSize),
366
+ ClangDecl(clangDecl) {
367
+ (void )ClangDecl;
368
+ }
369
+
370
+ TypeLayoutEntry *buildTypeLayoutEntry (IRGenModule &IGM,
371
+ SILType T) const override {
372
+ return IGM.typeLayoutCache .getOrCreateScalarEntry (*this , T);
373
+ }
374
+
375
+ void initializeFromParams (IRGenFunction &IGF, Explosion ¶ms,
376
+ Address addr, SILType T,
377
+ bool isOutlined) const override {
378
+ llvm_unreachable (" Address-only C++ types must be created by C++ special "
379
+ " member functions." );
380
+ }
381
+
382
+ llvm::NoneType getNonFixedOffsets (IRGenFunction &IGF) const { return None; }
383
+ llvm::NoneType getNonFixedOffsets (IRGenFunction &IGF, SILType T) const {
384
+ return None;
385
+ }
386
+ MemberAccessStrategy
387
+ getNonFixedFieldAccessStrategy (IRGenModule &IGM, SILType T,
388
+ const ClangFieldInfo &field) const {
389
+ llvm_unreachable (" non-fixed field in Clang type?" );
390
+ }
391
+ };
392
+
342
393
// / A type implementation for loadable struct types.
343
394
class LoadableStructTypeInfo final
344
395
: public StructTypeInfoBase<LoadableStructTypeInfo, LoadableTypeInfo> {
@@ -680,6 +731,10 @@ class ClangRecordLowering {
680
731
681
732
const TypeInfo *createTypeInfo (llvm::StructType *llvmType) {
682
733
llvmType->setBody (LLVMFields, /* packed*/ true );
734
+ if (SwiftType.getStructOrBoundGenericStruct ()->isCxxNonTrivial ()) {
735
+ return AddressOnlyClangRecordTypeInfo::create (
736
+ FieldInfos, llvmType, TotalStride, TotalAlignment, ClangDecl);
737
+ }
683
738
return LoadableClangRecordTypeInfo::create (FieldInfos, NextExplosionIndex,
684
739
llvmType, TotalStride,
685
740
std::move (SpareBits), TotalAlignment,
@@ -773,7 +828,7 @@ class ClangRecordLowering {
773
828
774
829
// If we have a Swift import of this type, use our lowered information.
775
830
if (swiftField) {
776
- auto &fieldTI = cast<LoadableTypeInfo >(IGM.getTypeInfo (
831
+ auto &fieldTI = cast<FixedTypeInfo >(IGM.getTypeInfo (
777
832
SwiftType.getFieldType (swiftField, IGM.getSILModule (),
778
833
IGM.getMaximalTypeExpansionContext ())));
779
834
addField (swiftField, offset, fieldTI);
@@ -812,7 +867,7 @@ class ClangRecordLowering {
812
867
813
868
// / Add storage for an (optional) Swift field at the given offset.
814
869
void addField (VarDecl *swiftField, Size offset,
815
- const LoadableTypeInfo &fieldType) {
870
+ const FixedTypeInfo &fieldType) {
816
871
assert (offset >= NextOffset && " adding fields out of order" );
817
872
818
873
// Add a padding field if required.
@@ -823,8 +878,11 @@ class ClangRecordLowering {
823
878
}
824
879
825
880
// / Add information to track a value field at the current offset.
826
- void addFieldInfo (VarDecl *swiftField, const LoadableTypeInfo &fieldType) {
827
- unsigned explosionSize = fieldType.getExplosionSize ();
881
+ void addFieldInfo (VarDecl *swiftField, const FixedTypeInfo &fieldType) {
882
+ bool isLoadableField = isa<LoadableTypeInfo>(fieldType);
883
+ unsigned explosionSize = 0 ;
884
+ if (isLoadableField)
885
+ explosionSize = cast<LoadableTypeInfo>(fieldType).getExplosionSize ();
828
886
unsigned explosionBegin = NextExplosionIndex;
829
887
NextExplosionIndex += explosionSize;
830
888
unsigned explosionEnd = NextExplosionIndex;
@@ -838,9 +896,12 @@ class ClangRecordLowering {
838
896
layout.completeFixed (fieldType.isPOD (ResilienceExpansion::Maximal),
839
897
NextOffset, LLVMFields.size ());
840
898
841
- FieldInfos.push_back (
842
- ClangFieldInfo (swiftField, layout, explosionBegin, explosionEnd));
843
-
899
+ if (isLoadableField)
900
+ FieldInfos.push_back (
901
+ ClangFieldInfo (swiftField, layout, explosionBegin, explosionEnd));
902
+ else
903
+ FieldInfos.push_back (ClangFieldInfo (swiftField, layout, fieldType));
904
+
844
905
if (!isEmpty) {
845
906
LLVMFields.push_back (fieldType.getStorageType ());
846
907
NextOffset += fieldType.getFixedSize ();
@@ -862,22 +923,26 @@ class ClangRecordLowering {
862
923
863
924
// / A convenient macro for delegating an operation to all of the
864
925
// / various struct implementations.
865
- #define FOR_STRUCT_IMPL (IGF, type, op, ...) do { \
866
- auto &structTI = IGF.getTypeInfo (type); \
867
- switch (getStructTypeInfoKind (structTI)) { \
868
- case StructTypeInfoKind::LoadableClangRecordTypeInfo: \
869
- return structTI.as <LoadableClangRecordTypeInfo>().op (IGF, __VA_ARGS__); \
870
- case StructTypeInfoKind::LoadableStructTypeInfo: \
871
- return structTI.as <LoadableStructTypeInfo>().op (IGF, __VA_ARGS__); \
872
- case StructTypeInfoKind::FixedStructTypeInfo: \
873
- return structTI.as <FixedStructTypeInfo>().op (IGF, __VA_ARGS__); \
874
- case StructTypeInfoKind::NonFixedStructTypeInfo: \
875
- return structTI.as <NonFixedStructTypeInfo>().op (IGF, __VA_ARGS__); \
876
- case StructTypeInfoKind::ResilientStructTypeInfo: \
877
- llvm_unreachable (" resilient structs are opaque" ); \
878
- } \
879
- llvm_unreachable (" bad struct type info kind!" ); \
880
- } while (0 )
926
+ #define FOR_STRUCT_IMPL (IGF, type, op, ...) \
927
+ do { \
928
+ auto &structTI = IGF.getTypeInfo (type); \
929
+ switch (getStructTypeInfoKind (structTI)) { \
930
+ case StructTypeInfoKind::LoadableClangRecordTypeInfo: \
931
+ return structTI.as <LoadableClangRecordTypeInfo>().op (IGF, __VA_ARGS__); \
932
+ case StructTypeInfoKind::AddressOnlyClangRecordTypeInfo: \
933
+ return structTI.as <AddressOnlyClangRecordTypeInfo>().op (IGF, \
934
+ __VA_ARGS__); \
935
+ case StructTypeInfoKind::LoadableStructTypeInfo: \
936
+ return structTI.as <LoadableStructTypeInfo>().op (IGF, __VA_ARGS__); \
937
+ case StructTypeInfoKind::FixedStructTypeInfo: \
938
+ return structTI.as <FixedStructTypeInfo>().op (IGF, __VA_ARGS__); \
939
+ case StructTypeInfoKind::NonFixedStructTypeInfo: \
940
+ return structTI.as <NonFixedStructTypeInfo>().op (IGF, __VA_ARGS__); \
941
+ case StructTypeInfoKind::ResilientStructTypeInfo: \
942
+ llvm_unreachable (" resilient structs are opaque" ); \
943
+ } \
944
+ llvm_unreachable (" bad struct type info kind!" ); \
945
+ } while (0 )
881
946
882
947
Address irgen::projectPhysicalStructMemberAddress(IRGenFunction &IGF,
883
948
Address base,
0 commit comments