Skip to content

Commit f184504

Browse files
authored
Merge pull request #61845 from DougGregor/getSourceFileContainingLocation-LRU
Introduce an LRU cache for getSourceFileContainingLocation()
2 parents c0abe0b + 0f30950 commit f184504

29 files changed

+400
-85
lines changed

docs/Generics/generics.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1351,7 +1351,7 @@ \subsection*{Module System}
13511351
\apiref{SourceFile}{class}
13521352
Represents a parsed source file from disk. Inherits from \texttt{FileUnit}.
13531353
\begin{itemize}
1354-
\item \texttt{getTopLevelDecls()} returns an array of all top-level declarations in this source file.
1354+
\item \texttt{getTopLevelItems()} returns an array of all top-level items in this source file.
13551355
\item \texttt{isPrimary()} returns \texttt{true} if this is a primary file, \texttt{false} if this is a secondary file.
13561356
\item \texttt{isScriptMode()} answers if this is the main file of a module.
13571357
\item \texttt{getScope()} returns the root of the scope tree for unqualified lookup.

include/swift/AST/ASTScope.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class ASTScopeImpl : public ASTAllocated<ASTScopeImpl> {
128128
friend class GenericTypeOrExtensionWherePortion;
129129
friend class IterableTypeBodyPortion;
130130
friend class ScopeCreator;
131+
friend class ASTSourceFileScope;
131132

132133
#pragma mark - tree state
133134
protected:

include/swift/AST/Module.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ enum class SourceFileKind {
106106
Library, ///< A normal .swift file.
107107
Main, ///< A .swift file that can have top-level code.
108108
SIL, ///< Came from a .sil file.
109-
Interface ///< Came from a .swiftinterface file, representing another module.
109+
Interface, ///< Came from a .swiftinterface file, representing another module.
110+
MacroExpansion, ///< Came from a macro expansion.
110111
};
111112

112113
/// Contains information about where a particular path is used in
@@ -158,6 +159,10 @@ enum class ResilienceStrategy : unsigned {
158159

159160
class OverlayFile;
160161

162+
/// A mapping used to find the source file that contains a particular source
163+
/// location.
164+
class ModuleSourceFileLocationMap;
165+
161166
/// The minimum unit of compilation.
162167
///
163168
/// A module is made up of several file-units, which are all part of the same
@@ -229,6 +234,13 @@ class ModuleDecl
229234

230235
SmallVector<FileUnit *, 2> Files;
231236

237+
/// Mapping used to find the source file associated with a given source
238+
/// location.
239+
ModuleSourceFileLocationMap *sourceFileLocationMap = nullptr;
240+
241+
/// The set of auxiliary source files build as part of this module.
242+
SmallVector<SourceFile *, 2> AuxiliaryFiles;
243+
232244
llvm::SmallDenseMap<Identifier, SmallVector<OverlayFile *, 1>>
233245
declaredCrossImports;
234246

@@ -328,6 +340,13 @@ class ModuleDecl
328340
/// SynthesizedFileUnit instead.
329341
void addFile(FileUnit &newFile);
330342

343+
/// Add an auxiliary source file, introduced as part of the translation.
344+
void addAuxiliaryFile(SourceFile &sourceFile);
345+
346+
/// Produces the source file that contains the given source location, or
347+
/// \c nullptr if the source location isn't in this module.
348+
SourceFile *getSourceFileContainingLocation(SourceLoc loc);
349+
331350
/// Creates a map from \c #filePath strings to corresponding \c #fileID
332351
/// strings, diagnosing any conflicts.
333352
///
@@ -414,6 +433,9 @@ class ModuleDecl
414433
/// present overlays as if they were part of their underlying module.
415434
std::pair<ModuleDecl *, Identifier> getDeclaringModuleAndBystander();
416435

436+
/// Update the source-file location map to make it current.
437+
void updateSourceFileLocationMap();
438+
417439
public:
418440
/// If this is a traditional (non-cross-import) overlay, get its underlying
419441
/// module if one exists.

include/swift/AST/ParseRequests.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
namespace swift {
2727

28+
struct ASTNode;
29+
2830
/// Report that a request of the given kind is being evaluated, so it
2931
/// can be recorded by the stats reporter.
3032
template<typename Request>
@@ -85,13 +87,13 @@ class ParseAbstractFunctionBodyRequest
8587
};
8688

8789
struct SourceFileParsingResult {
88-
ArrayRef<Decl *> TopLevelDecls;
90+
ArrayRef<ASTNode> TopLevelItems;
8991
Optional<ArrayRef<Token>> CollectedTokens;
9092
Optional<StableHasher> InterfaceHasher;
9193
Optional<syntax::SourceFileSyntax> SyntaxRoot;
9294
};
9395

94-
/// Parse the top-level decls of a SourceFile.
96+
/// Parse the top-level items of a SourceFile.
9597
class ParseSourceFileRequest
9698
: public SimpleRequest<
9799
ParseSourceFileRequest, SourceFileParsingResult(SourceFile *),
@@ -116,6 +118,25 @@ class ParseSourceFileRequest
116118
readDependencySource(const evaluator::DependencyRecorder &) const;
117119
};
118120

121+
/// Parse the top-level items of a SourceFile.
122+
class ParseTopLevelDeclsRequest
123+
: public SimpleRequest<
124+
ParseTopLevelDeclsRequest, ArrayRef<Decl *>(SourceFile *),
125+
RequestFlags::Cached> {
126+
public:
127+
using SimpleRequest::SimpleRequest;
128+
129+
private:
130+
friend SimpleRequest;
131+
132+
// Evaluation.
133+
ArrayRef<Decl *> evaluate(Evaluator &evaluator, SourceFile *SF) const;
134+
135+
public:
136+
// Caching.
137+
bool isCached() const { return true; }
138+
};
139+
119140
void simple_display(llvm::raw_ostream &out,
120141
const CodeCompletionCallbacksFactory *factory);
121142

include/swift/AST/ParseTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@ SWIFT_REQUEST(Parse, ParseAbstractFunctionBodyRequest,
2525
SWIFT_REQUEST(Parse, ParseSourceFileRequest,
2626
SourceFileParsingResult(SourceFile *), SeparatelyCached,
2727
NoLocationInfo)
28+
SWIFT_REQUEST(Parse, ParseTopLevelDeclsRequest,
29+
ArrayRef<Decl *>(SourceFile *), Cached,
30+
NoLocationInfo)

include/swift/AST/SourceFile.h

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
#ifndef SWIFT_AST_SOURCEFILE_H
1414
#define SWIFT_AST_SOURCEFILE_H
1515

16+
#include "swift/AST/ASTNode.h"
1617
#include "swift/AST/FileUnit.h"
1718
#include "swift/AST/Import.h"
1819
#include "swift/AST/SynthesizedFileUnit.h"
1920
#include "swift/Basic/Debug.h"
2021
#include "llvm/ADT/Hashing.h"
2122
#include "llvm/ADT/SetVector.h"
2223
#include "llvm/ADT/SmallPtrSet.h"
24+
#include "llvm/ADT/STLExtras.h"
2325

2426
namespace swift {
2527

@@ -151,11 +153,11 @@ class SourceFile final : public FileUnit {
151153
/// been validated.
152154
llvm::SetVector<ValueDecl *> UnvalidatedDeclsWithOpaqueReturnTypes;
153155

154-
/// The list of top-level declarations in the source file. This is \c None if
156+
/// The list of top-level items in the source file. This is \c None if
155157
/// they have not yet been parsed.
156158
/// FIXME: Once addTopLevelDecl/prependTopLevelDecl
157159
/// have been removed, this can become an optional ArrayRef.
158-
Optional<std::vector<Decl *>> Decls;
160+
Optional<std::vector<ASTNode>> Items;
159161

160162
/// The list of hoisted declarations. See Decl::isHoisted().
161163
/// This is only used by lldb.
@@ -195,42 +197,48 @@ class SourceFile final : public FileUnit {
195197
friend ASTContext;
196198

197199
public:
200+
/// For source files created to hold the source code created by expanding
201+
/// a macro, this is the AST node that describes the macro expansion.
202+
///
203+
/// The source location of this AST node is the place in the source that
204+
/// triggered the creation of the macro expansion whose resulting source
205+
/// code is in this source file. This field is only valid when
206+
/// the \c SourceFileKind is \c MacroExpansion.
207+
const ASTNode macroExpansion;
208+
198209
/// Appends the given declaration to the end of the top-level decls list. Do
199210
/// not add any additional uses of this function.
200-
void addTopLevelDecl(Decl *d) {
201-
// Force decl parsing if we haven't already.
202-
(void)getTopLevelDecls();
203-
Decls->push_back(d);
204-
}
211+
void addTopLevelDecl(Decl *d);
205212

206213
/// Prepends a declaration to the top-level decls list.
207214
///
208215
/// FIXME: This entrypoint exists to support LLDB. Calls to this function are
209216
/// always a mistake, and additional uses should not be added.
210217
///
211218
/// See rdar://58355191
212-
void prependTopLevelDecl(Decl *d) {
213-
// Force decl parsing if we haven't already.
214-
(void)getTopLevelDecls();
215-
Decls->insert(Decls->begin(), d);
216-
}
219+
void prependTopLevelDecl(Decl *d);
217220

218221
/// Add a hoisted declaration. See Decl::isHoisted().
219222
void addHoistedDecl(Decl *d);
220223

224+
/// Retrieves an immutable view of the list of top-level items in this file.
225+
ArrayRef<ASTNode> getTopLevelItems() const;
226+
221227
/// Retrieves an immutable view of the list of top-level decls in this file.
228+
///
229+
/// NOTE: Please use getTopLevelItems() instead.
222230
ArrayRef<Decl *> getTopLevelDecls() const;
223231

224232
/// Retrieves an immutable view of the list of hoisted decls in this file.
225233
/// See Decl::isHoisted().
226234
ArrayRef<Decl *> getHoistedDecls() const;
227235

228-
/// Retrieves an immutable view of the top-level decls if they have already
236+
/// Retrieves an immutable view of the top-level items if they have already
229237
/// been parsed, or \c None if they haven't. Should only be used for dumping.
230-
Optional<ArrayRef<Decl *>> getCachedTopLevelDecls() const {
231-
if (!Decls)
238+
Optional<ArrayRef<ASTNode>> getCachedTopLevelItems() const {
239+
if (!Items)
232240
return None;
233-
return llvm::makeArrayRef(*Decls);
241+
return llvm::makeArrayRef(*Items);
234242
}
235243

236244
/// Retrieve the parsing options for the file.
@@ -326,7 +334,8 @@ class SourceFile final : public FileUnit {
326334
llvm::StringMap<SourceFilePathInfo> getInfoForUsedFilePaths() const;
327335

328336
SourceFile(ModuleDecl &M, SourceFileKind K, Optional<unsigned> bufferID,
329-
ParsingOptions parsingOpts = {}, bool isPrimary = false);
337+
ParsingOptions parsingOpts = {}, bool isPrimary = false,
338+
ASTNode macroExpansion = ASTNode());
330339

331340
~SourceFile();
332341

@@ -487,6 +496,11 @@ class SourceFile final : public FileUnit {
487496
return BufferID;
488497
}
489498

499+
/// When this source file is enclosed within another source file, for example
500+
/// because it describes a macro expansion, return the source file it was
501+
/// enclosed in.
502+
SourceFile *getEnclosingSourceFile() const;
503+
490504
/// If this buffer corresponds to a file on disk, returns the path.
491505
/// Otherwise, return an empty string.
492506
StringRef getFilename() const;
@@ -506,7 +520,7 @@ class SourceFile final : public FileUnit {
506520
// FIXME: Ideally the parser state should be an output of
507521
// ParseSourceFileRequest, but the evaluator doesn't currently support
508522
// move-only outputs for cached requests.
509-
(void)getTopLevelDecls();
523+
(void)getTopLevelItems();
510524

511525
auto *state = DelayedParserState.get();
512526
assert(state && "Didn't set any delayed parser state!");
@@ -545,6 +559,7 @@ class SourceFile final : public FileUnit {
545559
case SourceFileKind::Library:
546560
case SourceFileKind::Interface:
547561
case SourceFileKind::SIL:
562+
case SourceFileKind::MacroExpansion:
548563
return false;
549564
}
550565
llvm_unreachable("bad SourceFileKind");

include/swift/Parse/Parser.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ namespace swift {
7979
InactiveConditionalBlock,
8080
/// The body of the active clause of an #if/#else/#endif block
8181
ActiveConditionalBlock,
82+
/// The top-level of a macro expansion "file".
83+
MacroExpansion,
8284
};
8385

8486
/// The receiver will be fed with consumed tokens while parsing. The main purpose
@@ -969,8 +971,10 @@ class Parser {
969971
/// Returns true if the parser is at the start of a SIL decl.
970972
bool isStartOfSILDecl();
971973

972-
/// Parse the top-level Swift decls into the provided vector.
973-
void parseTopLevel(SmallVectorImpl<Decl *> &decls);
974+
/// Parse the top-level Swift items into the provided vector.
975+
///
976+
/// Each item will be a declaration, statement, or expression.
977+
void parseTopLevelItems(SmallVectorImpl<ASTNode> &items);
974978

975979
/// Parse the top-level SIL decls into the SIL module.
976980
/// \returns \c true if there was a parsing error.

lib/AST/ASTDumper.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -804,13 +804,21 @@ namespace {
804804
PrintWithColorRAII(OS, ASTNodeColor) << "source_file ";
805805
PrintWithColorRAII(OS, LocationColor) << '\"' << SF.getFilename() << '\"';
806806

807-
if (auto decls = SF.getCachedTopLevelDecls()) {
808-
for (Decl *D : *decls) {
809-
if (D->isImplicit())
807+
if (auto items = SF.getCachedTopLevelItems()) {
808+
for (auto item : *items) {
809+
if (item.isImplicit())
810810
continue;
811811

812812
OS << '\n';
813-
printRec(D);
813+
814+
if (auto decl = item.dyn_cast<Decl *>()) {
815+
printRec(decl);
816+
} else if (auto stmt = item.dyn_cast<Stmt *>()) {
817+
stmt->dump(OS, &SF.getASTContext(), Indent + 2);
818+
} else {
819+
auto expr = item.get<Expr *>();
820+
expr->dump(OS, Indent + 2);
821+
}
814822
}
815823
}
816824
PrintWithColorRAII(OS, ParenthesisColor) << ')';
@@ -1470,7 +1478,7 @@ void SourceFile::dump(llvm::raw_ostream &OS, bool parseIfNeeded) const {
14701478
// parsing request as by default the dumping logic tries not to kick any
14711479
// requests.
14721480
if (parseIfNeeded)
1473-
(void)getTopLevelDecls();
1481+
(void)getTopLevelItems();
14741482

14751483
PrintDecl(OS).visitSourceFile(*this);
14761484
llvm::errs() << '\n';

lib/AST/ASTScope.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ using namespace ast_scope;
4141
void ASTScope::unqualifiedLookup(
4242
SourceFile *SF, SourceLoc loc,
4343
namelookup::AbstractASTScopeDeclConsumer &consumer) {
44+
if (loc.isValid()) {
45+
SF = SF->getParentModule()->getSourceFileContainingLocation(loc);
46+
}
47+
4448
if (auto *s = SF->getASTContext().Stats)
4549
++s->getFrontendCounters().NumASTScopeLookups;
4650
ASTScopeImpl::unqualifiedLookup(SF, loc, consumer);

lib/AST/ASTScopeCreation.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,14 @@ void ASTSourceFileScope::expandFunctionBody(AbstractFunctionDecl *AFD) {
246246

247247
ASTSourceFileScope::ASTSourceFileScope(SourceFile *SF,
248248
ScopeCreator *scopeCreator)
249-
: SF(SF), scopeCreator(scopeCreator) {}
249+
: SF(SF), scopeCreator(scopeCreator) {
250+
if (auto enclosingSF = SF->getEnclosingSourceFile()) {
251+
SourceLoc parentLoc = SF->macroExpansion.getStartLoc();
252+
if (auto parentScope = findStartingScopeForLookup(enclosingSF, parentLoc)) {
253+
parentAndWasExpanded.setPointer(const_cast<ASTScopeImpl *>(parentScope));
254+
}
255+
}
256+
}
250257

251258
#pragma mark NodeAdder
252259

@@ -692,9 +699,9 @@ ASTSourceFileScope::expandAScopeThatCreatesANewInsertionPoint(
692699
SourceLoc endLoc = getSourceRangeOfThisASTNode().End;
693700

694701
ASTScopeImpl *insertionPoint = this;
695-
for (auto *d : SF->getTopLevelDecls()) {
702+
for (auto node : SF->getTopLevelItems()) {
696703
insertionPoint = scopeCreator.addToScopeTreeAndReturnInsertionPoint(
697-
ASTNode(d), insertionPoint, endLoc);
704+
node, insertionPoint, endLoc);
698705
}
699706

700707
return {insertionPoint, "Next time decls are added they go here."};

lib/AST/ASTScopeSourceRange.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,12 @@ SourceRange ASTSourceFileScope::getSourceRangeOfThisASTNode(
181181
return SourceRange(charRange.getStart(), charRange.getEnd());
182182
}
183183

184-
if (SF->getTopLevelDecls().empty())
184+
if (SF->getTopLevelItems().empty())
185185
return SourceRange();
186186

187187
// Use the source ranges of the declarations in the file.
188-
return SourceRange(SF->getTopLevelDecls().front()->getStartLoc(),
189-
SF->getTopLevelDecls().back()->getEndLoc());
188+
return SourceRange(SF->getTopLevelItems().front().getStartLoc(),
189+
SF->getTopLevelItems().back().getEndLoc());
190190
}
191191

192192
SourceRange GenericTypeOrExtensionScope::getSourceRangeOfThisASTNode(

0 commit comments

Comments
 (0)