Skip to content

Commit 760e8f8

Browse files
Merge pull request #5459 from swiftwasm/main
[pull] swiftwasm from main
2 parents 586ff07 + e5f749b commit 760e8f8

File tree

24 files changed

+343
-178
lines changed

24 files changed

+343
-178
lines changed

include/swift/AST/ParseRequests.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,24 @@ class ParseSourceFileRequest
116116
readDependencySource(const evaluator::DependencyRecorder &) const;
117117
};
118118

119+
/// Parse the ExportedSourceFile for a given SourceFile.
120+
class ExportedSourceFileRequest
121+
: public SimpleRequest<ExportedSourceFileRequest,
122+
void *(const SourceFile *),
123+
RequestFlags::Cached> {
124+
public:
125+
using SimpleRequest::SimpleRequest;
126+
127+
private:
128+
friend SimpleRequest;
129+
130+
void *evaluate(Evaluator &evaluator, const SourceFile *SF) const;
131+
132+
public:
133+
// Cached.
134+
bool isCached() const { return true; }
135+
};
136+
119137
/// Parse the top-level items of a SourceFile.
120138
class ParseTopLevelDeclsRequest
121139
: public SimpleRequest<

include/swift/AST/ParseTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,6 @@ SWIFT_REQUEST(Parse, ParseSourceFileRequest,
2828
SWIFT_REQUEST(Parse, ParseTopLevelDeclsRequest,
2929
ArrayRef<Decl *>(SourceFile *), Cached,
3030
NoLocationInfo)
31+
SWIFT_REQUEST(Parse, ExportedSourceFileRequest,
32+
void *(const SourceFile *), Cached,
33+
NoLocationInfo)

include/swift/AST/SourceFile.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,11 @@ class SourceFile final : public FileUnit {
9191
/// files, as they get parsed multiple times.
9292
SuppressWarnings = 1 << 4,
9393

94-
/// Whether to disable the Swift Parser ASTGen
95-
/// e.g. in dependency scanning, where an AST is not needed.
96-
DisableSwiftParserASTGen = 1 << 5,
94+
/// Ensure that the SwiftSyntax tree round trips correctly.
95+
RoundTrip = 1 << 5,
96+
97+
/// Validate the new SwiftSyntax parser diagnostics.
98+
ValidateNewParserDiagnostics = 1 << 6,
9799
};
98100
using ParsingOptions = OptionSet<ParsingFlags>;
99101

@@ -262,6 +264,10 @@ class SourceFile final : public FileUnit {
262264
/// code for it. Note this method returns \c false in WMO.
263265
bool isPrimary() const { return IsPrimary; }
264266

267+
/// Retrieve the \c ExportedSourceFile instance produced by ASTGen, which
268+
/// includes the SourceFileSyntax node corresponding to this source file.
269+
void *getExportedSourceFile() const;
270+
265271
/// The list of local type declarations in the source file.
266272
llvm::SetVector<TypeDecl *> LocalTypeDecls;
267273

@@ -334,10 +340,6 @@ class SourceFile final : public FileUnit {
334340
/// this source file.
335341
llvm::SmallVector<Located<StringRef>, 0> VirtualFilePaths;
336342

337-
/// The \c ExportedSourceFile instance produced by ASTGen, which includes
338-
/// the SourceFileSyntax node corresponding to this source file.
339-
void *exportedSourceFile = nullptr;
340-
341343
/// Returns information about the file paths used for diagnostics and magic
342344
/// identifiers in this source file, including virtual filenames introduced by
343345
/// \c #sourceLocation(file:) declarations.

lib/AST/Module.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3687,6 +3687,10 @@ SourceFile::getDefaultParsingOptions(const LangOptions &langOpts) {
36873687
opts |= ParsingFlags::DisablePoundIfEvaluation;
36883688
if (langOpts.CollectParsedToken)
36893689
opts |= ParsingFlags::CollectParsedTokens;
3690+
if (langOpts.hasFeature(Feature::ParserRoundTrip))
3691+
opts |= ParsingFlags::RoundTrip;
3692+
if (langOpts.hasFeature(Feature::ParserValidation))
3693+
opts |= ParsingFlags::ValidateNewParserDiagnostics;
36903694
return opts;
36913695
}
36923696

@@ -3762,6 +3766,11 @@ ArrayRef<Decl *> SourceFile::getHoistedDecls() const {
37623766
return Hoisted;
37633767
}
37643768

3769+
void *SourceFile::getExportedSourceFile() const {
3770+
auto &eval = getASTContext().evaluator;
3771+
return evaluateOrDefault(eval, ExportedSourceFileRequest{this}, nullptr);
3772+
}
3773+
37653774
void SourceFile::addDeclWithRuntimeDiscoverableAttrs(ValueDecl *decl) {
37663775
assert(!decl->getRuntimeDiscoverableAttrs().empty());
37673776
DeclsWithRuntimeDiscoverableAttrs.insert(decl);

lib/Basic/Statistic.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,11 +419,14 @@ UnifiedStatsReporter::noteCurrentProcessExitStatus(int status) {
419419

420420
void
421421
UnifiedStatsReporter::publishAlwaysOnStatsToLLVM() {
422+
// NOTE: We do `Stat = 0` below to force LLVM to register the statistic,
423+
// ensuring we print counters, even if 0.
422424
if (FrontendCounters) {
423425
auto &C = getFrontendCounters();
424426
#define FRONTEND_STATISTIC(TY, NAME) \
425427
do { \
426428
static Statistic Stat = {#TY, #NAME, #NAME}; \
429+
Stat = 0; \
427430
Stat += (C).NAME; \
428431
} while (0);
429432
#include "swift/Basic/Statistics.def"
@@ -434,6 +437,7 @@ UnifiedStatsReporter::publishAlwaysOnStatsToLLVM() {
434437
#define DRIVER_STATISTIC(NAME) \
435438
do { \
436439
static Statistic Stat = {"Driver", #NAME, #NAME}; \
440+
Stat = 0; \
437441
Stat += (C).NAME; \
438442
} while (0);
439443
#include "swift/Basic/Statistics.def"

lib/Frontend/Frontend.cpp

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,6 +1513,9 @@ void CompilerInstance::finishTypeChecking() {
15131513

15141514
SourceFile::ParsingOptions
15151515
CompilerInstance::getSourceFileParsingOptions(bool forPrimary) const {
1516+
using ActionType = FrontendOptions::ActionType;
1517+
using ParsingFlags = SourceFile::ParsingFlags;
1518+
15161519
const auto &frontendOpts = Invocation.getFrontendOptions();
15171520
const auto action = frontendOpts.RequestedAction;
15181521

@@ -1521,42 +1524,45 @@ CompilerInstance::getSourceFileParsingOptions(bool forPrimary) const {
15211524
// Generally in a parse-only invocation, we want to disable #if evaluation.
15221525
// However, there are a couple of modes where we need to know which clauses
15231526
// are active.
1524-
if (action != FrontendOptions::ActionType::EmitImportedModules &&
1525-
action != FrontendOptions::ActionType::ScanDependencies) {
1526-
opts |= SourceFile::ParsingFlags::DisablePoundIfEvaluation;
1527+
if (action != ActionType::EmitImportedModules &&
1528+
action != ActionType::ScanDependencies) {
1529+
opts |= ParsingFlags::DisablePoundIfEvaluation;
15271530
}
15281531

15291532
// If we need to dump the parse tree, disable delayed bodies as we want to
15301533
// show everything.
1531-
if (action == FrontendOptions::ActionType::DumpParse)
1532-
opts |= SourceFile::ParsingFlags::DisableDelayedBodies;
1534+
if (action == ActionType::DumpParse)
1535+
opts |= ParsingFlags::DisableDelayedBodies;
15331536
}
15341537

1535-
auto typeOpts = getASTContext().TypeCheckerOpts;
1536-
if (forPrimary || isWholeModuleCompilation()) {
1538+
const auto &typeOpts = getASTContext().TypeCheckerOpts;
1539+
const auto isEffectivelyPrimary = forPrimary || isWholeModuleCompilation();
1540+
if (isEffectivelyPrimary) {
15371541
// Disable delayed body parsing for primaries and in WMO, unless
15381542
// forcefully skipping function bodies
15391543
if (typeOpts.SkipFunctionBodies == FunctionBodySkipping::None)
1540-
opts |= SourceFile::ParsingFlags::DisableDelayedBodies;
1544+
opts |= ParsingFlags::DisableDelayedBodies;
15411545
} else {
15421546
// Suppress parse warnings for non-primaries, as they'll get parsed multiple
15431547
// times.
1544-
opts |= SourceFile::ParsingFlags::SuppressWarnings;
1548+
opts |= ParsingFlags::SuppressWarnings;
15451549
}
15461550

1547-
// Dependency scanning does not require an AST, so disable Swift Parser
1548-
// ASTGen parsing completely.
1549-
if (frontendOpts.RequestedAction ==
1550-
FrontendOptions::ActionType::ScanDependencies)
1551-
opts |= SourceFile::ParsingFlags::DisableSwiftParserASTGen;
1551+
// Turn off round-trip checking for secondary files, and for dependency
1552+
// scanning and IDE inspection.
1553+
if (!isEffectivelyPrimary || SourceMgr.hasIDEInspectionTargetBuffer() ||
1554+
frontendOpts.RequestedAction == ActionType::ScanDependencies) {
1555+
opts -= ParsingFlags::RoundTrip;
1556+
opts -= ParsingFlags::ValidateNewParserDiagnostics;
1557+
}
15521558

15531559
// Enable interface hash computation for primaries or emit-module-separately,
15541560
// but not in WMO, as it's only currently needed for incremental mode.
15551561
if (forPrimary ||
15561562
typeOpts.SkipFunctionBodies ==
15571563
FunctionBodySkipping::NonInlinableWithoutTypes ||
15581564
frontendOpts.ReuseFrontendForMultipleCompilations) {
1559-
opts |= SourceFile::ParsingFlags::EnableInterfaceHash;
1565+
opts |= ParsingFlags::EnableInterfaceHash;
15601566
}
15611567
return opts;
15621568
}

lib/Parse/ParseDecl.cpp

Lines changed: 111 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -209,9 +209,7 @@ extern "C" void swift_ASTGen_buildTopLevelASTNodes(void *sourceFile,
209209
void Parser::parseTopLevelItems(SmallVectorImpl<ASTNode> &items) {
210210
#if SWIFT_SWIFT_PARSER
211211
Optional<DiagnosticTransaction> existingParsingTransaction;
212-
if (!SF.getParsingOptions()
213-
.contains(SourceFile::ParsingFlags::DisableSwiftParserASTGen))
214-
parseSourceFileViaASTGen(items, existingParsingTransaction);
212+
parseSourceFileViaASTGen(items, existingParsingTransaction);
215213
#endif
216214

217215
// Prime the lexer.
@@ -261,92 +259,135 @@ void Parser::parseTopLevelItems(SmallVectorImpl<ASTNode> &items) {
261259
}
262260

263261
#if SWIFT_SWIFT_PARSER
264-
if (!SF.getParsingOptions().contains(
265-
SourceFile::ParsingFlags::DisableSwiftParserASTGen)) {
266-
if (existingParsingTransaction)
267-
existingParsingTransaction->abort();
268-
269-
// Perform round-trip and/or validation checking.
270-
if ((Context.LangOpts.hasFeature(Feature::ParserRoundTrip) ||
271-
Context.LangOpts.hasFeature(Feature::ParserValidation)) &&
272-
SF.exportedSourceFile &&
273-
!SourceMgr.hasIDEInspectionTargetBuffer()) {
274-
if (Context.LangOpts.hasFeature(Feature::ParserRoundTrip) &&
275-
swift_ASTGen_roundTripCheck(SF.exportedSourceFile)) {
276-
SourceLoc loc;
277-
if (auto bufferID = SF.getBufferID()) {
278-
loc = Context.SourceMgr.getLocForBufferStart(*bufferID);
279-
}
280-
diagnose(loc, diag::parser_round_trip_error);
281-
} else if (Context.LangOpts.hasFeature(Feature::ParserValidation) &&
282-
!Context.Diags.hadAnyError() &&
283-
swift_ASTGen_emitParserDiagnostics(
284-
&Context.Diags, SF.exportedSourceFile,
285-
/*emitOnlyErrors=*/true,
286-
/*downgradePlaceholderErrorsToWarnings=*/
287-
Context.LangOpts.Playground ||
288-
Context.LangOpts.WarnOnEditorPlaceholder)) {
289-
// We might have emitted warnings in the C++ parser but no errors, in
290-
// which case we still have `hadAnyError() == false`. To avoid emitting
291-
// the same warnings from SwiftParser, only emit errors from SwiftParser
292-
SourceLoc loc;
293-
if (auto bufferID = SF.getBufferID()) {
262+
if (existingParsingTransaction)
263+
existingParsingTransaction->abort();
264+
265+
using ParsingFlags = SourceFile::ParsingFlags;
266+
const auto parsingOpts = SF.getParsingOptions();
267+
268+
// If we don't need to validate anything, we're done.
269+
if (!parsingOpts.contains(ParsingFlags::RoundTrip) &&
270+
!parsingOpts.contains(ParsingFlags::ValidateNewParserDiagnostics)) {
271+
return;
272+
}
273+
274+
auto *exportedSourceFile = SF.getExportedSourceFile();
275+
if (!exportedSourceFile)
276+
return;
277+
278+
// Perform round-trip and/or validation checking.
279+
if (parsingOpts.contains(ParsingFlags::RoundTrip) &&
280+
swift_ASTGen_roundTripCheck(exportedSourceFile)) {
281+
SourceLoc loc;
282+
if (auto bufferID = SF.getBufferID()) {
283+
loc = Context.SourceMgr.getLocForBufferStart(*bufferID);
284+
}
285+
diagnose(loc, diag::parser_round_trip_error);
286+
return;
287+
}
288+
if (parsingOpts.contains(ParsingFlags::ValidateNewParserDiagnostics) &&
289+
!Context.Diags.hadAnyError()) {
290+
auto hadSyntaxError = swift_ASTGen_emitParserDiagnostics(
291+
&Context.Diags, exportedSourceFile,
292+
/*emitOnlyErrors=*/true,
293+
/*downgradePlaceholderErrorsToWarnings=*/
294+
Context.LangOpts.Playground ||
295+
Context.LangOpts.WarnOnEditorPlaceholder);
296+
if (hadSyntaxError) {
297+
// We might have emitted warnings in the C++ parser but no errors, in
298+
// which case we still have `hadAnyError() == false`. To avoid
299+
// emitting the same warnings from SwiftParser, only emit errors from
300+
// SwiftParser
301+
SourceLoc loc;
302+
if (auto bufferID = SF.getBufferID()) {
294303
loc = Context.SourceMgr.getLocForBufferStart(*bufferID);
295-
}
296-
diagnose(loc, diag::parser_new_parser_errors);
297304
}
305+
diagnose(loc, diag::parser_new_parser_errors);
298306
}
299307
}
300308
#endif
301309
}
302310

311+
void *ExportedSourceFileRequest::evaluate(Evaluator &evaluator,
312+
const SourceFile *SF) const {
313+
#if SWIFT_SWIFT_PARSER
314+
// The SwiftSyntax parser doesn't (yet?) handle SIL.
315+
if (SF->Kind == SourceFileKind::SIL)
316+
return nullptr;
317+
318+
auto &ctx = SF->getASTContext();
319+
auto &SM = ctx.SourceMgr;
320+
321+
auto bufferID = SF->getBufferID();
322+
if (!bufferID)
323+
return nullptr;
324+
325+
StringRef contents = SM.extractText(SM.getRangeForBuffer(*bufferID));
326+
327+
// Parse the source file.
328+
auto exportedSourceFile = swift_ASTGen_parseSourceFile(
329+
contents.begin(), contents.size(),
330+
SF->getParentModule()->getName().str().str().c_str(),
331+
SF->getFilename().str().c_str());
332+
333+
ctx.addCleanup([exportedSourceFile] {
334+
swift_ASTGen_destroySourceFile(exportedSourceFile);
335+
});
336+
return exportedSourceFile;
337+
#else
338+
return nullptr;
339+
#endif
340+
}
341+
303342
void
304343
Parser::parseSourceFileViaASTGen(SmallVectorImpl<ASTNode> &items,
305344
Optional<DiagnosticTransaction> &transaction,
306345
bool suppressDiagnostics) {
307346
#if SWIFT_SWIFT_PARSER
308-
Optional<DiagnosticTransaction> existingParsingTransaction;
309-
if (SF.Kind != SourceFileKind::SIL) {
310-
StringRef contents =
311-
SourceMgr.extractText(SourceMgr.getRangeForBuffer(L->getBufferID()));
312-
313-
// Parse the source file.
314-
auto exportedSourceFile = swift_ASTGen_parseSourceFile(
315-
contents.begin(), contents.size(),
316-
SF.getParentModule()->getName().str().str().c_str(),
317-
SF.getFilename().str().c_str());
318-
SF.exportedSourceFile = exportedSourceFile;
319-
Context.addCleanup([exportedSourceFile] {
320-
swift_ASTGen_destroySourceFile(exportedSourceFile);
321-
});
347+
using ParsingFlags = SourceFile::ParsingFlags;
348+
const auto parsingOpts = SF.getParsingOptions();
349+
const auto &langOpts = Context.LangOpts;
350+
351+
// We only need to do parsing if we either have ASTGen enabled, or want the
352+
// new parser diagnostics.
353+
auto needToParse = [&]() {
354+
if (langOpts.hasFeature(Feature::ParserASTGen))
355+
return true;
356+
if (!suppressDiagnostics &&
357+
langOpts.hasFeature(Feature::ParserDiagnostics)) {
358+
return true;
359+
}
360+
return false;
361+
}();
362+
if (!needToParse)
363+
return;
322364

323-
// If we're supposed to emit diagnostics from the parser, do so now.
324-
if ((Context.LangOpts.hasFeature(Feature::ParserDiagnostics) ||
325-
Context.LangOpts.hasFeature(Feature::ParserASTGen)) &&
326-
!suppressDiagnostics &&
327-
swift_ASTGen_emitParserDiagnostics(
328-
&Context.Diags, SF.exportedSourceFile, /*emitOnlyErrors=*/false,
329-
/*downgradePlaceholderErrorsToWarnings=*/
330-
Context.LangOpts.Playground ||
331-
Context.LangOpts.WarnOnEditorPlaceholder) &&
332-
Context.Diags.hadAnyError() &&
333-
!Context.LangOpts.hasFeature(Feature::ParserASTGen)) {
365+
auto *exportedSourceFile = SF.getExportedSourceFile();
366+
if (!exportedSourceFile)
367+
return;
368+
369+
// If we're supposed to emit diagnostics from the parser, do so now.
370+
if (!suppressDiagnostics) {
371+
auto hadSyntaxError = swift_ASTGen_emitParserDiagnostics(
372+
&Context.Diags, exportedSourceFile, /*emitOnlyErrors=*/false,
373+
/*downgradePlaceholderErrorsToWarnings=*/langOpts.Playground ||
374+
langOpts.WarnOnEditorPlaceholder);
375+
if (hadSyntaxError && Context.Diags.hadAnyError() &&
376+
!langOpts.hasFeature(Feature::ParserASTGen)) {
334377
// Errors were emitted, and we're still using the C++ parser, so
335378
// disable diagnostics from the C++ parser.
336379
transaction.emplace(Context.Diags);
337380
}
381+
}
338382

339-
// If we want to do ASTGen, do so now.
340-
if (Context.LangOpts.hasFeature(Feature::ParserASTGen)) {
341-
swift_ASTGen_buildTopLevelASTNodes(
342-
exportedSourceFile, CurDeclContext, &Context, &items, appendToVector);
343-
344-
// Spin the C++ parser to the end; we won't be using it.
345-
while (!Tok.is(tok::eof)) {
346-
consumeToken();
347-
}
383+
// If we want to do ASTGen, do so now.
384+
if (langOpts.hasFeature(Feature::ParserASTGen)) {
385+
swift_ASTGen_buildTopLevelASTNodes(exportedSourceFile, CurDeclContext,
386+
&Context, &items, appendToVector);
348387

349-
return;
388+
// Spin the C++ parser to the end; we won't be using it.
389+
while (!Tok.is(tok::eof)) {
390+
consumeToken();
350391
}
351392
}
352393
#endif

0 commit comments

Comments
 (0)