Files
swift-mirror/include/swift/SIL/SILDefaultWitnessTable.h
Slava Pestov 5cdacb66a9 SIL: Add SILDefaultWitnessTable::getIdentifier()
For serialization purposes, we identify default witness tables by
the mangled name of their protocol.
2016-03-17 10:39:34 -07:00

205 lines
7.1 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 linkage of the witness table.
SILLinkage Linkage;
/// 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, SILLinkage Linkage,
const ProtocolDecl *Protocol);
/// Private constructor for making SILDefaultWitnessTable definitions.
SILDefaultWitnessTable(SILModule &M, SILLinkage Linkage,
const ProtocolDecl *Protocol,
ArrayRef<Entry> entries);
void addDefaultWitnessTable();
public:
/// Create a new SILDefaultWitnessTable declaration.
static SILDefaultWitnessTable *create(SILModule &M, SILLinkage Linkage,
const ProtocolDecl *Protocol);
/// Create a new SILDefaultWitnessTable definition with the given entries.
static SILDefaultWitnessTable *create(SILModule &M, SILLinkage Linkage,
const ProtocolDecl *Protocol,
ArrayRef<Entry> entries);
Identifier getIdentifier() const;
/// Get the linkage of the default witness table.
SILLinkage getLinkage() const { return Linkage; }
/// Set the linkage of the default witness table.
void setLinkage(SILLinkage l) { Linkage = l; }
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