[flang-commits] [flang] 0c7e895 - [flang] Move parser invocations into ParserActions (#130309)
via flang-commits
flang-commits at lists.llvm.org
Mon Mar 10 04:33:51 PDT 2025
Author: Kajetan Puchalski
Date: 2025-03-10T11:33:47Z
New Revision: 0c7e895de3a9df6ff702fbebd1cdd580cb65e3d1
URL: https://github.com/llvm/llvm-project/commit/0c7e895de3a9df6ff702fbebd1cdd580cb65e3d1
DIFF: https://github.com/llvm/llvm-project/commit/0c7e895de3a9df6ff702fbebd1cdd580cb65e3d1.diff
LOG: [flang] Move parser invocations into ParserActions (#130309)
FrontendActions.cpp is currently one of the biggest compilation units in
all of flang. Measuring its compilation gives the following metrics:
User time (seconds): 139.21
System time (seconds): 4.65
Maximum resident set size (kbytes): 5891440 (5.61 GB)
This commit separates out explicit invocations of the parser into a
separate compilation unit - ParserActions.cpp - through helper functions
in order to decrease the maximum compilation time and memory usage of a
single unit.
After the split, the measurements of FrontendActions.cpp are as follows:
User time (seconds): 70.08
System time (seconds): 3.16
Maximum resident set size (kbytes): 3961492 (3.7 GB)
While the ones for the newly created ParserActions.cpp as follows:
User time (seconds): 104.33
System time (seconds): 3.37
Maximum resident set size (kbytes): 4185600 (3.99 GB)
---------
Signed-off-by: Kajetan Puchalski <kajetan.puchalski at arm.com>
Added:
flang/include/flang/Frontend/ParserActions.h
flang/include/flang/Parser/options.h
flang/lib/Frontend/ParserActions.cpp
Modified:
flang/include/flang/Frontend/CompilerInstance.h
flang/include/flang/Frontend/CompilerInvocation.h
flang/include/flang/Frontend/FrontendActions.h
flang/include/flang/Parser/parsing.h
flang/lib/Frontend/CMakeLists.txt
flang/lib/Frontend/FrontendAction.cpp
flang/lib/Frontend/FrontendActions.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Frontend/CompilerInstance.h b/flang/include/flang/Frontend/CompilerInstance.h
index 509c9f4b9e91a..e37ef5e236871 100644
--- a/flang/include/flang/Frontend/CompilerInstance.h
+++ b/flang/include/flang/Frontend/CompilerInstance.h
@@ -15,9 +15,8 @@
#include "flang/Frontend/CompilerInvocation.h"
#include "flang/Frontend/FrontendAction.h"
+#include "flang/Frontend/ParserActions.h"
#include "flang/Frontend/PreprocessorOptions.h"
-#include "flang/Parser/parsing.h"
-#include "flang/Parser/provenance.h"
#include "flang/Semantics/runtime-type-info.h"
#include "flang/Semantics/semantics.h"
#include "flang/Support/StringOstream.h"
diff --git a/flang/include/flang/Frontend/CompilerInvocation.h b/flang/include/flang/Frontend/CompilerInvocation.h
index 9e6724be33033..d6ee1511cdb4b 100644
--- a/flang/include/flang/Frontend/CompilerInvocation.h
+++ b/flang/include/flang/Frontend/CompilerInvocation.h
@@ -18,7 +18,7 @@
#include "flang/Frontend/PreprocessorOptions.h"
#include "flang/Frontend/TargetOptions.h"
#include "flang/Lower/LoweringOptions.h"
-#include "flang/Parser/parsing.h"
+#include "flang/Parser/options.h"
#include "flang/Semantics/semantics.h"
#include "flang/Support/LangOptions.h"
#include "mlir/Support/Timing.h"
@@ -29,7 +29,7 @@
namespace llvm {
class TargetMachine;
-}
+} // namespace llvm
namespace Fortran::frontend {
diff --git a/flang/include/flang/Frontend/FrontendActions.h b/flang/include/flang/Frontend/FrontendActions.h
index 4e3d3cb2657db..f9a45bd6c0a56 100644
--- a/flang/include/flang/Frontend/FrontendActions.h
+++ b/flang/include/flang/Frontend/FrontendActions.h
@@ -13,10 +13,8 @@
#ifndef FORTRAN_FRONTEND_FRONTENDACTIONS_H
#define FORTRAN_FRONTEND_FRONTENDACTIONS_H
-#include "flang/Frontend/CodeGenOptions.h"
#include "flang/Frontend/FrontendAction.h"
-#include "flang/Parser/parsing.h"
-#include "flang/Semantics/semantics.h"
+#include "flang/Frontend/ParserActions.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/OwningOpRef.h"
@@ -26,21 +24,6 @@
namespace Fortran::frontend {
-// TODO: This is a copy from f18.cpp. It doesn't really belong here and should
-// be moved to a more suitable place in future.
-struct MeasurementVisitor {
- template <typename A>
- bool Pre(const A &) {
- return true;
- }
- template <typename A>
- void Post(const A &) {
- ++objects;
- bytes += sizeof(A);
- }
- size_t objects{0}, bytes{0};
-};
-
//===----------------------------------------------------------------------===//
// Custom Consumer Actions
//===----------------------------------------------------------------------===//
diff --git a/flang/include/flang/Frontend/ParserActions.h b/flang/include/flang/Frontend/ParserActions.h
new file mode 100644
index 0000000000000..8e7d1f71ec105
--- /dev/null
+++ b/flang/include/flang/Frontend/ParserActions.h
@@ -0,0 +1,67 @@
+//===- ParserActions.h -------------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_PARSER_ACTIONS_H_
+#define FORTRAN_PARSER_ACTIONS_H_
+
+#include <string>
+
+namespace llvm {
+class raw_string_ostream;
+class raw_ostream;
+class StringRef;
+} // namespace llvm
+
+namespace Fortran::lower {
+class LoweringBridge;
+} // namespace Fortran::lower
+
+namespace Fortran::parser {
+class Parsing;
+class AllCookedSources;
+} // namespace Fortran::parser
+
+namespace lower::pft {
+class Program;
+} // namespace lower::pft
+
+//=== Frontend Parser helpers ===
+
+namespace Fortran::frontend {
+class CompilerInstance;
+
+parser::AllCookedSources &getAllCooked(CompilerInstance &ci);
+
+void parseAndLowerTree(CompilerInstance &ci, lower::LoweringBridge &lb);
+
+void dumpTree(CompilerInstance &ci);
+
+void dumpProvenance(CompilerInstance &ci);
+
+void dumpPreFIRTree(CompilerInstance &ci);
+
+void formatOrDumpPrescanner(std::string &buf,
+ llvm::raw_string_ostream &outForPP,
+ CompilerInstance &ci);
+
+void debugMeasureParseTree(CompilerInstance &ci, llvm::StringRef filename);
+
+void debugUnparseNoSema(CompilerInstance &ci, llvm::raw_ostream &out);
+
+void debugUnparseWithSymbols(CompilerInstance &ci);
+
+void debugUnparseWithModules(CompilerInstance &ci);
+
+void debugDumpParsingLog(CompilerInstance &ci);
+} // namespace Fortran::frontend
+
+#endif // FORTRAN_PARSER_ACTIONS_H_
diff --git a/flang/include/flang/Parser/options.h b/flang/include/flang/Parser/options.h
new file mode 100644
index 0000000000000..dc363acb7c28a
--- /dev/null
+++ b/flang/include/flang/Parser/options.h
@@ -0,0 +1,43 @@
+//===-- include/flang/Parser/options.h --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_PARSER_OPTIONS_H_
+#define FORTRAN_PARSER_OPTIONS_H_
+
+#include "characters.h"
+#include "flang/Support/Fortran-features.h"
+
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace Fortran::parser {
+
+struct Options {
+ Options() {}
+
+ using Predefinition = std::pair<std::string, std::optional<std::string>>;
+
+ bool isFixedForm{false};
+ int fixedFormColumns{72};
+ common::LanguageFeatureControl features;
+ std::vector<std::string> searchDirectories;
+ std::vector<std::string> intrinsicModuleDirectories;
+ std::vector<Predefinition> predefinitions;
+ bool instrumentedParse{false};
+ bool isModuleFile{false};
+ bool needProvenanceRangeToCharBlockMappings{false};
+ Fortran::parser::Encoding encoding{Fortran::parser::Encoding::UTF_8};
+ bool prescanAndReformat{false}; // -E
+ bool expandIncludeLinesInPreprocessedOutput{true};
+ bool showColors{false};
+};
+
+} // namespace Fortran::parser
+
+#endif // FORTRAN_PARSER_OPTIONS_H_
diff --git a/flang/include/flang/Parser/parsing.h b/flang/include/flang/Parser/parsing.h
index 116b6bd6f191f..3365628dc4e0c 100644
--- a/flang/include/flang/Parser/parsing.h
+++ b/flang/include/flang/Parser/parsing.h
@@ -9,41 +9,18 @@
#ifndef FORTRAN_PARSER_PARSING_H_
#define FORTRAN_PARSER_PARSING_H_
-#include "characters.h"
#include "instrumented-parser.h"
#include "message.h"
+#include "options.h"
#include "parse-tree.h"
#include "provenance.h"
#include "flang/Parser/preprocessor.h"
-#include "flang/Support/Fortran-features.h"
#include "llvm/Support/raw_ostream.h"
#include <optional>
#include <string>
-#include <utility>
-#include <vector>
namespace Fortran::parser {
-struct Options {
- Options() {}
-
- using Predefinition = std::pair<std::string, std::optional<std::string>>;
-
- bool isFixedForm{false};
- int fixedFormColumns{72};
- common::LanguageFeatureControl features;
- std::vector<std::string> searchDirectories;
- std::vector<std::string> intrinsicModuleDirectories;
- std::vector<Predefinition> predefinitions;
- bool instrumentedParse{false};
- bool isModuleFile{false};
- bool needProvenanceRangeToCharBlockMappings{false};
- Fortran::parser::Encoding encoding{Fortran::parser::Encoding::UTF_8};
- bool prescanAndReformat{false}; // -E
- bool expandIncludeLinesInPreprocessedOutput{true};
- bool showColors{false};
-};
-
class Parsing {
public:
explicit Parsing(AllCookedSources &);
diff --git a/flang/lib/Frontend/CMakeLists.txt b/flang/lib/Frontend/CMakeLists.txt
index 80d63fca6fb76..c80373799b015 100644
--- a/flang/lib/Frontend/CMakeLists.txt
+++ b/flang/lib/Frontend/CMakeLists.txt
@@ -5,6 +5,7 @@ add_flang_library(flangFrontend
CompilerInstance.cpp
CompilerInvocation.cpp
CodeGenOptions.cpp
+ ParserActions.cpp
FrontendAction.cpp
FrontendActions.cpp
FrontendOptions.cpp
diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp
index 9a555bc7cd23b..ab77d143fa4b6 100644
--- a/flang/lib/Frontend/FrontendAction.cpp
+++ b/flang/lib/Frontend/FrontendAction.cpp
@@ -15,6 +15,7 @@
#include "flang/Frontend/FrontendActions.h"
#include "flang/Frontend/FrontendOptions.h"
#include "flang/Frontend/FrontendPluginRegistry.h"
+#include "flang/Parser/parsing.h"
#include "clang/Basic/DiagnosticFrontend.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/VirtualFileSystem.h"
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 72a656b3627f5..94de376aaf7d6 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -14,9 +14,8 @@
#include "flang/Frontend/CompilerInstance.h"
#include "flang/Frontend/CompilerInvocation.h"
#include "flang/Frontend/FrontendOptions.h"
-#include "flang/Frontend/PreprocessorOptions.h"
+#include "flang/Frontend/ParserActions.h"
#include "flang/Lower/Bridge.h"
-#include "flang/Lower/PFTBuilder.h"
#include "flang/Lower/Support/Verifier.h"
#include "flang/Optimizer/Dialect/Support/FIRContext.h"
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
@@ -25,13 +24,7 @@
#include "flang/Optimizer/Support/InitFIR.h"
#include "flang/Optimizer/Support/Utils.h"
#include "flang/Optimizer/Transforms/Passes.h"
-#include "flang/Parser/dump-parse-tree.h"
-#include "flang/Parser/parsing.h"
-#include "flang/Parser/provenance.h"
-#include "flang/Parser/source.h"
-#include "flang/Parser/unparse.h"
#include "flang/Semantics/runtime-type-info.h"
-#include "flang/Semantics/semantics.h"
#include "flang/Semantics/unparse-with-symbols.h"
#include "flang/Support/default-kinds.h"
#include "flang/Tools/CrossToolHelpers.h"
@@ -317,9 +310,9 @@ bool CodeGenAction::beginSourceFileAction() {
lower::LoweringBridge lb = Fortran::lower::LoweringBridge::create(
*mlirCtx, ci.getSemanticsContext(), defKinds,
ci.getSemanticsContext().intrinsics(),
- ci.getSemanticsContext().targetCharacteristics(),
- ci.getParsing().allCooked(), ci.getInvocation().getTargetOpts().triple,
- kindMap, ci.getInvocation().getLoweringOpts(),
+ ci.getSemanticsContext().targetCharacteristics(), getAllCooked(ci),
+ ci.getInvocation().getTargetOpts().triple, kindMap,
+ ci.getInvocation().getLoweringOpts(),
ci.getInvocation().getFrontendOpts().envDefaults,
ci.getInvocation().getFrontendOpts().features, targetMachine,
ci.getInvocation().getTargetOpts(), ci.getInvocation().getCodeGenOpts());
@@ -333,8 +326,7 @@ bool CodeGenAction::beginSourceFileAction() {
}
// Create a parse tree and lower it to FIR
- Fortran::parser::Program &parseTree{*ci.getParsing().parseTree()};
- lb.lower(parseTree, ci.getSemanticsContext());
+ parseAndLowerTree(ci, lb);
// Fetch module from lb, so we can set
mlirModule = lb.getModuleAndRelease();
@@ -431,19 +423,8 @@ void PrintPreprocessedAction::executeAction() {
std::string buf;
llvm::raw_string_ostream outForPP{buf};
- // Format or dump the prescanner's output
CompilerInstance &ci = this->getInstance();
- if (ci.getInvocation().getPreprocessorOpts().showMacros) {
- ci.getParsing().EmitPreprocessorMacros(outForPP);
- } else if (ci.getInvocation().getPreprocessorOpts().noReformat) {
- ci.getParsing().DumpCookedChars(outForPP);
- } else {
- ci.getParsing().EmitPreprocessedSource(
- outForPP, !ci.getInvocation().getPreprocessorOpts().noLineDirectives);
- }
-
- // Print getDiagnostics from the prescanner
- ci.getParsing().messages().Emit(llvm::errs(), ci.getAllCookedSources());
+ formatOrDumpPrescanner(buf, outForPP, ci);
// If a pre-defined output stream exists, dump the preprocessed content there
if (!ci.isOutputStreamNull()) {
@@ -463,60 +444,31 @@ void PrintPreprocessedAction::executeAction() {
}
void DebugDumpProvenanceAction::executeAction() {
- this->getInstance().getParsing().DumpProvenance(llvm::outs());
+ dumpProvenance(this->getInstance());
}
void ParseSyntaxOnlyAction::executeAction() {}
void DebugUnparseNoSemaAction::executeAction() {
- auto &invoc = this->getInstance().getInvocation();
- auto &parseTree{getInstance().getParsing().parseTree()};
-
- // TODO: Options should come from CompilerInvocation
- Unparse(llvm::outs(), *parseTree,
- /*encoding=*/Fortran::parser::Encoding::UTF_8,
- /*capitalizeKeywords=*/true, /*backslashEscapes=*/false,
- /*preStatement=*/nullptr,
- invoc.getUseAnalyzedObjectsForUnparse() ? &invoc.getAsFortran()
- : nullptr);
+ debugUnparseNoSema(this->getInstance(), llvm::outs());
}
void DebugUnparseAction::executeAction() {
- auto &invoc = this->getInstance().getInvocation();
- auto &parseTree{getInstance().getParsing().parseTree()};
-
CompilerInstance &ci = this->getInstance();
auto os{ci.createDefaultOutputFile(
/*Binary=*/false, /*InFile=*/getCurrentFileOrBufferName())};
- // TODO: Options should come from CompilerInvocation
- Unparse(*os, *parseTree,
- /*encoding=*/Fortran::parser::Encoding::UTF_8,
- /*capitalizeKeywords=*/true, /*backslashEscapes=*/false,
- /*preStatement=*/nullptr,
- invoc.getUseAnalyzedObjectsForUnparse() ? &invoc.getAsFortran()
- : nullptr);
-
- // Report fatal semantic errors
+ debugUnparseNoSema(ci, *os);
reportFatalSemanticErrors();
}
void DebugUnparseWithSymbolsAction::executeAction() {
- auto &parseTree{*getInstance().getParsing().parseTree()};
-
- Fortran::semantics::UnparseWithSymbols(
- llvm::outs(), parseTree, /*encoding=*/Fortran::parser::Encoding::UTF_8);
-
- // Report fatal semantic errors
+ debugUnparseWithSymbols(this->getInstance());
reportFatalSemanticErrors();
}
void DebugUnparseWithModulesAction::executeAction() {
- auto &parseTree{*getInstance().getParsing().parseTree()};
- CompilerInstance &ci{getInstance()};
- Fortran::semantics::UnparseWithModules(
- llvm::outs(), ci.getSemantics().context(), parseTree,
- /*encoding=*/Fortran::parser::Encoding::UTF_8);
+ debugUnparseWithModules(this->getInstance());
reportFatalSemanticErrors();
}
@@ -540,12 +492,7 @@ void DebugDumpAllAction::executeAction() {
CompilerInstance &ci = this->getInstance();
// Dump parse tree
- auto &parseTree{getInstance().getParsing().parseTree()};
- llvm::outs() << "========================";
- llvm::outs() << " Flang: parse tree dump ";
- llvm::outs() << "========================\n";
- Fortran::parser::DumpTree(llvm::outs(), parseTree,
- &ci.getInvocation().getAsFortran());
+ dumpTree(ci);
if (!ci.getRtTyTables().schemata) {
unsigned diagID = ci.getDiagnostics().getCustomDiagID(
@@ -564,21 +511,11 @@ void DebugDumpAllAction::executeAction() {
}
void DebugDumpParseTreeNoSemaAction::executeAction() {
- auto &parseTree{getInstance().getParsing().parseTree()};
-
- // Dump parse tree
- Fortran::parser::DumpTree(
- llvm::outs(), parseTree,
- &this->getInstance().getInvocation().getAsFortran());
+ dumpTree(this->getInstance());
}
void DebugDumpParseTreeAction::executeAction() {
- auto &parseTree{getInstance().getParsing().parseTree()};
-
- // Dump parse tree
- Fortran::parser::DumpTree(
- llvm::outs(), parseTree,
- &this->getInstance().getInvocation().getAsFortran());
+ dumpTree(this->getInstance());
// Report fatal semantic errors
reportFatalSemanticErrors();
@@ -586,62 +523,20 @@ void DebugDumpParseTreeAction::executeAction() {
void DebugMeasureParseTreeAction::executeAction() {
CompilerInstance &ci = this->getInstance();
-
- // Parse. In case of failure, report and return.
- ci.getParsing().Parse(llvm::outs());
-
- if ((ci.getParsing().parseTree().has_value() &&
- !ci.getParsing().consumedWholeFile()) ||
- (!ci.getParsing().messages().empty() &&
- (ci.getInvocation().getWarnAsErr() ||
- ci.getParsing().messages().AnyFatalError()))) {
- unsigned diagID = ci.getDiagnostics().getCustomDiagID(
- clang::DiagnosticsEngine::Error, "Could not parse %0");
- ci.getDiagnostics().Report(diagID) << getCurrentFileOrBufferName();
-
- ci.getParsing().messages().Emit(llvm::errs(),
- this->getInstance().getAllCookedSources());
- return;
- }
-
- // Report the getDiagnostics from parsing
- ci.getParsing().messages().Emit(llvm::errs(), ci.getAllCookedSources());
-
- auto &parseTree{*ci.getParsing().parseTree()};
-
- // Measure the parse tree
- MeasurementVisitor visitor;
- Fortran::parser::Walk(parseTree, visitor);
- llvm::outs() << "Parse tree comprises " << visitor.objects
- << " objects and occupies " << visitor.bytes
- << " total bytes.\n";
+ debugMeasureParseTree(ci, getCurrentFileOrBufferName());
}
void DebugPreFIRTreeAction::executeAction() {
- CompilerInstance &ci = this->getInstance();
// Report and exit if fatal semantic errors are present
if (reportFatalSemanticErrors()) {
return;
}
- auto &parseTree{*ci.getParsing().parseTree()};
-
- // Dump pre-FIR tree
- if (auto ast{
- Fortran::lower::createPFT(parseTree, ci.getSemanticsContext())}) {
- Fortran::lower::dumpPFT(llvm::outs(), *ast);
- } else {
- unsigned diagID = ci.getDiagnostics().getCustomDiagID(
- clang::DiagnosticsEngine::Error, "Pre FIR Tree is NULL.");
- ci.getDiagnostics().Report(diagID);
- }
+ dumpPreFIRTree(this->getInstance());
}
void DebugDumpParsingLogAction::executeAction() {
- CompilerInstance &ci = this->getInstance();
-
- ci.getParsing().Parse(llvm::errs());
- ci.getParsing().DumpParsingLog(llvm::outs());
+ debugDumpParsingLog(this->getInstance());
}
void GetDefinitionAction::executeAction() {
@@ -1473,17 +1368,7 @@ void InitOnlyAction::executeAction() {
void PluginParseTreeAction::executeAction() {}
void DebugDumpPFTAction::executeAction() {
- CompilerInstance &ci = this->getInstance();
-
- if (auto ast = Fortran::lower::createPFT(*ci.getParsing().parseTree(),
- ci.getSemantics().context())) {
- Fortran::lower::dumpPFT(llvm::outs(), *ast);
- return;
- }
-
- unsigned diagID = ci.getDiagnostics().getCustomDiagID(
- clang::DiagnosticsEngine::Error, "Pre FIR Tree is NULL.");
- ci.getDiagnostics().Report(diagID);
+ dumpPreFIRTree(this->getInstance());
}
Fortran::parser::Parsing &PluginParseTreeAction::getParsing() {
diff --git a/flang/lib/Frontend/ParserActions.cpp b/flang/lib/Frontend/ParserActions.cpp
new file mode 100644
index 0000000000000..cc7e72f696f96
--- /dev/null
+++ b/flang/lib/Frontend/ParserActions.cpp
@@ -0,0 +1,148 @@
+//===--- ParserActions.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Frontend/ParserActions.h"
+#include "flang/Frontend/CompilerInstance.h"
+#include "flang/Lower/Bridge.h"
+#include "flang/Lower/PFTBuilder.h"
+#include "flang/Parser/dump-parse-tree.h"
+#include "flang/Parser/parsing.h"
+#include "flang/Parser/provenance.h"
+#include "flang/Parser/source.h"
+#include "flang/Parser/unparse.h"
+#include "flang/Semantics/unparse-with-symbols.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace Fortran::frontend {
+
+parser::AllCookedSources &getAllCooked(CompilerInstance &ci) {
+ return ci.getParsing().allCooked();
+}
+
+void parseAndLowerTree(CompilerInstance &ci, lower::LoweringBridge &lb) {
+ parser::Program &parseTree{*ci.getParsing().parseTree()};
+ lb.lower(parseTree, ci.getSemanticsContext());
+}
+
+void dumpTree(CompilerInstance &ci) {
+ auto &parseTree{ci.getParsing().parseTree()};
+ llvm::outs() << "========================";
+ llvm::outs() << " Flang: parse tree dump ";
+ llvm::outs() << "========================\n";
+ parser::DumpTree(llvm::outs(), parseTree, &ci.getInvocation().getAsFortran());
+}
+
+void dumpProvenance(CompilerInstance &ci) {
+ ci.getParsing().DumpProvenance(llvm::outs());
+}
+
+void dumpPreFIRTree(CompilerInstance &ci) {
+ auto &parseTree{*ci.getParsing().parseTree()};
+
+ if (auto ast{lower::createPFT(parseTree, ci.getSemanticsContext())}) {
+ lower::dumpPFT(llvm::outs(), *ast);
+ } else {
+ unsigned diagID = ci.getDiagnostics().getCustomDiagID(
+ clang::DiagnosticsEngine::Error, "Pre FIR Tree is NULL.");
+ ci.getDiagnostics().Report(diagID);
+ }
+}
+
+void formatOrDumpPrescanner(std::string &buf,
+ llvm::raw_string_ostream &outForPP,
+ CompilerInstance &ci) {
+ if (ci.getInvocation().getPreprocessorOpts().showMacros) {
+ ci.getParsing().EmitPreprocessorMacros(outForPP);
+ } else if (ci.getInvocation().getPreprocessorOpts().noReformat) {
+ ci.getParsing().DumpCookedChars(outForPP);
+ } else {
+ ci.getParsing().EmitPreprocessedSource(
+ outForPP, !ci.getInvocation().getPreprocessorOpts().noLineDirectives);
+ }
+
+ // Print getDiagnostics from the prescanner
+ ci.getParsing().messages().Emit(llvm::errs(), ci.getAllCookedSources());
+}
+
+struct MeasurementVisitor {
+ template <typename A>
+ bool Pre(const A &) {
+ return true;
+ }
+ template <typename A>
+ void Post(const A &) {
+ ++objects;
+ bytes += sizeof(A);
+ }
+ size_t objects{0}, bytes{0};
+};
+
+void debugMeasureParseTree(CompilerInstance &ci, llvm::StringRef filename) {
+ // Parse. In case of failure, report and return.
+ ci.getParsing().Parse(llvm::outs());
+
+ if ((ci.getParsing().parseTree().has_value() &&
+ !ci.getParsing().consumedWholeFile()) ||
+ (!ci.getParsing().messages().empty() &&
+ (ci.getInvocation().getWarnAsErr() ||
+ ci.getParsing().messages().AnyFatalError()))) {
+ unsigned diagID = ci.getDiagnostics().getCustomDiagID(
+ clang::DiagnosticsEngine::Error, "Could not parse %0");
+ ci.getDiagnostics().Report(diagID) << filename;
+
+ ci.getParsing().messages().Emit(llvm::errs(), ci.getAllCookedSources());
+ return;
+ }
+
+ // Report the getDiagnostics from parsing
+ ci.getParsing().messages().Emit(llvm::errs(), ci.getAllCookedSources());
+
+ auto &parseTree{ci.getParsing().parseTree()};
+ MeasurementVisitor visitor;
+ parser::Walk(parseTree, visitor);
+ llvm::outs() << "Parse tree comprises " << visitor.objects
+ << " objects and occupies " << visitor.bytes
+ << " total bytes.\n";
+}
+
+void debugUnparseNoSema(CompilerInstance &ci, llvm::raw_ostream &out) {
+ auto &invoc = ci.getInvocation();
+ auto &parseTree{ci.getParsing().parseTree()};
+
+ // TODO: Options should come from CompilerInvocation
+ Unparse(out, *parseTree,
+ /*encoding=*/parser::Encoding::UTF_8,
+ /*capitalizeKeywords=*/true, /*backslashEscapes=*/false,
+ /*preStatement=*/nullptr,
+ invoc.getUseAnalyzedObjectsForUnparse() ? &invoc.getAsFortran()
+ : nullptr);
+}
+
+void debugUnparseWithSymbols(CompilerInstance &ci) {
+ auto &parseTree{*ci.getParsing().parseTree()};
+
+ semantics::UnparseWithSymbols(llvm::outs(), parseTree,
+ /*encoding=*/parser::Encoding::UTF_8);
+}
+
+void debugUnparseWithModules(CompilerInstance &ci) {
+ auto &parseTree{*ci.getParsing().parseTree()};
+ semantics::UnparseWithModules(llvm::outs(), ci.getSemantics().context(),
+ parseTree,
+ /*encoding=*/parser::Encoding::UTF_8);
+}
+
+void debugDumpParsingLog(CompilerInstance &ci) {
+ ci.getParsing().Parse(llvm::errs());
+ ci.getParsing().DumpParsingLog(llvm::outs());
+}
+} // namespace Fortran::frontend
More information about the flang-commits
mailing list