Skip to content

Commit ff70528

Browse files
authored
Merge pull request #18253 from rjmccall/reorganize-type-descriptor-flags
Reorganize TypeContextDescriptorFlags to be a bit more semantic
2 parents d36ae32 + 374f08f commit ff70528

File tree

10 files changed

+137
-62
lines changed

10 files changed

+137
-62
lines changed

include/swift/ABI/MetadataValues.h

Lines changed: 98 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,35 +1180,51 @@ class TypeContextDescriptorFlags : public FlagSet<uint16_t> {
11801180
// Generic flags build upwards from 0.
11811181
// Type-specific flags build downwards from 15.
11821182

1183-
/// Set if the type represents an imported C tag type.
1183+
/// Set if the type supports reflection. C and Objective-C enums
1184+
/// currently don't.
11841185
///
11851186
/// Meaningful for all type-descriptor kinds.
1186-
IsCTag = 0,
1187+
IsReflectable = 0,
11871188

1188-
/// Set if the type represents an imported C typedef type.
1189+
/// Whether there's something unusual about how the metadata is
1190+
/// initialized.
11891191
///
11901192
/// Meaningful for all type-descriptor kinds.
1191-
IsCTypedef = 1,
1192-
1193-
/// Set if the type supports reflection. C and Objective-C enums
1194-
/// currently don't.
1193+
MetadataInitialization = 1,
1194+
MetadataInitialization_width = 2,
1195+
1196+
/// The namespace of the imported declaration that gave rise to this type.
1197+
/// Some languages (most importantly, C/C++/Objective-C) have different
1198+
/// symbol namespaces in which types can be declared; for example,
1199+
/// `struct A` and `typedef ... A` can be declared in the same scope and
1200+
/// resolve to unrelated types. When these declarations are imported,
1201+
/// there are several possible ways to distinguish them in Swift, e.g.
1202+
/// by implicitly renaming them; however, the external name used for
1203+
/// mangling and metadata must be stable and so is based on the original
1204+
/// declared name. Therefore, in these languages, we privilege one
1205+
/// symbol namespace as the default (although which may depend on the
1206+
/// type kind), and declarations from the other(s) must be marked in
1207+
/// order to differentiate them.
11951208
///
11961209
/// Meaningful for all type-descriptor kinds.
1197-
IsReflectable = 2,
1210+
ImportNamespace = 3,
1211+
ImportNamespace_width = 3,
11981212

1199-
/// Set if the type is a Clang-importer-synthesized related entity. After
1200-
/// the null terminator for the type name is another null-terminated string
1201-
/// containing the tag that discriminates the entity from other synthesized
1202-
/// declarations associated with the same declaration.
1203-
IsSynthesizedRelatedEntity = 3,
1204-
1205-
/// Set if the type requires non-trivial but non-generic metadata
1206-
/// initialization. It may or may not be truly "in place" depending
1207-
/// on the kind of metadata.
1213+
/// Set if the type is an importer-synthesized related entity.
1214+
/// A related entity is an entity synthesized in response to an imported
1215+
/// type which is not the type itself; for example, when the importer
1216+
/// sees an ObjC error domain, it creates an error-wrapper type (a
1217+
/// related entity) and a Code enum (not a related entity because it's
1218+
/// exactly the original type).
1219+
///
1220+
/// The name and import namespace (together with the parent context)
1221+
/// identify the original declaration.
12081222
///
1209-
/// Currently only meaningful for value descriptors, but will be
1210-
/// extended to class descriptors.
1211-
HasInPlaceMetadataInitialization = 4,
1223+
/// If this flag is set, then after the null terminator for the type name
1224+
/// is another null-terminated string containing the tag that discriminates
1225+
/// the entity from other synthesized declarations associated with the
1226+
/// same declaration.
1227+
IsSynthesizedRelatedEntity = 6,
12121228

12131229
/// Set if the context descriptor is includes metadata for dynamically
12141230
/// constructing a class's vtables at metadata instantiation time.
@@ -1237,18 +1253,74 @@ class TypeContextDescriptorFlags : public FlagSet<uint16_t> {
12371253
explicit TypeContextDescriptorFlags(uint16_t bits) : FlagSet(bits) {}
12381254
constexpr TypeContextDescriptorFlags() {}
12391255

1240-
FLAGSET_DEFINE_FLAG_ACCESSORS(IsCTag, isCTag, setIsCTag)
1241-
FLAGSET_DEFINE_FLAG_ACCESSORS(IsCTypedef, isCTypedef, setIsCTypedef)
12421256
FLAGSET_DEFINE_FLAG_ACCESSORS(IsReflectable, isReflectable, setIsReflectable)
12431257

1258+
enum MetadataInitializationKind {
1259+
/// There are either no special rules for initializing the metadata
1260+
/// or the metadata is generic. (Genericity is set in the
1261+
/// non-kind-specific descriptor flags.)
1262+
NoMetadataInitialization = 0,
1263+
1264+
/// The type requires non-trivial singleton initialization using the
1265+
/// "in-place" code pattern.
1266+
InPlaceMetadataInitialization = 1,
1267+
1268+
// We only have two bits here, so if you add a third special kind,
1269+
// include more flag bits in its out-of-line storage.
1270+
};
1271+
1272+
FLAGSET_DEFINE_FIELD_ACCESSORS(MetadataInitialization,
1273+
MetadataInitialization_width,
1274+
MetadataInitializationKind,
1275+
getMetadataInitialization,
1276+
setMetadataInitialization)
1277+
1278+
bool hasInPlaceMetadataInitialization() const {
1279+
return getMetadataInitialization() == InPlaceMetadataInitialization;
1280+
}
1281+
1282+
enum ImportNamespaceKind {
1283+
/// The type comes the default namespace for its language.
1284+
DefaultNamespace = 0,
1285+
1286+
// The behavior for C imported types is complicated in ways that don't
1287+
// entirely make sense according to the design laid out in the comment
1288+
// on the ImportNamespace field. The rules are basically:
1289+
// - Classes are assumed to come from Objective-C by default.
1290+
// ObjC classes are in the ordinary namespace in C.
1291+
// - Protocols are assumed to come from Objective-C by default.
1292+
// ObjC protocols are in their own namespace in C.
1293+
// - Structs and enums seem to always get either CTag or CTypedef.
1294+
// It would probably make more sense to assume they come from the
1295+
// tag namespace in C and then just use CTypedef as an override.
1296+
1297+
/// The type comes from an imported C tag type.
1298+
CTag = 1,
1299+
1300+
/// The type comes from an imported C typedef type.
1301+
CTypedef = 2,
1302+
1303+
// We only have three bits here, so be judicious about adding new
1304+
// namespaces.
1305+
};
1306+
1307+
FLAGSET_DEFINE_FIELD_ACCESSORS(ImportNamespace,
1308+
ImportNamespace_width,
1309+
ImportNamespaceKind,
1310+
getImportNamespace,
1311+
setImportNamespace)
1312+
1313+
bool isCTag() const {
1314+
return getImportNamespace() == CTag;
1315+
}
1316+
bool isCTypedef() const {
1317+
return getImportNamespace() == CTypedef;
1318+
}
1319+
12441320
FLAGSET_DEFINE_FLAG_ACCESSORS(IsSynthesizedRelatedEntity,
12451321
isSynthesizedRelatedEntity,
12461322
setIsSynthesizedRelatedEntity)
12471323

1248-
FLAGSET_DEFINE_FLAG_ACCESSORS(HasInPlaceMetadataInitialization,
1249-
hasInPlaceMetadataInitialization,
1250-
setHasInPlaceMetadataInitialization)
1251-
12521324
FLAGSET_DEFINE_FLAG_ACCESSORS(Class_HasVTable,
12531325
class_hasVTable,
12541326
class_setHasVTable)

lib/IRGen/GenMeta.cpp

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -822,20 +822,25 @@ namespace {
822822
IGM.setTrueConstGlobal(var);
823823
return var;
824824
}
825+
826+
void setCommonFlags(TypeContextDescriptorFlags &flags) {
827+
setClangImportedFlags(flags);
828+
setMetadataInitializationKind(flags);
829+
}
825830

826831
/// Flags to indicate Clang-imported declarations so we mangle them
827832
/// consistently at runtime.
828-
void getClangImportedFlags(TypeContextDescriptorFlags &flags) const {
833+
void setClangImportedFlags(TypeContextDescriptorFlags &flags) {
829834
if (Type->getAttrs().getAttribute<ClangImporterSynthesizedTypeAttr>()) {
830835
flags.setIsSynthesizedRelatedEntity(true);
831836
}
832837

833838
if (auto clangDecl = Mangle::ASTMangler::getClangDeclForMangling(Type)) {
834839
if (isa<clang::TagDecl>(clangDecl)) {
835-
flags.setIsCTag(true);
840+
flags.setImportNamespace(TypeContextDescriptorFlags::CTag);
836841
} else if (isa<clang::TypedefNameDecl>(clangDecl)
837842
|| isa<clang::ObjCCompatibleAliasDecl>(clangDecl)) {
838-
flags.setIsCTypedef(true);
843+
flags.setImportNamespace(TypeContextDescriptorFlags::CTypedef);
839844
}
840845
}
841846
}
@@ -859,9 +864,11 @@ namespace {
859864
return HasInPlaceMetadataInitialization;
860865
}
861866

862-
void setHasInPlaceMetadataInitialization(TypeContextDescriptorFlags &flags){
863-
flags.setHasInPlaceMetadataInitialization(
864-
HasInPlaceMetadataInitialization);
867+
void setMetadataInitializationKind(TypeContextDescriptorFlags &flags) {
868+
if (HasInPlaceMetadataInitialization) {
869+
flags.setMetadataInitialization(
870+
TypeContextDescriptorFlags::InPlaceMetadataInitialization);
871+
}
865872
}
866873

867874
void maybeAddInPlaceMetadataInitialization() {
@@ -1011,9 +1018,7 @@ namespace {
10111018
flags.setIsReflectable(
10121019
!IGM.shouldEmitOpaqueTypeMetadataRecord(getType()));
10131020

1014-
setHasInPlaceMetadataInitialization(flags);
1015-
1016-
getClangImportedFlags(flags);
1021+
setCommonFlags(flags);
10171022
return flags.getOpaqueValue();
10181023
}
10191024
};
@@ -1071,9 +1076,7 @@ namespace {
10711076

10721077
flags.setIsReflectable(Strategy.isReflectable());
10731078

1074-
setHasInPlaceMetadataInitialization(flags);
1075-
1076-
getClangImportedFlags(flags);
1079+
setCommonFlags(flags);
10771080
return flags.getOpaqueValue();
10781081
}
10791082
};
@@ -1130,6 +1133,8 @@ namespace {
11301133
// Classes are always reflectable.
11311134
flags.setIsReflectable(true);
11321135

1136+
setCommonFlags(flags);
1137+
11331138
if (!getType()->isForeign()) {
11341139
if (MetadataLayout->areImmediateMembersNegative())
11351140
flags.class_setAreImmediateMembersNegative(true);
@@ -1145,8 +1150,6 @@ namespace {
11451150
flags.class_setSuperclassReferenceKind(SuperClassRef->getKind());
11461151
}
11471152

1148-
getClangImportedFlags(flags);
1149-
11501153
return flags.getOpaqueValue();
11511154
}
11521155

test/IRGen/cf.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
// CHECK-64: @"$SSo24CCMutableRefrigeratorRefaMn" = linkonce_odr hidden constant
2323
// -- is imported C typedef, is class, is nonunique
24-
// CHECK-64-SAME: <i32 0x0006_0010>
24+
// CHECK-64-SAME: <i32 0x0011_0010>
2525
// CHECK-64-SAME: [[MUTABLE_REFRIGERATOR_NAME]]
2626

2727
// CHECK-64: @"$SSo24CCMutableRefrigeratorRefaN" = linkonce_odr hidden global <{ {{.*}} }> <{

test/IRGen/class_metadata.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ class A {}
44

55
// CHECK: [[A_NAME:@.*]] = private constant [2 x i8] c"A\00"
66
// CHECK-LABEL: @"$S14class_metadata1ACMn" =
7-
// Flags. -2147221424 == 0x8004_0050 == HasVTable | Reflectable | Unique | Class
8-
// CHECK-SAME: i32 -2147221424,
7+
// Flags. -2147418032 == 0x8001_0050 == HasVTable | Reflectable | Unique | Class
8+
// CHECK-SAME: i32 -2147418032,
99
// Parent.
1010
// CHECK-SAME: i32 {{.*}} @"$S14class_metadataMXM"
1111
// Name.
@@ -33,8 +33,8 @@ class B : A {}
3333

3434
// CHECK: [[B_NAME:@.*]] = private constant [2 x i8] c"B\00"
3535
// CHECK-LABEL: @"$S14class_metadata1BCMn" =
36-
// Flags. 262224 == 0x0004_0050 == Reflectable | Unique | Class
37-
// CHECK-SAME: i32 262224,
36+
// Flags. 65616 == 0x0001_0050 == Reflectable | Unique | Class
37+
// CHECK-SAME: i32 65616,
3838
// Parent.
3939
// CHECK-SAME: i32 {{.*}} @"$S14class_metadataMXM"
4040
// Name.
@@ -53,8 +53,8 @@ class C<T> : B {}
5353

5454
// CHECK: [[C_NAME:@.*]] = private constant [2 x i8] c"C\00"
5555
// CHECK-LABEL: @"$S14class_metadata1CCMn" =
56-
// Flags. 262352 == 0x0004_00d0 == Reflectable | Generic | Unique | Class
57-
// CHECK-SAME: i32 262352,
56+
// Flags. 65744 == 0x0001_00d0 == Reflectable | Generic | Unique | Class
57+
// CHECK-SAME: i32 65744,
5858
// Parent.
5959
// CHECK-SAME: i32 {{.*}} @"$S14class_metadataMXM"
6060
// Name.
@@ -104,8 +104,8 @@ class D : E {}
104104

105105
// CHECK: [[D_NAME:@.*]] = private constant [2 x i8] c"D\00"
106106
// CHECK-LABEL: @"$S14class_metadata1DCMn" =
107-
// Flags. 268697680 == 0x1004_0050 == Reflectable | IndirectSuperclass | Unique | Class
108-
// CHECK-SAME: i32 268697680,
107+
// Flags. 268501072 == 0x1001_0050 == Reflectable | IndirectSuperclass | Unique | Class
108+
// CHECK-SAME: i32 268501072,
109109
// Parent.
110110
// CHECK-SAME: i32 {{.*}} @"$S14class_metadataMXM"
111111
// Name.

test/IRGen/class_resilience.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
// CHECK: @"$S16class_resilience14ResilientChildCMn" = {{(protected )?}}{{(dllexport )?}}constant <{{.*}}> <{
3434
// -- flags: class, unique, reflectable, has vtable, has resilient superclass
35-
// CHECK-SAME: <i32 0xD004_0050>
35+
// CHECK-SAME: <i32 0xD001_0050>
3636
// -- name:
3737
// CHECK-SAME: [15 x i8]* [[RESILIENTCHILD_NAME]]
3838
// -- num fields

test/IRGen/enum_resilience.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,12 @@ import resilient_struct
4848
// CHECK-SAME: internal global { %swift.type*, i8* } zeroinitializer, align
4949

5050
// CHECK: @"$S15enum_resilience24EnumWithResilientPayloadOMn" = {{.*}}constant
51-
// 1310802 == 0x00140052
52-
// 0x0010 - HasInPlaceMetadataInitialization
53-
// 0x0014 - IsReflectable
51+
// 196690 == 0x00030052
52+
// 0x0002 - InPlaceMetadataInitialization
53+
// 0x0001 - IsReflectable
5454
// 0x 0040 - IsUnique
5555
// 0x 0012 - Enum
56-
// CHECK-SAME: i32 1310802,
56+
// CHECK-SAME: i32 196690,
5757
// CHECK-SAME: @"$S15enum_resilience24EnumWithResilientPayloadOMl"
5858
// CHECK-SAME: @"$S15enum_resilience24EnumWithResilientPayloadOMf", i32 0, i32 1)
5959
// CHECK-SAME: @"$S15enum_resilience24EnumWithResilientPayloadOMr"

test/IRGen/generic_classes.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import Swift
1616

1717
// CHECK-LABEL: @"$S15generic_classes11RootGenericCMn" =
1818
// -- flags: class, generic, unique, reflectable, has vtable
19-
// CHECK-SAME: <i32 0x8004_00D0>
19+
// CHECK-SAME: <i32 0x8001_00D0>
2020
// -- name
2121
// CHECK-SAME: [12 x i8]* [[ROOTGENERIC_NAME]]
2222
// -- negative size in words
@@ -80,7 +80,7 @@ import Swift
8080
// CHECK: [[ROOTNONGENERIC_NAME:@.*]] = private constant [15 x i8] c"RootNonGeneric\00"
8181
// CHECK: @"$S15generic_classes14RootNonGenericCMn" = hidden constant <{ {{.*}} %swift.method_descriptor }> <{
8282
// -- flags: class, unique, has vtable, reflectable
83-
// CHECK-SAME: <i32 0x8004_0050>
83+
// CHECK-SAME: <i32 0x8001_0050>
8484
// -- name
8585
// CHECK-SAME: [15 x i8]* [[ROOTNONGENERIC_NAME]]
8686
// -- num fields

test/IRGen/generic_structs.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import Builtin
3939
// CHECK: [[SINGLEDYNAMIC_NAME:@.*]] = private constant [14 x i8] c"SingleDynamic\00"
4040
// CHECK: @"$S15generic_structs13SingleDynamicVMn" = hidden constant
4141
// -- flags: struct, unique, generic, reflectable
42-
// CHECK-SAME: <i32 0x0004_00D1>
42+
// CHECK-SAME: <i32 0x0001_00D1>
4343
// -- name
4444
// CHECK-SAME: [14 x i8]* [[SINGLEDYNAMIC_NAME]]
4545
// -- field count
@@ -65,7 +65,7 @@ import Builtin
6565
// CHECK: [[DYNAMICWITHREQUIREMENTS_NAME:@.*]] = private constant [24 x i8] c"DynamicWithRequirements\00"
6666
// CHECK: @"$S15generic_structs23DynamicWithRequirementsVMn" = hidden constant <{ {{.*}} i32 }> <{
6767
// -- flags: struct, unique, generic, reflectable
68-
// CHECK-SAME: <i32 0x0004_00D1>
68+
// CHECK-SAME: <i32 0x0001_00D1>
6969
// -- name
7070
// CHECK-SAME: [24 x i8]* [[DYNAMICWITHREQUIREMENTS_NAME]]
7171
// -- field count

test/IRGen/generic_types.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// CHECK-LABEL: @"$S13generic_types1ACMI" = internal global [16 x i8*] zeroinitializer, align 8
1212

1313
// CHECK-LABEL: @"$S13generic_types1ACMn" = hidden constant
14-
// CHECK-SAME: i32 -2147221296,
14+
// CHECK-SAME: i32 -2147417904,
1515
// CHECK-SAME: @"$S13generic_typesMXM"
1616
// <name>
1717
// CHECK-SAME: @"$S13generic_types1ACMa"

test/IRGen/generic_vtable.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public class Concrete : Derived<Int> {
2424

2525
// CHECK-LABEL: @"$S14generic_vtable4BaseCMn" = {{(dllexport )?}}{{(protected )?}}constant
2626
// -- flags: has vtable, reflectable, is class, is unique
27-
// CHECK-SAME: <i32 0x8004_0050>,
27+
// CHECK-SAME: <i32 0x8001_0050>,
2828
// -- vtable offset
2929
// CHECK-SAME: i32 10,
3030
// -- vtable size
@@ -49,7 +49,7 @@ public class Concrete : Derived<Int> {
4949

5050
// CHECK-LABEL: @"$S14generic_vtable7DerivedCMn" = {{(dllexport )?}}{{(protected )?}}constant
5151
// -- flags: has vtable, reflectable, is class, is unique, is generic
52-
// CHECK-SAME: <i32 0x8004_00D0>,
52+
// CHECK-SAME: <i32 0x8001_00D0>,
5353
// -- vtable offset
5454
// CHECK-SAME: i32 14,
5555
// -- vtable size
@@ -73,7 +73,7 @@ public class Concrete : Derived<Int> {
7373

7474
// CHECK-LABEL: @"$S14generic_vtable8ConcreteCMn" = {{(dllexport )?}}{{(protected )?}}constant
7575
// -- flags: has vtable, reflectable, is class, is unique
76-
// CHECK-SAME: <i32 0x8004_0050>,
76+
// CHECK-SAME: <i32 0x8001_0050>,
7777
// -- vtable offset
7878
// CHECK-SAME: i32 15,
7979
// -- vtable size

0 commit comments

Comments
 (0)