mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Previously SILDefaultWitnessTables only included "resilient" default implementations, which are currently defined as those that appear at the end of a protocol, after any requirements without defaults. However, this was too inflexible. Instead, include all entries in the SILDefaultWitnessTable, with invalid entries standing in for requirements without defaults. Previously, the minimum witness table size was a separate parameter, also appearing in SIL syntax; now it can be calculated by looking at the entries themselves. The getResilientDefaultEntries() method of SILDefaultWitnessTable returns the same result as getEntries() did previously.
192 lines
6.6 KiB
C++
192 lines
6.6 KiB
C++
//===--- SILDefaultWitnessTable.h -------------------------------*- C++ -*-===//
|
|
//
|
|
// 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.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_SIL_SILDEFAULTWITNESSTABLE_H
|
|
#define SWIFT_SIL_SILDEFAULTWITNESSTABLE_H
|
|
|
|
#include "swift/SIL/SILAllocated.h"
|
|
#include "swift/SIL/SILDeclRef.h"
|
|
#include "swift/SIL/SILFunction.h"
|
|
#include "llvm/ADT/ilist_node.h"
|
|
#include "llvm/ADT/ilist.h"
|
|
#include <string>
|
|
|
|
namespace swift {
|
|
|
|
class ProtocolDecl;
|
|
class SILFunction;
|
|
class SILModule;
|
|
|
|
/// A mapping from each requirement of a protocol to the SIL-level entity
|
|
/// satisfying the requirement for conformances which do not explicitly
|
|
/// provide a witness.
|
|
class SILDefaultWitnessTable : public llvm::ilist_node<SILDefaultWitnessTable>,
|
|
public SILAllocated<SILDefaultWitnessTable>
|
|
{
|
|
public:
|
|
/// A default witness table entry describing the default witness for a method.
|
|
class Entry {
|
|
/// The method required.
|
|
SILDeclRef Requirement;
|
|
/// The witness for the method.
|
|
/// This can be null in case no default implementation is available.
|
|
SILFunction *Witness;
|
|
|
|
public:
|
|
Entry()
|
|
: Requirement(), Witness(nullptr) {}
|
|
|
|
Entry(SILDeclRef Requirement, SILFunction *Witness)
|
|
: Requirement(Requirement), Witness(Witness) {}
|
|
|
|
bool isValid() const {
|
|
return !Requirement.isNull();
|
|
}
|
|
|
|
const SILDeclRef &getRequirement() const {
|
|
assert(isValid());
|
|
return Requirement;
|
|
}
|
|
SILFunction *getWitness() const {
|
|
assert(Witness != nullptr);
|
|
return Witness;
|
|
}
|
|
};
|
|
|
|
private:
|
|
/// The module which contains the SILDefaultWitnessTable.
|
|
SILModule &Mod;
|
|
|
|
/// The protocol declaration to which this default witness table applies.
|
|
const ProtocolDecl *Protocol;
|
|
|
|
/// The minimum size of a valid witness table conforming to this protocol,
|
|
/// with all resilient default requirements omitted.
|
|
unsigned MinimumWitnessTableSizeInWords;
|
|
|
|
/// The various witnesses containing in this default witness table.
|
|
MutableArrayRef<Entry> Entries;
|
|
|
|
/// Temporary state while SILGen is emitting a default witness table.
|
|
/// We can never have a true declaration since there's no way to reference
|
|
/// the default witness table from outside its defining translation unit.
|
|
bool IsDeclaration;
|
|
|
|
/// Private constructor for making SILDefaultWitnessTable declarations.
|
|
SILDefaultWitnessTable(SILModule &M, const ProtocolDecl *Protocol);
|
|
|
|
/// Private constructor for making SILDefaultWitnessTable definitions.
|
|
SILDefaultWitnessTable(SILModule &M, const ProtocolDecl *Protocol,
|
|
ArrayRef<Entry> entries);
|
|
|
|
void addDefaultWitnessTable();
|
|
|
|
public:
|
|
/// Create a new SILDefaultWitnessTable declaration.
|
|
static SILDefaultWitnessTable *create(SILModule &M,
|
|
const ProtocolDecl *Protocol);
|
|
|
|
/// Create a new SILDefaultWitnessTable definition with the given entries.
|
|
static SILDefaultWitnessTable *create(SILModule &M,
|
|
const ProtocolDecl *Protocol,
|
|
ArrayRef<Entry> entries);
|
|
|
|
void convertToDefinition(ArrayRef<Entry> entries);
|
|
|
|
~SILDefaultWitnessTable();
|
|
|
|
/// Return true if this is a declaration with no body.
|
|
bool isDeclaration() const { return IsDeclaration; }
|
|
|
|
/// Return the AST ProtocolDecl this default witness table is associated with.
|
|
const ProtocolDecl *getProtocol() const { return Protocol; }
|
|
|
|
/// Return the minimum witness table size, in words.
|
|
///
|
|
/// This will not change if requirements with default implementations are
|
|
/// added at the end of the protocol.
|
|
unsigned getMinimumWitnessTableSize() const;
|
|
|
|
/// Return the default witness table size, in words.
|
|
///
|
|
/// This is the number of resilient default entries that were known when the
|
|
/// protocol definition was compiled; at runtime, it may be smaller or larger,
|
|
/// so this should only be used when emitting metadata for the protocol
|
|
/// definition itself.
|
|
unsigned getDefaultWitnessTableSize() const {
|
|
return Entries.size() - getMinimumWitnessTableSize();
|
|
}
|
|
|
|
/// Return all of the default witness table entries.
|
|
ArrayRef<Entry> getEntries() const { return Entries; }
|
|
|
|
/// Return all of the resilient default implementations.
|
|
///
|
|
/// This is the array of witnesses actually emitted as part of the protocol's
|
|
/// metadata; see the comment in getMinimumWitnessTableSize().
|
|
ArrayRef<Entry> getResilientDefaultEntries() {
|
|
return Entries.slice(getMinimumWitnessTableSize());
|
|
}
|
|
|
|
/// Verify that the default witness table is well-formed.
|
|
void verify(const SILModule &M) const;
|
|
|
|
/// Print the default witness table.
|
|
void print(llvm::raw_ostream &OS, bool Verbose = false) const;
|
|
|
|
/// Dump the default witness table to stderr.
|
|
void dump() const;
|
|
};
|
|
|
|
} // end swift namespace
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ilist_traits for SILDefaultWitnessTable
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace llvm {
|
|
|
|
template <>
|
|
struct ilist_traits<::swift::SILDefaultWitnessTable> :
|
|
public ilist_default_traits<::swift::SILDefaultWitnessTable> {
|
|
typedef ::swift::SILDefaultWitnessTable SILDefaultWitnessTable;
|
|
|
|
private:
|
|
mutable ilist_half_node<SILDefaultWitnessTable> Sentinel;
|
|
|
|
public:
|
|
SILDefaultWitnessTable *createSentinel() const {
|
|
return static_cast<SILDefaultWitnessTable*>(&Sentinel);
|
|
}
|
|
void destroySentinel(SILDefaultWitnessTable *) const {}
|
|
|
|
SILDefaultWitnessTable *provideInitialHead() const { return createSentinel(); }
|
|
SILDefaultWitnessTable *ensureHead(SILDefaultWitnessTable*) const { return createSentinel(); }
|
|
static void noteHead(SILDefaultWitnessTable*, SILDefaultWitnessTable*) {}
|
|
static void deleteNode(SILDefaultWitnessTable *WT) { WT->~SILDefaultWitnessTable(); }
|
|
|
|
private:
|
|
void createNode(const SILDefaultWitnessTable &);
|
|
};
|
|
|
|
} // end llvm namespace
|
|
|
|
#endif
|