blob: 6c89487ceb4b9522149c0967e5bc635bf20360a2 [file] [log] [blame]
//===--- SILOpenedArchetypesTracker.h - Track opened archetypes -*- C++ -*-===//
// This source file is part of the 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 for license information
// See for the list of Swift project authors
#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 {
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)
// 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;
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