Files
swift-mirror/lib/AST/ASTContext.cpp
Joe Groff cf457d2210 Revert "Add support for Axle library." It breaks the build.
This reverts commit r9292.

Swift SVN r9296
2013-10-13 22:38:22 +00:00

1506 lines
53 KiB
C++

//===--- ASTContext.cpp - ASTContext Implementation -----------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements the ASTContext class.
//
//===----------------------------------------------------------------------===//
#include "swift/AST/ASTContext.h"
#include "swift/AST/AST.h"
#include "swift/AST/ASTMutationListener.h"
#include "swift/AST/ConcreteDeclRef.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/ExprHandle.h"
#include "swift/AST/KnownProtocols.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/ModuleLoader.h"
#include "swift/AST/ModuleLoadListener.h"
#include "swift/AST/NameLookup.h"
#include "swift/Basic/SourceManager.h"
#include "llvm/Support/Allocator.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include <memory>
using namespace swift;
ASTMutationListener::~ASTMutationListener() { }
ModuleLoadListener::~ModuleLoadListener() { }
LazyResolver::~LazyResolver() { }
llvm::StringRef swift::getProtocolName(KnownProtocolKind kind) {
switch (kind) {
#define PROTOCOL(Id) \
case KnownProtocolKind::Id: \
return #Id;
#include "swift/AST/KnownProtocols.def"
}
}
struct ASTContext::Implementation {
Implementation();
~Implementation();
llvm::BumpPtrAllocator Allocator; // used in later initializations
/// The set of cleanups to be called when the ASTContext is destroyed.
std::vector<std::function<void(void)>> Cleanups;
llvm::StringMap<char, llvm::BumpPtrAllocator&> IdentifierTable;
/// The declaration of swift.Slice<T>.
NominalTypeDecl *SliceDecl = nullptr;
/// The declaration of swift.Optional<T>.
NominalTypeDecl *OptionalDecl = nullptr;
/// func _doesOptionalHaveValue<T>(v : [inout] Optional<T>) -> T
FuncDecl *DoesOptionalHaveValueDecl = nullptr;
/// func _getOptionalValue<T>(v : Optional<T>) -> T
FuncDecl *GetOptionalValueDecl = nullptr;
/// func _injectValueIntoOptional<T>(v : T) -> Optional<T>
FuncDecl *InjectValueIntoOptionalDecl = nullptr;
/// func _injectNothingIntoOptional<T>() -> Optional<T>
FuncDecl *InjectNothingIntoOptionalDecl = nullptr;
/// func _getBool(Builtin.Int1) -> Bool
FuncDecl *GetBoolDecl = nullptr;
/// \brief The set of known protocols, lazily populated as needed.
ProtocolDecl *KnownProtocols[NumKnownProtocols] = { };
/// \brief The various module loaders that import external modules into this
/// ASTContext.
SmallVector<llvm::IntrusiveRefCntPtr<swift::ModuleLoader>, 4> ModuleLoaders;
/// \brief The module loader used to load Clang modules.
// FIXME: We shouldn't be special-casing Clang.
llvm::IntrusiveRefCntPtr<swift::ModuleLoader> ClangModuleLoader;
/// \brief The set of AST mutation listeners.
SmallVector<ASTMutationListener *, 4> MutationListeners;
/// \brief The set of 'module load' event listeners.
SmallVector<ModuleLoadListener *, 2> ModuleLoadListeners;
/// \brief Map from Swift declarations to the Clang nodes from which
/// they were imported.
llvm::DenseMap<swift::Decl *, ClangNode> ClangNodes;
/// \brief Structure that captures data that is segregated into different
/// arenas.
struct Arena {
llvm::FoldingSet<TupleType> TupleTypes;
llvm::DenseMap<Type, MetaTypeType*> MetaTypeTypes;
llvm::DenseMap<std::pair<Type,std::pair<Type,char>>, FunctionType*>
FunctionTypes;
llvm::DenseMap<std::pair<Type, uint64_t>, ArrayType*> ArrayTypes;
llvm::DenseMap<Type, ArraySliceType*> ArraySliceTypes;
llvm::DenseMap<Type, OptionalType*> OptionalTypes;
llvm::DenseMap<std::pair<Type, unsigned>, VecType*> VecTypes;
llvm::FoldingSet<MatrixType> MatrixTypes;
llvm::DenseMap<Type, ParenType*> ParenTypes;
llvm::DenseMap<uintptr_t, ReferenceStorageType*> ReferenceStorageTypes;
llvm::DenseMap<std::pair<Type, LValueType::Qual::opaque_type>, LValueType*>
LValueTypes;
llvm::DenseMap<std::pair<Type, Type>, SubstitutedType *> SubstitutedTypes;
llvm::DenseMap<std::pair<Type, void*>, DependentMemberType *>
DependentMemberTypes;
llvm::FoldingSet<EnumType> EnumTypes;
llvm::FoldingSet<StructType> StructTypes;
llvm::FoldingSet<ClassType> ClassTypes;
llvm::FoldingSet<UnboundGenericType> UnboundGenericTypes;
llvm::FoldingSet<BoundGenericType> BoundGenericTypes;
};
llvm::DenseMap<Module*, ModuleType*> ModuleTypes;
llvm::DenseMap<std::pair<unsigned, unsigned>, GenericTypeParamType *>
GenericParamTypes;
llvm::FoldingSet<GenericFunctionType> GenericFunctionTypes;
llvm::FoldingSet<SILFunctionType> SILFunctionTypes;
llvm::DenseMap<unsigned, BuiltinIntegerType*> IntegerTypes;
llvm::FoldingSet<ProtocolCompositionType> ProtocolCompositionTypes;
llvm::FoldingSet<BuiltinVectorType> BuiltinVectorTypes;
/// \brief The permanent arena.
Arena Permanent;
/// FIXME: Move into arena.
llvm::DenseMap<BoundGenericType *, ArrayRef<Substitution>>
BoundGenericSubstitutions;
using ConformanceListPair = std::pair<unsigned, SmallVector<Decl *, 8>>;
/// \brief The set of nominal types and extensions thereof known to conform
/// to compiler-known protocols.
ConformanceListPair KnownProtocolConformances[NumKnownProtocols];
/// The list of normal protocol conformances.
///
/// Since these conformances are tied explicitly to the source code, semantic
/// analysis is responsible for handling the uniquing.
SmallVector<NormalProtocolConformance *, 2> NormalConformances;
/// The set of specialized protocol conformances.
llvm::FoldingSet<SpecializedProtocolConformance> SpecializedConformances;
/// The set of inherited protocol conformances.
llvm::FoldingSet<InheritedProtocolConformance> InheritedConformances;
/// \brief Temporary arena used for a constraint solver.
struct ConstraintSolverArena : public Arena {
/// \brief The allocator used for all allocations within this arena.
llvm::BumpPtrAllocator &Allocator;
ConstraintSolverArena(llvm::BumpPtrAllocator &Allocator)
: Allocator(Allocator) { }
ConstraintSolverArena(const ConstraintSolverArena &) = delete;
ConstraintSolverArena(ConstraintSolverArena &&) = delete;
ConstraintSolverArena &operator=(const ConstraintSolverArena &) = delete;
ConstraintSolverArena &operator=(ConstraintSolverArena &&) = delete;
};
/// \brief The current constraint solver arena, if any.
std::unique_ptr<ConstraintSolverArena> CurrentConstraintSolverArena;
Arena &getArena(AllocationArena arena) {
switch (arena) {
case AllocationArena::Permanent:
return Permanent;
case AllocationArena::ConstraintSolver:
assert(CurrentConstraintSolverArena && "No constraint solver active?");
return *CurrentConstraintSolverArena;
}
}
};
ASTContext::Implementation::Implementation()
: IdentifierTable(Allocator) {}
ASTContext::Implementation::~Implementation() {
for (auto &cleanup : Cleanups)
cleanup();
}
ConstraintCheckerArenaRAII::
ConstraintCheckerArenaRAII(ASTContext &self, llvm::BumpPtrAllocator &allocator)
: Self(self), Data(self.Impl.CurrentConstraintSolverArena.release())
{
Self.Impl.CurrentConstraintSolverArena.reset(
new ASTContext::Implementation::ConstraintSolverArena(allocator));
}
ConstraintCheckerArenaRAII::~ConstraintCheckerArenaRAII() {
Self.Impl.CurrentConstraintSolverArena.reset(
(ASTContext::Implementation::ConstraintSolverArena *)Data);
}
ASTContext::ASTContext(LangOptions &langOpts, SourceManager &SourceMgr,
DiagnosticEngine &Diags)
: Impl(*new Implementation()),
LangOpts(langOpts),
SourceMgr(SourceMgr),
Diags(Diags),
TheBuiltinModule(new (*this) BuiltinModule(getIdentifier("Builtin"), *this)),
StdlibModuleName(getIdentifier("swift")),
TheErrorType(new (*this, AllocationArena::Permanent) ErrorType(*this)),
TheEmptyTupleType(TupleType::get(ArrayRef<TupleTypeElt>(), *this)),
TheObjectPointerType(new (*this, AllocationArena::Permanent)
BuiltinObjectPointerType(*this)),
TheObjCPointerType(new (*this, AllocationArena::Permanent)
BuiltinObjCPointerType(*this)),
TheRawPointerType(new (*this, AllocationArena::Permanent)
BuiltinRawPointerType(*this)),
TheIEEE32Type(new (*this, AllocationArena::Permanent)
BuiltinFloatType(BuiltinFloatType::IEEE32,*this)),
TheIEEE64Type(new (*this, AllocationArena::Permanent)
BuiltinFloatType(BuiltinFloatType::IEEE64,*this)),
TheIEEE16Type(new (*this, AllocationArena::Permanent)
BuiltinFloatType(BuiltinFloatType::IEEE16,*this)),
TheIEEE80Type(new (*this, AllocationArena::Permanent)
BuiltinFloatType(BuiltinFloatType::IEEE80,*this)),
TheIEEE128Type(new (*this, AllocationArena::Permanent)
BuiltinFloatType(BuiltinFloatType::IEEE128, *this)),
ThePPC128Type(new (*this, AllocationArena::Permanent)
BuiltinFloatType(BuiltinFloatType::PPC128,*this)){
}
ASTContext::~ASTContext() {
// Tear down protocol conformances.
for (auto conformance : Impl.NormalConformances)
conformance->~NormalProtocolConformance();
for (auto &conformance : Impl.SpecializedConformances)
conformance.~SpecializedProtocolConformance();
delete &Impl;
}
llvm::BumpPtrAllocator &ASTContext::getAllocator(AllocationArena arena) const {
switch (arena) {
case AllocationArena::Permanent:
return Impl.Allocator;
case AllocationArena::ConstraintSolver:
assert(Impl.CurrentConstraintSolverArena.get() != nullptr);
return Impl.CurrentConstraintSolverArena->Allocator;
}
}
/// getIdentifier - Return the uniqued and AST-Context-owned version of the
/// specified string.
Identifier ASTContext::getIdentifier(StringRef Str) const {
// Make sure null pointers stay null.
if (Str.data() == nullptr) return Identifier(0);
return Identifier(Impl.IdentifierTable.GetOrCreateValue(Str).getKeyData());
}
void ASTContext::lookupInSwiftModule(
StringRef name,
SmallVectorImpl<ValueDecl *> &results) const {
// Find the "swift" module.
auto module = LoadedModules.find(StdlibModuleName.str());
if (module == LoadedModules.end())
return;
// Find all of the declarations with this name in the Swift module.
auto identifier = getIdentifier(name);
module->second->lookupValue({ }, identifier, NLKind::UnqualifiedLookup,
results);
}
/// Find the generic implementation declaration for the named syntactic-sugar
/// type.
static NominalTypeDecl *findSyntaxSugarImpl(const ASTContext &ctx,
StringRef name) {
// Find all of the declarations with this name in the Swift module.
SmallVector<ValueDecl *, 1> results;
ctx.lookupInSwiftModule(name, results);
for (auto result : results) {
if (auto nominal = dyn_cast<NominalTypeDecl>(result)) {
if (auto params = nominal->getGenericParams()) {
if (params->size() == 1) {
// We found it.
return nominal;
}
}
}
}
return nullptr;
}
NominalTypeDecl *ASTContext::getSliceDecl() const {
if (!Impl.SliceDecl)
Impl.SliceDecl = findSyntaxSugarImpl(*this, "Slice");
return Impl.SliceDecl;
}
NominalTypeDecl *ASTContext::getOptionalDecl() const {
if (!Impl.OptionalDecl)
Impl.OptionalDecl = findSyntaxSugarImpl(*this, "Optional");
return Impl.OptionalDecl;
}
ProtocolDecl *ASTContext::getProtocol(KnownProtocolKind kind) const {
// Check whether we've already looked for and cached this protocol.
unsigned index = (unsigned)kind;
assert(index < NumKnownProtocols && "Number of known protocols is wrong");
if (Impl.KnownProtocols[index])
return Impl.KnownProtocols[index];
// Find all of the declarations with this name in the Swift module.
SmallVector<ValueDecl *, 1> results;
lookupInSwiftModule(getProtocolName(kind), results);
for (auto result : results) {
if (auto protocol = dyn_cast<ProtocolDecl>(result)) {
Impl.KnownProtocols[index] = protocol;
return protocol;
}
}
return nullptr;
}
/// Find the implementation for the given "intrinsic" library function.
static FuncDecl *findLibraryIntrinsic(const ASTContext &ctx,
StringRef name) {
SmallVector<ValueDecl *, 1> results;
ctx.lookupInSwiftModule(name, results);
if (results.size() == 1)
return dyn_cast<FuncDecl>(results.front());
return nullptr;
}
static CanType stripImmediateLabels(CanType type) {
while (auto tuple = dyn_cast<TupleType>(type)) {
if (tuple->getNumElements() == 1) {
type = tuple.getElementType(0);
} else {
break;
}
}
return type;
}
/// Check whether the given function is non-generic.
static bool isNonGenericIntrinsic(FuncDecl *fn, CanType &input,
CanType &output) {
auto fnType = dyn_cast<FunctionType>(fn->getType()->getCanonicalType());
if (!fnType)
return false;
input = stripImmediateLabels(fnType.getInput());
output = stripImmediateLabels(fnType.getResult());
return true;
}
/// Check whether the given type is Builtin.Int1.
static bool isBuiltinInt1Type(CanType type) {
if (auto intType = dyn_cast<BuiltinIntegerType>(type))
return intType->getBitWidth() == 1;
return false;
}
FuncDecl *ASTContext::getGetBoolDecl() const {
if (Impl.GetBoolDecl)
return Impl.GetBoolDecl;
// Look for the function.
CanType input, output;
auto decl = findLibraryIntrinsic(*this, "_getBool");
if (!decl || !isNonGenericIntrinsic(decl, input, output))
return nullptr;
// Input must be Builtin.Int1
if (!isBuiltinInt1Type(input))
return nullptr;
// Output must be a global type named Bool.
auto nominalType = dyn_cast<NominalType>(output);
if (!nominalType ||
nominalType.getParent() ||
nominalType->getDecl()->getName().str() != "Bool")
return nullptr;
Impl.GetBoolDecl = decl;
return decl;
}
/// Check whether the given function is generic over a single,
/// unconstrained archetype.
static bool isGenericIntrinsic(FuncDecl *fn, CanType &input, CanType &output,
CanType &param) {
auto fnType =
dyn_cast<PolymorphicFunctionType>(fn->getType()->getCanonicalType());
if (!fnType || fnType->getAllArchetypes().size() != 1)
return false;
auto paramType = CanArchetypeType(fnType->getAllArchetypes()[0]);
if (paramType->hasRequirements())
return false;
param = paramType;
input = stripImmediateLabels(fnType.getInput());
output = stripImmediateLabels(fnType.getResult());
return true;
}
/// Check whether the given type is Optional applied to the given
/// type argument.
static bool isOptionalType(const ASTContext &ctx, CanType type,
CanType arg) {
if (auto boundType = dyn_cast<BoundGenericType>(type)) {
return (boundType->getDecl() == ctx.getOptionalDecl() &&
boundType.getGenericArgs().size() == 1 &&
boundType.getGenericArgs()[0] == arg);
}
return false;
}
FuncDecl *ASTContext::getDoesOptionalHaveValueDecl() const {
if (Impl.DoesOptionalHaveValueDecl)
return Impl.DoesOptionalHaveValueDecl;
// Look for a generic function.
CanType input, output, param;
auto decl = findLibraryIntrinsic(*this, "_doesOptionalHaveValue");
if (!decl || !isGenericIntrinsic(decl, input, output, param))
return nullptr;
// Input must be [inout] Optional<T>.
auto inputInOut = dyn_cast<LValueType>(input);
if (!inputInOut || !isOptionalType(*this, inputInOut.getObjectType(), param))
return nullptr;
// Output must be Builtin.Int1.
if (!isBuiltinInt1Type(output))
return nullptr;
Impl.DoesOptionalHaveValueDecl = decl;
return decl;
}
FuncDecl *ASTContext::getGetOptionalValueDecl() const {
if (Impl.GetOptionalValueDecl)
return Impl.GetOptionalValueDecl;
// Look for the function.
CanType input, output, param;
auto decl = findLibraryIntrinsic(*this, "_getOptionalValue");
if (!decl || !isGenericIntrinsic(decl, input, output, param))
return nullptr;
// Input must be Optional<T>.
if (!isOptionalType(*this, input, param))
return nullptr;
// Output must be T.
if (output != param)
return nullptr;
Impl.GetOptionalValueDecl = decl;
return decl;
}
FuncDecl *ASTContext::getInjectValueIntoOptionalDecl() const {
if (Impl.InjectValueIntoOptionalDecl)
return Impl.InjectValueIntoOptionalDecl;
// Look for the function.
CanType input, output, param;
auto decl = findLibraryIntrinsic(*this, "_injectValueIntoOptional");
if (!decl || !isGenericIntrinsic(decl, input, output, param))
return nullptr;
// Input must be T.
if (input != param)
return nullptr;
// Output must be Optional<T>.
if (!isOptionalType(*this, output, param))
return nullptr;
Impl.InjectValueIntoOptionalDecl = decl;
return decl;
}
FuncDecl *ASTContext::getInjectNothingIntoOptionalDecl() const {
if (Impl.InjectNothingIntoOptionalDecl)
return Impl.InjectNothingIntoOptionalDecl;
// Look for the function.
CanType input, output, param;
auto decl = findLibraryIntrinsic(*this, "_injectNothingIntoOptional");
if (!decl || !isGenericIntrinsic(decl, input, output, param))
return nullptr;
// Input must be ().
auto inputTuple = dyn_cast<TupleType>(input);
if (!inputTuple || inputTuple->getNumElements() != 0)
return nullptr;
// Output must be Optional<T>.
if (!isOptionalType(*this, output, param))
return nullptr;
Impl.InjectNothingIntoOptionalDecl = decl;
return decl;
}
bool ASTContext::hasOptionalIntrinsics() const {
return getDoesOptionalHaveValueDecl() &&
getGetOptionalValueDecl() &&
getInjectValueIntoOptionalDecl() &&
getInjectNothingIntoOptionalDecl();
}
void ASTContext::addMutationListener(ASTMutationListener &listener) {
Impl.MutationListeners.push_back(&listener);
}
void ASTContext::removeMutationListener(ASTMutationListener &listener) {
auto known = std::find(Impl.MutationListeners.rbegin(),
Impl.MutationListeners.rend(),
&listener);
assert(known != Impl.MutationListeners.rend() && "listener not registered");
Impl.MutationListeners.erase(known.base()-1);
}
void ASTContext::addedExternalDecl(Decl *decl) {
for (auto listener : Impl.MutationListeners)
listener->addedExternalDecl(decl);
}
void ASTContext::addCleanup(std::function<void(void)> cleanup) {
Impl.Cleanups.push_back(std::move(cleanup));
}
bool ASTContext::hadError() const {
return Diags.hadAnyError();
}
Optional<ArrayRef<Substitution>>
ASTContext::createTrivialSubstitutions(BoundGenericType *BGT) const {
assert(BGT->isCanonical() && "Requesting non-canonical substitutions");
ArrayRef<GenericParam> Params =
BGT->getDecl()->getGenericParams()->getParams();
assert(Params.size() == 1);
auto Param = Params[0];
assert(Param.getAsTypeParam()->getArchetype() && "Not type-checked yet");
Substitution Subst;
Subst.Archetype = Param.getAsTypeParam()->getArchetype();
Subst.Replacement = BGT->getGenericArgs()[0];
auto Substitutions = AllocateCopy(llvm::makeArrayRef(Subst));
Impl.BoundGenericSubstitutions.insert(std::make_pair(BGT, Substitutions));
return Substitutions;
}
Optional<ArrayRef<Substitution>>
ASTContext::getSubstitutions(BoundGenericType* bound) const {
assert(bound->isCanonical() && "Requesting non-canonical substitutions");
auto known = Impl.BoundGenericSubstitutions.find(bound);
if (known != Impl.BoundGenericSubstitutions.end())
return known->second;
// We can trivially create substitutions for Slice and Optional.
if (bound->getDecl() == getSliceDecl() ||
bound->getDecl() == getOptionalDecl())
return createTrivialSubstitutions(bound);
return Nothing;
}
void ASTContext::setSubstitutions(BoundGenericType* Bound,
ArrayRef<Substitution> Subs) const {
assert(Bound->isCanonical() && "Requesting non-canonical substitutions");
assert(Impl.BoundGenericSubstitutions.count(Bound) == 0 &&
"Already have substitutions?");
Impl.BoundGenericSubstitutions[Bound] = Subs;
}
void ASTContext::addModuleLoader(llvm::IntrusiveRefCntPtr<ModuleLoader> loader,
bool IsClang) {
Impl.ModuleLoaders.push_back(loader);
if (IsClang) {
assert(!Impl.ClangModuleLoader && "Already have a Clang module loader");
Impl.ClangModuleLoader = std::move(loader);
}
}
void ASTContext::loadExtensions(NominalTypeDecl *nominal,
unsigned previousGeneration) {
for (auto loader : Impl.ModuleLoaders) {
loader->loadExtensions(nominal, previousGeneration);
}
}
llvm::IntrusiveRefCntPtr<ModuleLoader> ASTContext::getClangModuleLoader() const{
return Impl.ClangModuleLoader;
}
static void recordKnownProtocol(Module *Stdlib, StringRef Name,
KnownProtocolKind Kind) {
Identifier ID = Stdlib->Ctx.getIdentifier(Name);
UnqualifiedLookup Lookup(ID, Stdlib, nullptr, SourceLoc(), /*IsType=*/true);
if (auto Proto = dyn_cast_or_null<ProtocolDecl>(Lookup.getSingleTypeResult()))
Proto->setKnownProtocolKind(Kind);
}
void ASTContext::recordKnownProtocols(Module *Stdlib) {
#define PROTOCOL(Name) \
recordKnownProtocol(Stdlib, #Name, KnownProtocolKind::Name);
#include "swift/AST/KnownProtocols.def"
}
Module *
ASTContext::getModule(ArrayRef<std::pair<Identifier, SourceLoc>> modulePath) {
assert(!modulePath.empty());
auto moduleID = modulePath[0];
// TODO: Swift submodules.
if (modulePath.size() == 1) {
if (Module *M = LoadedModules.lookup(moduleID.first.str()))
return M;
}
for (auto importer : Impl.ModuleLoaders) {
if (Module *M = importer->loadModule(moduleID.second, modulePath)) {
if (modulePath.size() == 1 && modulePath[0].first == StdlibModuleName)
recordKnownProtocols(M);
return M;
}
}
return nullptr;
}
void ASTContext::addModuleLoadListener(ModuleLoadListener &Listener) {
Impl.ModuleLoadListeners.push_back(&Listener);
}
void ASTContext::removeModuleLoadListener(ModuleLoadListener &Listener) {
auto Known = std::find(Impl.ModuleLoadListeners.rbegin(),
Impl.ModuleLoadListeners.rend(),
&Listener);
assert(Known != Impl.ModuleLoadListeners.rend() && "listener not registered");
Impl.ModuleLoadListeners.erase(Known.base() - 1);
}
ClangNode ASTContext::getClangNode(Decl *decl) {
auto known = Impl.ClangNodes.find(decl);
assert(known != Impl.ClangNodes.end() && "No Clang node?");
return known->second;
}
void ASTContext::setClangNode(Decl *decl, ClangNode node) {
Impl.ClangNodes[decl] = node;
}
void ASTContext::recordConformance(KnownProtocolKind protocolKind, Decl *decl) {
assert(isa<NominalTypeDecl>(decl) || isa<ExtensionDecl>(decl));
auto index = static_cast<unsigned>(protocolKind);
assert(index < NumKnownProtocols);
Impl.KnownProtocolConformances[index].second.push_back(decl);
}
/// \brief Retrieve the set of nominal types and extensions thereof that
/// conform to the given protocol.
ArrayRef<Decl *> ASTContext::getTypesThatConformTo(KnownProtocolKind kind) {
auto index = static_cast<unsigned>(kind);
assert(index < NumKnownProtocols);
for (auto loader : Impl.ModuleLoaders) {
loader->loadDeclsConformingTo(kind,
Impl.KnownProtocolConformances[index].first);
}
Impl.KnownProtocolConformances[index].first = CurrentGeneration;
return Impl.KnownProtocolConformances[index].second;
}
NormalProtocolConformance *
ASTContext::getConformance(Type conformingType,
ProtocolDecl *protocol,
Module *containingModule,
WitnessMap &&witnesses,
TypeWitnessMap &&typeWitnesses,
InheritedConformanceMap &&inheritedConformances,
ArrayRef<ValueDecl *> defaultedDefinitions) {
auto result
= new (*this) NormalProtocolConformance(conformingType, protocol,
containingModule,
std::move(witnesses),
std::move(typeWitnesses),
std::move(inheritedConformances),
defaultedDefinitions);
Impl.NormalConformances.push_back(result);
return result;
}
SpecializedProtocolConformance *
ASTContext::getSpecializedConformance(Type type,
ProtocolConformance *generic,
ArrayRef<Substitution> substitutions,
TypeWitnessMap &&typeWitnesses) {
llvm::FoldingSetNodeID id;
SpecializedProtocolConformance::Profile(id, type, generic);
// Did we already record the specialized conformance?
void *insertPos;
if (auto result
= Impl.SpecializedConformances.FindNodeOrInsertPos(id, insertPos))
return result;
// Build a new specialized conformance.
auto result
= new (*this) SpecializedProtocolConformance(type, generic, substitutions,
std::move(typeWitnesses));
Impl.SpecializedConformances.InsertNode(result, insertPos);
return result;
}
InheritedProtocolConformance *
ASTContext::getInheritedConformance(Type type, ProtocolConformance *inherited) {
llvm::FoldingSetNodeID id;
InheritedProtocolConformance::Profile(id, type, inherited);
// Did we already record the specialized conformance?
void *insertPos;
if (auto result
= Impl.InheritedConformances.FindNodeOrInsertPos(id, insertPos))
return result;
// Build a new specialized conformance.
auto result = new (*this) InheritedProtocolConformance(type, inherited);
Impl.InheritedConformances.InsertNode(result, insertPos);
return result;
}
//===----------------------------------------------------------------------===//
// Type manipulation routines.
//===----------------------------------------------------------------------===//
// Simple accessors.
Type ErrorType::get(const ASTContext &C) { return C.TheErrorType; }
BuiltinIntegerType *BuiltinIntegerType::get(unsigned BitWidth,
const ASTContext &C) {
BuiltinIntegerType *&Result = C.Impl.IntegerTypes[BitWidth];
if (Result == 0)
Result = new (C, AllocationArena::Permanent) BuiltinIntegerType(BitWidth,C);
return Result;
}
/// \brief Retrieve the arena from which we should allocate storage for a type.
static AllocationArena getArena(bool hasTypeVariable) {
return hasTypeVariable? AllocationArena::ConstraintSolver
: AllocationArena::Permanent;;
}
BuiltinVectorType *BuiltinVectorType::get(const ASTContext &context,
Type elementType,
unsigned numElements) {
llvm::FoldingSetNodeID id;
BuiltinVectorType::Profile(id, elementType, numElements);
void *insertPos;
if (BuiltinVectorType *vecType
= context.Impl.BuiltinVectorTypes.FindNodeOrInsertPos(id, insertPos))
return vecType;
assert(elementType->isCanonical() && "Non-canonical builtin vector?");
BuiltinVectorType *vecTy
= new (context, AllocationArena::Permanent)
BuiltinVectorType(context, elementType, numElements);
context.Impl.BuiltinVectorTypes.InsertNode(vecTy, insertPos);
return vecTy;
}
ParenType *ParenType::get(const ASTContext &C, Type underlying) {
bool hasTypeVariable = underlying->hasTypeVariable();
auto arena = getArena(hasTypeVariable);
ParenType *&Result = C.Impl.getArena(arena).ParenTypes[underlying];
if (Result == 0) {
Result = new (C, arena) ParenType(underlying, hasTypeVariable);
}
return Result;
}
CanTupleType TupleType::getEmpty(const ASTContext &C) {
return cast<TupleType>(CanType(C.TheEmptyTupleType));
}
void TupleType::Profile(llvm::FoldingSetNodeID &ID,
ArrayRef<TupleTypeElt> Fields) {
ID.AddInteger(Fields.size());
for (const TupleTypeElt &Elt : Fields) {
ID.AddPointer(Elt.getName().get());
ID.AddPointer(Elt.TyAndDefaultOrVarArg.getOpaqueValue());
}
}
/// getTupleType - Return the uniqued tuple type with the specified elements.
Type TupleType::get(ArrayRef<TupleTypeElt> Fields, const ASTContext &C) {
if (Fields.size() == 1 && !Fields[0].isVararg() && !Fields[0].hasName())
return ParenType::get(C, Fields[0].getType());
bool HasTypeVariable = false;
for (const TupleTypeElt &Elt : Fields) {
if (Elt.getType() && Elt.getType()->hasTypeVariable()) {
HasTypeVariable = true;
break;
}
}
auto arena = getArena(HasTypeVariable);
void *InsertPos = 0;
// Check to see if we've already seen this tuple before.
llvm::FoldingSetNodeID ID;
TupleType::Profile(ID, Fields);
if (TupleType *TT
= C.Impl.getArena(arena).TupleTypes.FindNodeOrInsertPos(ID,InsertPos))
return TT;
// Make a copy of the fields list into ASTContext owned memory.
TupleTypeElt *FieldsCopy =
C.AllocateCopy<TupleTypeElt>(Fields.begin(), Fields.end(), arena);
bool IsCanonical = true; // All canonical elts means this is canonical.
for (const TupleTypeElt &Elt : Fields) {
if (Elt.getType().isNull() || !Elt.getType()->isCanonical()) {
IsCanonical = false;
break;
}
}
Fields = ArrayRef<TupleTypeElt>(FieldsCopy, Fields.size());
TupleType *New = new (C, arena) TupleType(Fields, IsCanonical ? &C : 0,
HasTypeVariable);
C.Impl.getArena(arena).TupleTypes.InsertNode(New, InsertPos);
return New;
}
void UnboundGenericType::Profile(llvm::FoldingSetNodeID &ID,
NominalTypeDecl *TheDecl, Type Parent) {
ID.AddPointer(TheDecl);
ID.AddPointer(Parent.getPointer());
}
UnboundGenericType* UnboundGenericType::get(NominalTypeDecl *TheDecl,
Type Parent,
const ASTContext &C) {
llvm::FoldingSetNodeID ID;
UnboundGenericType::Profile(ID, TheDecl, Parent);
void *InsertPos = 0;
bool hasTypeVariable = Parent && Parent->hasTypeVariable();
auto arena = getArena(hasTypeVariable);
if (auto unbound = C.Impl.getArena(arena).UnboundGenericTypes
.FindNodeOrInsertPos(ID, InsertPos))
return unbound;
auto result = new (C, arena) UnboundGenericType(TheDecl, Parent, C,
hasTypeVariable);
C.Impl.getArena(arena).UnboundGenericTypes.InsertNode(result, InsertPos);
return result;
}
void BoundGenericType::Profile(llvm::FoldingSetNodeID &ID,
NominalTypeDecl *TheDecl, Type Parent,
ArrayRef<Type> GenericArgs,
bool &hasTypeVariable) {
ID.AddPointer(TheDecl);
ID.AddPointer(Parent.getPointer());
if (Parent && Parent->hasTypeVariable())
hasTypeVariable = true;
ID.AddInteger(GenericArgs.size());
for (Type Arg : GenericArgs) {
ID.AddPointer(Arg.getPointer());
if (Arg->hasTypeVariable())
hasTypeVariable = true;
}
}
BoundGenericType::BoundGenericType(TypeKind theKind,
NominalTypeDecl *theDecl,
Type parent,
ArrayRef<Type> genericArgs,
const ASTContext *context,
bool hasTypeVariable)
: TypeBase(theKind, context, hasTypeVariable),
TheDecl(theDecl), Parent(parent), GenericArgs(genericArgs)
{
}
BoundGenericType *BoundGenericType::get(NominalTypeDecl *TheDecl,
Type Parent,
ArrayRef<Type> GenericArgs) {
ASTContext &C = TheDecl->getDeclContext()->getASTContext();
llvm::FoldingSetNodeID ID;
bool HasTypeVariable = false;
BoundGenericType::Profile(ID, TheDecl, Parent, GenericArgs, HasTypeVariable);
auto arena = getArena(HasTypeVariable);
void *InsertPos = 0;
if (BoundGenericType *BGT =
C.Impl.getArena(arena).BoundGenericTypes.FindNodeOrInsertPos(ID,
InsertPos))
return BGT;
ArrayRef<Type> ArgsCopy = C.AllocateCopy(GenericArgs, arena);
bool IsCanonical = !Parent || Parent->isCanonical();
if (IsCanonical) {
for (Type Arg : GenericArgs) {
if (!Arg->isCanonical()) {
IsCanonical = false;
break;
}
}
}
BoundGenericType *newType;
if (auto theClass = dyn_cast<ClassDecl>(TheDecl)) {
newType = new (C, arena) BoundGenericClassType(theClass, Parent, ArgsCopy,
IsCanonical ? &C : 0,
HasTypeVariable);
} else if (auto theStruct = dyn_cast<StructDecl>(TheDecl)) {
newType = new (C, arena) BoundGenericStructType(theStruct, Parent, ArgsCopy,
IsCanonical ? &C : 0,
HasTypeVariable);
} else {
auto theEnum = cast<EnumDecl>(TheDecl);
newType = new (C, arena) BoundGenericEnumType(theEnum, Parent, ArgsCopy,
IsCanonical ? &C : 0,
HasTypeVariable);
}
C.Impl.getArena(arena).BoundGenericTypes.InsertNode(newType, InsertPos);
return newType;
}
NominalType *NominalType::get(NominalTypeDecl *D, Type Parent, const ASTContext &C) {
switch (D->getKind()) {
case DeclKind::Enum:
return EnumType::get(cast<EnumDecl>(D), Parent, C);
case DeclKind::Struct:
return StructType::get(cast<StructDecl>(D), Parent, C);
case DeclKind::Class:
return ClassType::get(cast<ClassDecl>(D), Parent, C);
case DeclKind::Protocol: {
return ProtocolType::get(cast<ProtocolDecl>(D), C);
}
default:
llvm_unreachable("Not a nominal declaration!");
}
}
EnumType::EnumType(EnumDecl *TheDecl, Type Parent, const ASTContext &C,
bool HasTypeVariable)
: NominalType(TypeKind::Enum, &C, TheDecl, Parent, HasTypeVariable) { }
EnumType *EnumType::get(EnumDecl *D, Type Parent, const ASTContext &C) {
llvm::FoldingSetNodeID id;
EnumType::Profile(id, D, Parent);
bool hasTypeVariable = Parent && Parent->hasTypeVariable();
auto arena = getArena(hasTypeVariable);
void *insertPos = 0;
if (auto enumTy
= C.Impl.getArena(arena).EnumTypes.FindNodeOrInsertPos(id, insertPos))
return enumTy;
auto enumTy = new (C, arena) EnumType(D, Parent, C, hasTypeVariable);
C.Impl.getArena(arena).EnumTypes.InsertNode(enumTy, insertPos);
return enumTy;
}
void EnumType::Profile(llvm::FoldingSetNodeID &ID, EnumDecl *D, Type Parent) {
ID.AddPointer(D);
ID.AddPointer(Parent.getPointer());
}
StructType::StructType(StructDecl *TheDecl, Type Parent, const ASTContext &C,
bool HasTypeVariable)
: NominalType(TypeKind::Struct, &C, TheDecl, Parent, HasTypeVariable) { }
StructType *StructType::get(StructDecl *D, Type Parent, const ASTContext &C) {
llvm::FoldingSetNodeID id;
StructType::Profile(id, D, Parent);
bool hasTypeVariable = Parent && Parent->hasTypeVariable();
auto arena = getArena(hasTypeVariable);
void *insertPos = 0;
if (auto structTy
= C.Impl.getArena(arena).StructTypes.FindNodeOrInsertPos(id, insertPos))
return structTy;
auto structTy = new (C, arena) StructType(D, Parent, C, hasTypeVariable);
C.Impl.getArena(arena).StructTypes.InsertNode(structTy, insertPos);
return structTy;
}
void StructType::Profile(llvm::FoldingSetNodeID &ID, StructDecl *D, Type Parent) {
ID.AddPointer(D);
ID.AddPointer(Parent.getPointer());
}
ClassType::ClassType(ClassDecl *TheDecl, Type Parent, const ASTContext &C,
bool HasTypeVariable)
: NominalType(TypeKind::Class, &C, TheDecl, Parent, HasTypeVariable) { }
ClassType *ClassType::get(ClassDecl *D, Type Parent, const ASTContext &C) {
llvm::FoldingSetNodeID id;
ClassType::Profile(id, D, Parent);
bool hasTypeVariable = Parent && Parent->hasTypeVariable();
auto arena = getArena(hasTypeVariable);
void *insertPos = 0;
if (auto classTy
= C.Impl.getArena(arena).ClassTypes.FindNodeOrInsertPos(id, insertPos))
return classTy;
auto classTy = new (C, arena) ClassType(D, Parent, C, hasTypeVariable);
C.Impl.getArena(arena).ClassTypes.InsertNode(classTy, insertPos);
return classTy;
}
void ClassType::Profile(llvm::FoldingSetNodeID &ID, ClassDecl *D, Type Parent) {
ID.AddPointer(D);
ID.AddPointer(Parent.getPointer());
}
ProtocolCompositionType *
ProtocolCompositionType::build(const ASTContext &C, ArrayRef<Type> Protocols) {
// Check to see if we've already seen this protocol composition before.
void *InsertPos = 0;
llvm::FoldingSetNodeID ID;
ProtocolCompositionType::Profile(ID, Protocols);
if (ProtocolCompositionType *Result
= C.Impl.ProtocolCompositionTypes.FindNodeOrInsertPos(ID, InsertPos))
return Result;
bool isCanonical = true;
for (Type t : Protocols) {
if (!t->isCanonical())
isCanonical = false;
}
// Create a new protocol composition type.
ProtocolCompositionType *New
= new (C, AllocationArena::Permanent)
ProtocolCompositionType(isCanonical ? &C : nullptr,
C.AllocateCopy(Protocols));
C.Impl.ProtocolCompositionTypes.InsertNode(New, InsertPos);
return New;
}
ReferenceStorageType *ReferenceStorageType::get(Type T, Ownership ownership,
const ASTContext &C) {
assert(ownership != Ownership::Strong &&
"ReferenceStorageType is unnecessary for strong ownership");
assert(!T->hasTypeVariable()); // not meaningful in type-checker
auto arena = AllocationArena::Permanent;
auto key = uintptr_t(T.getPointer()) | unsigned(ownership);
auto &entry = C.Impl.getArena(arena).ReferenceStorageTypes[key];
if (entry) return entry;
switch (ownership) {
case Ownership::Strong: llvm_unreachable("not possible");
case Ownership::Unowned:
return entry =
new (C, arena) UnownedStorageType(T, T->isCanonical() ? &C : 0);
case Ownership::Weak:
return entry =
new (C, arena) WeakStorageType(T, T->isCanonical() ? &C : 0);
}
llvm_unreachable("bad ownership");
}
MetaTypeType *MetaTypeType::get(Type T, const ASTContext &C) {
bool hasTypeVariable = T->hasTypeVariable();
auto arena = getArena(hasTypeVariable);
MetaTypeType *&Entry = C.Impl.getArena(arena).MetaTypeTypes[T];
if (Entry) return Entry;
return Entry = new (C, arena) MetaTypeType(T, T->isCanonical() ? &C : 0,
hasTypeVariable);
}
MetaTypeType::MetaTypeType(Type T, const ASTContext *C, bool HasTypeVariable)
: TypeBase(TypeKind::MetaType, C, HasTypeVariable),
InstanceType(T) {
}
ModuleType *ModuleType::get(Module *M) {
ASTContext &C = M->getASTContext();
ModuleType *&Entry = C.Impl.ModuleTypes[M];
if (Entry) return Entry;
return Entry = new (C, AllocationArena::Permanent) ModuleType(M, C);
}
/// FunctionType::get - Return a uniqued function type with the specified
/// input and result.
FunctionType *FunctionType::get(Type Input, Type Result,
const ExtInfo &Info,
const ASTContext &C) {
bool hasTypeVariable = Input->hasTypeVariable() || Result->hasTypeVariable();
auto arena = getArena(hasTypeVariable);
char attrKey = Info.getFuncAttrKey();
FunctionType *&Entry
= C.Impl.getArena(arena).FunctionTypes[{Input, {Result, attrKey} }];
if (Entry) return Entry;
return Entry = new (C, arena) FunctionType(Input, Result,
hasTypeVariable,
Info);
}
// If the input and result types are canonical, then so is the result.
FunctionType::FunctionType(Type input, Type output,
bool hasTypeVariable,
const ExtInfo &Info)
: AnyFunctionType(TypeKind::Function,
(input->isCanonical() && output->isCanonical()) ?
&input->getASTContext() : 0,
input, output,
hasTypeVariable,
Info)
{ }
/// FunctionType::get - Return a uniqued function type with the specified
/// input and result.
PolymorphicFunctionType *PolymorphicFunctionType::get(Type input, Type output,
GenericParamList *params,
const ExtInfo &Info,
const ASTContext &C) {
// FIXME: one day we should do canonicalization properly.
bool hasTypeVariable = input->hasTypeVariable() || output->hasTypeVariable();
auto arena = getArena(hasTypeVariable);
return new (C, arena) PolymorphicFunctionType(input, output, params,
Info, C);
}
PolymorphicFunctionType::PolymorphicFunctionType(Type input, Type output,
GenericParamList *params,
const ExtInfo &Info,
const ASTContext &C)
: AnyFunctionType(TypeKind::PolymorphicFunction,
(input->isCanonical() && output->isCanonical()) ?&C : 0,
input, output,
/*HasTypeVariable=*/false,
Info),
Params(params)
{
assert(!input->hasTypeVariable() && !output->hasTypeVariable());
}
void GenericFunctionType::Profile(llvm::FoldingSetNodeID &ID,
ArrayRef<GenericTypeParamType *> params,
ArrayRef<Requirement> requirements,
Type input,
Type result,
const ExtInfo &info) {
ID.AddInteger(params.size());
for (auto param : params)
ID.AddPointer(param);
ID.AddInteger(requirements.size());
for (const auto &req : requirements) {
ID.AddInteger(static_cast<unsigned>(req.getKind()));
ID.AddPointer(req.getFirstType().getPointer());
ID.AddPointer(req.getSecondType().getPointer());
}
ID.AddPointer(input.getPointer());
ID.AddPointer(result.getPointer());
ID.AddInteger(info.getFuncAttrKey());
}
GenericFunctionType *
GenericFunctionType::get(ArrayRef<GenericTypeParamType *> params,
ArrayRef<Requirement> requirements,
Type input,
Type output,
const ExtInfo &info,
const ASTContext &ctx) {
assert(!input->hasTypeVariable() && !output->hasTypeVariable());
llvm::FoldingSetNodeID id;
GenericFunctionType::Profile(id, params, requirements, input, output, info);
// Do we already have this generic function type?
void *insertPos;
if (auto result
= ctx.Impl.GenericFunctionTypes.FindNodeOrInsertPos(id, insertPos))
return result;
// We have to construct this generic function type. Determine whether
// it's canonical.
bool isCanonical = input->isCanonical() && output->isCanonical();
if (isCanonical) {
for (auto param : params) {
if (!param->isCanonical()) {
isCanonical = false;
break;
}
}
}
if (isCanonical ) {
for (const auto &req : requirements) {
if (!req.getFirstType()->isCanonical() ||
!req.getSecondType()->isCanonical()) {
isCanonical = false;
break;
}
}
}
// Allocate storage for the object.
size_t bytes = sizeof(GenericFunctionType)
+ sizeof(GenericTypeParamType *) * params.size()
+ sizeof(Requirement) * requirements.size();
void *mem = ctx.Allocate(bytes, alignof(GenericFunctionType));
auto result = new (mem) GenericFunctionType(params, requirements, input,
output, info,
isCanonical? &ctx : nullptr);
ctx.Impl.GenericFunctionTypes.InsertNode(result, insertPos);
return result;
}
GenericFunctionType::GenericFunctionType(
ArrayRef<GenericTypeParamType *> genericParams,
ArrayRef<Requirement> requirements,
Type input,
Type result,
const ExtInfo &info,
const ASTContext *ctx)
: AnyFunctionType(TypeKind::GenericFunction, ctx, input, result,
/*hasTypeVariable=*/false, info),
NumGenericParams(genericParams.size()),
NumRequirements(requirements.size())
{
std::copy(genericParams.begin(), genericParams.end(),
getGenericParamsBuffer().data());
std::copy(requirements.begin(), requirements.end(),
getRequirementsBuffer().data());
}
GenericTypeParamType *GenericTypeParamType::get(unsigned depth, unsigned index,
const ASTContext &ctx) {
auto known = ctx.Impl.GenericParamTypes.find({ depth, index });
if (known != ctx.Impl.GenericParamTypes.end())
return known->second;
auto result = new (ctx, AllocationArena::Permanent)
GenericTypeParamType(depth, index, ctx);
ctx.Impl.GenericParamTypes[{depth, index}] = result;
return result;
}
void SILFunctionType::Profile(llvm::FoldingSetNodeID &id,
GenericParamList *genericParams,
ExtInfo info,
ParameterConvention calleeConvention,
ArrayRef<SILParameterInfo> params,
SILResultInfo result) {
id.AddPointer(genericParams);
id.AddInteger(info.getFuncAttrKey());
id.AddInteger(unsigned(calleeConvention));
id.AddInteger(params.size());
for (auto param : params)
param.profile(id);
result.profile(id);
}
SILFunctionType *SILFunctionType::get(GenericParamList *genericParams,
ExtInfo ext, ParameterConvention callee,
ArrayRef<SILParameterInfo> params,
SILResultInfo result, ASTContext &ctx) {
llvm::FoldingSetNodeID id;
SILFunctionType::Profile(id, genericParams, ext, callee, params, result);
// Do we already have this generic function type?
void *insertPos;
if (auto result
= ctx.Impl.SILFunctionTypes.FindNodeOrInsertPos(id, insertPos))
return result;
// All SILFunctionTypes are canonical.
// Allocate storage for the object.
size_t bytes = sizeof(SILFunctionType)
+ sizeof(SILParameterInfo) * params.size();
void *mem = ctx.Allocate(bytes, alignof(SILFunctionType));
auto fnType =
new (mem) SILFunctionType(genericParams, ext, callee, params, result, ctx);
ctx.Impl.SILFunctionTypes.InsertNode(fnType, insertPos);
return fnType;
}
/// Return a uniqued array type with the specified base type and the
/// specified size.
ArrayType *ArrayType::get(Type BaseType, uint64_t Size, const ASTContext &C) {
assert(Size != 0);
bool hasTypeVariable = BaseType->hasTypeVariable();
auto arena = getArena(hasTypeVariable);
ArrayType *&Entry
= C.Impl.getArena(arena).ArrayTypes[std::make_pair(BaseType, Size)];
if (Entry) return Entry;
return Entry = new (C, arena) ArrayType(BaseType, Size, hasTypeVariable);
}
ArrayType::ArrayType(Type base, uint64_t size, bool hasTypeVariable)
: TypeBase(TypeKind::Array,
base->isCanonical() ? &base->getASTContext() : 0,
hasTypeVariable),
Base(base), Size(size) {}
ArraySliceType *ArraySliceType::get(Type base, const ASTContext &C) {
bool hasTypeVariable = base->hasTypeVariable();
auto arena = getArena(hasTypeVariable);
ArraySliceType *&entry = C.Impl.getArena(arena).ArraySliceTypes[base];
if (entry) return entry;
return entry = new (C, arena) ArraySliceType(C, base, hasTypeVariable);
}
OptionalType *OptionalType::get(Type base, const ASTContext &C) {
bool hasTypeVariable = base->hasTypeVariable();
auto arena = getArena(hasTypeVariable);
OptionalType *&entry = C.Impl.getArena(arena).OptionalTypes[base];
if (entry) return entry;
return entry = new (C, arena) OptionalType(C, base, hasTypeVariable);
}
ProtocolType *ProtocolType::get(ProtocolDecl *D, const ASTContext &C) {
if (auto declaredTy = D->getDeclaredType())
return declaredTy->castTo<ProtocolType>();
auto protoTy = new (C, AllocationArena::Permanent) ProtocolType(D, C);
D->setDeclaredType(protoTy);
return protoTy;
}
VecType *VecType::get(Type base, unsigned length, const ASTContext &C) {
bool hasTypeVariable = base->hasTypeVariable();
auto arena = getArena(hasTypeVariable);
VecType *&entry = C.Impl.getArena(arena).VecTypes[{base, length}];
if (entry) return entry;
return entry = new (C, arena) VecType(C, base, length, hasTypeVariable);
}
MatrixType *MatrixType::get(Type baseTy, unsigned rows,
Optional<unsigned> columns,
const ASTContext &ctx) {
llvm::FoldingSetNodeID id;
MatrixType::Profile(id, baseTy, rows, columns);
auto arena = getArena(baseTy->hasTypeVariable());
void *insertPos;
if (MatrixType *matrixType
= ctx.Impl.getArena(arena).MatrixTypes.FindNodeOrInsertPos(id,
insertPos))
return matrixType;
auto matrixTy = new (ctx, arena) MatrixType(ctx, baseTy, rows, columns,
baseTy->hasTypeVariable());
ctx.Impl.getArena(arena).MatrixTypes.InsertNode(matrixTy, insertPos);
return matrixTy;
}
void MatrixType::Profile(llvm::FoldingSetNodeID &id, Type baseType,
unsigned rows, Optional<unsigned> columns) {
id.AddPointer(baseType.getPointer());
id.AddInteger(rows);
id.AddBoolean(static_cast<bool>(columns));
if (columns)
id.AddInteger(*columns);
}
ProtocolType::ProtocolType(ProtocolDecl *TheDecl, const ASTContext &Ctx)
: NominalType(TypeKind::Protocol, &Ctx, TheDecl, /*Parent=*/Type(),
/*HasTypeVariable=*/false) { }
LValueType *LValueType::get(Type objectTy, Qual quals, const ASTContext &C) {
assert(!objectTy->is<ErrorType>() &&
"can not have ErrorType wrapped inside LValueType");
bool hasTypeVariable = objectTy->hasTypeVariable();
auto arena = getArena(hasTypeVariable);
auto key = std::make_pair(objectTy, quals.getOpaqueData());
auto &entry = C.Impl.getArena(arena).LValueTypes[key];
if (entry)
return entry;
const ASTContext *canonicalContext = objectTy->isCanonical() ? &C : nullptr;
return entry = new (C, arena) LValueType(objectTy, quals, canonicalContext,
hasTypeVariable);
}
/// Return a uniqued substituted type.
SubstitutedType *SubstitutedType::get(Type Original, Type Replacement,
const ASTContext &C) {
bool hasTypeVariable = Replacement->hasTypeVariable();
auto arena = getArena(hasTypeVariable);
SubstitutedType *&Known
= C.Impl.getArena(arena).SubstitutedTypes[{Original, Replacement}];
if (!Known) {
Known = new (C, arena) SubstitutedType(Original, Replacement,
hasTypeVariable);
}
return Known;
}
DependentMemberType *DependentMemberType::get(Type base, Identifier name,
const ASTContext &ctx) {
bool hasTypeVariable = base->hasTypeVariable();
auto arena = getArena(hasTypeVariable);
llvm::PointerUnion<Identifier, AssociatedTypeDecl *> stored(name);
auto *&known = ctx.Impl.getArena(arena).DependentMemberTypes[
{base, stored.getOpaqueValue()}];
if (!known) {
const ASTContext *canonicalCtx = base->isCanonical() ? &ctx : nullptr;
known = new (ctx, arena) DependentMemberType(base, name, canonicalCtx,
hasTypeVariable);
}
return known;
}
DependentMemberType *DependentMemberType::get(Type base,
AssociatedTypeDecl *assocType,
const ASTContext &ctx) {
bool hasTypeVariable = base->hasTypeVariable();
auto arena = getArena(hasTypeVariable);
llvm::PointerUnion<Identifier, AssociatedTypeDecl *> stored(assocType);
auto *&known = ctx.Impl.getArena(arena).DependentMemberTypes[
{base, stored.getOpaqueValue()}];
if (!known) {
const ASTContext *canonicalCtx = base->isCanonical() ? &ctx : nullptr;
known = new (ctx, arena) DependentMemberType(base, assocType, canonicalCtx,
hasTypeVariable);
}
return known;
}
void *ExprHandle::operator new(size_t Bytes, ASTContext &C,
unsigned Alignment) {
return C.Allocate(Bytes, Alignment);
}
ExprHandle *ExprHandle::get(ASTContext &Context, Expr *E) {
return new (Context) ExprHandle(E);
}
void TypeLoc::setInvalidType(ASTContext &C) {
TAndValidBit.setPointerAndInt(ErrorType::get(C), true);
}