//===--- 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; /// IdentifierTableMapTy - This is the type underlying IdentifierTable. typedef llvm::StringMap IdentifierTableMapTy; /// TupleTypesMapTy - This is the actual type underlying ASTContext::TupleTypes. typedef llvm::FoldingSet TupleTypesMapTy; /// MetatypeTypesMapTy - This is the underlying type of MetaTypeTypes. typedef llvm::DenseMap MetaTypeTypesMapTy; /// ModuleTypesMapTy - This is the underlying type of ModuleTypes. typedef llvm::DenseMap ModuleTypesMapTy; /// FunctionTypesMapTy - This is the actual type underlying 'FunctionTypes'. typedef llvm::DenseMap, FunctionType*> FunctionTypesMapTy; /// ArrayTypesMapTy - This is the actual type underlying 'ArrayTypes'. typedef llvm::DenseMap, ArrayType*> ArrayTypesMapTy; /// IntegerTypesMapTy - This is the actual type underlying 'IntegerTypes'. typedef llvm::DenseMap IntegerTypesMapTy; /// ParenTypesMapTy - This is the actual type underlying 'ParenTypes'. typedef llvm::DenseMap ParenTypesMapTy; /// LValueTypesMapTy - This is the actual type underlying 'LValueTypes'. typedef llvm::DenseMap LValueTypesMapTy; ASTContext::ASTContext(llvm::SourceMgr &sourcemgr, DiagnosticEngine &Diags) : Allocator(new llvm::BumpPtrAllocator()), IdentifierTable(new IdentifierTableMapTy(*Allocator)), TupleTypes(new TupleTypesMapTy()), MetaTypeTypes(new MetaTypeTypesMapTy()), ModuleTypes(new ModuleTypesMapTy()), FunctionTypes(new FunctionTypesMapTy()), ArrayTypes(new ArrayTypesMapTy()), IntegerTypes(new IntegerTypesMapTy()), ParenTypes(new ParenTypesMapTy()), LValueTypes(new LValueTypesMapTy()), SourceMgr(sourcemgr), Diags(Diags), TheBuiltinModule(new (*this) BuiltinModule(getIdentifier("Builtin"),*this)), TheErrorType(new (*this) ErrorType(*this)), TheEmptyTupleType(TupleType::get(ArrayRef(), *this)), TheDependentType(new (*this) DependentType(*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 (TupleTypesMapTy*)TupleTypes; TupleTypes = 0; delete (FunctionTypesMapTy*)FunctionTypes; FunctionTypes = 0; delete (MetaTypeTypesMapTy*)MetaTypeTypes; MetaTypeTypes = 0; delete (ModuleTypesMapTy*)ModuleTypes; ModuleTypes = 0; delete (ArrayTypesMapTy*)ArrayTypes; ArrayTypes = 0; delete (IdentifierTableMapTy*)IdentifierTable; IdentifierTable = 0; delete (IntegerTypesMapTy*)IntegerTypes; IntegerTypes = 0; delete (ParenTypesMapTy*)ParenTypes; ParenTypes = 0; delete (LValueTypesMapTy*)LValueTypes; LValueTypes = 0; delete Allocator; Allocator = 0; } void *ASTContext::Allocate(unsigned long Bytes, unsigned Alignment) { return 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); IdentifierTableMapTy &Table = *((IdentifierTableMapTy*)IdentifierTable); return Identifier(Table.GetOrCreateValue(Str).getKeyData()); } bool ASTContext::hadError() const { return Diags.hadAnyError(); } //===----------------------------------------------------------------------===// // Type manipulation routines. //===----------------------------------------------------------------------===// // Simple accessors. Type ErrorType::get(ASTContext &C) { return C.TheErrorType; } Type DependentType::get(ASTContext &C) { return C.TheDependentType; } BuiltinIntegerType *BuiltinIntegerType::get(unsigned BitWidth, ASTContext &C) { IntegerTypesMapTy &IntegerTypesMap = *(IntegerTypesMapTy*)C.IntegerTypes; BuiltinIntegerType *&Result = IntegerTypesMap[BitWidth]; if (Result == 0) Result = new (C) BuiltinIntegerType(BitWidth, C); return Result; } ParenType *ParenType::get(ASTContext &C, Type underlying) { ParenTypesMapTy &ParenTypesMap = *(ParenTypesMapTy*) C.ParenTypes; ParenType *&Result = ParenTypesMap[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()); } } /// getTupleType - Return the uniqued tuple type with the specified elements. TupleType *TupleType::get(ArrayRef Fields, ASTContext &C) { // Check to see if we've already seen this tuple before. llvm::FoldingSetNodeID ID; TupleType::Profile(ID, Fields); TupleTypesMapTy &TupleTypesMap = *(TupleTypesMapTy*)C.TupleTypes; // FIXME: This is pointless for types with named fields. The ValueDecl fields // themselves are not unique'd so they all get their own addresses, which // means that we'll never get a hit here. This should unique all-type tuples // though. Likewise with default values. void *InsertPos = 0; if (TupleType *TT = TupleTypesMap.FindNodeOrInsertPos(ID, InsertPos)) return TT; // Okay, we didn't find one. 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); TupleTypesMap.InsertNode(New, InsertPos); return New; } /// getNewOneOfType - Return a new instance of oneof type. These are never /// uniqued because the loc is generally different. OneOfType *OneOfType::getNew(SourceLoc OneOfLoc, ArrayRef InElts, TypeAliasDecl *TheDecl) { ASTContext &C = TheDecl->getASTContext(); return new (C) OneOfType(OneOfLoc, C.AllocateCopy(InElts), TheDecl); } // oneof types are always canonical. OneOfType::OneOfType(SourceLoc OneOfLoc, ArrayRef Elts, TypeAliasDecl *TheDecl) : TypeBase(TypeKind::OneOf, &TheDecl->getASTContext()), DeclContext(DeclContextKind::OneOfType, TheDecl->getDeclContext()), OneOfLoc(OneOfLoc), Elements(Elts), TheDecl(TheDecl) { } IdentifierType *IdentifierType::getNew(ASTContext &C, MutableArrayRef Components) { Components = C.AllocateCopy(Components); return new (C) IdentifierType(Components); } MetaTypeType *MetaTypeType::get(TypeAliasDecl *Type) { ASTContext &C = Type->getASTContext(); MetaTypeType *&Entry = (*(MetaTypeTypesMapTy*)C.MetaTypeTypes)[Type]; if (Entry) return Entry; return Entry = new (C) MetaTypeType(Type, C); } ModuleType *ModuleType::get(Module *M) { ASTContext &C = M->getASTContext(); ModuleType *&Entry = (*(ModuleTypesMapTy*)C.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, ASTContext &C) { FunctionType *&Entry = (*(FunctionTypesMapTy*)C.FunctionTypes)[std::make_pair(Input, Result)]; if (Entry) return Entry; return Entry = new (C) FunctionType(Input, Result); } // If the input and result types are canonical, then so is the result. FunctionType::FunctionType(Type input, Type result) : TypeBase(TypeKind::Function, (input->isCanonical() && result->isCanonical()) ? &input->getASTContext() : 0), Input(input), Result(result) { } /// getArrayType - Return a uniqued array type with the specified base type /// and the specified size. Size=0 indicates an unspecified size array. ArrayType *ArrayType::get(Type BaseType, uint64_t Size, ASTContext &C) { ArrayType *&Entry = (*(ArrayTypesMapTy*)C.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(base), Size(size) {} /// getNew - Return a new instance of a protocol type. These are never /// uniqued since each syntactic instance of them is semantically considered /// to be a different type. ProtocolType *ProtocolType::getNew(SourceLoc ProtocolLoc, ArrayRef Elts, TypeAliasDecl *TheDecl) { ASTContext &C = TheDecl->getASTContext(); return new (C) ProtocolType(ProtocolLoc, C.AllocateCopy(Elts), TheDecl); } ProtocolType::ProtocolType(SourceLoc ProtocolLoc, ArrayRef Elts, TypeAliasDecl *TheDecl) : TypeBase(TypeKind::Protocol, &TheDecl->getASTContext()), DeclContext(DeclContextKind::ProtocolType, TheDecl->getDeclContext()), ProtocolLoc(ProtocolLoc), Elements(Elts), TheDecl(TheDecl) { } LValueType *LValueType::get(Type objectTy, ASTContext &C) { LValueType *&entry = (*(LValueTypesMapTy*)C.LValueTypes)[objectTy]; if (!entry) entry = new (C) LValueType(objectTy); return entry; }