Skip to content

Commit fdef6ef

Browse files
authored
Merge pull request #13468 from jckarter/generic-requirement-details
Context descriptors
2 parents 9182327 + a7a3b17 commit fdef6ef

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+3408
-1281
lines changed

docs/ABI/Mangling.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ Globals
5555
global ::= type 'ML' // type metadata lazy cache variable
5656
global ::= nominal-type 'Mm' // class metaclass
5757
global ::= nominal-type 'Mn' // nominal type descriptor
58+
global ::= module 'MXM' // module descriptor
59+
global ::= context 'MXE' // extension descriptor
60+
global ::= context 'MXX' // anonymous context descriptor
61+
global ::= context identifier 'MXY' // anonymous context descriptor
62+
global ::= type assoc_type_path 'MXA' // generic parameter ref
5863
global ::= nominal-type 'Mo' // class metadata immediate member base offset
5964
global ::= protocol 'Mp' // protocol descriptor
6065
global ::= protocol-conformance 'Mc' // protocol conformance descriptor
@@ -283,6 +288,15 @@ destructor, the non-allocating or non-deallocating variant is used.
283288
module ::= identifier // module name
284289
module ::= known-module // abbreviation
285290

291+
context ::= entity identifier type-list 'XZ' // unknown runtime context
292+
293+
The runtime produces manglings of unknown runtime contexts when a declaration
294+
context has no preserved runtime information, or when a declaration is encoded
295+
in runtime in a way that the current runtime does not understand. These
296+
manglings are unstable and may change between runs of the process.
297+
298+
::
299+
286300
known-module ::= 's' // Swift
287301
known-module ::= 'SC' // Clang-importer-synthesized
288302
known-module ::= 'So' // C and Objective-C
@@ -300,6 +314,7 @@ Types
300314
any-generic-type ::= context decl-name 'C' // nominal class type
301315
any-generic-type ::= context decl-name 'O' // nominal enum type
302316
any-generic-type ::= context decl-name 'V' // nominal struct type
317+
any-generic-type ::= context decl-name 'XY' // unknown nominal type
303318
any-generic-type ::= protocol 'P' // nominal protocol type
304319
any-generic-type ::= context decl-name 'a' // typealias type (used in DWARF and USRs)
305320

include/swift/ABI/MetadataValues.h

Lines changed: 248 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -239,77 +239,6 @@ enum class ProtocolDispatchStrategy: uint8_t {
239239
Swift = 1,
240240
};
241241

242-
/// Flags in a generic nominal type descriptor.
243-
class GenericParameterDescriptorFlags {
244-
typedef uint16_t int_type;
245-
enum : int_type {
246-
IsNonUnique = 0x0002,
247-
HasVTable = 0x0004,
248-
HasResilientSuperclass = 0x0008,
249-
};
250-
int_type Data;
251-
252-
constexpr GenericParameterDescriptorFlags(int_type data) : Data(data) {}
253-
public:
254-
constexpr GenericParameterDescriptorFlags() : Data(0) {}
255-
256-
constexpr GenericParameterDescriptorFlags withHasVTable(bool b) const {
257-
return GenericParameterDescriptorFlags(b ? (Data | HasVTable)
258-
: (Data & ~HasVTable));
259-
}
260-
261-
constexpr GenericParameterDescriptorFlags withIsUnique(bool b) const {
262-
return GenericParameterDescriptorFlags(!b ? (Data | IsNonUnique)
263-
: (Data & ~IsNonUnique));
264-
}
265-
266-
/// Whether this nominal type descriptor is known to be nonunique, requiring
267-
/// comparison operations to check string equality of the mangled name.
268-
bool isUnique() const {
269-
return !(Data & IsNonUnique);
270-
}
271-
272-
/// If this type is a class, does it have a vtable? If so, the number
273-
/// of vtable entries immediately follows the generic requirement
274-
/// descriptor.
275-
bool hasVTable() const {
276-
return Data & HasVTable;
277-
}
278-
279-
constexpr GenericParameterDescriptorFlags withHasResilientSuperclass(bool b) const {
280-
return GenericParameterDescriptorFlags(b ? (Data | HasResilientSuperclass)
281-
: (Data & ~HasResilientSuperclass));
282-
}
283-
284-
/// If this type is a class, does it have a resilient superclass?
285-
/// If so, the generic parameter offset, field offset vector offset
286-
/// and vtable start offsets are relative to the start of the class's
287-
/// immediate members in the metadata, and not the start of the
288-
/// metadata itself.
289-
///
290-
/// Note that the immediate members begin at the same offset where the
291-
/// superclass metadata ends.
292-
bool hasResilientSuperclass() const {
293-
return Data & HasResilientSuperclass;
294-
}
295-
296-
int_type getIntValue() const {
297-
return Data;
298-
}
299-
300-
static GenericParameterDescriptorFlags fromIntValue(int_type Data) {
301-
return GenericParameterDescriptorFlags(Data);
302-
}
303-
304-
bool operator==(GenericParameterDescriptorFlags other) const {
305-
return Data == other.Data;
306-
}
307-
bool operator!=(GenericParameterDescriptorFlags other) const {
308-
return Data != other.Data;
309-
}
310-
};
311-
312-
313242
/// Flags for protocol descriptors.
314243
class ProtocolDescriptorFlags {
315244
typedef uint32_t int_type;
@@ -919,6 +848,254 @@ constexpr unsigned NumDirectGenericTypeMetadataAccessFunctionArgs = 3;
919848
/// The offset (in pointers) to the first requirement in a witness table.
920849
constexpr unsigned WitnessTableFirstRequirementOffset = 1;
921850

851+
/// Kinds of context descriptor.
852+
enum class ContextDescriptorKind : uint8_t {
853+
/// This context descriptor represents a module.
854+
Module = 0,
855+
856+
/// This context descriptor represents an extension.
857+
Extension = 1,
858+
859+
/// This context descriptor represents an anonymous possibly-generic context
860+
/// such as a function body.
861+
Anonymous = 2,
862+
863+
/// First kind that represents a type of any sort.
864+
Type_First = 16,
865+
866+
/// This context descriptor represents a class.
867+
Class = Type_First,
868+
869+
/// This context descriptor represents a struct.
870+
Struct = Type_First + 1,
871+
872+
/// This context descriptor represents an enum.
873+
Enum = Type_First + 2,
874+
875+
/// Last kind that represents a type of any sort.
876+
Type_Last = 31,
877+
};
878+
879+
/// Common flags stored in the first 32-bit word of any context descriptor.
880+
struct ContextDescriptorFlags {
881+
private:
882+
uint32_t Value;
883+
884+
explicit constexpr ContextDescriptorFlags(uint32_t Value)
885+
: Value(Value) {}
886+
public:
887+
constexpr ContextDescriptorFlags() : Value(0) {}
888+
constexpr ContextDescriptorFlags(ContextDescriptorKind kind,
889+
bool isGeneric,
890+
bool isUnique,
891+
uint8_t version,
892+
uint16_t kindSpecificFlags)
893+
: ContextDescriptorFlags(ContextDescriptorFlags()
894+
.withKind(kind)
895+
.withGeneric(isGeneric)
896+
.withUnique(isUnique)
897+
.withVersion(version)
898+
.withKindSpecificFlags(kindSpecificFlags))
899+
{}
900+
901+
/// The kind of context this descriptor describes.
902+
constexpr ContextDescriptorKind getKind() const {
903+
return ContextDescriptorKind(Value & 0x1Fu);
904+
}
905+
906+
/// Whether the context being described is generic.
907+
constexpr bool isGeneric() const {
908+
return (Value & 0x80u) != 0;
909+
}
910+
911+
/// Whether this is a unique record describing the referenced context.
912+
constexpr bool isUnique() const {
913+
return (Value & 0x40u) != 0;
914+
}
915+
916+
/// The format version of the descriptor. Higher version numbers may have
917+
/// additional fields that aren't present in older versions.
918+
constexpr uint8_t getVersion() const {
919+
return (Value >> 8u) & 0xFFu;
920+
}
921+
922+
/// The most significant two bytes of the flags word, which can have
923+
/// kind-specific meaning.
924+
constexpr uint16_t getKindSpecificFlags() const {
925+
return (Value >> 16u) & 0xFFFFu;
926+
}
927+
928+
constexpr ContextDescriptorFlags withKind(ContextDescriptorKind kind) const {
929+
return assert((uint8_t(kind) & 0x1F) == uint8_t(kind)),
930+
ContextDescriptorFlags((Value & 0xFFFFFFE0u) | uint8_t(kind));
931+
}
932+
933+
constexpr ContextDescriptorFlags withGeneric(bool isGeneric) const {
934+
return ContextDescriptorFlags((Value & 0xFFFFFF7Fu)
935+
| (isGeneric ? 0x80u : 0));
936+
}
937+
938+
constexpr ContextDescriptorFlags withUnique(bool isUnique) const {
939+
return ContextDescriptorFlags((Value & 0xFFFFFFBFu)
940+
| (isUnique ? 0x40u : 0));
941+
}
942+
943+
constexpr ContextDescriptorFlags withVersion(uint8_t version) const {
944+
return ContextDescriptorFlags((Value & 0xFFFF00FFu) | (version << 8u));
945+
}
946+
947+
constexpr ContextDescriptorFlags
948+
withKindSpecificFlags(uint16_t flags) const {
949+
return ContextDescriptorFlags((Value & 0xFFFFu) | (flags << 16u));
950+
}
951+
952+
constexpr uint32_t getIntValue() const {
953+
return Value;
954+
}
955+
};
956+
957+
/// Flags for nominal type context descriptors. These values are used as the
958+
/// kindSpecificFlags of the ContextDescriptorFlags for the type.
959+
enum class TypeContextDescriptorFlags: uint16_t {
960+
/// Set if the context descriptor is includes metadata for dynamically
961+
/// constructing a class's vtables at metadata instantiation time.
962+
HasVTable = 0x8000u,
963+
964+
/// Set if the context descriptor is for a class with resilient ancestry.
965+
HasResilientSuperclass = 0x4000u,
966+
967+
/// Set if the type represents an imported C tag type.
968+
IsCTag = 0x2000u,
969+
970+
/// Set if the type represents an imported C typedef type.
971+
IsCTypedef = 0x1000u,
972+
};
973+
974+
enum class GenericParamKind : uint8_t {
975+
/// A type parameter.
976+
Type = 0,
977+
978+
Max = 0x3F,
979+
};
980+
981+
class GenericParamDescriptor {
982+
uint8_t Value;
983+
984+
explicit constexpr GenericParamDescriptor(uint8_t Value)
985+
: Value(Value) {}
986+
public:
987+
constexpr GenericParamDescriptor(GenericParamKind kind,
988+
bool hasKeyArgument,
989+
bool hasExtraArgument)
990+
: GenericParamDescriptor(GenericParamDescriptor(0)
991+
.withKind(kind)
992+
.withKeyArgument(hasKeyArgument)
993+
.withExtraArgument(hasExtraArgument))
994+
{}
995+
996+
constexpr bool hasKeyArgument() const {
997+
return (Value & 0x80u) != 0;
998+
}
999+
1000+
constexpr bool hasExtraArgument() const {
1001+
return (Value & 0x40u) != 0;
1002+
}
1003+
1004+
constexpr GenericParamKind getKind() const {
1005+
return GenericParamKind(Value & 0x3Fu);
1006+
}
1007+
1008+
constexpr GenericParamDescriptor
1009+
withKeyArgument(bool hasKeyArgument) const {
1010+
return GenericParamDescriptor((Value & 0x7Fu)
1011+
| (hasKeyArgument ? 0x80u : 0));
1012+
}
1013+
1014+
constexpr GenericParamDescriptor
1015+
withExtraArgument(bool hasExtraArgument) const {
1016+
return GenericParamDescriptor((Value & 0xBFu)
1017+
| (hasExtraArgument ? 0x40u : 0));
1018+
}
1019+
1020+
constexpr GenericParamDescriptor withKind(GenericParamKind kind) const {
1021+
return assert((uint8_t(kind) & 0x3Fu) == uint8_t(kind)),
1022+
GenericParamDescriptor((Value & 0xC0u) | uint8_t(kind));
1023+
}
1024+
1025+
constexpr uint8_t getIntValue() const {
1026+
return Value;
1027+
}
1028+
};
1029+
1030+
enum class GenericRequirementKind : uint8_t {
1031+
/// A protocol requirement.
1032+
Protocol = 0,
1033+
/// A same-type requirement.
1034+
SameType = 1,
1035+
/// A base class requirement.
1036+
BaseClass = 2,
1037+
/// A "same-conformance" requirement, implied by a same-type or base-class
1038+
/// constraint that binds a parameter with protocol requirements.
1039+
SameConformance = 3,
1040+
/// A layout constraint.
1041+
Layout = 0x1F,
1042+
};
1043+
1044+
class GenericRequirementFlags {
1045+
uint32_t Value;
1046+
1047+
explicit constexpr GenericRequirementFlags(uint32_t Value)
1048+
: Value(Value) {}
1049+
public:
1050+
constexpr GenericRequirementFlags(GenericRequirementKind kind,
1051+
bool hasKeyArgument,
1052+
bool hasExtraArgument)
1053+
: GenericRequirementFlags(GenericRequirementFlags(0)
1054+
.withKind(kind)
1055+
.withKeyArgument(hasKeyArgument)
1056+
.withExtraArgument(hasExtraArgument))
1057+
{}
1058+
1059+
constexpr bool hasKeyArgument() const {
1060+
return (Value & 0x80u) != 0;
1061+
}
1062+
1063+
constexpr bool hasExtraArgument() const {
1064+
return (Value & 0x40u) != 0;
1065+
}
1066+
1067+
constexpr GenericRequirementKind getKind() const {
1068+
return GenericRequirementKind(Value & 0x1Fu);
1069+
}
1070+
1071+
constexpr GenericRequirementFlags
1072+
withKeyArgument(bool hasKeyArgument) const {
1073+
return GenericRequirementFlags((Value & 0x7Fu)
1074+
| (hasKeyArgument ? 0x80u : 0));
1075+
}
1076+
1077+
constexpr GenericRequirementFlags
1078+
withExtraArgument(bool hasExtraArgument) const {
1079+
return GenericRequirementFlags((Value & 0xBFu)
1080+
| (hasExtraArgument ? 0x40u : 0));
1081+
}
1082+
1083+
constexpr GenericRequirementFlags
1084+
withKind(GenericRequirementKind kind) const {
1085+
return assert((uint8_t(kind) & 0x1Fu) == uint8_t(kind)),
1086+
GenericRequirementFlags((Value & 0xE0u) | uint8_t(kind));
1087+
}
1088+
1089+
constexpr uint32_t getIntValue() const {
1090+
return Value;
1091+
}
1092+
};
1093+
1094+
enum class GenericRequirementLayoutKind : uint32_t {
1095+
// A class constraint.
1096+
Class = 0,
1097+
};
1098+
9221099
} // end namespace swift
9231100

9241101
#endif /* SWIFT_ABI_METADATAVALUES_H */

0 commit comments

Comments
 (0)