Skip to content

Commit 011f4f1

Browse files
committed
Requestify SourceFile parsing
Add ParseSourceFileRequest that parses a SourceFile for its top-level decls.
1 parent 92ba948 commit 011f4f1

20 files changed

+213
-130
lines changed

include/swift/AST/ParseRequests.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,27 @@ class ParseAbstractFunctionBodyRequest :
8080
void cacheResult(BraceStmt *value) const;
8181
};
8282

83+
/// Parse the top-level decls of a SourceFile.
84+
class ParseSourceFileRequest
85+
: public SimpleRequest<ParseSourceFileRequest,
86+
ArrayRef<Decl *>(SourceFile *),
87+
CacheKind::SeparatelyCached> {
88+
public:
89+
using SimpleRequest::SimpleRequest;
90+
91+
private:
92+
friend SimpleRequest;
93+
94+
// Evaluation.
95+
ArrayRef<Decl *> evaluate(Evaluator &evaluator, SourceFile *SF) const;
96+
97+
public:
98+
// Caching.
99+
bool isCached() const { return true; }
100+
Optional<ArrayRef<Decl *>> getCachedResult() const;
101+
void cacheResult(ArrayRef<Decl *> decls) const;
102+
};
103+
83104
/// The zone number for the parser.
84105
#define SWIFT_TYPEID_ZONE Parse
85106
#define SWIFT_TYPEID_HEADER "swift/AST/ParseTypeIDZone.def"

include/swift/AST/ParseTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,6 @@ SWIFT_REQUEST(Parse, ParseMembersRequest,
1919
SWIFT_REQUEST(Parse, ParseAbstractFunctionBodyRequest,
2020
BraceStmt *(AbstractFunctionDecl *), SeparatelyCached,
2121
NoLocationInfo)
22+
SWIFT_REQUEST(Parse, ParseSourceFileRequest,
23+
ArrayRef<Decl *>(SourceFile *), SeparatelyCached,
24+
NoLocationInfo)

include/swift/AST/SourceFile.h

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class PersistentParserState;
2727
/// before being used for anything; a full type-check is also necessary for
2828
/// IR generation.
2929
class SourceFile final : public FileUnit {
30+
friend class ParseSourceFileRequest;
31+
3032
public:
3133
class Impl;
3234
struct SourceFileSyntaxInfo;
@@ -175,8 +177,11 @@ class SourceFile final : public FileUnit {
175177
/// been validated.
176178
llvm::SetVector<ValueDecl *> UnvalidatedDeclsWithOpaqueReturnTypes;
177179

178-
/// The list of top-level declarations in the source file.
179-
std::vector<Decl *> Decls;
180+
/// The list of top-level declarations in the source file. This is \c None if
181+
/// they have not yet been parsed.
182+
/// FIXME: Once addTopLevelDecl/prependTopLevelDecl/truncateTopLevelDecls
183+
/// have been removed, this can become an optional ArrayRef.
184+
Optional<std::vector<Decl *>> Decls;
180185

181186
using SeparatelyImportedOverlayMap =
182187
llvm::SmallDenseMap<ModuleDecl *, llvm::SmallPtrSet<ModuleDecl *, 1>>;
@@ -203,9 +208,12 @@ class SourceFile final : public FileUnit {
203208
friend Impl;
204209

205210
public:
206-
/// Appends the given declaration to the end of the top-level decls list.
211+
/// Appends the given declaration to the end of the top-level decls list. Do
212+
/// not add any additional uses of this function.
207213
void addTopLevelDecl(Decl *d) {
208-
Decls.push_back(d);
214+
// Force decl parsing if we haven't already.
215+
(void)getTopLevelDecls();
216+
Decls->push_back(d);
209217
}
210218

211219
/// Prepends a declaration to the top-level decls list.
@@ -215,18 +223,29 @@ class SourceFile final : public FileUnit {
215223
///
216224
/// See rdar://58355191
217225
void prependTopLevelDecl(Decl *d) {
218-
Decls.insert(Decls.begin(), d);
226+
// Force decl parsing if we haven't already.
227+
(void)getTopLevelDecls();
228+
Decls->insert(Decls->begin(), d);
219229
}
220230

221231
/// Retrieves an immutable view of the list of top-level decls in this file.
222-
ArrayRef<Decl *> getTopLevelDecls() const {
223-
return Decls;
232+
ArrayRef<Decl *> getTopLevelDecls() const;
233+
234+
/// Retrieves an immutable view of the top-level decls if they have already
235+
/// been parsed, or \c None if they haven't. Should only be used for dumping.
236+
Optional<ArrayRef<Decl *>> getCachedTopLevelDecls() const {
237+
if (!Decls)
238+
return None;
239+
return llvm::makeArrayRef(*Decls);
224240
}
225241

226-
/// Truncates the list of top-level decls so it contains \c count elements.
242+
/// Truncates the list of top-level decls so it contains \c count elements. Do
243+
/// not add any additional uses of this function.
227244
void truncateTopLevelDecls(unsigned count) {
228-
assert(count <= Decls.size() && "Can only truncate top-level decls!");
229-
Decls.resize(count);
245+
// Force decl parsing if we haven't already.
246+
(void)getTopLevelDecls();
247+
assert(count <= Decls->size() && "Can only truncate top-level decls!");
248+
Decls->resize(count);
230249
}
231250

232251
/// Retrieve the parsing options for the file.
@@ -456,6 +475,13 @@ class SourceFile final : public FileUnit {
456475
/// Retrieves the previously set delayed parser state, asserting that it
457476
/// exists.
458477
PersistentParserState *getDelayedParserState() {
478+
// Force parsing of the top-level decls, which will set DelayedParserState
479+
// if necessary.
480+
// FIXME: Ideally the parser state should be an output of
481+
// ParseSourceFileRequest, but the evaluator doesn't currently support
482+
// move-only outputs for cached requests.
483+
(void)getTopLevelDecls();
484+
459485
auto *state = DelayedParserState.get();
460486
assert(state && "Didn't set any delayed parser state!");
461487
return state;

include/swift/Parse/ParseSILSupport.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,6 @@ namespace swift {
3737
virtual bool parseSILProperty(Parser &P) = 0;
3838
virtual bool parseSILScope(Parser &P) = 0;
3939
};
40-
41-
/// To assist debugging parser crashes, tell us the location of the
42-
/// current token.
43-
class PrettyStackTraceParser : public llvm::PrettyStackTraceEntry {
44-
Parser &P;
45-
public:
46-
explicit PrettyStackTraceParser(Parser &P) : P(P) {}
47-
void print(llvm::raw_ostream &out) const override;
48-
};
4940
} // end namespace swift
5041

5142
#endif // SWIFT_PARSER_PARSESILSUPPORT_H

include/swift/Parse/Parser.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,14 +114,17 @@ class Parser {
114114
DiagnosticEngine &Diags;
115115
SourceFile &SF;
116116
Lexer *L;
117-
SILParserTUStateBase *SIL; // Non-null when parsing a .sil file.
117+
SILParserTUStateBase *SIL; // Non-null when parsing SIL decls.
118118
PersistentParserState *State;
119119
std::unique_ptr<PersistentParserState> OwnedState;
120120
DeclContext *CurDeclContext;
121121
ASTContext &Context;
122122
CodeCompletionCallbacks *CodeCompletion = nullptr;
123123
std::vector<Located<std::vector<ParamDecl*>>> AnonClosureVars;
124124

125+
/// Tracks parsed decls that LLDB requires to be inserted at the top-level.
126+
std::vector<Decl *> ContextSwitchedTopLevelDecls;
127+
125128
NullablePtr<llvm::MD5> CurrentTokenHash;
126129
void recordTokenHash(const Token Tok) {
127130
if (!Tok.getText().empty())
@@ -881,8 +884,8 @@ class Parser {
881884
/// Returns true if the parser is at the start of a SIL decl.
882885
bool isStartOfSILDecl();
883886

884-
/// Parse the top-level Swift decls into the source file.
885-
void parseTopLevel();
887+
/// Parse the top-level Swift decls into the provided vector.
888+
void parseTopLevel(SmallVectorImpl<Decl *> &decls);
886889

887890
/// Parse the top-level SIL decls into the SIL module.
888891
void parseTopLevelSIL();
@@ -1728,6 +1731,15 @@ struct ParsedDeclName {
17281731
DeclNameRef formDeclNameRef(ASTContext &ctx) const;
17291732
};
17301733

1734+
/// To assist debugging parser crashes, tell us the location of the
1735+
/// current token.
1736+
class PrettyStackTraceParser : public llvm::PrettyStackTraceEntry {
1737+
Parser &P;
1738+
public:
1739+
explicit PrettyStackTraceParser(Parser &P) : P(P) {}
1740+
void print(llvm::raw_ostream &out) const override;
1741+
};
1742+
17311743
/// Parse a stringified Swift declaration name,
17321744
/// e.g. "Foo.translateBy(self:x:y:)".
17331745
ParsedDeclName parseDeclName(StringRef name) LLVM_READONLY;

include/swift/Subsystems.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,6 @@ namespace swift {
103103

104104
/// @}
105105

106-
/// Parse a single buffer into the given source file.
107-
///
108-
/// \param SF The file within the module being parsed.
109-
///
110-
/// \param BufferID The buffer to parse from.
111-
void parseIntoSourceFile(SourceFile &SF, unsigned BufferID);
112-
113106
/// Parse a source file's SIL declarations into a given SIL module.
114107
void parseSourceFileSIL(SourceFile &SF, SILParserState *sil);
115108

lib/AST/ASTDumper.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -781,13 +781,15 @@ namespace {
781781
PrintWithColorRAII(OS, ParenthesisColor) << '(';
782782
PrintWithColorRAII(OS, ASTNodeColor) << "source_file ";
783783
PrintWithColorRAII(OS, LocationColor) << '\"' << SF.getFilename() << '\"';
784-
785-
for (Decl *D : SF.getTopLevelDecls()) {
786-
if (D->isImplicit())
787-
continue;
788784

789-
OS << '\n';
790-
printRec(D);
785+
if (auto decls = SF.getCachedTopLevelDecls()) {
786+
for (Decl *D : *decls) {
787+
if (D->isImplicit())
788+
continue;
789+
790+
OS << '\n';
791+
printRec(D);
792+
}
791793
}
792794
PrintWithColorRAII(OS, ParenthesisColor) << ')';
793795
}

lib/AST/Module.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "swift/AST/ModuleLoader.h"
3333
#include "swift/AST/NameLookup.h"
3434
#include "swift/AST/ReferencedNameTracker.h"
35+
#include "swift/AST/ParseRequests.h"
3536
#include "swift/AST/PrettyStackTrace.h"
3637
#include "swift/AST/PrintOptions.h"
3738
#include "swift/AST/ProtocolConformance.h"
@@ -674,7 +675,8 @@ void ModuleDecl::getTopLevelDeclsWhereAttributesMatch(
674675
}
675676

676677
void SourceFile::getTopLevelDecls(SmallVectorImpl<Decl*> &Results) const {
677-
Results.append(Decls.begin(), Decls.end());
678+
auto decls = getTopLevelDecls();
679+
Results.append(decls.begin(), decls.end());
678680
}
679681

680682
void ModuleDecl::getPrecedenceGroups(
@@ -1688,7 +1690,7 @@ void SourceFile::print(raw_ostream &OS, const PrintOptions &PO) {
16881690
void SourceFile::print(ASTPrinter &Printer, const PrintOptions &PO) {
16891691
std::set<DeclKind> MajorDeclKinds = {DeclKind::Class, DeclKind::Enum,
16901692
DeclKind::Extension, DeclKind::Protocol, DeclKind::Struct};
1691-
for (auto decl : Decls) {
1693+
for (auto decl : getTopLevelDecls()) {
16921694
if (!decl->shouldPrintInContext(PO))
16931695
continue;
16941696
// For a major decl, we print an empty line before it.
@@ -1971,6 +1973,13 @@ bool SourceFile::hasDelayedBodyParsing() const {
19711973
return true;
19721974
}
19731975

1976+
ArrayRef<Decl *> SourceFile::getTopLevelDecls() const {
1977+
auto &ctx = getASTContext();
1978+
auto *mutableThis = const_cast<SourceFile *>(this);
1979+
return evaluateOrDefault(ctx.evaluator, ParseSourceFileRequest{mutableThis},
1980+
{});
1981+
}
1982+
19741983
bool FileUnit::walk(ASTWalker &walker) {
19751984
SmallVector<Decl *, 64> Decls;
19761985
getTopLevelDecls(Decls);
@@ -2004,7 +2013,7 @@ bool FileUnit::walk(ASTWalker &walker) {
20042013
bool SourceFile::walk(ASTWalker &walker) {
20052014
llvm::SaveAndRestore<ASTWalker::ParentTy> SAR(walker.Parent,
20062015
getParentModule());
2007-
for (Decl *D : Decls) {
2016+
for (Decl *D : getTopLevelDecls()) {
20082017
#ifndef NDEBUG
20092018
PrettyStackTraceDecl debugStack("walking into decl", D);
20102019
#endif

lib/Frontend/Frontend.cpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -970,7 +970,7 @@ void CompilerInstance::parseLibraryFile(
970970
SourceFileKind::Library, implicitImports.kind, BufferID);
971971
addAdditionalInitialImportsTo(NextInput, implicitImports);
972972

973-
parseIntoSourceFile(*NextInput, BufferID);
973+
// Name binding will lazily trigger parsing of the file.
974974
performNameBinding(*NextInput);
975975
}
976976

@@ -1013,11 +1013,8 @@ void CompilerInstance::parseAndTypeCheckMainFileUpTo(
10131013
auto DidSuppressWarnings = Diags.getSuppressWarnings();
10141014
Diags.setSuppressWarnings(DidSuppressWarnings || !mainIsPrimary);
10151015

1016-
// Parse the Swift decls into the source file.
1017-
parseIntoSourceFile(MainFile, MainBufferID);
1018-
1019-
// For a primary, also perform type checking if needed. Otherwise, just do
1020-
// name binding.
1016+
// For a primary, perform type checking if needed. Otherwise, just do name
1017+
// binding.
10211018
if (mainIsPrimary && LimitStage >= SourceFile::TypeChecked) {
10221019
performTypeChecking(MainFile);
10231020
} else {
@@ -1138,17 +1135,18 @@ void CompilerInstance::performParseOnly(bool EvaluateConditionals,
11381135
SourceFileKind::Library, SourceFile::ImplicitModuleImportKind::None,
11391136
BufferID, parsingOpts);
11401137

1141-
parseIntoSourceFile(*NextInput, BufferID);
1138+
// Force the parsing of the top level decls.
1139+
(void)NextInput->getTopLevelDecls();
11421140
}
11431141

11441142
// Now parse the main file.
11451143
if (MainBufferID != NO_SUCH_BUFFER) {
11461144
SourceFile &MainFile =
11471145
MainModule->getMainSourceFile(Invocation.getSourceFileKind());
11481146
MainFile.SyntaxParsingCache = Invocation.getMainFileSyntaxParsingCache();
1149-
assert(MainBufferID == MainFile.getBufferID());
11501147

1151-
parseIntoSourceFile(MainFile, MainBufferID);
1148+
// Force the parsing of the top level decls.
1149+
(void)MainFile.getTopLevelDecls();
11521150
}
11531151

11541152
assert(Context->LoadedModules.size() == 1 &&

lib/IDE/CompletionInstance.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ bool CompletionInstance::performCachedOperaitonIfPossible(
199199
DiagnosticEngine tmpDiags(tmpSM);
200200
std::unique_ptr<ASTContext> tmpCtx(
201201
ASTContext::get(langOpts, typeckOpts, searchPathOpts, tmpSM, tmpDiags));
202+
registerParseRequestFunctions(tmpCtx->evaluator);
202203
registerIDERequestFunctions(tmpCtx->evaluator);
203204
registerTypeCheckerRequestFunctions(tmpCtx->evaluator);
204205
registerSILGenRequestFunctions(tmpCtx->evaluator);
@@ -209,7 +210,6 @@ bool CompletionInstance::performCachedOperaitonIfPossible(
209210
tmpSF->enableInterfaceHash();
210211
// Ensure all non-function-body tokens are hashed into the interface hash
211212
tmpCtx->LangOpts.EnableTypeFingerprints = false;
212-
parseIntoSourceFile(*tmpSF, tmpBufferID);
213213

214214
// Couldn't find any completion token?
215215
auto *newState = tmpSF->getDelayedParserState();
@@ -324,8 +324,8 @@ bool CompletionInstance::performCachedOperaitonIfPossible(
324324
// Tell the compiler instance we've replaced the code completion file.
325325
CI.setCodeCompletionFile(newSF);
326326

327-
// Re-parse the whole file. Still re-use imported modules.
328-
parseIntoSourceFile(*newSF, newBufferID);
327+
// Re-process the whole file (parsing will be lazily triggered). Still
328+
// re-use imported modules.
329329
performNameBinding(*newSF);
330330
bindExtensions(*newSF);
331331

0 commit comments

Comments
 (0)