//===--- 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/DiagnosticEngine.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/SourceMgr.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" using namespace swift; struct ASTContext::Implementation { Implementation(); ~Implementation(); llvm::BumpPtrAllocator Allocator; // used in later initializations llvm::StringMap IdentifierTable; llvm::FoldingSet TupleTypes; llvm::DenseMap MetaTypeTypes; llvm::DenseMap ModuleTypes; llvm::DenseMap>, FunctionType*> FunctionTypes; llvm::DenseMap, ArrayType*> ArrayTypes; llvm::DenseMap ArraySliceTypes; llvm::DenseMap IntegerTypes; llvm::DenseMap ParenTypes; llvm::DenseMap, LValueType*> LValueTypes; llvm::DenseMap, SubstitutedType *> SubstitutedTypes; llvm::FoldingSet ProtocolCompositionTypes; llvm::FoldingSet BoundGenericTypes; }; ASTContext::Implementation::Implementation() : IdentifierTable(Allocator) {} ASTContext::Implementation::~Implementation() {} ASTContext::ASTContext(llvm::SourceMgr &sourcemgr, DiagnosticEngine &Diags) : Impl(*new Implementation()), SourceMgr(sourcemgr), Diags(Diags), TheBuiltinModule(new (*this) BuiltinModule(getIdentifier("Builtin"),*this)), TheErrorType(new (*this) ErrorType(*this)), TheEmptyTupleType(TupleType::get(ArrayRef(), *this)), TheObjectPointerType(new (*this) BuiltinObjectPointerType(*this)), TheObjCPointerType(new (*this) BuiltinObjCPointerType(*this)), TheRawPointerType(new (*this) BuiltinRawPointerType(*this)), TheUnstructuredUnresolvedType(new (*this) UnstructuredUnresolvedType(*this)), TheIEEE32Type(new (*this) BuiltinFloatType(BuiltinFloatType::IEEE32,*this)), TheIEEE64Type(new (*this) BuiltinFloatType(BuiltinFloatType::IEEE64,*this)), TheIEEE16Type(new (*this) BuiltinFloatType(BuiltinFloatType::IEEE16,*this)), TheIEEE80Type(new (*this) BuiltinFloatType(BuiltinFloatType::IEEE80,*this)), TheIEEE128Type(new (*this) BuiltinFloatType(BuiltinFloatType::IEEE128, *this)), ThePPC128Type(new (*this) BuiltinFloatType(BuiltinFloatType::PPC128,*this)){ } ASTContext::~ASTContext() { delete &Impl; for (auto &entry : ConformsTo) delete const_cast(entry.second); } void *ASTContext::Allocate(unsigned long Bytes, unsigned Alignment) { return Impl.Allocator.Allocate(Bytes, Alignment); } /// getIdentifier - Return the uniqued and AST-Context-owned version of the /// specified string. Identifier ASTContext::getIdentifier(StringRef Str) { // Make sure null pointers stay null. if (Str.empty()) return Identifier(0); return Identifier(Impl.IdentifierTable.GetOrCreateValue(Str).getKeyData()); } bool ASTContext::hadError() const { return Diags.hadAnyError(); } //===----------------------------------------------------------------------===// // Type manipulation routines. //===----------------------------------------------------------------------===// // Simple accessors. Type ErrorType::get(ASTContext &C) { return C.TheErrorType; } Type UnstructuredUnresolvedType::get(ASTContext &C) { return C.TheUnstructuredUnresolvedType; } BuiltinIntegerType *BuiltinIntegerType::get(unsigned BitWidth, ASTContext &C) { BuiltinIntegerType *&Result = C.Impl.IntegerTypes[BitWidth]; if (Result == 0) Result = new (C) BuiltinIntegerType(BitWidth, C); return Result; } ParenType *ParenType::get(ASTContext &C, Type underlying) { ParenType *&Result = C.Impl.ParenTypes[underlying]; if (Result == 0) Result = new (C) ParenType(underlying); return Result; } Type TupleType::getEmpty(ASTContext &C) { return C.TheEmptyTupleType; } void TupleType::Profile(llvm::FoldingSetNodeID &ID, ArrayRef Fields) { ID.AddInteger(Fields.size()); for (const TupleTypeElt &Elt : Fields) { ID.AddPointer(Elt.getType().getPointer()); ID.AddPointer(Elt.getName().get()); ID.AddPointer(Elt.getInit()); ID.AddPointer(Elt.getVarargBaseTy().getPointer()); } } /// getTupleType - Return the uniqued tuple type with the specified elements. TupleType *TupleType::get(ArrayRef Fields, ASTContext &C) { bool HasAnyDefaultValues = false; for (const TupleTypeElt &Elt : Fields) { if (Elt.hasInit()) { HasAnyDefaultValues = true; break; } } void *InsertPos = 0; if (!HasAnyDefaultValues) { // Check to see if we've already seen this tuple before. llvm::FoldingSetNodeID ID; TupleType::Profile(ID, Fields); if (TupleType *TT = C.Impl.TupleTypes.FindNodeOrInsertPos(ID, InsertPos)) return TT; } // Make a copy of the fields list into ASTContext owned memory. TupleTypeElt *FieldsCopy = C.AllocateCopy(Fields.begin(), Fields.end()); 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(FieldsCopy, Fields.size()); TupleType *New = new (C) TupleType(Fields, IsCanonical ? &C : 0); if (!HasAnyDefaultValues) C.Impl.TupleTypes.InsertNode(New, InsertPos); return New; } void BoundGenericType::Profile(llvm::FoldingSetNodeID &ID, NominalTypeDecl *TheDecl, ArrayRef GenericArgs) { ID.AddPointer(TheDecl); ID.AddInteger(GenericArgs.size()); for (Type Arg : GenericArgs) ID.AddPointer(Arg.getPointer()); } BoundGenericType::BoundGenericType(NominalTypeDecl *TheDecl, ArrayRef GenericArgs, ASTContext *C) : TypeBase(TypeKind::BoundGeneric, C, /*Unresolved=*/false), TheDecl(TheDecl), GenericArgs(GenericArgs), AllConformances(nullptr) { // Determine whether this type is unresolved. for (Type Arg : GenericArgs) { if (Arg->isUnresolvedType()) { setUnresolved(); break; } } } BoundGenericType* BoundGenericType::get(NominalTypeDecl *TheDecl, ArrayRef GenericArgs) { ASTContext &C = TheDecl->getDeclContext()->getASTContext(); llvm::FoldingSetNodeID ID; BoundGenericType::Profile(ID, TheDecl, GenericArgs); void *InsertPos = 0; if (BoundGenericType *BGT = C.Impl.BoundGenericTypes.FindNodeOrInsertPos(ID, InsertPos)) return BGT; ArrayRef ArgsCopy = C.AllocateCopy(GenericArgs); bool IsCanonical = true; // All canonical elts means this is canonical. for (Type Arg : GenericArgs) { if (!Arg->isCanonical()) { IsCanonical = false; break; } } BoundGenericType *New = new (C) BoundGenericType(TheDecl, ArgsCopy, IsCanonical ? &C : 0); C.Impl.BoundGenericTypes.InsertNode(New, InsertPos); return New; } OneOfType::OneOfType(OneOfDecl *TheDecl, ASTContext &C) : NominalType(TypeKind::OneOf, &C, TheDecl) { } StructType::StructType(StructDecl *TheDecl, ASTContext &C) : NominalType(TypeKind::Struct, &C, TheDecl) { } ClassType::ClassType(ClassDecl *TheDecl, ASTContext &C) : NominalType(TypeKind::Class, &C, TheDecl) { } IdentifierType *IdentifierType::getNew(ASTContext &C, MutableArrayRef Components) { Components = C.AllocateCopy(Components); return new (C) IdentifierType(Components); } ProtocolCompositionType * ProtocolCompositionType::build(ASTContext &C, SourceLoc FirstLoc, ArrayRef 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) ProtocolCompositionType(isCanonical ? &C : nullptr, FirstLoc, C.AllocateCopy(Protocols)); C.Impl.ProtocolCompositionTypes.InsertNode(New, InsertPos); return New; } MetaTypeType *MetaTypeType::get(Type T, ASTContext &C) { MetaTypeType *&Entry = C.Impl.MetaTypeTypes[T]; if (Entry) return Entry; return Entry = new (C) MetaTypeType(T, T->isCanonical() ? &C : 0); } MetaTypeType::MetaTypeType(Type T, ASTContext *C) : TypeBase(TypeKind::MetaType, C, T->isUnresolvedType()), 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) ModuleType(M, C); } /// FunctionType::get - Return a uniqued function type with the specified /// input and result. FunctionType *FunctionType::get(Type Input, Type Result, bool isAutoClosure, ASTContext &C) { FunctionType *&Entry = C.Impl.FunctionTypes[std::make_pair(Input, std::make_pair(Result, (char)isAutoClosure))]; if (Entry) return Entry; return Entry = new (C) FunctionType(Input, Result, isAutoClosure); } // If the input and result types are canonical, then so is the result. FunctionType::FunctionType(Type input, Type output, bool isAutoClosure) : AnyFunctionType(TypeKind::Function, (input->isCanonical() && output->isCanonical()) ? &input->getASTContext() : 0, input, output, (input->isUnresolvedType() || output->isUnresolvedType())), AutoClosure(isAutoClosure) { } /// FunctionType::get - Return a uniqued function type with the specified /// input and result. PolymorphicFunctionType *PolymorphicFunctionType::get(Type input, Type output, GenericParamList *params, ASTContext &C) { // FIXME: one day we should do canonicalization properly. return new (C) PolymorphicFunctionType(input, output, params, C); } PolymorphicFunctionType::PolymorphicFunctionType(Type input, Type output, GenericParamList *params, ASTContext &C) : AnyFunctionType(TypeKind::PolymorphicFunction, (input->isCanonical() && output->isCanonical()) ?&C : 0, input, output, (input->isUnresolvedType() || output->isUnresolvedType())), Params(params) { } /// Return a uniqued array type with the specified base type and the /// specified size. ArrayType *ArrayType::get(Type BaseType, uint64_t Size, ASTContext &C) { assert(Size != 0); ArrayType *&Entry = C.Impl.ArrayTypes[std::make_pair(BaseType, Size)]; if (Entry) return Entry; return Entry = new (C) ArrayType(BaseType, Size); } ArrayType::ArrayType(Type base, uint64_t size) : TypeBase(TypeKind::Array, base->isCanonical() ? &base->getASTContext() : 0, base->isUnresolvedType()), Base(base), Size(size) {} /// Return a uniqued array slice type with the specified base type. ArraySliceType *ArraySliceType::get(Type base, SourceLoc loc, ASTContext &C) { ArraySliceType *&entry = C.Impl.ArraySliceTypes[base]; if (entry) return entry; return entry = new (C) ArraySliceType(loc, base); } ProtocolType::ProtocolType(ProtocolDecl *TheDecl, ASTContext &Ctx) : NominalType(TypeKind::Protocol, &Ctx, TheDecl) { } LValueType *LValueType::get(Type objectTy, Qual quals, ASTContext &C) { auto key = std::make_pair(objectTy, quals.getOpaqueData()); auto it = C.Impl.LValueTypes.find(key); if (it != C.Impl.LValueTypes.end()) return it->second; ASTContext *canonicalContext = (objectTy->isCanonical() ? &C : nullptr); LValueType *type = new (C) LValueType(objectTy, quals, canonicalContext); C.Impl.LValueTypes.insert(std::make_pair(key, type)); return type; } /// Return a uniqued substituted type. SubstitutedType *SubstitutedType::get(Type Original, Type Replacement, ASTContext &C) { SubstitutedType *&Known = C.Impl.SubstitutedTypes[{Original, Replacement}]; if (!Known) Known = new (C) SubstitutedType(Original, Replacement); return Known; }