mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
For serialization purposes, we identify default witness tables by the mangled name of their protocol.
145 lines
4.9 KiB
C++
145 lines
4.9 KiB
C++
//===--- SILDefaultWitnessTable.cpp ---------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the SILDefaultWitnessTable class, which is used to provide
|
|
// default implementations of protocol requirements for resilient protocols,
|
|
// allowing IRGen to generate the appropriate metadata so that the runtime can
|
|
// insert those requirements to witness tables that were emitted prior to the
|
|
// requirement being added.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/AST/Mangle.h"
|
|
#include "swift/SIL/SILDefaultWitnessTable.h"
|
|
#include "swift/SIL/SILModule.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
|
|
using namespace swift;
|
|
|
|
void SILDefaultWitnessTable::addDefaultWitnessTable() {
|
|
// Make sure we have not seen this witness table yet.
|
|
assert(Mod.DefaultWitnessTableMap.find(Protocol) ==
|
|
Mod.DefaultWitnessTableMap.end() && "Attempting to create duplicate "
|
|
"default witness table.");
|
|
Mod.DefaultWitnessTableMap[Protocol] = this;
|
|
Mod.defaultWitnessTables.push_back(this);
|
|
}
|
|
|
|
SILDefaultWitnessTable *
|
|
SILDefaultWitnessTable::create(SILModule &M, SILLinkage Linkage,
|
|
const ProtocolDecl *Protocol,
|
|
ArrayRef<SILDefaultWitnessTable::Entry> entries){
|
|
// Allocate the witness table and initialize it.
|
|
void *buf = M.allocate(sizeof(SILDefaultWitnessTable),
|
|
alignof(SILDefaultWitnessTable));
|
|
SILDefaultWitnessTable *wt =
|
|
::new (buf) SILDefaultWitnessTable(M, Linkage, Protocol, entries);
|
|
|
|
wt->addDefaultWitnessTable();
|
|
|
|
// Return the resulting default witness table.
|
|
return wt;
|
|
}
|
|
|
|
SILDefaultWitnessTable *
|
|
SILDefaultWitnessTable::create(SILModule &M, SILLinkage Linkage,
|
|
const ProtocolDecl *Protocol) {
|
|
// Allocate the witness table and initialize it.
|
|
void *buf = M.allocate(sizeof(SILDefaultWitnessTable),
|
|
alignof(SILDefaultWitnessTable));
|
|
SILDefaultWitnessTable *wt =
|
|
::new (buf) SILDefaultWitnessTable(M, Linkage, Protocol);
|
|
|
|
wt->addDefaultWitnessTable();
|
|
|
|
// Return the resulting default witness table.
|
|
return wt;
|
|
}
|
|
|
|
SILDefaultWitnessTable::
|
|
SILDefaultWitnessTable(SILModule &M,
|
|
SILLinkage Linkage,
|
|
const ProtocolDecl *Protocol,
|
|
ArrayRef<Entry> entries)
|
|
: Mod(M), Linkage(Linkage), Protocol(Protocol), Entries(),
|
|
IsDeclaration(true) {
|
|
|
|
convertToDefinition(entries);
|
|
}
|
|
|
|
SILDefaultWitnessTable::SILDefaultWitnessTable(SILModule &M,
|
|
SILLinkage Linkage,
|
|
const ProtocolDecl *Protocol)
|
|
: Mod(M), Linkage(Linkage), Protocol(Protocol), Entries(),
|
|
IsDeclaration(true) {}
|
|
|
|
void SILDefaultWitnessTable::
|
|
convertToDefinition(ArrayRef<Entry> entries) {
|
|
assert(IsDeclaration);
|
|
IsDeclaration = false;
|
|
|
|
void *buf = Mod.allocate(sizeof(Entry)*entries.size(), alignof(Entry));
|
|
memcpy(buf, entries.begin(), sizeof(Entry)*entries.size());
|
|
Entries = MutableArrayRef<Entry>(static_cast<Entry*>(buf), entries.size());
|
|
|
|
// Bump the reference count of witness functions referenced by this table.
|
|
for (auto entry : getEntries()) {
|
|
if (entry.isValid()) {
|
|
entry.getWitness()->incrementRefCount();
|
|
}
|
|
}
|
|
}
|
|
|
|
Identifier SILDefaultWitnessTable::getIdentifier() const {
|
|
std::string name;
|
|
{
|
|
Mangle::Mangler mangler;
|
|
mangler.mangleType(getProtocol()->getDeclaredType(), /*uncurry*/ 0);
|
|
name = mangler.finalize();
|
|
}
|
|
return Mod.getASTContext().getIdentifier(name);
|
|
}
|
|
|
|
unsigned SILDefaultWitnessTable::getMinimumWitnessTableSize() const {
|
|
unsigned defaultEntries = 0;
|
|
unsigned minimumEntries = 0;
|
|
|
|
// Count the number of entries up to and including the last null entry.
|
|
// This is the number of witnesses that all conforming types must
|
|
// provide.
|
|
//
|
|
// Any witnesses after the last null entry all have defaults, and can
|
|
// be omitted from conformances; these are the resilient defaults.
|
|
//
|
|
// FIXME: Really this should look at availability instead.
|
|
for (auto entry : Entries) {
|
|
if (entry.isValid()) {
|
|
defaultEntries++;
|
|
} else {
|
|
minimumEntries++;
|
|
minimumEntries += defaultEntries;
|
|
defaultEntries = 0;
|
|
}
|
|
}
|
|
|
|
return minimumEntries;
|
|
}
|
|
|
|
SILDefaultWitnessTable::~SILDefaultWitnessTable() {
|
|
// Drop the reference count of witness functions referenced by this table.
|
|
for (auto entry : getEntries()) {
|
|
if (entry.isValid()) {
|
|
entry.getWitness()->decrementRefCount();
|
|
}
|
|
}
|
|
}
|