blob: 6e11947f53a35f4bc0a59ea8709f0e30a3b60bc7 [file] [log] [blame]
//===--- 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