Skip to content

Commit 0cbcd56

Browse files
authored
Merge pull request #84726 from jckarter/dont-hide-load-bearing-noncopyable-metadata
IRGen: Don't hide noncopyable metadata from access functions in load-bearing mangled names.
2 parents a83ea3c + b4d7e98 commit 0cbcd56

File tree

6 files changed

+119
-29
lines changed

6 files changed

+119
-29
lines changed

lib/IRGen/GenReflection.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ getTypeRefByFunction(IRGenModule &IGM, CanGenericSignature sig, CanType t,
320320
IRGenMangler mangler(IGM.Context);
321321
std::string symbolName =
322322
mangler.mangleSymbolNameForMangledMetadataAccessorString(
323-
"get_type_metadata", sig, t);
323+
"get_type_metadata", sig, t, role);
324324
auto constant = IGM.getAddrOfStringForMetadataRef(symbolName, /*align*/2,
325325
/*low bit*/false,
326326
[&](ConstantInitBuilder &B) {
@@ -351,9 +351,22 @@ getTypeRefByFunction(IRGenModule &IGM, CanGenericSignature sig, CanType t,
351351
? genericEnv->mapTypeIntoContext(t)->getCanonicalType()
352352
: t;
353353

354-
// If a type is noncopyable, lie about the resolved type unless the
355-
// runtime is sufficiently aware of noncopyable types.
356-
if (substT->isNoncopyable()) {
354+
// If a type is noncopyable, lie about the resolved type to reflection
355+
// APIs unless the runtime is sufficiently aware of noncopyable types.
356+
bool shouldHideNoncopyableTypeFromOldRuntimes;
357+
switch (role) {
358+
case MangledTypeRefRole::Metadata:
359+
case MangledTypeRefRole::DefaultAssociatedTypeWitness:
360+
case MangledTypeRefRole::FlatUnique:
361+
shouldHideNoncopyableTypeFromOldRuntimes = false;
362+
break;
363+
case MangledTypeRefRole::FieldMetadata:
364+
case MangledTypeRefRole::Reflection:
365+
shouldHideNoncopyableTypeFromOldRuntimes = true;
366+
break;
367+
}
368+
if (shouldHideNoncopyableTypeFromOldRuntimes
369+
&& substT->isNoncopyable()) {
357370
// Darwin-based platforms have ABI stability, and we want binaries
358371
// that use noncopyable types nongenerically today to be forward
359372
// compatible with a future OS runtime that supports noncopyable

lib/IRGen/IRGenMangler.cpp

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
#include "IRGenMangler.h"
1414
#include "ExtendedExistential.h"
1515
#include "GenClass.h"
16+
#include "IRGenModule.h"
1617
#include "swift/AST/ExistentialLayout.h"
18+
#include "swift/AST/GenericEnvironment.h"
1719
#include "swift/AST/IRGenOptions.h"
1820
#include "swift/AST/ProtocolAssociations.h"
1921
#include "swift/AST/ProtocolConformance.h"
@@ -414,15 +416,44 @@ std::string IRGenMangler::mangleSymbolNameForAssociatedConformanceWitness(
414416
std::string IRGenMangler::mangleSymbolNameForMangledMetadataAccessorString(
415417
const char *kind,
416418
CanGenericSignature genericSig,
417-
CanType type) {
419+
CanType type,
420+
MangledTypeRefRole role) {
418421
beginManglingWithoutPrefix();
419422
Buffer << kind << " ";
420423

421-
if (genericSig)
424+
if (genericSig) {
422425
appendGenericSignature(genericSig);
426+
}
423427

424-
if (type)
428+
if (type) {
425429
appendType(type, genericSig);
430+
}
431+
432+
// Noncopyable types get additional runtime capability checks before we reveal
433+
// their metadata to reflection APIs, while core metadata queries always provide
434+
// the metadata. So we need a separate symbol mangling for the two variants in
435+
// this case.
436+
switch (role) {
437+
case MangledTypeRefRole::DefaultAssociatedTypeWitness:
438+
case MangledTypeRefRole::FlatUnique:
439+
case MangledTypeRefRole::Metadata:
440+
// Core metadata, never conditionalized.
441+
break;
442+
443+
case MangledTypeRefRole::Reflection:
444+
case MangledTypeRefRole::FieldMetadata: {
445+
// Reflection metadata is conditionalized for noncopyable types.
446+
CanType contextType = type;
447+
if (genericSig) {
448+
contextType = genericSig.getGenericEnvironment()->mapTypeIntoContext(contextType)
449+
->getReducedType(genericSig);
450+
}
451+
if (contextType->isNoncopyable()) {
452+
Buffer << " noncopyable";
453+
}
454+
}
455+
}
456+
426457
return finalize();
427458
}
428459

lib/IRGen/IRGenMangler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,8 @@ class IRGenMangler : public Mangle::ASTMangler {
685685
std::string mangleSymbolNameForMangledMetadataAccessorString(
686686
const char *kind,
687687
CanGenericSignature genericSig,
688-
CanType type);
688+
CanType type,
689+
MangledTypeRefRole role);
689690

690691
std::string mangleSymbolNameForMangledConformanceAccessorString(
691692
const char *kind,

lib/IRGen/TypeLayout.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,8 @@ llvm::Function *createMetatypeAccessorFunction(IRGenModule &IGM, SILType ty,
472472
std::string symbolName =
473473
mangler.mangleSymbolNameForMangledMetadataAccessorString(
474474
"get_type_metadata_for_layout_string", sig,
475-
fieldType->mapTypeOutOfContext()->getCanonicalType());
475+
fieldType->mapTypeOutOfContext()->getCanonicalType(),
476+
MangledTypeRefRole::Metadata);
476477

477478
auto helperFn = IGM.getOrCreateHelperFunction(
478479
symbolName, IGM.TypeMetadataPtrTy /*retTy*/,
@@ -1738,7 +1739,8 @@ AlignedGroupEntry::layoutString(IRGenModule &IGM,
17381739
std::string symbolName =
17391740
mangler.mangleSymbolNameForMangledMetadataAccessorString(
17401741
"type_layout_string", genericSig.getCanonicalSignature(),
1741-
ty.getASTType()->mapTypeOutOfContext()->getCanonicalType());
1742+
ty.getASTType()->mapTypeOutOfContext()->getCanonicalType(),
1743+
MangledTypeRefRole::Metadata);
17421744

17431745
auto *global = SB.finishAndCreateGlobal(symbolName, IGM.getPointerAlignment(),
17441746
/*constant*/ true);
@@ -2339,7 +2341,8 @@ EnumTypeLayoutEntry::layoutString(IRGenModule &IGM,
23392341
std::string symbolName =
23402342
mangler.mangleSymbolNameForMangledMetadataAccessorString(
23412343
"type_layout_string", genericSig.getCanonicalSignature(),
2342-
ty.getASTType()->mapTypeOutOfContext()->getCanonicalType());
2344+
ty.getASTType()->mapTypeOutOfContext()->getCanonicalType(),
2345+
MangledTypeRefRole::Metadata);
23432346

23442347
auto *global = SB.finishAndCreateGlobal(symbolName, IGM.getPointerAlignment(),
23452348
/*constant*/ true);

test/IRGen/noncopyable_field_descriptors.swift

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,16 @@ public struct NonCopyable: ~Copyable { }
3939
// 'MF' constant as a separator that precedes each field descriptor.
4040

4141
// NEW: @"$s4test8CC_TestsCMF" =
42-
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyxG.{{[0-9]+}}"
42+
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyxG noncopyable
4343
// NEW-SAME: @"symbolic _____yq_G 4test21ConditionallyCopyableOAARi_zrlE"
44-
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyAA03NonC0VG.{{[0-9]+}}"
44+
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyAA03NonC0VG noncopyable
4545
// NEW-SAME: @"symbolic _____ySSG 4test21ConditionallyCopyableOAARi_zrlE"
4646

4747
// OLD: @"$s4test8CC_TestsCMF" =
48-
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyxG.{{[0-9]+}}"
49-
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyq_G.{{[0-9]+}}"
50-
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyAA03NonC0VG.{{[0-9]+}}"
51-
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOySSG.{{[0-9]+}}"
48+
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyxG noncopyable
49+
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyq_G
50+
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOyAA03NonC0VG noncopyable
51+
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test21ConditionallyCopyableOySSG
5252
public class CC_Tests<NCG: ~Copyable, T> {
5353
var ccNCG: ConditionallyCopyable<NCG> = .none
5454
var ccT: ConditionallyCopyable<T> = .none
@@ -62,16 +62,16 @@ public class CC_Tests<NCG: ~Copyable, T> {
6262
/// fields until a future runtime says they're safe to reflect.
6363

6464
// NEW: @"$s4test8NC_TestsCMF" =
65-
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyxG.{{[0-9]+}}"
66-
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyq_G.{{[0-9]+}}"
67-
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyAA03NonC0VG.{{[0-9]+}}"
68-
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOySSG.{{[0-9]+}}"
65+
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyxG noncopyable
66+
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyq_G noncopyable
67+
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyAA03NonC0VG noncopyable
68+
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOySSG noncopyable
6969

7070
// OLD: @"$s4test8NC_TestsCMF" =
71-
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyxG.{{[0-9]+}}"
72-
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyq_G.{{[0-9]+}}"
73-
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyAA03NonC0VG.{{[0-9]+}}"
74-
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOySSG.{{[0-9]+}}"
71+
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyxG noncopyable
72+
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyq_G noncopyable
73+
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOyAA03NonC0VG noncopyable
74+
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test13NeverCopyableOySSG noncopyable
7575
public class NC_Tests<NCG: ~Copyable, T> {
7676
var ncNCG: NeverCopyable<NCG> = .none
7777
var ncT: NeverCopyable<T> = .none
@@ -83,7 +83,7 @@ public class NC_Tests<NCG: ~Copyable, T> {
8383
// NEW: @"$s4test17StdlibTypes_TestsCMF" =
8484
// NEW-SAME: @"symbolic xSg"
8585
// NEW-SAME: @"symbolic q_Sg"
86-
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test11NonCopyableVSg.{{[0-9]+}}"
86+
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test11NonCopyableVSg noncopyable
8787
// NEW-SAME: @"symbolic SSSg"
8888
// NEW-SAME: @"symbolic SPyxG"
8989
// NEW-SAME: @"symbolic SPyq_G"
@@ -93,7 +93,7 @@ public class NC_Tests<NCG: ~Copyable, T> {
9393
// OLD: @"$s4test17StdlibTypes_TestsCMF" =
9494
// OLD-SAME: @"symbolic xSg"
9595
// OLD-SAME: @"symbolic q_Sg"
96-
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test11NonCopyableVSg.{{[0-9]+}}"
96+
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test11NonCopyableVSg noncopyable
9797
// OLD-SAME: @"symbolic SSSg"
9898
// OLD-SAME: @"symbolic SPyxG"
9999
// OLD-SAME: @"symbolic SPyq_G"
@@ -115,13 +115,13 @@ public class StdlibTypes_Tests<NCG: ~Copyable, T> {
115115
// NEW: @"$s4test19PlainlyStored_TestsCMF" =
116116
// NEW-SAME: @"symbolic x"
117117
// NEW-SAME: @"symbolic q_"
118-
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test11NonCopyableV.{{[0-9]+}}"
118+
// NEW-SAME: @"get_type_metadata Ri_zr0_l4test11NonCopyableV noncopyable
119119
// NEW-SAME: @"symbolic SS"
120120

121121
// OLD: @"$s4test19PlainlyStored_TestsCMF" =
122122
// OLD-SAME: @"symbolic x"
123123
// OLD-SAME: @"symbolic q_"
124-
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test11NonCopyableV.{{[0-9]+}}"
124+
// OLD-SAME: @"get_type_metadata Ri_zr0_l4test11NonCopyableV noncopyable
125125
// OLD-SAME: @"symbolic SS"
126126
public class PlainlyStored_Tests<NCG: ~Copyable, T> {
127127
var ncg: NCG
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: %target-run-simple-swift(-enable-experimental-feature SuppressedAssociatedTypes)
2+
// REQUIRES: executable_test
3+
// REQUIRES: swift_feature_SuppressedAssociatedTypes
4+
5+
// Noncopyable types are suppressed in field metadata in runtimes lacking
6+
// reflection support for them (currently all runtimes). However, we want
7+
// to ensure that noncopyable type metadata is still produced where it is
8+
// "load-bearing" to the generics system, such as in associated types in
9+
// protocol conformances.
10+
11+
protocol Barrable: ~Copyable {
12+
}
13+
14+
struct Bar<T: ~Copyable>: Barrable & ~Copyable {
15+
var x: Int = 0
16+
}
17+
18+
protocol F: ~Copyable {
19+
associatedtype B: Barrable & ~Copyable
20+
}
21+
22+
struct Foo: F & ~Copyable {
23+
typealias B = Bar<Int>
24+
}
25+
26+
func test<T: F & ~Copyable>(_: T.Type) {
27+
print("\(T.B.self)")
28+
}
29+
30+
// CHECK: Bar<Int>
31+
test(Foo.self)
32+
33+
class Mirrored {
34+
var noncopyableField: Bar<Int>
35+
36+
init() {
37+
self.noncopyableField = Bar()
38+
}
39+
}
40+
41+
// CHECK: noncopyableField (0 elements)
42+
dump(Mirrored())

0 commit comments

Comments
 (0)