| //===--- TypeExpansionContext.h - Swift Type Expansion Context --*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2019 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 TypeExpansionContext class. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_TYPEEXPANSIONCONTEXT_H |
| #define SWIFT_TYPEEXPANSIONCONTEXT_H |
| |
| #include "swift/AST/ResilienceExpansion.h" |
| #include "llvm/ADT/DenseMap.h" |
| |
| namespace swift { |
| class DeclContext; |
| class SILFunction; |
| |
| /// Describes the context in which SIL types should eventually be expanded. |
| /// Required for lowering resilient types and deciding whether to look through |
| /// opaque result types to their underlying type. |
| class TypeExpansionContext { |
| ResilienceExpansion expansion; |
| // The context (module, function, ...) we are expanding the type in. |
| const DeclContext *inContext; |
| // Is the context in which we are expanding in the whole module. |
| bool isContextWholeModule; |
| |
| // The minimal expansion. |
| TypeExpansionContext() { |
| inContext = nullptr; |
| expansion = ResilienceExpansion::Minimal; |
| isContextWholeModule = false; |
| } |
| |
| public: |
| |
| // Infer the expansion for the SIL function. |
| TypeExpansionContext(const SILFunction &f); |
| |
| TypeExpansionContext(ResilienceExpansion expansion, |
| const DeclContext *inContext, bool isWholeModuleContext) |
| : expansion(expansion), inContext(inContext), |
| isContextWholeModule(isWholeModuleContext) {} |
| |
| ResilienceExpansion getResilienceExpansion() const { return expansion; } |
| |
| const DeclContext *getContext() const { return inContext; } |
| |
| bool isWholeModuleContext() const { return isContextWholeModule; } |
| |
| bool shouldLookThroughOpaqueTypeArchetypes() const { |
| return inContext != nullptr; |
| } |
| |
| bool isMinimal() const { return *this == TypeExpansionContext(); } |
| |
| static TypeExpansionContext minimal() { |
| return TypeExpansionContext(); |
| } |
| |
| static TypeExpansionContext maximal(const DeclContext *inContext, |
| bool isContextWholeModule) { |
| return TypeExpansionContext(ResilienceExpansion::Maximal, inContext, |
| isContextWholeModule); |
| } |
| |
| static TypeExpansionContext maximalResilienceExpansionOnly() { |
| return maximal(nullptr, false); |
| } |
| |
| static TypeExpansionContext |
| noOpaqueTypeArchetypesSubstitution(ResilienceExpansion expansion) { |
| return TypeExpansionContext(expansion, nullptr, false); |
| } |
| |
| bool operator==(const TypeExpansionContext &other) const { |
| assert(other.inContext != this->inContext || |
| other.isContextWholeModule == this->isContextWholeModule); |
| return other.inContext == this->inContext && |
| other.expansion == this->expansion; |
| } |
| |
| bool operator!=(const TypeExpansionContext &other) const { |
| return !operator==(other); |
| } |
| |
| bool operator<(const TypeExpansionContext other) const { |
| assert(other.inContext != this->inContext || |
| other.isContextWholeModule == this->isContextWholeModule); |
| if (this->expansion == other.expansion) |
| return this->inContext < other.inContext; |
| return this->expansion < other.expansion; |
| } |
| |
| bool operator>(const TypeExpansionContext other) const { |
| assert(other.inContext != this->inContext || |
| other.isContextWholeModule == this->isContextWholeModule); |
| if (this->expansion == other.expansion) |
| return this->inContext > other.inContext; |
| return this->expansion > other.expansion; |
| } |
| |
| uintptr_t getHashKey() const { |
| uintptr_t key = (uintptr_t)inContext | (uintptr_t)expansion; |
| return key; |
| } |
| }; |
| |
| } // namespace swift |
| |
| namespace llvm { |
| template <> struct DenseMapInfo<swift::TypeExpansionContext> { |
| using TypeExpansionContext = swift::TypeExpansionContext; |
| |
| static TypeExpansionContext getEmptyKey() { |
| return TypeExpansionContext( |
| swift::ResilienceExpansion::Minimal, |
| reinterpret_cast<swift::DeclContext *>( |
| DenseMapInfo<swift::DeclContext *>::getEmptyKey()), |
| false); |
| } |
| static TypeExpansionContext getTombstoneKey() { |
| return TypeExpansionContext( |
| swift::ResilienceExpansion::Minimal, |
| reinterpret_cast<swift::DeclContext *>( |
| DenseMapInfo<swift::DeclContext *>::getTombstoneKey()), |
| false); |
| } |
| |
| static unsigned getHashValue(TypeExpansionContext val) { |
| return DenseMapInfo<uintptr_t>::getHashValue(val.getHashKey()); |
| } |
| |
| static bool isEqual(TypeExpansionContext LHS, TypeExpansionContext RHS) { |
| return LHS == RHS; |
| } |
| }; |
| } // namespace llvm |
| |
| #endif |