[flang-commits] [flang] 2186a4a - [flang] Make the plugin API independent of the driver internals

Andrzej Warzynski via flang-commits flang-commits at lists.llvm.org
Fri Apr 22 02:18:15 PDT 2022


Author: Andrzej Warzynski
Date: 2022-04-22T09:18:04Z
New Revision: 2186a4aea0e3e50e51b121d304889349c4e033ef

URL: https://github.com/llvm/llvm-project/commit/2186a4aea0e3e50e51b121d304889349c4e033ef
DIFF: https://github.com/llvm/llvm-project/commit/2186a4aea0e3e50e51b121d304889349c4e033ef.diff

LOG: [flang] Make the plugin API independent of the driver internals

This patch adds a few new member methods in the `PluginParseTreeAction`
frontend action base class. With these new methods, the plugin API
becomes independent of the driver internals. In particular, plugin
writers no longer require the `CompilerInstance.h` header file to access
various driver data structures (instead, they can use newly added
hooks).

This change is desirable as `CompilerInstance.h` includes various
headers from Clang (both explicitly and implicitly). Some of these
header files are generated at build time (through TableGen) and
including them creates a dependency on some of Clang's build targets.
However, plugins in Flang should not depend on Clang build targets.

Note that plugins might still work fine most of the time, even without
this change and without adding Clang build targets as dependency in
plugin's CMake definition. Indeed, these Clang build targets are often
generated early in the build process. However, that's not guaranteed and
we did notice that on occasions plugins would fail to build.

Differential Revision: https://reviews.llvm.org/D120999

Added: 
    

Modified: 
    flang/docs/FlangDriver.md
    flang/examples/FlangOmpReport/FlangOmpReport.cpp
    flang/examples/FlangOmpReport/yaml_summarizer.py
    flang/examples/PrintFlangFunctionNames/PrintFlangFunctionNames.cpp
    flang/include/flang/Frontend/FrontendActions.h
    flang/lib/Frontend/FrontendActions.cpp

Removed: 
    


################################################################################
diff  --git a/flang/docs/FlangDriver.md b/flang/docs/FlangDriver.md
index cf363d19714f1..ec75162741068 100644
--- a/flang/docs/FlangDriver.md
+++ b/flang/docs/FlangDriver.md
@@ -395,25 +395,30 @@ to run, so in order for your plugin to do something, you will need to implement
 the `ExecuteAction` method in your plugin class. This method will contain the
 implementation of what the plugin actually does, for example:
 ```cpp
+// Forward declaration
+struct ParseTreeVisitor;
+
 void ExecuteAction() override {
-  auto &parseTree{instance().parsing().parseTree()};
   ParseTreeVisitor visitor;
-  Fortran::parser::Walk(parseTree, visitor);
+  Fortran::parser::Walk(getParsing().parseTree(), visitor);
 }
 ```
-In the example plugin, the `ExecuteAction` method first gets a reference to the
-parse tree, `instance().parsing().parseTree()`, then declares a `visitor`
-struct, before passing both of these to the `Fortran::parser::Walk` function
-that will traverse the parse tree. Implementation and details of the `Walk`
-function can be found in `flang/include/flang/Parser/parse-tree-visitor.h`.
-
-A `visitor` struct should define 
diff erent `Pre` and `Post` functions that take
-the type of a specific `ParseTree` node as an argument. When the `Walk` function
-is traversing the parse tree, these functions will be run before/after a node
-of that type is visited. Template functions for `Pre`/`Post` are defined so that
-when a node is visited that you have not defined a function for, it will still
-be able to continue. `Pre` returns a `bool` indicating whether to visit that
-node's children or not. For example:
+In the example plugin, the `ExecuteAction` method first creates an instance of
+`visitor` struct, before passing it together with the parse tree to the
+`Fortran::parser::Walk` function that will traverse the parse tree. The parse
+tree will normally be generated by the frontend driver and can be retrieved in
+your plugin through the `getParsing()` member method. Implementation and
+details of the `Walk` function can be found in
+`flang/include/flang/Parser/parse-tree-visitor.h`.
+
+You will have to define your own `visitor` struct. It should define 
diff erent
+`Pre` and `Post` functions that take the type of a specific `ParseTree` node as
+an argument. When the `Walk` function is traversing the parse tree, these
+functions will be run before/after a node of that type is visited. Template
+functions for `Pre`/`Post` are defined so that when a node is visited that you
+have not defined a function for, it will still be able to continue. `Pre`
+returns a `bool` indicating whether to visit that node's children or not. For
+example:
 ```cpp
 struct ParseTreeVisitor {
   template <typename A> bool Pre(const A&) { return true; }

diff  --git a/flang/examples/FlangOmpReport/FlangOmpReport.cpp b/flang/examples/FlangOmpReport/FlangOmpReport.cpp
index 0fa7582561d27..229d6d1c120a7 100644
--- a/flang/examples/FlangOmpReport/FlangOmpReport.cpp
+++ b/flang/examples/FlangOmpReport/FlangOmpReport.cpp
@@ -5,19 +5,17 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-// This plugin parses a Fortran source file and generates a YAML
-// report with all the OpenMP constructs and clauses and which
-// line they're located on.
+// This plugin parses a Fortran source file and generates a YAML report with
+// all the OpenMP constructs and clauses and which line they're located on.
 //
 // The plugin may be invoked as:
-// ./bin/flang-new -fc1 -load lib/flangOmpReport.so -plugin
-// flang-omp-report -fopenmp -o - <source_file.f90>
+// ./bin/flang-new -fc1 -load lib/flangOmpReport.so -plugin flang-omp-report
+// -fopenmp
 //
 //===----------------------------------------------------------------------===//
 
 #include "FlangOmpReportVisitor.h"
 
-#include "flang/Frontend/CompilerInstance.h"
 #include "flang/Frontend/FrontendActions.h"
 #include "flang/Frontend/FrontendPluginRegistry.h"
 #include "flang/Parser/dump-parse-tree.h"
@@ -53,20 +51,18 @@ template <> struct MappingTraits<LogRecord> {
 class FlangOmpReport : public PluginParseTreeAction {
   void ExecuteAction() override {
     // Prepare the parse tree and the visitor
-    CompilerInstance &ci = this->instance();
-    Parsing &parsing = ci.parsing();
-    const Program &parseTree = *parsing.parseTree();
+    Parsing &parsing = getParsing();
     OpenMPCounterVisitor visitor;
     visitor.parsing = &parsing;
 
     // Walk the parse tree
-    Walk(parseTree, visitor);
+    Walk(parsing.parseTree(), visitor);
 
     // Dump the output
-    std::unique_ptr<llvm::raw_pwrite_stream> OS{ci.CreateDefaultOutputFile(
-        /*Binary=*/true, /*InFile=*/GetCurrentFileOrBufferName(),
-        /*Extension=*/".yaml")};
+    std::unique_ptr<llvm::raw_pwrite_stream> OS{
+        createOutputFile(/*extension=*/"yaml")};
     llvm::yaml::Output yout(*OS);
+
     yout << visitor.constructClauses;
   }
 };

diff  --git a/flang/examples/FlangOmpReport/yaml_summarizer.py b/flang/examples/FlangOmpReport/yaml_summarizer.py
index 4c9981dffd015..9d8df285d6169 100644
--- a/flang/examples/FlangOmpReport/yaml_summarizer.py
+++ b/flang/examples/FlangOmpReport/yaml_summarizer.py
@@ -1,6 +1,6 @@
 """YAML Summariser
 
-The flang plugin ``flang-omp-report`` takes one fortran
+The flang plugin ``flang-omp-report`` takes one Fortran
 file in and returns a YAML report file of the input file.
 This becomes an issue when you want to analyse an entire project
 into one final report.

diff  --git a/flang/examples/PrintFlangFunctionNames/PrintFlangFunctionNames.cpp b/flang/examples/PrintFlangFunctionNames/PrintFlangFunctionNames.cpp
index 0afbf9f35e531..90590bedb292b 100644
--- a/flang/examples/PrintFlangFunctionNames/PrintFlangFunctionNames.cpp
+++ b/flang/examples/PrintFlangFunctionNames/PrintFlangFunctionNames.cpp
@@ -18,7 +18,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "flang/Frontend/CompilerInstance.h"
 #include "flang/Frontend/FrontendActions.h"
 #include "flang/Frontend/FrontendPluginRegistry.h"
 #include "flang/Parser/dump-parse-tree.h"
@@ -67,10 +66,8 @@ class PrintFunctionNamesAction : public PluginParseTreeAction {
   };
 
   void ExecuteAction() override {
-    auto &parseTree{instance().parsing().parseTree()};
-
     ParseTreeVisitor visitor;
-    Fortran::parser::Walk(parseTree, visitor);
+    Fortran::parser::Walk(getParsing().parseTree(), visitor);
 
     llvm::outs() << "\n====   Functions: " << visitor.fcounter << " ====\n";
     llvm::outs() << "==== Subroutines: " << visitor.scounter << " ====\n";

diff  --git a/flang/include/flang/Frontend/FrontendActions.h b/flang/include/flang/Frontend/FrontendActions.h
index 48836c6d41e21..4831b1ece955f 100644
--- a/flang/include/flang/Frontend/FrontendActions.h
+++ b/flang/include/flang/Frontend/FrontendActions.h
@@ -10,9 +10,11 @@
 #define LLVM_FLANG_FRONTEND_FRONTENDACTIONS_H
 
 #include "flang/Frontend/FrontendAction.h"
+#include "flang/Parser/parsing.h"
 #include "flang/Semantics/semantics.h"
 
 #include "mlir/IR/BuiltinOps.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/IR/Module.h"
 #include <memory>
 
@@ -131,6 +133,17 @@ class ParseSyntaxOnlyAction : public PrescanAndSemaAction {
 
 class PluginParseTreeAction : public PrescanAndSemaAction {
   void ExecuteAction() override = 0;
+
+public:
+  Fortran::parser::Parsing &getParsing();
+  /// Creates an output file. This is just a wrapper for calling
+  /// CreateDefaultOutputFile from CompilerInstance. Use it to make sure that
+  /// your plugin respects driver's `-o` flag.
+  /// \param extension  The extension to use for the output file (ignored when
+  ///                   the user decides to print to stdout via `-o -`)
+  /// \return           Null on error, ostream for the output file otherwise
+  std::unique_ptr<llvm::raw_pwrite_stream> createOutputFile(
+      llvm::StringRef extension);
 };
 
 //===----------------------------------------------------------------------===//

diff  --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 83e795c16906f..fd93bcaed7a83 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -648,3 +648,17 @@ void DebugDumpPFTAction::ExecuteAction() {
       clang::DiagnosticsEngine::Error, "Pre FIR Tree is NULL.");
   ci.diagnostics().Report(DiagID);
 }
+
+Fortran::parser::Parsing &PluginParseTreeAction::getParsing() {
+  return instance().parsing();
+}
+
+std::unique_ptr<llvm::raw_pwrite_stream>
+PluginParseTreeAction::createOutputFile(llvm::StringRef extension = "") {
+
+  std::unique_ptr<llvm::raw_pwrite_stream> OS{
+      instance().CreateDefaultOutputFile(
+          /*Binary=*/false, /*InFile=*/GetCurrentFileOrBufferName(),
+          extension)};
+  return OS;
+}


        


More information about the flang-commits mailing list