Skip to content

Commit e4d3d6d

Browse files
authored
Merge pull request #64215 from jckarter/noncopyable-hide-type-metadata-records
IRGen: Hide type metadata records for noncopyable types from discovery by existing runtimes.
2 parents d3587a7 + df3f332 commit e4d3d6d

File tree

4 files changed

+85
-31
lines changed

4 files changed

+85
-31
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 62 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,14 @@ emitGlobalList(IRGenModule &IGM, ArrayRef<llvm::WeakTrackingVH> handles,
656656

657657
void IRGenModule::emitRuntimeRegistration() {
658658
// Duck out early if we have nothing to register.
659+
// Note that we don't consider `RuntimeResolvableTypes2` here because the
660+
// current Swift runtime is unable to handle move-only types at runtime, and
661+
// we only use this runtime registration path in JIT mode, so there are no
662+
// ABI forward compatibility concerns.
663+
//
664+
// We should incorporate the types from
665+
// `RuntimeResolvableTypes2` into the list of types to register when we do
666+
// have runtime support in place.
659667
if (SwiftProtocols.empty() && ProtocolConformances.empty() &&
660668
RuntimeResolvableTypes.empty() &&
661669
(!ObjCInterop || (ObjCProtocols.empty() && ObjCClasses.empty() &&
@@ -1033,7 +1041,16 @@ void IRGenModule::addObjCClassStub(llvm::Constant *classPtr) {
10331041

10341042
void IRGenModule::addRuntimeResolvableType(GenericTypeDecl *type) {
10351043
// Collect the nominal type records we emit into a special section.
1036-
RuntimeResolvableTypes.push_back(type);
1044+
if (type->isMoveOnly()) {
1045+
// Older runtimes should not be allowed to discover noncopyable types, since
1046+
// they will try to expose them dynamically as copyable types. Record
1047+
// noncopyable type descriptors in a separate vector so that future
1048+
// noncopyable-type-aware runtimes and reflection libraries can still find
1049+
// them.
1050+
RuntimeResolvableTypes2.push_back(type);
1051+
} else {
1052+
RuntimeResolvableTypes.push_back(type);
1053+
}
10371054

10381055
if (auto nominal = dyn_cast<NominalTypeDecl>(type)) {
10391056
// As soon as the type metadata is available, all the type's conformances
@@ -4202,21 +4219,26 @@ llvm::Constant *IRGenModule::emitProtocolConformances(bool asContiguousArray) {
42024219
/// otherwise the descriptors are emitted as individual globals and nullptr is
42034220
/// returned).
42044221
llvm::Constant *IRGenModule::emitTypeMetadataRecords(bool asContiguousArray) {
4205-
if (RuntimeResolvableTypes.empty())
4222+
if (RuntimeResolvableTypes.empty()
4223+
&& RuntimeResolvableTypes2.empty())
42064224
return nullptr;
42074225

42084226
std::string sectionName;
4227+
std::string section2Name;
42094228
switch (TargetInfo.OutputObjectFormat) {
42104229
case llvm::Triple::MachO:
42114230
sectionName = "__TEXT, __swift5_types, regular";
4231+
section2Name = "__TEXT, __swift5_types2, regular";
42124232
break;
42134233
case llvm::Triple::ELF:
42144234
case llvm::Triple::Wasm:
42154235
sectionName = "swift5_type_metadata";
4236+
section2Name = "swift5_type_metadata_2";
42164237
break;
42174238
case llvm::Triple::XCOFF:
42184239
case llvm::Triple::COFF:
42194240
sectionName = ".sw5tymd$B";
4241+
section2Name = ".sw5tym2$B";
42204242
break;
42214243
case llvm::Triple::DXContainer:
42224244
case llvm::Triple::GOFF:
@@ -4276,39 +4298,50 @@ llvm::Constant *IRGenModule::emitTypeMetadataRecords(bool asContiguousArray) {
42764298
}
42774299

42784300
// In non-JIT mode, emit the type records as individual globals.
4279-
for (auto type : RuntimeResolvableTypes) {
4280-
auto ref = getTypeEntityReference(type);
4281-
4282-
std::string recordMangledName;
4283-
if (auto opaque = dyn_cast<OpaqueTypeDecl>(type)) {
4284-
recordMangledName =
4285-
LinkEntity::forOpaqueTypeDescriptorRecord(opaque).mangleAsString();
4286-
} else if (auto nominal = dyn_cast<NominalTypeDecl>(type)) {
4287-
recordMangledName =
4288-
LinkEntity::forNominalTypeDescriptorRecord(nominal).mangleAsString();
4289-
} else {
4290-
llvm_unreachable("bad type in RuntimeResolvableTypes");
4301+
4302+
auto generateGlobalTypeList = [&](ArrayRef<GenericTypeDecl *> typesList,
4303+
StringRef section) {
4304+
if (typesList.empty()) {
4305+
return;
42914306
}
4307+
4308+
for (auto type : typesList) {
4309+
auto ref = getTypeEntityReference(type);
42924310

4293-
auto var = new llvm::GlobalVariable(
4294-
Module, TypeMetadataRecordTy, /*isConstant*/ true,
4295-
llvm::GlobalValue::PrivateLinkage, /*initializer*/ nullptr,
4296-
recordMangledName);
4311+
std::string recordMangledName;
4312+
if (auto opaque = dyn_cast<OpaqueTypeDecl>(type)) {
4313+
recordMangledName =
4314+
LinkEntity::forOpaqueTypeDescriptorRecord(opaque).mangleAsString();
4315+
} else if (auto nominal = dyn_cast<NominalTypeDecl>(type)) {
4316+
recordMangledName =
4317+
LinkEntity::forNominalTypeDescriptorRecord(nominal).mangleAsString();
4318+
} else {
4319+
llvm_unreachable("bad type in RuntimeResolvableTypes");
4320+
}
42974321

4298-
auto record = generateRecord(ref, var, {0});
4299-
var->setInitializer(record);
4322+
auto var = new llvm::GlobalVariable(
4323+
Module, TypeMetadataRecordTy, /*isConstant*/ true,
4324+
llvm::GlobalValue::PrivateLinkage, /*initializer*/ nullptr,
4325+
recordMangledName);
43004326

4301-
var->setSection(sectionName);
4302-
var->setAlignment(llvm::MaybeAlign(4));
4303-
disableAddressSanitizer(*this, var);
4304-
addUsedGlobal(var);
4327+
auto record = generateRecord(ref, var, {0});
4328+
var->setInitializer(record);
43054329

4306-
if (IRGen.Opts.ConditionalRuntimeRecords) {
4307-
// Allow dead-stripping `var` (the type record) when the type (`ref`) is
4308-
// not referenced.
4309-
appendLLVMUsedConditionalEntry(var, ref.getValue());
4330+
var->setSection(section);
4331+
var->setAlignment(llvm::MaybeAlign(4));
4332+
disableAddressSanitizer(*this, var);
4333+
addUsedGlobal(var);
4334+
4335+
if (IRGen.Opts.ConditionalRuntimeRecords) {
4336+
// Allow dead-stripping `var` (the type record) when the type (`ref`) is
4337+
// not referenced.
4338+
appendLLVMUsedConditionalEntry(var, ref.getValue());
4339+
}
43104340
}
4311-
}
4341+
};
4342+
4343+
generateGlobalTypeList(RuntimeResolvableTypes, sectionName);
4344+
generateGlobalTypeList(RuntimeResolvableTypes2, section2Name);
43124345

43134346
return nullptr;
43144347
}

lib/IRGen/IRGenModule.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1243,8 +1243,12 @@ class IRGenModule {
12431243
SmallVector<ProtocolDecl *, 4> SwiftProtocols;
12441244
/// List of protocol conformances to generate descriptors for.
12451245
std::vector<ConformanceDescription> ProtocolConformances;
1246-
/// List of types to generate runtime-resolvable metadata records for.
1246+
/// List of types to generate runtime-resolvable metadata records for that
1247+
/// are consumable for any Swift runtime.
12471248
SmallVector<GenericTypeDecl *, 4> RuntimeResolvableTypes;
1249+
/// List of types to generate runtime-resolvable metadata records for that
1250+
/// are consumable for any Swift runtime aware of noncopyable types.
1251+
SmallVector<GenericTypeDecl *, 4> RuntimeResolvableTypes2;
12481252
/// List of ExtensionDecls corresponding to the generated
12491253
/// categories.
12501254
SmallVector<ExtensionDecl*, 4> ObjCCategoryDecls;

stdlib/public/runtime/ImageInspectionCommon.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,12 @@
2727
/// The Mach-O section name for the section containing protocol conformances.
2828
/// This lives within SEG_TEXT.
2929
#define MachOProtocolConformancesSection "__swift5_proto"
30-
/// The Mach-O section name for the section containing type references.
30+
/// The Mach-O section name for the section containing copyable type references.
3131
/// This lives within SEG_TEXT.
3232
#define MachOTypeMetadataRecordSection "__swift5_types"
33+
/// The Mach-O section name for the section containing additional type references.
34+
/// This lives within SEG_TEXT.
35+
#define MachOExtraTypeMetadataRecordSection "__swift5_types2"
3336
/// The Mach-O section name for the section containing dynamic replacements.
3437
/// This lives within SEG_TEXT.
3538
#define MachODynamicReplacementSection "__swift5_replace"

test/IRGen/moveonly_deinit.sil

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,20 @@ struct MOSingleRefcountLikeStructNoDeinit {
130130
var x: C
131131
}
132132

133+
// Type metadata records for noncopyable types should be in a separate list
134+
// from copyable types.
135+
136+
// CHECK-LABEL: @"$s{{.*}}1CCHn" =
137+
// CHECK-SAME: section "[[COPYABLE_SECTION_NAME:[^"]+]]"
138+
139+
// CHECK-NOT: @"$s{{.*}}8MOStructVHn" = {{.*}} section "[[COPYABLE_SECTION_NAME]]"
140+
141+
// CHECK-LABEL: @"$s{{.*}}8MOStructVHn" =
142+
// CHECK-SAME: section "[[NONCOPYABLE_SECTION_NAME:[^"]+]]"
143+
144+
// CHECK-LABEL: @"$s{{.*}}6MOEnumOHn" =
145+
// CHECK-SAME: section "[[NONCOPYABLE_SECTION_NAME]]"
146+
133147
// Very large structs will use indirect conventions for their deinit.
134148

135149
@_moveOnly

0 commit comments

Comments
 (0)