| //===--- SILOpenedArchetypesTracker.h - Track opened archetypes -*- 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_SIL_SILOPENEDARCHETYPESTRACKER_H |
| #define SWIFT_SIL_SILOPENEDARCHETYPESTRACKER_H |
| |
| #include "swift/SIL/Notifications.h" |
| #include "swift/SIL/SILModule.h" |
| #include "swift/SIL/SILFunction.h" |
| #include "swift/SIL/SILUndef.h" |
| |
| namespace swift { |
| |
| /// SILOpenedArchetypesTracker is a helper class that can be used to create |
| /// and maintain a mapping from opened archetypes to instructions |
| /// defining them, e.g. open_existential_ref, open_existential_addr, |
| /// open_existential_metatype. |
| /// |
| /// This information is useful for representing and maintaining the |
| /// dependencies of instructions on opened archetypes they are using. |
| /// |
| /// The intended clients of this class are SILGen, SIL deserializers, etc. |
| class SILOpenedArchetypesTracker : public DeleteNotificationHandler { |
| public: |
| using OpenedArchetypeDefsMap = |
| llvm::DenseMap<ArchetypeType*, SingleValueInstruction*>; |
| |
| SILOpenedArchetypesTracker(SILOpenedArchetypesTracker &Tracker) |
| : SILOpenedArchetypesTracker(Tracker.F, Tracker) {} |
| |
| // Re-use pre-populated map if available. |
| SILOpenedArchetypesTracker(const SILFunction *F, |
| SILOpenedArchetypesTracker &Tracker) |
| : F(F), OpenedArchetypeDefs(Tracker.OpenedArchetypeDefs) { } |
| |
| // Re-use pre-populated map if available. |
| SILOpenedArchetypesTracker(const SILFunction *F, |
| OpenedArchetypeDefsMap &OpenedArchetypeDefs) |
| : F(F), OpenedArchetypeDefs(OpenedArchetypeDefs) { } |
| |
| // Use its own local map if no pre-populated map is provided. |
| SILOpenedArchetypesTracker(const SILFunction *F) |
| : F(F), OpenedArchetypeDefs(LocalOpenedArchetypeDefs) { } |
| |
| |
| const SILFunction *getFunction() const { |
| assert(F && "no function context available"); |
| return F; |
| } |
| |
| // Register a definition of a given opened archetype. |
| void addOpenedArchetypeDef(CanArchetypeType archetype, |
| SingleValueInstruction *def); |
| |
| // Return the SILInstruciton* defining a given archetype. |
| // If the defining value is not known, return a null instruction. |
| SingleValueInstruction * |
| getOpenedArchetypeDef(CanArchetypeType archetype) const { |
| return OpenedArchetypeDefs.lookup(archetype); |
| } |
| |
| const OpenedArchetypeDefsMap &getOpenedArchetypeDefs() const { |
| return OpenedArchetypeDefs; |
| } |
| |
| // Register archetypes opened by a given instruction. |
| // Can be used to incrementally populate the mapping, e.g. |
| // if it is done when performing a scan of all instructions |
| // inside a function. |
| // Returns true if any opened archetypes were registered. |
| bool registerOpenedArchetypes(const SILInstruction *I); |
| |
| // Register opened archetypes whose definitions are referenced by |
| // the typedef operands of this instruction. |
| // Returns true if any opened archetypes were registered. |
| bool registerUsedOpenedArchetypes(const SILInstruction *I); |
| |
| // Register opened archetypes referenced by this type, if they |
| // are not registered yet. Create placeholders representing forward |
| // definitions of these opened archetypes. |
| // Returns true if any opened archetypes were registered. |
| bool registerUsedOpenedArchetypes(CanType Ty); |
| |
| // Unregister archetypes opened by a given instruction. |
| // Should be only called when this instruction is to be removed. |
| void unregisterOpenedArchetypes(const SILInstruction *I); |
| |
| // Returns true of some of the forward opened archetype definitions |
| // are unresolved. |
| bool hasUnresolvedOpenedArchetypeDefinitions(); |
| |
| // Handling of instruction removal notifications. |
| bool needsNotifications() override { return true; } |
| |
| // Handle notifications about removals of instructions. |
| void handleDeleteNotification(SILNode *node) override; |
| |
| // Dump the contents. |
| void dump() const; |
| |
| virtual ~SILOpenedArchetypesTracker() { |
| // Unregister the handler. |
| if (F) |
| F->getModule().removeDeleteNotificationHandler(this); |
| } |
| |
| private: |
| // Never copy |
| SILOpenedArchetypesTracker &operator = (const SILOpenedArchetypesTracker &) = delete; |
| /// The function whose opened archetypes are being tracked. |
| /// Used only for verification purposes. |
| const SILFunction *F; |
| |
| /// Mapping from opened archetypes to their definitions. |
| OpenedArchetypeDefsMap &OpenedArchetypeDefs; |
| /// Local map to be used if no other map was provided in the |
| /// constructor. |
| OpenedArchetypeDefsMap LocalOpenedArchetypeDefs; |
| }; |
| |
| // A state object containing information about opened archetypes. |
| // This information can be used by constructors of SILInstructions, |
| // their create methods, etc. |
| // The object can be configured to use different sources for providing |
| // archetypes, but none of those archetype sets can be modified through |
| // this object, which makes it essentially immutable. |
| class SILOpenedArchetypesState { |
| // A set of opened archetypes operands for quick lookup. |
| // It usually provides opened archetypes operands of the |
| // instruction being currently processed. |
| ArrayRef<Operand> OpenedArchetypeOperands; |
| // A non-modifiable mapping provided by the tracker. |
| const SILOpenedArchetypesTracker *OpenedArchetypesTracker; |
| public: |
| SILOpenedArchetypesState(const SILOpenedArchetypesTracker *Tracker = nullptr) |
| : OpenedArchetypesTracker(Tracker) {} |
| |
| SILOpenedArchetypesState(const SILOpenedArchetypesTracker &Tracker) |
| : OpenedArchetypesTracker(&Tracker) { } |
| |
| void setOpenedArchetypesTracker(const SILOpenedArchetypesTracker *Tracker) { |
| OpenedArchetypesTracker = Tracker; |
| } |
| |
| void addOpenedArchetypeOperands(ArrayRef<Operand> Operands) { |
| OpenedArchetypeOperands = Operands; |
| } |
| |
| const SILOpenedArchetypesTracker *getOpenedArchetypesTracker() const { |
| return OpenedArchetypesTracker; |
| } |
| |
| /// Lookup the instruction defining an opened archetype by first |
| /// performing a quick lookup in the opened archetypes operands |
| /// and then in the opened archetypes tracker. |
| SILValue getOpenedArchetypeDef(CanArchetypeType archetypeTy) const; |
| |
| // Dump the contents. |
| void dump() const; |
| }; |
| |
| /// Find an opened archetype defined by an instruction. |
| /// \returns The found archetype or empty type otherwise. |
| CanArchetypeType getOpenedArchetypeOf(const SILInstruction *I); |
| |
| /// Find an opened archetype represented by this type. |
| /// It is assumed by this method that the type contains |
| /// at most one opened archetype. |
| /// Typically, it would be called from a type visitor. |
| /// It checks only the type itself, but does not try to |
| /// recursively check any children of this type, because |
| /// this is the task of the type visitor invoking it. |
| /// \returns The found archetype or empty type otherwise. |
| CanArchetypeType getOpenedArchetypeOf(CanType Ty); |
| |
| } // end swift namespace |
| #endif |