Skip to content

Commit c26012d

Browse files
committed
Reorganize TypeContextDescriptorFlags to be a bit more semantic.
Leave space for new kinds of non-generic metadata initialization (one of which I'm about to claim for "foreign") and non-default type namespaces.
1 parent f7b62cb commit c26012d

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
@@ -1174,35 +1174,51 @@ class TypeContextDescriptorFlags : public FlagSet<uint16_t> {
11741174
// Generic flags build upwards from 0.
11751175
// Type-specific flags build downwards from 15.
11761176

1177-
/// Set if the type represents an imported C tag type.
1177+
/// Set if the type supports reflection. C and Objective-C enums
1178+
/// currently don't.
11781179
///
11791180
/// Meaningful for all type-descriptor kinds.
1180-
IsCTag = 0,
1181+
IsReflectable = 0,
11811182

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

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

12071223
/// Set if the context descriptor is includes metadata for dynamically
12081224
/// constructing a class's vtables at metadata instantiation time.
@@ -1231,18 +1247,74 @@ class TypeContextDescriptorFlags : public FlagSet<uint16_t> {
12311247
explicit TypeContextDescriptorFlags(uint16_t bits) : FlagSet(bits) {}
12321248
constexpr TypeContextDescriptorFlags() {}
12331249

1234-
FLAGSET_DEFINE_FLAG_ACCESSORS(IsCTag, isCTag, setIsCTag)
1235-
FLAGSET_DEFINE_FLAG_ACCESSORS(IsCTypedef, isCTypedef, setIsCTypedef)
12361250
FLAGSET_DEFINE_FLAG_ACCESSORS(IsReflectable, isReflectable, setIsReflectable)
12371251

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

1242-
FLAGSET_DEFINE_FLAG_ACCESSORS(HasInPlaceMetadataInitialization,
1243-
hasInPlaceMetadataInitialization,
1244-
setHasInPlaceMetadataInitialization)
1245-
12461318
FLAGSET_DEFINE_FLAG_ACCESSORS(Class_HasVTable,
12471319
class_hasVTable,
12481320
class_setHasVTable)

lib/IRGen/GenMeta.cpp

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -642,20 +642,25 @@ namespace {
642642
IGM.setTrueConstGlobal(var);
643643
return var;
644644
}
645+
646+
void setCommonFlags(TypeContextDescriptorFlags &flags) {
647+
setClangImportedFlags(flags);
648+
setMetadataInitializationKind(flags);
649+
}
645650

646651
/// Flags to indicate Clang-imported declarations so we mangle them
647652
/// consistently at runtime.
648-
void getClangImportedFlags(TypeContextDescriptorFlags &flags) const {
653+
void setClangImportedFlags(TypeContextDescriptorFlags &flags) {
649654
if (Type->getAttrs().getAttribute<ClangImporterSynthesizedTypeAttr>()) {
650655
flags.setIsSynthesizedRelatedEntity(true);
651656
}
652657

653658
if (auto clangDecl = Mangle::ASTMangler::getClangDeclForMangling(Type)) {
654659
if (isa<clang::TagDecl>(clangDecl)) {
655-
flags.setIsCTag(true);
660+
flags.setImportNamespace(TypeContextDescriptorFlags::CTag);
656661
} else if (isa<clang::TypedefNameDecl>(clangDecl)
657662
|| isa<clang::ObjCCompatibleAliasDecl>(clangDecl)) {
658-
flags.setIsCTypedef(true);
663+
flags.setImportNamespace(TypeContextDescriptorFlags::CTypedef);
659664
}
660665
}
661666
}
@@ -679,9 +684,11 @@ namespace {
679684
return HasInPlaceMetadataInitialization;
680685
}
681686

682-
void setHasInPlaceMetadataInitialization(TypeContextDescriptorFlags &flags){
683-
flags.setHasInPlaceMetadataInitialization(
684-
HasInPlaceMetadataInitialization);
687+
void setMetadataInitializationKind(TypeContextDescriptorFlags &flags) {
688+
if (HasInPlaceMetadataInitialization) {
689+
flags.setMetadataInitialization(
690+
TypeContextDescriptorFlags::InPlaceMetadataInitialization);
691+
}
685692
}
686693

687694
void maybeAddInPlaceMetadataInitialization() {
@@ -831,9 +838,7 @@ namespace {
831838
flags.setIsReflectable(
832839
!IGM.shouldEmitOpaqueTypeMetadataRecord(getType()));
833840

834-
setHasInPlaceMetadataInitialization(flags);
835-
836-
getClangImportedFlags(flags);
841+
setCommonFlags(flags);
837842
return flags.getOpaqueValue();
838843
}
839844
};
@@ -891,9 +896,7 @@ namespace {
891896

892897
flags.setIsReflectable(Strategy.isReflectable());
893898

894-
setHasInPlaceMetadataInitialization(flags);
895-
896-
getClangImportedFlags(flags);
899+
setCommonFlags(flags);
897900
return flags.getOpaqueValue();
898901
}
899902
};
@@ -950,6 +953,8 @@ namespace {
950953
// Classes are always reflectable.
951954
flags.setIsReflectable(true);
952955

956+
setCommonFlags(flags);
957+
953958
if (!getType()->isForeign()) {
954959
if (MetadataLayout->areImmediateMembersNegative())
955960
flags.class_setAreImmediateMembersNegative(true);
@@ -965,8 +970,6 @@ namespace {
965970
flags.class_setSuperclassReferenceKind(SuperClassRef->getKind());
966971
}
967972

968-
getClangImportedFlags(flags);
969-
970973
return flags.getOpaqueValue();
971974
}
972975

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)