Skip to content

Commit 7e6f523

Browse files
committed
[Runtime] Move conformance kind into low bits of witness table reference.
Move the 2-bit conformance reference kind from the conformance flags (which is meant to go away) into the lower two bits of the witness table offset.
1 parent 8c668ba commit 7e6f523

File tree

6 files changed

+36
-49
lines changed

6 files changed

+36
-49
lines changed

docs/ABI/TypeMetadata.rst

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -417,21 +417,23 @@ section, which is scanned by the Swift runtime when needed (e.g., in response to
417417
a `swift_conformsToProtocol()` query). Each protocol conformance record
418418
contains:
419419

420-
- The `protocol descriptor`_ describing the protocol of the conformance.
421-
- A reference to the metadata for the **conforming type**, whose form is
420+
- The `protocol descriptor`_ describing the protocol of the conformance,
421+
represented as an indirect 32-bit offset relative to the field.
422+
- A reference to the metadata for the **conforming type**, represented as
423+
an indirect 32-bit offset relative to the field, whose form is
422424
determined by the **protocol conformance flags** described below.
423425
- The **witness table field** that provides access to the witness table
424-
describing the conformance itself; the form of this field is determined by the
425-
**protocol conformance flags** described below.
426-
- The **protocol conformance flags** is a 32-bit field comprised of:
427-
428-
* **Bits 0-3** contain the type metadata record kind, which indicates how
429-
the **conforming type** field is encoded.
430-
* **Bits 4-5** contain the kind of witness table. The value can be one of:
431-
426+
describing the conformance itself; the form of this field is determined by
427+
the lower two bits, and can be one of:
432428
0. The **witness table field** is a reference to a witness table.
433429
1. The **witness table field** is a reference to a **witness table
434430
accessor** function for an unconditional conformance.
435431
2. The **witness table field** is a reference to a **witness table
436432
accessor** function for a conditional conformance.
433+
3. Reserved for future use.
434+
All references are direct 32-bit offsets relative to the field.
435+
- The **protocol conformance flags** is a 32-bit field comprised of:
436+
437+
* **Bits 0-3** contain the type metadata record kind, which indicates how
438+
the **conforming type** field is encoded.
437439

include/swift/ABI/MetadataValues.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -253,13 +253,6 @@ struct TypeMetadataRecordFlags {
253253

254254
// Protocol conformance discriminant
255255
struct ProtocolConformanceFlags : public TypeMetadataRecordFlags {
256-
private:
257-
enum : int_type {
258-
ConformanceKindMask = 0x00000030U,
259-
ConformanceKindShift = 4,
260-
};
261-
262-
public:
263256
constexpr ProtocolConformanceFlags() : TypeMetadataRecordFlags(0) {}
264257
constexpr ProtocolConformanceFlags(int_type Data) : TypeMetadataRecordFlags(Data) {}
265258

@@ -268,15 +261,6 @@ struct ProtocolConformanceFlags : public TypeMetadataRecordFlags {
268261
return ProtocolConformanceFlags(
269262
(Data & ~TypeKindMask) | (int_type(ptk) << TypeKindShift));
270263
}
271-
constexpr ProtocolConformanceReferenceKind getConformanceKind() const {
272-
return ProtocolConformanceReferenceKind((Data & ConformanceKindMask)
273-
>> ConformanceKindShift);
274-
}
275-
constexpr ProtocolConformanceFlags withConformanceKind(
276-
ProtocolConformanceReferenceKind pck) const {
277-
return ProtocolConformanceFlags(
278-
(Data & ~ConformanceKindMask) | (int_type(pck) << ConformanceKindShift));
279-
}
280264
};
281265

282266
/// Flag that indicates whether an existential type is class-constrained or not.

include/swift/Basic/RelativePointer.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -398,9 +398,6 @@ class RelativeDirectPointerIntPair {
398398
= delete;
399399

400400
static Offset getMask() {
401-
static_assert(alignof(PointeeTy) >= alignof(Offset),
402-
"pointee alignment must be at least as strict as offset type");
403-
404401
return alignof(Offset) - 1;
405402
}
406403

include/swift/Runtime/Metadata.h

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2555,11 +2555,15 @@ struct TargetProtocolConformanceRecord {
25552555
// The conformance, or a generator function for the conformance.
25562556
union {
25572557
/// A direct reference to the witness table for the conformance.
2558-
RelativeDirectPointer<const WitnessTable> WitnessTable;
2558+
RelativeDirectPointerIntPair<const WitnessTable,
2559+
ProtocolConformanceReferenceKind>
2560+
WitnessTable;
25592561

25602562
/// A function that produces the witness table given an instance of the
25612563
/// type.
2562-
RelativeDirectPointer<WitnessTableAccessorFn> WitnessTableAccessor;
2564+
RelativeDirectPointerIntPair<WitnessTableAccessorFn,
2565+
ProtocolConformanceReferenceKind>
2566+
WitnessTableAccessor;
25632567
};
25642568

25652569
/// Flags describing the protocol conformance.
@@ -2569,16 +2573,17 @@ struct TargetProtocolConformanceRecord {
25692573
const ProtocolDescriptor *getProtocol() const {
25702574
return Protocol;
25712575
}
2572-
2576+
25732577
ProtocolConformanceFlags getFlags() const {
25742578
return Flags;
25752579
}
25762580

25772581
TypeMetadataRecordKind getTypeKind() const {
25782582
return Flags.getTypeKind();
25792583
}
2584+
25802585
ProtocolConformanceReferenceKind getConformanceKind() const {
2581-
return Flags.getConformanceKind();
2586+
return WitnessTable.getInt();
25822587
}
25832588

25842589
const TargetMetadata<Runtime> *getDirectType() const {
@@ -2658,7 +2663,7 @@ struct TargetProtocolConformanceRecord {
26582663

26592664
/// Get the directly-referenced static witness table.
26602665
const swift::WitnessTable *getStaticWitnessTable() const {
2661-
switch (Flags.getConformanceKind()) {
2666+
switch (getConformanceKind()) {
26622667
case ProtocolConformanceReferenceKind::WitnessTable:
26632668
break;
26642669

@@ -2669,11 +2674,11 @@ struct TargetProtocolConformanceRecord {
26692674
case ProtocolConformanceReferenceKind::Reserved:
26702675
break;
26712676
}
2672-
return WitnessTable;
2677+
return WitnessTable.getPointer();
26732678
}
26742679

26752680
WitnessTableAccessorFn *getWitnessTableAccessor() const {
2676-
switch (Flags.getConformanceKind()) {
2681+
switch (getConformanceKind()) {
26772682
case ProtocolConformanceReferenceKind::WitnessTableAccessor:
26782683
case ProtocolConformanceReferenceKind::ConditionalWitnessTableAccessor:
26792684
case ProtocolConformanceReferenceKind::Reserved:
@@ -2682,7 +2687,7 @@ struct TargetProtocolConformanceRecord {
26822687
case ProtocolConformanceReferenceKind::WitnessTable:
26832688
assert(false && "not witness table accessor");
26842689
}
2685-
return WitnessTableAccessor;
2690+
return WitnessTableAccessor.getPointer();
26862691
}
26872692

26882693
/// Get the canonical metadata for the type referenced by this record, or

lib/IRGen/GenDecl.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2340,33 +2340,32 @@ llvm::Constant *IRGenModule::emitProtocolConformances() {
23402340
// Figure out what kind of witness table we have.
23412341
auto flags = typeEntity.flags;
23422342
llvm::Constant *witnessTableVar;
2343+
ProtocolConformanceReferenceKind conformanceKind;
23432344
if (!isResilient(conformance->getProtocol(),
23442345
ResilienceExpansion::Maximal) &&
23452346
conformance->getConditionalRequirements().empty()) {
2346-
flags = flags.withConformanceKind(
2347-
ProtocolConformanceReferenceKind::WitnessTable);
2347+
conformanceKind = ProtocolConformanceReferenceKind::WitnessTable;
23482348

23492349
// If the conformance is in this object's table, then the witness table
23502350
// should also be in this object file, so we can always directly reference
23512351
// it.
23522352
witnessTableVar = getAddrOfWitnessTable(conformance);
23532353
} else {
23542354
if (conformance->getConditionalRequirements().empty()) {
2355-
flags = flags.withConformanceKind(
2356-
ProtocolConformanceReferenceKind::WitnessTableAccessor);
2355+
conformanceKind =
2356+
ProtocolConformanceReferenceKind::WitnessTableAccessor;
23572357
} else {
2358-
flags = flags.withConformanceKind(
2359-
ProtocolConformanceReferenceKind::ConditionalWitnessTableAccessor);
2358+
conformanceKind =
2359+
ProtocolConformanceReferenceKind::ConditionalWitnessTableAccessor;
23602360
}
23612361

23622362
witnessTableVar = getAddrOfWitnessTableAccessFunction(
23632363
conformance, ForDefinition);
23642364
}
23652365

23662366
// Relative reference to the witness table.
2367-
auto witnessTableRef =
2368-
ConstantReference(witnessTableVar, ConstantReference::Direct);
2369-
record.addRelativeAddress(witnessTableRef);
2367+
record.addTaggedRelativeOffset(RelativeAddressTy, witnessTableVar,
2368+
static_cast<unsigned>(conformanceKind));
23702369

23712370
// Flags.
23722371
record.addInt(Int32Ty, flags.getValue());

test/IRGen/protocol_conformance_records.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,9 @@ public protocol Spoon { }
9393
// -- nominal type descriptor
9494
// CHECK-SAME: @_T028protocol_conformance_records17NativeGenericTypeVMn
9595
// -- witness table accessor
96-
// CHECK-SAME: @_T028protocol_conformance_records17NativeGenericTypeVyxGAA5SpoonA2aERzlWa
97-
// -- flags 0x04: unique nominal type descriptor + conditional accessor
98-
// CHECK-SAME: i32 36
96+
// CHECK-SAME: i32 add{{.*}}@_T028protocol_conformance_records17NativeGenericTypeVyxGAA5SpoonA2aERzlWa{{.*}}i32 2),
97+
// -- flags 0x04: unique nominal type descriptor
98+
// CHECK-SAME: i32 4
9999
// CHECK-SAME: }
100100
extension NativeGenericType : Spoon where T: Spoon {
101101
public func runce() {}

0 commit comments

Comments
 (0)