Skip to content

[ABI] Collapse generic witness table into protocol conformance record. #19994

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Globals
global ::= protocol-conformance 'WP' // protocol witness table
global ::= protocol-conformance 'Wa' // protocol witness table accessor

global ::= protocol-conformance 'WG' // generic protocol witness table
global ::= protocol-conformance 'WG' // generic protocol witness table (HISTORICAL)
global ::= protocol-conformance 'Wp' // protocol witness table pattern
global ::= protocol-conformance 'Wr' // resilient witness table (HISTORICAL)
global ::= protocol-conformance 'WI' // generic protocol witness table instantiation function
Expand Down
21 changes: 18 additions & 3 deletions include/swift/ABI/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -1989,7 +1989,7 @@ struct TargetResilientWitnessTable final
using ResilientWitnessTable = TargetResilientWitnessTable<InProcess>;

/// \brief The control structure of a generic or resilient protocol
/// conformance.
/// conformance, which is embedded in the protocol conformance descriptor.
///
/// Witness tables need to be instantiated at runtime in these cases:
/// - For a generic conforming type, associated type requirements might be
Expand Down Expand Up @@ -2245,14 +2245,16 @@ struct TargetProtocolConformanceDescriptor final
RelativeContextPointer<Runtime>,
TargetGenericRequirementDescriptor<Runtime>,
TargetResilientWitnessesHeader<Runtime>,
TargetResilientWitness<Runtime>> {
TargetResilientWitness<Runtime>,
TargetGenericWitnessTable<Runtime>> {

using TrailingObjects = swift::ABI::TrailingObjects<
TargetProtocolConformanceDescriptor<Runtime>,
RelativeContextPointer<Runtime>,
TargetGenericRequirementDescriptor<Runtime>,
TargetResilientWitnessesHeader<Runtime>,
TargetResilientWitness<Runtime>>;
TargetResilientWitness<Runtime>,
TargetGenericWitnessTable<Runtime>>;
friend TrailingObjects;

template<typename T>
Expand All @@ -2268,6 +2270,7 @@ struct TargetProtocolConformanceDescriptor final

using ResilientWitnessesHeader = TargetResilientWitnessesHeader<Runtime>;
using ResilientWitness = TargetResilientWitness<Runtime>;
using GenericWitnessTable = TargetGenericWitnessTable<Runtime>;

private:
/// The protocol being conformed to.
Expand Down Expand Up @@ -2375,6 +2378,14 @@ struct TargetProtocolConformanceDescriptor final
numTrailingObjects(OverloadToken<ResilientWitness>()));
}

ConstTargetPointer<Runtime, GenericWitnessTable>
getGenericWitnessTable() const {
if (!Flags.hasGenericWitnessTable())
return nullptr;

return this->template getTrailingObjects<GenericWitnessTable>();
}

#if !defined(NDEBUG) && SWIFT_OBJC_INTEROP
void dump() const;
#endif
Expand Down Expand Up @@ -2409,6 +2420,10 @@ struct TargetProtocolConformanceDescriptor final
->NumWitnesses
: 0;
}

size_t numTrailingObjects(OverloadToken<GenericWitnessTable>) const {
return Flags.hasGenericWitnessTable() ? 1 : 0;
}
};
using ProtocolConformanceDescriptor
= TargetProtocolConformanceDescriptor<InProcess>;
Expand Down
15 changes: 15 additions & 0 deletions include/swift/ABI/MetadataValues.h
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,7 @@ class ConformanceFlags {
NumConditionalRequirementsShift = 8,

HasResilientWitnessesMask = 0x01 << 16,
HasGenericWitnessTableMask = 0x01 << 17,
};

int_type Value;
Expand Down Expand Up @@ -668,6 +669,14 @@ class ConformanceFlags {
: 0));
}

ConformanceFlags withHasGenericWitnessTable(
bool hasGenericWitnessTable) const {
return ConformanceFlags((Value & ~HasGenericWitnessTableMask)
| (hasGenericWitnessTable
? HasGenericWitnessTableMask
: 0));
}

/// Retrieve the conformance kind.
ConformanceKind getConformanceKind() const {
return ConformanceKind(Value & ConformanceKindMask);
Expand Down Expand Up @@ -709,6 +718,12 @@ class ConformanceFlags {
return Value & HasResilientWitnessesMask;
}

/// Whether this conformance has a generic witness table that may need to
/// be instantiated.
bool hasGenericWitnessTable() const {
return Value & HasGenericWitnessTableMask;
}

int_type getIntValue() const { return Value; }
};

Expand Down
11 changes: 0 additions & 11 deletions include/swift/IRGen/Linking.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,6 @@ class LinkEntity {
/// ProtocolConformance*.
ProtocolWitnessTableAccessFunction,

/// A generic protocol witness table cache. The secondary pointer is a
/// ProtocolConformance*.
GenericProtocolWitnessTableCache,

/// The instantiation function for a generic protocol witness table.
/// The secondary pointer is a ProtocolConformance*.
GenericProtocolWitnessTableInstantiationFunction,
Expand Down Expand Up @@ -738,13 +734,6 @@ class LinkEntity {
return entity;
}

static LinkEntity
forGenericProtocolWitnessTableCache(const ProtocolConformance *C) {
LinkEntity entity;
entity.setForProtocolConformance(Kind::GenericProtocolWitnessTableCache, C);
return entity;
}

static LinkEntity
forGenericProtocolWitnessTableInstantiationFunction(
const ProtocolConformance *C) {
Expand Down
14 changes: 7 additions & 7 deletions include/swift/Runtime/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -387,10 +387,10 @@ MetadataResponse swift_checkMetadataState(MetadataRequest request,

/// Instantiate a resilient or generic protocol witness table.
///
/// \param genericTable - The witness table template for the
/// conformance. It may either have fields that require runtime
/// initialization, or be missing requirements at the end for
/// which default witnesses are available.
/// \param conformance - The protocol conformance descriptor, which
/// contains the generic witness table record. It may either have fields
/// that require runtime initialization, or be missing requirements at the
/// end for which default witnesses are available.
///
/// \param type - The conforming type, used to form a uniquing key
/// for the conformance. If the witness table is not dependent on
Expand All @@ -406,9 +406,9 @@ MetadataResponse swift_checkMetadataState(MetadataRequest request,
/// conformances.
SWIFT_RUNTIME_EXPORT
const WitnessTable *
swift_getGenericWitnessTable(GenericWitnessTable *genericTable,
const Metadata *type,
void **const *instantiationArgs);
swift_instantiateWitnessTable(ProtocolConformanceDescriptor *conformance,
const Metadata *type,
void **const *instantiationArgs);

/// Retrieve an associated type witness from the given witness table.
///
Expand Down
10 changes: 5 additions & 5 deletions include/swift/Runtime/RuntimeFunctions.def
Original file line number Diff line number Diff line change
Expand Up @@ -635,12 +635,12 @@ FUNCTION(CheckMetadataState, swift_checkMetadataState, SwiftCC,
ATTRS(NoUnwind, ReadOnly))

// const ProtocolWitnessTable *
// swift_getGenericWitnessTable(GenericProtocolWitnessTable *genericTable,
// const Metadata *type,
// void ** const *instantiationArgs);
FUNCTION(GetGenericWitnessTable, swift_getGenericWitnessTable, C_CC,
// swift_instantiateWitnessTable(const ProtocolConformanceDescriptor *conf,
// const Metadata *type,
// void ** const *instantiationArgs);
FUNCTION(InstantiateWitnessTable, swift_instantiateWitnessTable, C_CC,
RETURNS(WitnessTablePtrTy),
ARGS(getGenericWitnessTableCacheTy()->getPointerTo(),
ARGS(ProtocolConformanceDescriptorPtrTy,
TypeMetadataPtrTy,
WitnessTablePtrPtrTy),
ATTRS(NoUnwind, ReadOnly))
Expand Down
28 changes: 0 additions & 28 deletions lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3644,15 +3644,6 @@ IRGenModule::getResilienceExpansionForLayout(SILGlobalVariable *global) {
return ResilienceExpansion::Maximal;
}

llvm::Constant *IRGenModule::
getAddrOfGenericWitnessTableCache(const NormalProtocolConformance *conf,
ForDefinition_t forDefinition) {
auto entity = LinkEntity::forGenericProtocolWitnessTableCache(conf);
auto expectedTy = getGenericWitnessTableCacheTy();
return getAddrOfLLVMVariable(entity, getPointerAlignment(), forDefinition,
expectedTy, DebugTypeInfo());
}

llvm::Function *
IRGenModule::getAddrOfGenericWitnessTableInstantiationFunction(
const NormalProtocolConformance *conf) {
Expand All @@ -3675,25 +3666,6 @@ IRGenModule::getAddrOfGenericWitnessTableInstantiationFunction(
return entry;
}

llvm::StructType *IRGenModule::getGenericWitnessTableCacheTy() {
if (auto ty = GenericWitnessTableCacheTy) return ty;

GenericWitnessTableCacheTy = llvm::StructType::create(getLLVMContext(),
{
// WitnessTableSizeInWords
Int16Ty,
// WitnessTablePrivateSizeInWords + RequiresInstantiation bit
Int16Ty,
// Pattern
RelativeAddressTy,
// Instantiator
RelativeAddressTy,
// PrivateData
RelativeAddressTy
}, "swift.generic_witness_table_cache");
return GenericWitnessTableCacheTy;
}

/// Fetch the witness table access function for a protocol conformance.
llvm::Function *
IRGenModule::getAddrOfWitnessTableAccessFunction(
Expand Down
Loading