Skip to content

Commit df17f7b

Browse files
committed
Implement dependent layouts for raw types
Update raw_layout.swift Allow for concrete specializations of raw layout Make test platform agnostic
1 parent 984b4f2 commit df17f7b

File tree

16 files changed

+298
-30
lines changed

16 files changed

+298
-30
lines changed

include/swift/Runtime/Metadata.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,14 @@ SWIFT_RUNTIME_STDLIB_SPI
10381038
void _swift_registerConcurrencyStandardTypeDescriptors(
10391039
const ConcurrencyStandardTypeDescriptors *descriptors);
10401040

1041+
/// Initialize the value witness table for a struct using the provided like type
1042+
/// as the basis for the layout.
1043+
SWIFT_RUNTIME_EXPORT
1044+
void swift_initRawStructMetadata(StructMetadata *self,
1045+
StructLayoutFlags flags,
1046+
const TypeLayout *likeType,
1047+
size_t count);
1048+
10411049
#pragma clang diagnostic pop
10421050

10431051
} // end namespace swift

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2486,6 +2486,18 @@ FUNCTION(GenericInstantiateLayoutString,
24862486
ATTRS(NoUnwind),
24872487
EFFECT(MetaData))
24882488

2489+
// void swift_initRawStructMetadata(Metadata *structType,
2490+
// StructLayoutFlags flags,
2491+
// const TypeLayout *likeType,
2492+
// size_t count);
2493+
FUNCTION(InitRawStructMetadata,
2494+
swift_initRawStructMetadata,
2495+
C_CC, AlwaysAvailable,
2496+
RETURNS(VoidTy),
2497+
ARGS(TypeMetadataPtrTy, SizeTy, Int8PtrPtrTy->getPointerTo(0), SizeTy),
2498+
ATTRS(NoUnwind),
2499+
EFFECT(MetaData))
2500+
24892501
#undef RETURNS
24902502
#undef ARGS
24912503
#undef ATTRS

lib/IRGen/GenCall.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,8 @@ AsyncContextLayout::AsyncContextLayout(
134134
IRGenModule &IGM, LayoutStrategy strategy, ArrayRef<SILType> fieldTypes,
135135
ArrayRef<const TypeInfo *> fieldTypeInfos, CanSILFunctionType originalType,
136136
CanSILFunctionType substitutedType, SubstitutionMap substitutionMap)
137-
: StructLayout(IGM, /*decl=*/nullptr, LayoutKind::NonHeapObject, strategy,
138-
fieldTypeInfos, /*typeToFill*/ nullptr),
137+
: StructLayout(IGM, /*type=*/ llvm::None, LayoutKind::NonHeapObject,
138+
strategy, fieldTypeInfos, /*typeToFill*/ nullptr),
139139
originalType(originalType), substitutedType(substitutedType),
140140
substitutionMap(substitutionMap) {
141141
assert(fieldTypeInfos.size() == fieldTypes.size() &&

lib/IRGen/GenDiffFunc.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ class DifferentiableFuncTypeBuilder
211211
}
212212

213213
StructLayout performLayout(ArrayRef<const TypeInfo *> fieldTypes) {
214-
return StructLayout(IGM, /*decl=*/nullptr, LayoutKind::NonHeapObject,
214+
return StructLayout(IGM, /*type=*/ llvm::None, LayoutKind::NonHeapObject,
215215
LayoutStrategy::Universal, fieldTypes);
216216
}
217217
};
@@ -383,7 +383,7 @@ class LinearFuncTypeBuilder
383383
}
384384

385385
StructLayout performLayout(ArrayRef<const TypeInfo *> fieldTypes) {
386-
return StructLayout(IGM, /*decl=*/nullptr, LayoutKind::NonHeapObject,
386+
return StructLayout(IGM, /*type=*/ llvm::None, LayoutKind::NonHeapObject,
387387
LayoutStrategy::Universal, fieldTypes);
388388
}
389389
};

lib/IRGen/GenHeap.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ HeapLayout::HeapLayout(IRGenModule &IGM, LayoutStrategy strategy,
274274
ArrayRef<const TypeInfo *> fieldTypeInfos,
275275
llvm::StructType *typeToFill,
276276
NecessaryBindings &&bindings, unsigned bindingsIndex)
277-
: StructLayout(IGM, /*decl=*/nullptr, LayoutKind::HeapObject, strategy,
277+
: StructLayout(IGM, /*type=*/ llvm::None, LayoutKind::HeapObject, strategy,
278278
fieldTypeInfos, typeToFill),
279279
ElementTypes(fieldTypes.begin(), fieldTypes.end()),
280280
Bindings(std::move(bindings)), BindingsIndex(bindingsIndex) {

lib/IRGen/GenMeta.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2983,6 +2983,20 @@ static void emitInitializeFieldOffsetVectorWithLayoutString(
29832983
IGM.getPointerSize() * numFields);
29842984
}
29852985

2986+
static void emitInitializeRawLayout(IRGenFunction &IGF, SILType likeType,
2987+
Size count, SILType T,
2988+
llvm::Value *metadata,
2989+
MetadataDependencyCollector *collector) {
2990+
auto &IGM = IGF.IGM;
2991+
auto likeTypeLayout = emitTypeLayoutRef(IGF, likeType, collector);
2992+
StructLayoutFlags flags = StructLayoutFlags::Swift5Algorithm;
2993+
2994+
// Call swift_initRawStructMetadata().
2995+
IGF.Builder.CreateCall(IGM.getInitRawStructMetadataFunctionPointer(),
2996+
{metadata, IGM.getSize(Size(uintptr_t(flags))),
2997+
likeTypeLayout, IGM.getSize(count)});
2998+
}
2999+
29863000
static void emitInitializeValueMetadata(IRGenFunction &IGF,
29873001
NominalTypeDecl *nominalDecl,
29883002
llvm::Value *metadata,
@@ -2996,10 +3010,34 @@ static void emitInitializeValueMetadata(IRGenFunction &IGF,
29963010
IGM.getOptions().EnableLayoutStringValueWitnesses &&
29973011
IGM.getOptions().EnableLayoutStringValueWitnessesInstantiation;
29983012

2999-
if (isa<StructDecl>(nominalDecl)) {
3013+
if (auto sd = dyn_cast<StructDecl>(nominalDecl)) {
30003014
auto &fixedTI = IGM.getTypeInfo(loweredTy);
30013015
if (isa<FixedTypeInfo>(fixedTI)) return;
30023016

3017+
// Use a different runtime function to initialize the value witness table
3018+
// if the struct has a raw layout. The existing swift_initStructMetadata
3019+
// is the wrong thing for these types.
3020+
if (auto rawLayout = nominalDecl->getAttrs().getAttribute<RawLayoutAttr>()) {
3021+
SILType loweredLikeType;
3022+
Size count;
3023+
3024+
if (auto likeType = rawLayout->getResolvedScalarLikeType(sd)) {
3025+
loweredLikeType = IGM.getLoweredType(AbstractionPattern::getOpaque(),
3026+
*likeType);
3027+
count = Size(-1);
3028+
} else if (auto likeArray = rawLayout->getResolvedArrayLikeTypeAndCount(sd)) {
3029+
auto likeType = likeArray->first;
3030+
loweredLikeType = IGM.getLoweredType(AbstractionPattern::getOpaque(),
3031+
likeType);
3032+
3033+
count = Size(likeArray->second);
3034+
}
3035+
3036+
emitInitializeRawLayout(IGF, loweredLikeType, count, loweredTy, metadata,
3037+
collector);
3038+
return;
3039+
}
3040+
30033041
if (useLayoutStrings) {
30043042
emitInitializeFieldOffsetVectorWithLayoutString(IGF, loweredTy, metadata,
30053043
isVWTMutable, collector);

lib/IRGen/GenRecord.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -863,7 +863,6 @@ class RecordTypeBuilder {
863863
fields.reserve(astFields.size());
864864
fieldTypesForLayout.reserve(astFields.size());
865865

866-
bool loadable = true;
867866
auto fieldsABIAccessible = FieldsAreABIAccessible;
868867

869868
unsigned explosionSize = 0;
@@ -880,7 +879,6 @@ class RecordTypeBuilder {
880879

881880
auto loadableFieldTI = dyn_cast<LoadableTypeInfo>(&fieldTI);
882881
if (!loadableFieldTI) {
883-
loadable = false;
884882
continue;
885883
}
886884

@@ -902,7 +900,7 @@ class RecordTypeBuilder {
902900
}
903901

904902
// Create the type info.
905-
if (loadable) {
903+
if (layout.isLoadable()) {
906904
assert(layout.isFixedLayout());
907905
assert(fieldsABIAccessible);
908906
return asImpl()->createLoadable(fields, std::move(layout), explosionSize);

lib/IRGen/GenStruct.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,35 @@ namespace {
10881088
fields.push_back(
10891089
field.getTypeInfo().buildTypeLayoutEntry(IGM, fieldTy, useStructLayouts));
10901090
}
1091+
1092+
auto decl = T.getASTType()->getStructOrBoundGenericStruct();
1093+
auto rawLayout = decl->getAttrs().getAttribute<RawLayoutAttr>();
1094+
1095+
// If we have a raw layout struct who is non-fixed size, it means the
1096+
// layout of the struct is dependent on the archetype of the thing it's
1097+
// like.
1098+
if (rawLayout) {
1099+
SILType loweredLikeType;
1100+
1101+
if (auto likeType = rawLayout->getResolvedScalarLikeType(decl)) {
1102+
loweredLikeType = IGM.getLoweredType(*likeType);
1103+
} else if (auto likeArray = rawLayout->getResolvedArrayLikeTypeAndCount(decl)) {
1104+
loweredLikeType = IGM.getLoweredType(likeArray->first);
1105+
}
1106+
1107+
// The given struct type T that we're building may be in a generic
1108+
// environment that is different than that which was built our
1109+
// resolved rawLayout like type. Map our like type into the given
1110+
// environment.
1111+
auto subs = T.getASTType()->getContextSubstitutionMap(
1112+
IGM.getSwiftModule(), decl);
1113+
1114+
loweredLikeType = loweredLikeType.subst(IGM.getSILModule(), subs);
1115+
1116+
return IGM.getTypeInfo(loweredLikeType).buildTypeLayoutEntry(IGM,
1117+
loweredLikeType, useStructLayouts);
1118+
}
1119+
10911120
assert(!fields.empty() &&
10921121
"Empty structs should not be NonFixedStructTypeInfo");
10931122

@@ -1244,8 +1273,7 @@ namespace {
12441273
}
12451274

12461275
StructLayout performLayout(ArrayRef<const TypeInfo *> fieldTypes) {
1247-
return StructLayout(IGM, TheStruct->getAnyNominal(),
1248-
LayoutKind::NonHeapObject,
1276+
return StructLayout(IGM, TheStruct, LayoutKind::NonHeapObject,
12491277
LayoutStrategy::Optimal, fieldTypes, StructTy);
12501278
}
12511279
};

lib/IRGen/GenTuple.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ namespace {
512512
}
513513

514514
StructLayout performLayout(ArrayRef<const TypeInfo *> fieldTypes) {
515-
return StructLayout(IGM, /*decl=*/nullptr, LayoutKind::NonHeapObject,
515+
return StructLayout(IGM, /*type=*/ llvm::None, LayoutKind::NonHeapObject,
516516
LayoutStrategy::Universal, fieldTypes);
517517
}
518518
};

lib/IRGen/GenType.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2437,6 +2437,17 @@ namespace {
24372437
if (IGM.isResilient(decl, ResilienceExpansion::Maximal))
24382438
return true;
24392439

2440+
auto rawLayout = decl->getAttrs().getAttribute<RawLayoutAttr>();
2441+
2442+
// If our struct has a raw layout, it may be dependent on the like type.
2443+
if (rawLayout) {
2444+
if (auto likeType = rawLayout->getResolvedScalarLikeType(decl)) {
2445+
return visit((*likeType)->getCanonicalType());
2446+
} else if (auto likeArray = rawLayout->getResolvedArrayLikeTypeAndCount(decl)) {
2447+
return visit(likeArray->first->getCanonicalType());
2448+
}
2449+
}
2450+
24402451
for (auto field : decl->getStoredProperties()) {
24412452
if (visit(field->getInterfaceType()->getCanonicalType()))
24422453
return true;

0 commit comments

Comments
 (0)