mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
"Accessibility" has a different meaning for app developers, so we've already deliberately excised it from our diagnostics in favor of terms like "access control" and "access level". Do the same in the compiler now that we aren't constantly pulling things into the release branch. This commit changes the 'Accessibility' enum to be named 'AccessLevel'.
174 lines
6.3 KiB
C++
174 lines
6.3 KiB
C++
//===--- SILWitnessTable.cpp - Defines the SILWitnessTable class ----------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the SILWitnessTable class, which is used to map a protocol
|
|
// conformance for a type to its implementing SILFunctions. This information is
|
|
// (FIXME will be) used by IRGen to create witness tables for protocol dispatch.
|
|
// It can also be used by generic specialization and existential
|
|
// devirtualization passes to promote witness_method and protocol_method
|
|
// instructions to static function_refs.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/SIL/SILWitnessTable.h"
|
|
#include "swift/AST/ASTMangler.h"
|
|
#include "swift/AST/Module.h"
|
|
#include "swift/AST/ProtocolConformance.h"
|
|
#include "swift/SIL/SILModule.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
|
|
using namespace swift;
|
|
|
|
static std::string mangleConstant(NormalProtocolConformance *C) {
|
|
Mangle::ASTMangler Mangler;
|
|
return Mangler.mangleWitnessTable(C);
|
|
}
|
|
|
|
void SILWitnessTable::addWitnessTable() {
|
|
// Make sure we have not seen this witness table yet.
|
|
assert(Mod.WitnessTableMap.find(Conformance) ==
|
|
Mod.WitnessTableMap.end() && "Attempting to create duplicate "
|
|
"witness table.");
|
|
Mod.WitnessTableMap[Conformance] = this;
|
|
Mod.witnessTables.push_back(this);
|
|
}
|
|
|
|
SILWitnessTable *
|
|
SILWitnessTable::create(SILModule &M, SILLinkage Linkage,
|
|
IsSerialized_t Serialized,
|
|
NormalProtocolConformance *Conformance,
|
|
ArrayRef<SILWitnessTable::Entry> entries) {
|
|
assert(Conformance && "Cannot create a witness table for a null "
|
|
"conformance.");
|
|
|
|
// Create the mangled name of our witness table...
|
|
Identifier Name = M.getASTContext().getIdentifier(mangleConstant(Conformance));
|
|
|
|
// Allocate the witness table and initialize it.
|
|
void *buf = M.allocate(sizeof(SILWitnessTable), alignof(SILWitnessTable));
|
|
SILWitnessTable *wt = ::new (buf) SILWitnessTable(M, Linkage, Serialized,
|
|
Name.str(), Conformance, entries);
|
|
|
|
wt->addWitnessTable();
|
|
|
|
// Return the resulting witness table.
|
|
return wt;
|
|
}
|
|
|
|
SILWitnessTable *
|
|
SILWitnessTable::create(SILModule &M, SILLinkage Linkage,
|
|
NormalProtocolConformance *Conformance) {
|
|
assert(Conformance && "Cannot create a witness table for a null "
|
|
"conformance.");
|
|
|
|
// Create the mangled name of our witness table...
|
|
Identifier Name = M.getASTContext().getIdentifier(mangleConstant(Conformance));
|
|
|
|
|
|
// Allocate the witness table and initialize it.
|
|
void *buf = M.allocate(sizeof(SILWitnessTable), alignof(SILWitnessTable));
|
|
SILWitnessTable *wt = ::new (buf) SILWitnessTable(M, Linkage, Name.str(),
|
|
Conformance);
|
|
|
|
wt->addWitnessTable();
|
|
|
|
// Return the resulting witness table.
|
|
return wt;
|
|
}
|
|
|
|
SILWitnessTable::SILWitnessTable(SILModule &M, SILLinkage Linkage,
|
|
IsSerialized_t Serialized, StringRef N,
|
|
NormalProtocolConformance *Conformance,
|
|
ArrayRef<Entry> entries)
|
|
: Mod(M), Name(N), Linkage(Linkage), Conformance(Conformance), Entries(),
|
|
IsDeclaration(true), Serialized(false) {
|
|
convertToDefinition(entries, Serialized);
|
|
}
|
|
|
|
SILWitnessTable::SILWitnessTable(SILModule &M, SILLinkage Linkage, StringRef N,
|
|
NormalProtocolConformance *Conformance)
|
|
: Mod(M), Name(N), Linkage(Linkage), Conformance(Conformance), Entries(),
|
|
IsDeclaration(true), Serialized(false)
|
|
{}
|
|
|
|
SILWitnessTable::~SILWitnessTable() {
|
|
if (isDeclaration())
|
|
return;
|
|
|
|
// Drop the reference count of witness functions referenced by this table.
|
|
for (auto entry : getEntries()) {
|
|
switch (entry.getKind()) {
|
|
case Method:
|
|
if (entry.getMethodWitness().Witness) {
|
|
entry.getMethodWitness().Witness->decrementRefCount();
|
|
}
|
|
break;
|
|
case AssociatedType:
|
|
case AssociatedTypeProtocol:
|
|
case BaseProtocol:
|
|
case MissingOptional:
|
|
case Invalid:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
IsSerialized_t SILWitnessTable::isSerialized() const {
|
|
return Serialized ? IsSerialized : IsNotSerialized;
|
|
}
|
|
|
|
void SILWitnessTable::convertToDefinition(ArrayRef<Entry> entries,
|
|
IsSerialized_t isSerialized) {
|
|
assert(isDeclaration() && "Definitions should never call this method.");
|
|
IsDeclaration = false;
|
|
assert(isSerialized != IsSerializable);
|
|
Serialized = (isSerialized == IsSerialized);
|
|
|
|
Entries = Mod.allocateCopy(entries);
|
|
|
|
// Bump the reference count of witness functions referenced by this table.
|
|
for (auto entry : getEntries()) {
|
|
switch (entry.getKind()) {
|
|
case Method:
|
|
if (entry.getMethodWitness().Witness) {
|
|
entry.getMethodWitness().Witness->incrementRefCount();
|
|
}
|
|
break;
|
|
case AssociatedType:
|
|
case AssociatedTypeProtocol:
|
|
case BaseProtocol:
|
|
case MissingOptional:
|
|
case Invalid:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
Identifier SILWitnessTable::getIdentifier() const {
|
|
return Mod.getASTContext().getIdentifier(Name);
|
|
}
|
|
|
|
bool SILWitnessTable::conformanceIsSerialized(ProtocolConformance *conformance,
|
|
ResilienceStrategy strategy,
|
|
bool silSerializeWitnessTables) {
|
|
auto *nominal = conformance->getType()->getAnyNominal();
|
|
// Only serialize if the witness table is sufficiently static, and resilience
|
|
// is explicitly enabled for this compilation or if we serialize all eligible
|
|
// witness tables.
|
|
auto moduleIsResilient = strategy == ResilienceStrategy::Resilient;
|
|
auto protocolIsPublic =
|
|
conformance->getProtocol()->getEffectiveAccess() >= AccessLevel::Public;
|
|
auto typeIsPublic = nominal->getEffectiveAccess() >= AccessLevel::Public;
|
|
return (moduleIsResilient || silSerializeWitnessTables) &&
|
|
nominal->hasFixedLayout() && protocolIsPublic && typeIsPublic;
|
|
}
|