Skip to content

Commit a8d4d57

Browse files
authored
[IRGen] Generate compressed representation of value witnesses (#63813)
rdar://105837040 * WIP: Store layout string in type metadata * WIP: More cases working * WIP: Layout strings almost working * Add layout string pointer to struct metadata * Fetch bytecode layout strings from metadata in runtime * More efficient bytecode layout * Add support for interpreted generics in layout strings * Layout string instantiation, take and more * Remove duplicate information from layout strings * Include size of previous object in next objects offset to reduce number of increments at runtime * Add support for existentials * Build type layout strings with StructBuilder to support target sizes and metadata pointers * Add support for resilient types * Properly cache layout strings in compiler * Generic resilient types working * Non-generic resilient types working * Instantiate resilient type in layout when possible * Fix a few issues around alignment and signing * Disable generics, fix static alignment * Fix MultiPayloadEnum size when no extra tag is necessary * Fixes after rebase * Cleanup * Fix most tests * Fix objcImplementattion and non-Darwin builds * Fix BytecodeLayouts on non-Darwin * Fix Linux build * Fix sizes in linux tests * Sign layout string pointers * Use nullptr instead of debug value
1 parent 2d52058 commit a8d4d57

File tree

154 files changed

+2907
-2228
lines changed

Some content is hidden

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

154 files changed

+2907
-2228
lines changed

docs/proposals/RuntimeValueWitness.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ copied, but do not need to be released or retained.
5858
I16 = 's',
5959
I32 = 'l',
6060
I64 = 'L',
61+
I128 = 'Q',
6162

6263
We also have reference types. While they are all 64bit sized, we need to
6364
differentiate between them because they have different ways of being

include/swift/ABI/Metadata.h

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,15 @@ struct MetadataDependency {
116116
}
117117
};
118118

119+
/// Prefix of a metadata header, containing a pointer to the
120+
/// type layout string.
121+
template <typename Runtime>
122+
struct TargetTypeMetadataLayoutPrefix {
123+
TargetSignedPointer<Runtime, const uint8_t *
124+
__ptrauth_swift_type_layout_string>
125+
layoutString;
126+
};
127+
119128
/// The header before a metadata object which appears on all type
120129
/// metadata. Note that heap metadata are not necessarily type
121130
/// metadata, even for objects of a heap type: for example, objects of
@@ -124,11 +133,25 @@ struct MetadataDependency {
124133
/// This case can be distinguished using the isTypeMetadata() flag
125134
/// on ClassMetadata.
126135
template <typename Runtime>
127-
struct TargetTypeMetadataHeader {
136+
struct TargetTypeMetadataHeaderBase {
128137
/// A pointer to the value-witnesses for this type. This is only
129138
/// present for type metadata.
130139
TargetPointer<Runtime, const ValueWitnessTable> ValueWitnesses;
131140
};
141+
142+
template <typename Runtime>
143+
struct TargetTypeMetadataHeader
144+
: TargetTypeMetadataLayoutPrefix<Runtime>,
145+
TargetTypeMetadataHeaderBase<Runtime> {
146+
147+
TargetTypeMetadataHeader() = default;
148+
constexpr TargetTypeMetadataHeader(
149+
const TargetTypeMetadataLayoutPrefix<Runtime> &layout,
150+
const TargetTypeMetadataHeaderBase<Runtime> &header)
151+
: TargetTypeMetadataLayoutPrefix<Runtime>(layout),
152+
TargetTypeMetadataHeaderBase<Runtime>(header) {}
153+
};
154+
132155
using TypeMetadataHeader = TargetTypeMetadataHeader<InProcess>;
133156

134157
/// A "full" metadata pointer is simply an adjusted address point on a
@@ -284,6 +307,17 @@ struct TargetMetadata {
284307
return isAnyKindOfClass(getKind());
285308
}
286309

310+
const uint8_t *getLayoutString() const {
311+
assert(hasLayoutString());
312+
if (isAnyClass()) {
313+
return asFullMetadata(
314+
reinterpret_cast<const TargetAnyClassMetadata<Runtime> *>(
315+
this))
316+
->layoutString;
317+
}
318+
return asFullMetadata(this)->layoutString;
319+
}
320+
287321
const ValueWitnessTable *getValueWitnesses() const {
288322
return asFullMetadata(this)->ValueWitnesses;
289323
}
@@ -295,6 +329,19 @@ struct TargetMetadata {
295329
void setValueWitnesses(const ValueWitnessTable *table) {
296330
asFullMetadata(this)->ValueWitnesses = table;
297331
}
332+
333+
void setLayoutString(const uint8_t *layoutString) {
334+
if (isAnyClass()) {
335+
asFullMetadata(reinterpret_cast<TargetAnyClassMetadata<Runtime> *>(this))
336+
->layoutString = layoutString;
337+
} else {
338+
asFullMetadata(this)->layoutString = layoutString;
339+
}
340+
}
341+
342+
bool hasLayoutString() const {
343+
return getTypeContextDescriptor()->hasLayoutString();
344+
}
298345

299346
// Define forwarders for value witnesses. These invoke this metadata's value
300347
// witness table with itself as the 'self' parameter.
@@ -445,7 +492,7 @@ struct TargetMetadata {
445492
/// The common structure of opaque metadata. Adds nothing.
446493
template <typename Runtime>
447494
struct TargetOpaqueMetadata {
448-
typedef TargetTypeMetadataHeader<Runtime> HeaderType;
495+
typedef TargetTypeMetadataHeaderBase<Runtime> HeaderType;
449496

450497
// We have to represent this as a member so we can list-initialize it.
451498
TargetMetadata<Runtime> base;
@@ -469,13 +516,16 @@ using HeapMetadataHeaderPrefix =
469516
/// The header present on all heap metadata.
470517
template <typename Runtime>
471518
struct TargetHeapMetadataHeader
472-
: TargetHeapMetadataHeaderPrefix<Runtime>,
473-
TargetTypeMetadataHeader<Runtime> {
519+
: TargetTypeMetadataLayoutPrefix<Runtime>,
520+
TargetHeapMetadataHeaderPrefix<Runtime>,
521+
TargetTypeMetadataHeaderBase<Runtime> {
474522
constexpr TargetHeapMetadataHeader(
523+
const TargetTypeMetadataLayoutPrefix<Runtime> &typeLayoutPrefix,
475524
const TargetHeapMetadataHeaderPrefix<Runtime> &heapPrefix,
476-
const TargetTypeMetadataHeader<Runtime> &typePrefix)
477-
: TargetHeapMetadataHeaderPrefix<Runtime>(heapPrefix),
478-
TargetTypeMetadataHeader<Runtime>(typePrefix) {}
525+
const TargetTypeMetadataHeaderBase<Runtime> &typePrefix)
526+
: TargetTypeMetadataLayoutPrefix<Runtime>(typeLayoutPrefix),
527+
TargetHeapMetadataHeaderPrefix<Runtime>(heapPrefix),
528+
TargetTypeMetadataHeaderBase<Runtime>(typePrefix) {}
479529
};
480530
using HeapMetadataHeader =
481531
TargetHeapMetadataHeader<InProcess>;
@@ -1511,6 +1561,7 @@ using MetatypeMetadata = TargetMetatypeMetadata<InProcess>;
15111561
template <typename Runtime>
15121562
struct TargetTupleTypeMetadata : public TargetMetadata<Runtime> {
15131563
using StoredSize = typename Runtime::StoredSize;
1564+
using HeaderType = TargetTypeMetadataHeaderBase<Runtime>;
15141565
TargetTupleTypeMetadata() = default;
15151566
constexpr TargetTupleTypeMetadata(const TargetMetadata<Runtime> &base,
15161567
uint32_t numElements,
@@ -1696,6 +1747,7 @@ struct TargetExistentialTypeMetadata
16961747
TargetExistentialTypeMetadata<Runtime>,
16971748
ConstTargetMetadataPointer<Runtime, TargetMetadata>,
16981749
TargetProtocolDescriptorRef<Runtime>> {
1750+
using HeaderType = TargetTypeMetadataHeaderBase<Runtime>;
16991751

17001752
private:
17011753
using ProtocolDescriptorRef = TargetProtocolDescriptorRef<Runtime>;
@@ -3642,6 +3694,10 @@ class TargetTypeContextDescriptor
36423694
return getTypeContextDescriptorFlags().hasCanonicalMetadataPrespecializations();
36433695
}
36443696

3697+
bool hasLayoutString() const {
3698+
return getTypeContextDescriptorFlags().hasLayoutString();
3699+
}
3700+
36453701
/// Given that this type has foreign metadata initialization, return the
36463702
/// control structure for it.
36473703
const TargetForeignMetadataInitialization<Runtime> &

include/swift/ABI/MetadataValues.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,6 +1445,8 @@ namespace SpecialPointerAuthDiscriminators {
14451445

14461446
// Relative protocol witness table descriminator
14471447
const uint16_t RelativeProtocolWitnessTable = 0xb830; // = 47152
1448+
1449+
const uint16_t TypeLayoutString = 0x8b65; // = 35685
14481450
}
14491451

14501452
/// The number of arguments that will be passed directly to a generic
@@ -1598,6 +1600,9 @@ class TypeContextDescriptorFlags : public FlagSet<uint16_t> {
15981600
/// prespecializations.
15991601
HasCanonicalMetadataPrespecializations = 3,
16001602

1603+
/// Set if the metadata contains a pointer to a layout string
1604+
HasLayoutString = 4,
1605+
16011606
// Type-specific flags:
16021607

16031608
/// Set if the class is an actor.
@@ -1680,6 +1685,10 @@ class TypeContextDescriptorFlags : public FlagSet<uint16_t> {
16801685

16811686
FLAGSET_DEFINE_FLAG_ACCESSORS(HasCanonicalMetadataPrespecializations, hasCanonicalMetadataPrespecializations, setHasCanonicalMetadataPrespecializations)
16821687

1688+
FLAGSET_DEFINE_FLAG_ACCESSORS(HasLayoutString,
1689+
hasLayoutString,
1690+
setHasLayoutString)
1691+
16831692
FLAGSET_DEFINE_FLAG_ACCESSORS(Class_HasVTable,
16841693
class_hasVTable,
16851694
class_setHasVTable)

include/swift/AST/IRGenOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ struct PointerAuthOptions : clang::PointerAuthOptions {
207207

208208
/// Relative protocol witness table descriminator.
209209
PointerAuthSchema RelativeProtocolWitnessTable;
210+
211+
/// Type layout string descriminator.
212+
PointerAuthSchema TypeLayoutString;
210213
};
211214

212215
enum class JITDebugArtifact : unsigned {

include/swift/Basic/Features.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ EXPERIMENTAL_FEATURE(TypeWitnessSystemInference, false)
118118
EXPERIMENTAL_FEATURE(LayoutPrespecialization, true)
119119
EXPERIMENTAL_FEATURE(ModuleInterfaceExportAs, true)
120120

121+
/// Whether to enable experimental layout string value witnesses
122+
EXPERIMENTAL_FEATURE(LayoutStringValueWitnesses, true)
123+
121124
/// Whether to enable experimental differentiable programming features:
122125
/// `@differentiable` declaration attribute, etc.
123126
EXPERIMENTAL_FEATURE(DifferentiableProgramming, false)

include/swift/Runtime/Config.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ extern uintptr_t __COMPATIBILITY_LIBRARIES_CANNOT_CHECK_THE_IS_SWIFT_BIT_DIRECTL
310310
#define __ptrauth_swift_objc_superclass \
311311
__ptrauth(ptrauth_key_process_independent_data, 1, \
312312
swift::SpecialPointerAuthDiscriminators::ObjCSuperclass)
313-
#define __ptrauth_swift_nonunique_extended_existential_type_shape \
313+
#define __ptrauth_swift_nonunique_extended_existential_type_shape \
314314
__ptrauth(ptrauth_key_process_independent_data, 1, \
315315
SpecialPointerAuthDiscriminators::NonUniqueExtendedExistentialTypeShape)
316316
#define swift_ptrauth_sign_opaque_read_resume_function(__fn, __buffer) \
@@ -323,6 +323,9 @@ extern uintptr_t __COMPATIBILITY_LIBRARIES_CANNOT_CHECK_THE_IS_SWIFT_BIT_DIRECTL
323323
ptrauth_key_process_independent_code, \
324324
ptrauth_blend_discriminator(__buffer, \
325325
SpecialPointerAuthDiscriminators::OpaqueModifyResumeFunction))
326+
#define __ptrauth_swift_type_layout_string \
327+
__ptrauth(ptrauth_key_process_independent_data, 1, \
328+
SpecialPointerAuthDiscriminators::TypeLayoutString)
326329
#else
327330
#define SWIFT_PTRAUTH 0
328331
#define __ptrauth_swift_function_pointer(__typekey)
@@ -350,6 +353,7 @@ extern uintptr_t __COMPATIBILITY_LIBRARIES_CANNOT_CHECK_THE_IS_SWIFT_BIT_DIRECTL
350353
#define __ptrauth_swift_dynamic_replacement_key
351354
#define swift_ptrauth_sign_opaque_read_resume_function(__fn, __buffer) (__fn)
352355
#define swift_ptrauth_sign_opaque_modify_resume_function(__fn, __buffer) (__fn)
356+
#define __ptrauth_swift_type_layout_string
353357
#endif
354358

355359
#ifdef __cplusplus

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2160,34 +2160,61 @@ FUNCTION(StoreMultiPayloadEnumTagSinglePayload,
21602160
ATTRS(NoUnwind),
21612161
EFFECT(NoEffect))
21622162

2163-
// void *swift_generic_destroy(opaque*, const Metadata* type, const char*);
2163+
// void swift_generic_destroy(opaque*, const Metadata* type);
21642164
FUNCTION(GenericDestroy,
21652165
swift_generic_destroy,
21662166
C_CC, AlwaysAvailable,
21672167
RETURNS(VoidTy),
2168-
ARGS(Int8PtrTy, TypeMetadataPtrTy, Int8PtrTy),
2168+
ARGS(Int8PtrTy, TypeMetadataPtrTy),
21692169
ATTRS(NoUnwind),
21702170
EFFECT(Deallocating))
21712171

21722172

2173-
// void *swift_generic_assign(opaque* dest, opaque* src, const Metadata* type, const char*, bool isTake);
2174-
FUNCTION(GenericAssign,
2175-
swift_generic_assign,
2173+
// void *swift_generic_assignWithCopy(opaque* dest, opaque* src, const Metadata* type);
2174+
FUNCTION(GenericAssignWithCopy,
2175+
swift_generic_assignWithCopy,
21762176
C_CC, AlwaysAvailable,
2177-
RETURNS(VoidTy),
2178-
ARGS(Int8PtrTy, Int8PtrTy, TypeMetadataPtrTy, Int8PtrTy, Int1Ty),
2177+
RETURNS(Int8PtrTy),
2178+
ARGS(Int8PtrTy, Int8PtrTy, TypeMetadataPtrTy),
21792179
ATTRS(NoUnwind),
21802180
EFFECT(Refcounting, Deallocating))
21812181

2182-
// void *swift_generic_initialize(opaque* dest, opaque* src, const Metadata* type, const char*, bool isTake);
2183-
FUNCTION(GenericInitialize,
2184-
swift_generic_initialize,
2182+
// void *swift_generic_assignWithTake(opaque* dest, opaque* src, const Metadata* type);
2183+
FUNCTION(GenericAssignWithTake,
2184+
swift_generic_assignWithTake,
21852185
C_CC, AlwaysAvailable,
2186-
RETURNS(VoidTy),
2187-
ARGS(Int8PtrTy, Int8PtrTy, TypeMetadataPtrTy, Int8PtrTy, Int1Ty),
2186+
RETURNS(Int8PtrTy),
2187+
ARGS(Int8PtrTy, Int8PtrTy, TypeMetadataPtrTy),
2188+
ATTRS(NoUnwind),
2189+
EFFECT(Refcounting, Deallocating))
2190+
2191+
// void *swift_generic_initWithCopy(opaque* dest, opaque* src, const Metadata* type);
2192+
FUNCTION(GenericInitWithCopy,
2193+
swift_generic_initWithCopy,
2194+
C_CC, AlwaysAvailable,
2195+
RETURNS(Int8PtrTy),
2196+
ARGS(Int8PtrTy, Int8PtrTy, TypeMetadataPtrTy),
21882197
ATTRS(NoUnwind),
21892198
EFFECT(Refcounting))
21902199

2200+
// void *swift_generic_initWithTake(opaque* dest, opaque* src, const Metadata* type);
2201+
FUNCTION(GenericInitWithTake,
2202+
swift_generic_initWithTake,
2203+
C_CC, AlwaysAvailable,
2204+
RETURNS(Int8PtrTy),
2205+
ARGS(Int8PtrTy, Int8PtrTy, TypeMetadataPtrTy),
2206+
ATTRS(NoUnwind),
2207+
EFFECT(Refcounting))
2208+
2209+
// void swift_generic_instantiateLayoutString(const uint8_t* layoutStr, Metadata* type);
2210+
FUNCTION(GenericInstantiateLayoutString,
2211+
swift_generic_instantiateLayoutString,
2212+
C_CC, AlwaysAvailable,
2213+
RETURNS(VoidTy),
2214+
ARGS(Int8PtrTy, TypeMetadataPtrTy),
2215+
ATTRS(NoUnwind),
2216+
EFFECT(MetaData))
2217+
21912218
#undef RETURNS
21922219
#undef ARGS
21932220
#undef ATTRS

lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3110,6 +3110,10 @@ static bool usesFeatureLayoutPrespecialization(Decl *decl) {
31103110
return false;
31113111
}
31123112

3113+
static bool usesFeatureLayoutStringValueWitnesses(Decl *decl) {
3114+
return false;
3115+
}
3116+
31133117
static bool usesFeatureModuleInterfaceExportAs(Decl *decl) {
31143118
return false;
31153119
}

lib/IRGen/ClassMetadataVisitor.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,12 @@ template <class Impl> class ClassMetadataVisitor
6565

6666
public:
6767
void layout() {
68-
static_assert(MetadataAdjustmentIndex::Class == 2,
68+
static_assert(MetadataAdjustmentIndex::Class == 3,
6969
"Adjustment index must be synchronized with this layout");
7070

71+
// Pointer to layout string
72+
asImpl().addLayoutStringPointer();
73+
7174
// HeapMetadata header.
7275
asImpl().addDestructorFunction();
7376

@@ -225,6 +228,7 @@ class ClassMetadataScanner : public ClassMetadataVisitor<Impl> {
225228
void addNominalTypeDescriptor() { addPointer(); }
226229
void addIVarDestroyer() { addPointer(); }
227230
void addValueWitnessTable() { addPointer(); }
231+
void addLayoutStringPointer() { addPointer(); }
228232
void addDestructorFunction() { addPointer(); }
229233
void addSuperclass() { addPointer(); }
230234
void addClassFlags() { addInt32(); }

lib/IRGen/EnumMetadataVisitor.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,11 @@ template <class Impl> class EnumMetadataVisitor
4444

4545
public:
4646
void layout() {
47-
static_assert(MetadataAdjustmentIndex::ValueType == 1,
47+
static_assert(MetadataAdjustmentIndex::ValueType == 2,
4848
"Adjustment index must be synchronized with this layout");
4949

50+
asImpl().addLayoutStringPointer();
51+
5052
// Metadata header.
5153
super::layout();
5254

@@ -91,6 +93,7 @@ class EnumMetadataScanner : public EnumMetadataVisitor<Impl> {
9193

9294
public:
9395
void addMetadataFlags() { addPointer(); }
96+
void addLayoutStringPointer() { addPointer(); }
9497
void addValueWitnessTable() { addPointer(); }
9598
void addNominalTypeDescriptor() { addPointer(); }
9699
void addGenericRequirement(GenericRequirement requirement) { addPointer(); }

lib/IRGen/ForeignClassMetadataVisitor.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class ForeignClassMetadataVisitor
3535
: super(IGM), Target(target) {}
3636

3737
void layout() {
38+
asImpl().addLayoutStringPointer();
3839
super::layout();
3940
asImpl().addNominalTypeDescriptor();
4041
asImpl().addSuperclass();
@@ -60,6 +61,7 @@ class ForeignClassMetadataScanner : public ForeignClassMetadataVisitor<Impl> {
6061

6162
public:
6263
void addMetadataFlags() { addPointer(); }
64+
void addLayoutStringPointer() { addPointer(); }
6365
void addValueWitnessTable() { addPointer(); }
6466
void addNominalTypeDescriptor() { addPointer(); }
6567
void addSuperclass() { addPointer(); }
@@ -83,6 +85,7 @@ class ForeignReferenceTypeMetadataVisitor
8385
: super(IGM), Target(target) {}
8486

8587
void layout() {
88+
asImpl().addLayoutStringPointer();
8689
super::layout();
8790
asImpl().addNominalTypeDescriptor();
8891
asImpl().addReservedWord();

lib/IRGen/GenArchetype.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,10 @@ class OpaqueArchetypeTypeInfo
116116
collector.collectTypeMetadataForLayout(T);
117117
}
118118

119-
TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,
120-
SILType T) const override {
119+
TypeLayoutEntry
120+
*buildTypeLayoutEntry(IRGenModule &IGM,
121+
SILType T,
122+
bool useStructLayouts) const override {
121123
return IGM.typeLayoutCache.getOrCreateArchetypeEntry(T.getObjectType());
122124
}
123125
};

0 commit comments

Comments
 (0)