Skip to content

Commit 2f8c1a4

Browse files
authored
[IRGen] Make pointers to accessor functions in layout strings relative (#64155)
* [IRGen] Make pointers to accessor functions in layout strings relative rdar://106319336 Pointers embedded in static layout strings should always be relative, so layout strings can reside in read-only memory. * Properly handle reference storage ownership * Pass layout tag and metadata / type layout ppointers separately * Layout string instantiation fully working * Fix cases where hasLayoutString flag was not set when it should have * Update include/swift/ABI/Metadata.h
1 parent e8be44d commit 2f8c1a4

File tree

13 files changed

+525
-522
lines changed

13 files changed

+525
-522
lines changed

include/swift/Runtime/Metadata.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,8 @@ SWIFT_RUNTIME_EXPORT
648648
void swift_initStructMetadataWithLayoutString(StructMetadata *self,
649649
StructLayoutFlags flags,
650650
size_t numFields,
651-
const Metadata *const *fieldTypes,
651+
const uint8_t *const *fieldTypes,
652+
const uint8_t *fieldTags,
652653
uint32_t *fieldOffsets);
653654

654655
/// Allocate the metadata for a class and copy fields from the given pattern.

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1260,7 +1260,8 @@ FUNCTION(InitStructMetadataWithLayoutString,
12601260
swift_initStructMetadataWithLayoutString, C_CC, AlwaysAvailable,
12611261
RETURNS(VoidTy),
12621262
ARGS(TypeMetadataPtrTy, SizeTy, SizeTy,
1263-
TypeMetadataPtrPtrTy,
1263+
Int8PtrPtrTy->getPointerTo(0),
1264+
Int8PtrTy,
12641265
Int32Ty->getPointerTo()),
12651266
ATTRS(NoUnwind),
12661267
EFFECT(MetaData))

lib/IRGen/GenExistential.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,7 @@ namespace {
760760
case ReferenceCounting::Bridge: kind = ScalarKind::BridgeReference; break; \
761761
case ReferenceCounting::Error: kind = ScalarKind::ErrorReference; break; \
762762
case ReferenceCounting::None: kind = ScalarKind::TriviallyDestroyable; break; \
763-
case ReferenceCounting::Custom: kind = ScalarKind::UnknownReference; break; \
763+
case ReferenceCounting::Custom: kind = ScalarKind::CustomReference; break; \
764764
} \
765765
return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T, kind); \
766766
} \

lib/IRGen/GenMeta.cpp

Lines changed: 66 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2585,12 +2585,31 @@ void irgen::emitLazyTypeContextDescriptor(IRGenModule &IGM,
25852585
RequireMetadata_t requireMetadata) {
25862586
eraseExistingTypeContextDescriptor(IGM, type);
25872587

2588+
bool hasLayoutString = false;
2589+
auto lowered = getLoweredTypeInPrimaryContext(
2590+
IGM, type->getDeclaredType()->getCanonicalType());
2591+
auto &ti = IGM.getTypeInfo(lowered);
2592+
auto *typeLayoutEntry =
2593+
ti.buildTypeLayoutEntry(IGM, lowered, /*useStructLayouts*/ true);
2594+
if (IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnesses)) {
2595+
2596+
auto genericSig =
2597+
lowered.getNominalOrBoundGenericNominal()->getGenericSignature();
2598+
hasLayoutString = !!typeLayoutEntry->layoutString(IGM, genericSig);
2599+
}
2600+
25882601
if (auto sd = dyn_cast<StructDecl>(type)) {
2602+
if (IGM.Context.LangOpts.hasFeature(Feature::LayoutStringValueWitnessesInstantiation)) {
2603+
hasLayoutString |= requiresForeignTypeMetadata(type) ||
2604+
needsSingletonMetadataInitialization(IGM, type) ||
2605+
(type->isGenericContext() && !isa<FixedTypeInfo>(ti));
2606+
}
2607+
25892608
StructContextDescriptorBuilder(IGM, sd, requireMetadata,
2590-
/*hasLayoutString*/ false).emit();
2609+
hasLayoutString).emit();
25912610
} else if (auto ed = dyn_cast<EnumDecl>(type)) {
25922611
EnumContextDescriptorBuilder(IGM, ed, requireMetadata,
2593-
/*hasLayoutString*/ false)
2612+
hasLayoutString)
25942613
.emit();
25952614
} else if (auto cd = dyn_cast<ClassDecl>(type)) {
25962615
ClassContextDescriptorBuilder(IGM, cd, requireMetadata).emit();
@@ -2873,8 +2892,8 @@ static void emitInitializeFieldOffsetVector(IRGenFunction &IGF,
28732892
}
28742893

28752894
static void emitInitializeFieldOffsetVectorWithLayoutString(
2876-
IRGenFunction &IGF, SILType T, llvm::Value *metadata, bool isVWTMutable,
2877-
MetadataDependencyCollector *collector) {
2895+
IRGenFunction &IGF, SILType T, llvm::Value *metadata,
2896+
bool isVWTMutable, MetadataDependencyCollector *collector) {
28782897
auto &IGM = IGF.IGM;
28792898
assert(IGM.Context.LangOpts.hasFeature(
28802899
Feature::LayoutStringValueWitnessesInstantiation));
@@ -2892,38 +2911,68 @@ static void emitInitializeFieldOffsetVectorWithLayoutString(
28922911

28932912
// Fill out an array with the field type metadata records.
28942913
Address fieldsMetadata =
2895-
IGF.createAlloca(llvm::ArrayType::get(IGM.TypeMetadataPtrTy, numFields),
2914+
IGF.createAlloca(llvm::ArrayType::get(IGM.Int8PtrPtrTy, numFields),
28962915
IGM.getPointerAlignment(), "fieldsMetadata");
28972916
IGF.Builder.CreateLifetimeStart(fieldsMetadata,
28982917
IGM.getPointerSize() * numFields);
28992918
fieldsMetadata = IGF.Builder.CreateStructGEP(fieldsMetadata, 0, Size(0));
29002919

2920+
Address fieldTags =
2921+
IGF.createAlloca(llvm::ArrayType::get(IGM.Int8Ty, numFields),
2922+
Alignment(1), "fieldTags");
2923+
IGF.Builder.CreateLifetimeStart(fieldTags, Size(numFields));
2924+
fieldTags = IGF.Builder.CreateStructGEP(fieldTags, 0, Size(0));
2925+
29012926
unsigned index = 0;
29022927
forEachField(IGM, target, [&](Field field) {
29032928
assert(field.isConcrete() &&
29042929
"initializing offset vector for type with missing member?");
29052930
SILType propTy = field.getType(IGM, T);
29062931
llvm::Value *fieldMetatype;
2932+
llvm::Value *fieldTag;
29072933
if (auto ownership = propTy.getReferenceStorageOwnership()) {
2934+
auto &ti = IGF.getTypeInfo(propTy.getObjectType());
2935+
auto *fixedTI = dyn_cast<FixedTypeInfo>(&ti);
2936+
assert(fixedTI && "Reference should have fixed layout");
2937+
auto fixedSize = fixedTI->getFixedSize();
2938+
fieldMetatype = emitTypeLayoutRef(IGF, propTy, collector);
29082939
switch (*ownership) {
2940+
case ReferenceOwnership::Unowned:
2941+
fieldTag = llvm::Constant::getIntegerValue(
2942+
IGM.Int8Ty, APInt(IGM.Int8Ty->getBitWidth(),
2943+
fixedSize == IGM.getPointerSize() ? 0x1 : 0x2));
2944+
break;
29092945
case ReferenceOwnership::Weak:
2910-
fieldMetatype = llvm::Constant::getIntegerValue(
2911-
IGM.TypeMetadataPtrTy, APInt(IGM.IntPtrTy->getBitWidth(), 0x7));
2946+
fieldTag = llvm::Constant::getIntegerValue(
2947+
IGM.Int8Ty, APInt(IGM.Int8Ty->getBitWidth(),
2948+
fixedSize == IGM.getPointerSize() ? 0x3 : 0x4));
29122949
break;
2913-
case ReferenceOwnership::Strong:
2914-
case ReferenceOwnership::Unowned:
29152950
case ReferenceOwnership::Unmanaged:
2916-
llvm_unreachable("Unmanaged reference should have been lowered");
2951+
fieldTag = llvm::Constant::getIntegerValue(
2952+
IGM.Int8Ty, APInt(IGM.Int8Ty->getBitWidth(),
2953+
fixedSize == IGM.getPointerSize() ? 0x5 : 0x6));
2954+
break;
2955+
case ReferenceOwnership::Strong:
2956+
llvm_unreachable("Strong reference should have been lowered");
2957+
break;
29172958
}
29182959
} else {
2960+
fieldTag = llvm::Constant::getIntegerValue(
2961+
IGM.Int8Ty, APInt(IGM.Int8Ty->getBitWidth(), 0x0));
29192962
auto request = DynamicMetadataRequest::getNonBlocking(
29202963
MetadataState::LayoutComplete, collector);
29212964
fieldMetatype = IGF.emitTypeMetadataRefForLayout(propTy, request);
2965+
fieldMetatype = IGF.Builder.CreateBitCast(fieldMetatype, IGM.Int8PtrPtrTy);
29222966
}
29232967

2968+
Address fieldTagAddr = IGF.Builder.CreateConstArrayGEP(
2969+
fieldTags, index, Size::forBits(IGM.Int8Ty->getBitWidth()));
2970+
IGF.Builder.CreateStore(fieldTag, fieldTagAddr);
2971+
29242972
Address fieldMetatypeAddr = IGF.Builder.CreateConstArrayGEP(
29252973
fieldsMetadata, index, IGM.getPointerSize());
29262974
IGF.Builder.CreateStore(fieldMetatype, fieldMetatypeAddr);
2975+
29272976
++index;
29282977
});
29292978
assert(index == numFields);
@@ -2937,8 +2986,10 @@ static void emitInitializeFieldOffsetVectorWithLayoutString(
29372986
IGF.Builder.CreateCall(
29382987
IGM.getInitStructMetadataWithLayoutStringFunctionPointer(),
29392988
{metadata, IGM.getSize(Size(uintptr_t(flags))), numFieldsV,
2940-
fieldsMetadata.getAddress(), fieldVector});
2989+
fieldsMetadata.getAddress(), fieldTags.getAddress(), fieldVector});
29412990

2991+
IGF.Builder.CreateLifetimeEnd(fieldTags,
2992+
IGM.getPointerSize() * numFields);
29422993
IGF.Builder.CreateLifetimeEnd(fieldsMetadata,
29432994
IGM.getPointerSize() * numFields);
29442995
}
@@ -5133,8 +5184,10 @@ namespace {
51335184
return false;
51345185
}
51355186
return !!getLayoutString() ||
5136-
IGM.Context.LangOpts.hasFeature(
5137-
Feature::LayoutStringValueWitnessesInstantiation);
5187+
(IGM.Context.LangOpts.hasFeature(
5188+
Feature::LayoutStringValueWitnessesInstantiation) &&
5189+
(HasDependentVWT || HasDependentMetadata) &&
5190+
!isa<FixedTypeInfo>(IGM.getTypeInfo(getLoweredType())));
51385191
}
51395192

51405193
llvm::Constant *emitNominalTypeDescriptor() {

lib/IRGen/GenStruct.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,9 @@ namespace {
731731
std::vector<TypeLayoutEntry *> fields;
732732
for (auto &field : getFields()) {
733733
auto fieldTy = field.getType(IGM, T);
734+
if (!fieldTy) {
735+
return IGM.typeLayoutCache.getOrCreateTypeInfoBasedEntry(*this, T);
736+
}
734737
fields.push_back(
735738
field.getTypeInfo().buildTypeLayoutEntry(IGM, fieldTy, useStructLayouts));
736739
}

0 commit comments

Comments
 (0)