//===--- Module.cpp - Swift Language Module 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 Module class and subclasses. // //===----------------------------------------------------------------------===// #include "swift/AST/Module.h" #include "swift/AST/AST.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/TinyPtrVector.h" using namespace swift; //===----------------------------------------------------------------------===// // Builtin Module Name lookup //===----------------------------------------------------------------------===// namespace { /// BuiltinModuleCache - This is the type of the cache for the BuiltinModule. /// This is lazily created on its first use an hangs off /// Module::LookupCachePimpl. class BuiltinModuleCache { /// The cache of identifiers we've already looked up. We use a /// single hashtable for both types and values as a minor /// optimization; this prevents us from having both a builtin type /// and a builtin value with the same name, but that's okay. llvm::DenseMap Cache; public: TypeAliasDecl *lookupType(Identifier Name, NLKind LookupKind, BuiltinModule &M); void lookupValue(Identifier Name, NLKind LookupKind, BuiltinModule &M, SmallVectorImpl &Result); }; } // end anonymous namespace. static BuiltinModuleCache &getBuiltinCachePimpl(void *&Ptr) { // FIXME: This leaks. Sticking this into ASTContext isn't enough because then // the DenseMap will leak. if (Ptr == 0) Ptr = new BuiltinModuleCache(); return *(BuiltinModuleCache*)Ptr; } TypeAliasDecl *BuiltinModuleCache::lookupType(Identifier Name, NLKind LookupKind, BuiltinModule &M) { // Only qualified lookup ever finds anything in the builtin module. if (LookupKind != NLKind::QualifiedLookup) return nullptr; NamedDecl *&Entry = Cache[Name]; if (Entry == 0) if (Type Ty = getBuiltinType(M.Ctx, Name)) Entry = new (M.Ctx) TypeAliasDecl(SourceLoc(), Name, Ty, DeclAttributes(), M.Ctx.TheBuiltinModule); return dyn_cast_or_null(Entry); } void BuiltinModuleCache::lookupValue(Identifier Name, NLKind LookupKind, BuiltinModule &M, SmallVectorImpl &Result) { // Only qualified lookup ever finds anything in the builtin module. if (LookupKind != NLKind::QualifiedLookup) return; NamedDecl *&Entry = Cache[Name]; if (Entry == 0) Entry = getBuiltinValue(M.Ctx, Name); if (ValueDecl *VD = dyn_cast_or_null(Entry)) Result.push_back(VD); } //===----------------------------------------------------------------------===// // Normal Module Name Lookup //===----------------------------------------------------------------------===// namespace { /// TUModuleCache - This is the type of the cache for the TranslationUnit. /// This is lazily created on its first use an hangs off /// Module::LookupCachePimpl. class TUModuleCache { llvm::DenseMap> TopLevelValues; llvm::DenseMap TopLevelTypes; public: typedef Module::AccessPathTy AccessPathTy; TypeAliasDecl *lookupType(AccessPathTy AccessPath, Identifier Name, NLKind LookupKind, TranslationUnit &TU); void lookupValue(AccessPathTy AccessPath, Identifier Name, NLKind LookupKind, TranslationUnit &TU, SmallVectorImpl &Result); }; } // end anonymous namespace. static TUModuleCache &getTUCachePimpl(void *&Ptr) { // FIXME: This leaks. Sticking this into ASTContext isn't enough because then // the DenseMap will leak. if (Ptr == 0) Ptr = new TUModuleCache(); return *(TUModuleCache*)Ptr; } TypeAliasDecl *TUModuleCache::lookupType(AccessPathTy AccessPath, Identifier Name, NLKind LookupKind, TranslationUnit &TU) { assert(AccessPath.size() <= 1 && "Don't handle this yet"); // If this import is specific to some named type or decl ("import swift.int") // then filter out any lookups that don't match. if (AccessPath.size() == 1 && AccessPath[0].first != Name) return 0; if (TopLevelTypes.empty()) { for (auto Elt : TU.Body->getElements()) if (Decl *D = Elt.dyn_cast()) if (TypeAliasDecl *TAD = dyn_cast(D)) if (!TAD->Name.empty()) TopLevelTypes[TAD->Name] = TAD; } auto I = TopLevelTypes.find(Name); return I != TopLevelTypes.end() ? I->second : 0; } void TUModuleCache::lookupValue(AccessPathTy AccessPath, Identifier Name, NLKind LookupKind, TranslationUnit &TU, SmallVectorImpl &Result) { // TODO: ImportDecls cannot specified namespaces or individual entities // yet, so everything is just a lookup at the top-level. assert(AccessPath.size() <= 1 && "Don't handle this yet"); // If this import is specific to some named type or decl ("import swift.int") // then filter out any lookups that don't match. if (AccessPath.size() == 1 && AccessPath[0].first != Name) return; // If we haven't built a map of the top-level values, do so now. if (TopLevelValues.empty()) { for (auto Elt : TU.Body->getElements()) if (Decl *D = Elt.dyn_cast()) if (ValueDecl *VD = dyn_cast(D)) if (!VD->Name.empty()) TopLevelValues[VD->Name].push_back(VD); } auto I = TopLevelValues.find(Name); if (I == TopLevelValues.end()) return; Result.reserve(I->second.size()); for (ValueDecl *Elt : I->second) { // Dot Lookup ignores values with non-function types. if (LookupKind == NLKind::DotLookup && !Elt->Ty->is()) continue; Result.push_back(Elt); } } //===----------------------------------------------------------------------===// // Module Implementation //===----------------------------------------------------------------------===// /// lookupType - Look up a type at top-level scope (but with the specified /// access path, which may come from an import decl) within the current /// module. This does a simple local lookup, not recursively looking through /// imports. TypeAliasDecl *Module::lookupType(AccessPathTy AccessPath, Identifier Name, NLKind LookupKind) { if (BuiltinModule *BM = dyn_cast(this)) { assert(AccessPath.empty() && "builtin module's access path always empty!"); return getBuiltinCachePimpl(LookupCachePimpl) .lookupType(Name, LookupKind, *BM); } // Otherwise must be TranslationUnit. Someday we should generalize this to // allow modules with multiple translation units. return getTUCachePimpl(LookupCachePimpl) .lookupType(AccessPath, Name, LookupKind, *cast(this)); } /// lookupValue - Look up a (possibly overloaded) value set at top-level scope /// (but with the specified access path, which may come from an import decl) /// within the current module. This does a simple local lookup, not /// recursively looking through imports. void Module::lookupValue(AccessPathTy AccessPath, Identifier Name, NLKind LookupKind, SmallVectorImpl &Result) { if (BuiltinModule *BM = dyn_cast(this)) { assert(AccessPath.empty() && "builtin module's access path always empty!"); return getBuiltinCachePimpl(LookupCachePimpl) .lookupValue(Name, LookupKind, *BM, Result); } // Otherwise must be TranslationUnit. Someday we should generalize this to // allow modules with multiple translation units. return getTUCachePimpl(LookupCachePimpl) .lookupValue(AccessPath, Name, LookupKind, *cast(this), Result); }