| //===--- SILVTable.h - Defines the SILVTable class --------------*- C++ -*-===// |
| // |
| // 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 SILVTable class, which is used to map dynamically |
| // dispatchable class methods and properties to their concrete implementations |
| // for a dynamic type. This information is (FIXME will be) used by IRGen to lay |
| // out class vtables, and can be used by devirtualization passes to promote |
| // class_method instructions to static function_refs. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_SIL_SILVTABLE_H |
| #define SWIFT_SIL_SILVTABLE_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 "llvm/ADT/Optional.h" |
| #include <algorithm> |
| |
| namespace swift { |
| |
| class ClassDecl; |
| enum IsSerialized_t : unsigned char; |
| class SILFunction; |
| class SILModule; |
| |
| /// A mapping from each dynamically-dispatchable method of a class to the |
| /// SILFunction that implements the method for that class. |
| /// Note that dead methods are completely removed from the vtable. |
| class SILVTable : public llvm::ilist_node<SILVTable>, |
| public SILAllocated<SILVTable> { |
| public: |
| // TODO: Entry should include substitutions needed to invoke an overridden |
| // generic base class method. |
| struct Entry { |
| enum Kind : uint8_t { |
| /// The vtable entry is for a method defined directly in this class. |
| Normal, |
| /// The vtable entry is inherited from the superclass. |
| Inherited, |
| /// The vtable entry is inherited from the superclass, and overridden |
| /// in this class. |
| Override, |
| }; |
| |
| Entry() |
| : Implementation(nullptr), |
| TheKind(Kind::Normal), |
| Linkage(SILLinkage::Private) { } |
| |
| Entry(SILDeclRef Method, SILFunction *Implementation, |
| Kind TheKind, SILLinkage Linkage) |
| : Method(Method), |
| Implementation(Implementation), |
| TheKind(TheKind), |
| Linkage(Linkage) { } |
| |
| /// The declaration reference to the least-derived method visible through |
| /// the class. |
| SILDeclRef Method; |
| |
| /// The function which implements the method for the class. |
| SILFunction *Implementation; |
| |
| /// The entry kind. |
| Kind TheKind; |
| |
| /// The linkage of the implementing function. |
| /// |
| /// This is usually the same as |
| /// stripExternalFromLinkage(Implementation->getLinkage()) |
| /// except if Implementation is a thunk (which has private or shared |
| /// linkage). |
| SILLinkage Linkage; |
| }; |
| |
| // Disallow copying into temporary objects. |
| SILVTable(const SILVTable &other) = delete; |
| SILVTable &operator=(const SILVTable &) = delete; |
| |
| private: |
| /// The ClassDecl mapped to this VTable. |
| ClassDecl *Class; |
| |
| /// Whether or not this vtable is serialized, which allows |
| /// devirtualization from another module. |
| bool Serialized : 1; |
| |
| /// The number of SILVTables entries. |
| unsigned NumEntries : 31; |
| |
| /// Tail-allocated SILVTable entries. |
| Entry Entries[1]; |
| |
| /// Private constructor. Create SILVTables by calling SILVTable::create. |
| SILVTable(ClassDecl *c, IsSerialized_t serialized, ArrayRef<Entry> entries); |
| |
| public: |
| ~SILVTable(); |
| |
| /// Create a new SILVTable with the given method-to-implementation mapping. |
| /// The SILDeclRef keys should reference the most-overridden members available |
| /// through the class. |
| static SILVTable *create(SILModule &M, ClassDecl *Class, |
| IsSerialized_t Serialized, |
| ArrayRef<Entry> Entries); |
| |
| /// Return the class that the vtable represents. |
| ClassDecl *getClass() const { return Class; } |
| |
| /// Returns true if this vtable is going to be (or was) serialized. |
| IsSerialized_t isSerialized() const; |
| |
| /// Return all of the method entries. |
| ArrayRef<Entry> getEntries() const { return {Entries, NumEntries}; } |
| |
| /// Look up the implementation function for the given method. |
| Optional<Entry> getEntry(SILModule &M, SILDeclRef method) const; |
| |
| /// Removes entries from the vtable. |
| /// \p predicate Returns true if the passed entry should be removed. |
| template <typename Predicate> void removeEntries_if(Predicate predicate) { |
| Entry *end = std::remove_if(Entries, Entries + NumEntries, |
| [&](Entry &entry) -> bool { |
| if (predicate(entry)) { |
| entry.Implementation->decrementRefCount(); |
| removeFromVTableCache(entry); |
| return true; |
| } |
| return false; |
| }); |
| NumEntries = end - Entries; |
| } |
| |
| /// Verify that the vtable is well-formed for the given class. |
| void verify(const SILModule &M) const; |
| |
| /// Print the vtable. |
| void print(llvm::raw_ostream &OS, bool Verbose = false) const; |
| void dump() const; |
| |
| private: |
| void removeFromVTableCache(Entry &entry); |
| }; |
| |
| } // end swift namespace |
| |
| //===----------------------------------------------------------------------===// |
| // ilist_traits for SILVTable |
| //===----------------------------------------------------------------------===// |
| |
| namespace llvm { |
| |
| template <> |
| struct ilist_traits<::swift::SILVTable> : |
| public ilist_default_traits<::swift::SILVTable> { |
| typedef ::swift::SILVTable SILVTable; |
| |
| static void deleteNode(SILVTable *VT) { VT->~SILVTable(); } |
| |
| private: |
| void createNode(const SILVTable &); |
| }; |
| |
| } // end llvm namespace |
| |
| #endif |