[clang] e81b340 - [flang][driver] Add debug options not requiring semantic checks

Andrzej Warzynski via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 8 02:45:08 PDT 2021


Author: Andrzej Warzynski
Date: 2021-04-08T09:44:19Z
New Revision: e81b3401177a67481605447ea5250d8345cb4341

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

LOG: [flang][driver] Add debug options not requiring semantic checks

This patch adds two debugging options in the new Flang driver
(flang-new):
  *fdebug-unparse-no-sema
  *fdebug-dump-parse-tree-no-sema
Each of these options combines two options from the "throwaway" driver
(left: f18, right: flang-new):
  * `-fdebug-uparse -fdebug-no-semantics` --> `-fdebug-unparse-no-sema`
  * `-fdebug-dump-parse-tree -fdebug-no-semantics` -->
    `-fdebug-dump-parse-tree-no-sema`

There are no plans to implement `-fdebug-no-semantics` in the new
driver.  Such option would be too powerful. Also, it would only make
sense when combined with specific frontend actions (`-fdebug-unparse`
and `-fdebug-dump-parse-tree`). Instead, this patch adds 2 specialised
options listed above. Each of these is implemented through a dedicated
FrontendAction (also added).

The new frontend actions are implemented in terms of a new abstract base
action: `PrescanAndSemaAction`. This new base class was required so that
we can have finer control over what steps within the frontend are
executed:
  * `PrescanAction`: run the _prescanner_
  * `PrescanAndSemaAction`: run the _prescanner_ and the _parser_ (new
     in this patch)
  * `PrescanAndSemaAction`: run the _prescanner_, _parser_ and run the
    _semantic checks_

This patch introduces `PrescanAndParseAction::BeginSourceFileAction`.
Apart from the semantic checks removed at the end, it is similar to
`PrescanAndSemaAction::BeginSourceFileAction`.

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

Added: 
    flang/test/Driver/dump-parse-tree-no-sema.f90

Modified: 
    clang/include/clang/Driver/Options.td
    flang/include/flang/Frontend/FrontendActions.h
    flang/include/flang/Frontend/FrontendOptions.h
    flang/lib/Frontend/CompilerInvocation.cpp
    flang/lib/Frontend/FrontendActions.cpp
    flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
    flang/test/Driver/driver-help.f90
    flang/test/Parser/omp-allocate-unparse.f90
    flang/test/Parser/omp-atomic-unparse.f90
    flang/tools/f18/f18.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 240656a6e519d..24bb3b8c34c7b 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4377,14 +4377,26 @@ let Flags = [FC1Option, FlangOnlyOption] in {
 
 def test_io : Flag<["-"], "test-io">, Group<Action_Group>,
   HelpText<"Run the InputOuputTest action. Use for development and testing only.">;
+def fdebug_unparse_no_sema : Flag<["-"], "fdebug-unparse-no-sema">, Group<Action_Group>,
+  HelpText<"Unparse and stop (skips the semantic checks)">,
+  DocBrief<[{Only run the parser, then unparse the parse-tree and output the
+generated Fortran source file. Semantic checks are disabled.}]>;
 def fdebug_unparse : Flag<["-"], "fdebug-unparse">, Group<Action_Group>,
-  HelpText<"Unparse and stop.">;
+  HelpText<"Unparse and stop.">,
+  DocBrief<[{Run the parser and the semantic checks. Then unparse the
+parse-tree and output the generated Fortran source file.}]>;
 def fdebug_unparse_with_symbols : Flag<["-"], "fdebug-unparse-with-symbols">, Group<Action_Group>,
   HelpText<"Unparse and stop.">;
 def fdebug_dump_symbols : Flag<["-"], "fdebug-dump-symbols">, Group<Action_Group>,
   HelpText<"Dump symbols after the semantic analysis">;
 def fdebug_dump_parse_tree : Flag<["-"], "fdebug-dump-parse-tree">, Group<Action_Group>,
-  HelpText<"Dump the parse tree">;
+  HelpText<"Dump the parse tree">,
+  DocBrief<[{Run the Parser and the semantic checks, and then output the
+parse tree.}]>;
+def fdebug_dump_parse_tree_no_sema : Flag<["-"], "fdebug-dump-parse-tree-no-sema">, Group<Action_Group>,
+  HelpText<"Dump the parse tree (skips the semantic checks)">,
+  DocBrief<[{Run the Parser and then output the parse tree. Semantic
+checks are disabled.}]>;
 def fdebug_dump_provenance : Flag<["-"], "fdebug-dump-provenance">, Group<Action_Group>,
   HelpText<"Dump provenance">;
 def fdebug_dump_parsing_log : Flag<["-"], "fdebug-dump-parsing-log">, Group<Action_Group>,

diff  --git a/flang/include/flang/Frontend/FrontendActions.h b/flang/include/flang/Frontend/FrontendActions.h
index f49f9f4714b53..83e9652153ae3 100644
--- a/flang/include/flang/Frontend/FrontendActions.h
+++ b/flang/include/flang/Frontend/FrontendActions.h
@@ -62,6 +62,22 @@ class DebugMeasureParseTreeAction : public PrescanAction {
   void ExecuteAction() override;
 };
 
+//===----------------------------------------------------------------------===//
+// PrescanAndParse Actions
+//===----------------------------------------------------------------------===//
+class PrescanAndParseAction : public FrontendAction {
+  void ExecuteAction() override = 0;
+  bool BeginSourceFileAction(CompilerInstance &ci) override;
+};
+
+class DebugUnparseNoSemaAction : public PrescanAndParseAction {
+  void ExecuteAction() override;
+};
+
+class DebugDumpParseTreeNoSemaAction : public PrescanAndParseAction {
+  void ExecuteAction() override;
+};
+
 //===----------------------------------------------------------------------===//
 // PrescanAndSema Actions
 //===----------------------------------------------------------------------===//

diff  --git a/flang/include/flang/Frontend/FrontendOptions.h b/flang/include/flang/Frontend/FrontendOptions.h
index b58ca9ce87701..43b38f6db2a5d 100644
--- a/flang/include/flang/Frontend/FrontendOptions.h
+++ b/flang/include/flang/Frontend/FrontendOptions.h
@@ -37,6 +37,10 @@ enum ActionKind {
   /// Parse, unparse the parse-tree and output a Fortran source file
   DebugUnparse,
 
+  /// Parse, unparse the parse-tree and output a Fortran source file, skip the
+  /// semantic checks
+  DebugUnparseNoSema,
+
   /// Parse, resolve the sybmols, unparse the parse-tree and then output a
   /// Fortran source file
   DebugUnparseWithSymbols,
@@ -47,6 +51,9 @@ enum ActionKind {
   /// Parse, run semantics and then output the parse tree
   DebugDumpParseTree,
 
+  /// Parse and then output the parse tree, skip the semantic checks
+  DebugDumpParseTreeNoSema,
+
   /// Dump provenance
   DebugDumpProvenance,
 

diff  --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 43d9d41bd8d48..d1203c7912d03 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -127,6 +127,9 @@ static InputKind ParseFrontendArgs(FrontendOptions &opts,
     case clang::driver::options::OPT_fdebug_unparse:
       opts.programAction_ = DebugUnparse;
       break;
+    case clang::driver::options::OPT_fdebug_unparse_no_sema:
+      opts.programAction_ = DebugUnparseNoSema;
+      break;
     case clang::driver::options::OPT_fdebug_unparse_with_symbols:
       opts.programAction_ = DebugUnparseWithSymbols;
       break;
@@ -136,6 +139,9 @@ static InputKind ParseFrontendArgs(FrontendOptions &opts,
     case clang::driver::options::OPT_fdebug_dump_parse_tree:
       opts.programAction_ = DebugDumpParseTree;
       break;
+    case clang::driver::options::OPT_fdebug_dump_parse_tree_no_sema:
+      opts.programAction_ = DebugDumpParseTreeNoSema;
+      break;
     case clang::driver::options::OPT_fdebug_dump_provenance:
       opts.programAction_ = DebugDumpProvenance;
       break;

diff  --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 6aa7e2602ea63..00b46c90dfd1f 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -67,6 +67,55 @@ bool PrescanAction::BeginSourceFileAction(CompilerInstance &c1) {
   return true;
 }
 
+bool PrescanAndParseAction::BeginSourceFileAction(CompilerInstance &c1) {
+  CompilerInstance &ci = this->instance();
+
+  std::string currentInputPath{GetCurrentFileOrBufferName()};
+
+  Fortran::parser::Options parserOptions = ci.invocation().fortranOpts();
+
+  if (ci.invocation().frontendOpts().fortranForm_ == FortranForm::Unknown) {
+    // Switch between fixed and free form format based on the input file
+    // extension.
+    //
+    // Ideally we should have all Fortran options set before entering this
+    // method (i.e. before processing any specific input files). However, we
+    // can't decide between fixed and free form based on the file extension
+    // earlier than this.
+    parserOptions.isFixedForm = currentInput().IsFixedForm();
+  }
+
+  // Prescan. In case of failure, report and return.
+  ci.parsing().Prescan(currentInputPath, parserOptions);
+
+  if (ci.parsing().messages().AnyFatalError()) {
+    const unsigned diagID = ci.diagnostics().getCustomDiagID(
+        clang::DiagnosticsEngine::Error, "Could not scan %0");
+    ci.diagnostics().Report(diagID) << GetCurrentFileOrBufferName();
+    ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources());
+
+    return false;
+  }
+
+  // Parse. In case of failure, report and return.
+  ci.parsing().Parse(llvm::outs());
+
+  if (ci.parsing().messages().AnyFatalError()) {
+    unsigned diagID = ci.diagnostics().getCustomDiagID(
+        clang::DiagnosticsEngine::Error, "Could not parse %0");
+    ci.diagnostics().Report(diagID) << GetCurrentFileOrBufferName();
+
+    ci.parsing().messages().Emit(
+        llvm::errs(), this->instance().allCookedSources());
+    return false;
+  }
+
+  // Report the diagnostics from parsing
+  ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources());
+
+  return true;
+}
+
 bool PrescanAndSemaAction::BeginSourceFileAction(CompilerInstance &c1) {
   CompilerInstance &ci = this->instance();
   std::string currentInputPath{GetCurrentFileOrBufferName()};
@@ -117,6 +166,7 @@ bool PrescanAndSemaAction::BeginSourceFileAction(CompilerInstance &c1) {
 
   // Report the diagnostics from the semantic checks
   semantics.EmitMessages(ci.semaOutputStream());
+
   return true;
 }
 
@@ -191,6 +241,19 @@ void ParseSyntaxOnlyAction::ExecuteAction() {
       GetCurrentFileOrBufferName());
 }
 
+void DebugUnparseNoSemaAction::ExecuteAction() {
+  auto &parseTree{instance().parsing().parseTree()};
+
+  Fortran::parser::AnalyzedObjectsAsFortran asFortran =
+      Fortran::frontend::getBasicAsFortran();
+
+  // TODO: Options should come from CompilerInvocation
+  Unparse(llvm::outs(), *parseTree,
+      /*encoding=*/Fortran::parser::Encoding::UTF_8,
+      /*capitalizeKeywords=*/true, /*backslashEscapes=*/false,
+      /*preStatement=*/nullptr, &asFortran);
+}
+
 void DebugUnparseAction::ExecuteAction() {
   auto &parseTree{instance().parsing().parseTree()};
   Fortran::parser::AnalyzedObjectsAsFortran asFortran =
@@ -228,6 +291,15 @@ void DebugDumpSymbolsAction::ExecuteAction() {
       semantics, this->instance().diagnostics(), GetCurrentFileOrBufferName());
 }
 
+void DebugDumpParseTreeNoSemaAction::ExecuteAction() {
+  auto &parseTree{instance().parsing().parseTree()};
+  Fortran::parser::AnalyzedObjectsAsFortran asFortran =
+      Fortran::frontend::getBasicAsFortran();
+
+  // Dump parse tree
+  Fortran::parser::DumpTree(llvm::outs(), parseTree, &asFortran);
+}
+
 void DebugDumpParseTreeAction::ExecuteAction() {
   auto &parseTree{instance().parsing().parseTree()};
   Fortran::parser::AnalyzedObjectsAsFortran asFortran =

diff  --git a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 2a08e388a9d81..462de5241f3e6 100644
--- a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -40,6 +40,9 @@ static std::unique_ptr<FrontendAction> CreateFrontendBaseAction(
   case DebugUnparse:
     return std::make_unique<DebugUnparseAction>();
     break;
+  case DebugUnparseNoSema:
+    return std::make_unique<DebugUnparseNoSemaAction>();
+    break;
   case DebugUnparseWithSymbols:
     return std::make_unique<DebugUnparseWithSymbolsAction>();
     break;
@@ -49,6 +52,9 @@ static std::unique_ptr<FrontendAction> CreateFrontendBaseAction(
   case DebugDumpParseTree:
     return std::make_unique<DebugDumpParseTreeAction>();
     break;
+  case DebugDumpParseTreeNoSema:
+    return std::make_unique<DebugDumpParseTreeNoSemaAction>();
+    break;
   case DebugDumpProvenance:
     return std::make_unique<DebugDumpProvenanceAction>();
     break;

diff  --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90
index ed4648cfa48a2..dd43990bb1ac1 100644
--- a/flang/test/Driver/driver-help.f90
+++ b/flang/test/Driver/driver-help.f90
@@ -69,6 +69,8 @@
 ! HELP-FC1-NEXT: -falternative-parameter-statement
 ! HELP-FC1-NEXT: Enable the old style PARAMETER statement
 ! HELP-FC1-NEXT: -fbackslash            Specify that backslash in string introduces an escape character
+! HELP-FC1-NEXT: -fdebug-dump-parse-tree-no-sema
+! HELP-FC1-NEXT:                        Dump the parse tree (skips the semantic checks)
 ! HELP-FC1-NEXT: -fdebug-dump-parse-tree Dump the parse tree
 ! HELP-FC1-NEXT: -fdebug-dump-parsing-log
 ! HELP-FC1-NEXT:                   Run instrumented parse and dump the parsing log
@@ -78,6 +80,7 @@
 ! HELP-FC1-NEXT:                         Measure the parse tree
 ! HELP-FC1-NEXT: -fdebug-module-writer   Enable debug messages while writing module files
 ! HELP-FC1-NEXT: -fdebug-pre-fir-tree    Dump the pre-FIR tree
+! HELP-FC1-NEXT: -fdebug-unparse-no-sema Unparse and stop (skips the semantic checks)
 ! HELP-FC1-NEXT: -fdebug-unparse-with-symbols
 ! HELP-FC1-NEXT:                        Unparse and stop.
 ! HELP-FC1-NEXT: -fdebug-unparse        Unparse and stop.

diff  --git a/flang/test/Driver/dump-parse-tree-no-sema.f90 b/flang/test/Driver/dump-parse-tree-no-sema.f90
new file mode 100644
index 0000000000000..7179b1d4174e5
--- /dev/null
+++ b/flang/test/Driver/dump-parse-tree-no-sema.f90
@@ -0,0 +1,22 @@
+!----------
+! RUN lines
+!----------
+! RUN: %flang_fc1 -fdebug-dump-parse-tree %s 2>&1 | FileCheck %s --check-prefix=SEMA_ON
+! RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema %s 2>&1 | FileCheck %s --check-prefix=SEMA_OFF
+
+!-----------------
+! EXPECTEED OUTPUT
+!-----------------
+! SEMA_ON: | | | NamedConstant -> Name = 'i'
+! SEMA_ON-NEXT: | | | Constant -> Expr = '1_4'
+! SEMA_ON-NEXT: | | | | LiteralConstant -> IntLiteralConstant = '1'
+
+! SEMA_OFF: | | | NamedConstant -> Name = 'i'
+! SEMA_OFF-NEXT: | | | Constant -> Expr -> LiteralConstant -> IntLiteralConstant = '1'
+
+!-------
+! INPUT
+!-------
+parameter(i=1)
+integer :: j
+end program

diff  --git a/flang/test/Parser/omp-allocate-unparse.f90 b/flang/test/Parser/omp-allocate-unparse.f90
index 3f517c1e2d04e..81b3677ad954b 100644
--- a/flang/test/Parser/omp-allocate-unparse.f90
+++ b/flang/test/Parser/omp-allocate-unparse.f90
@@ -1,4 +1,4 @@
-! RUN: %f18 -fdebug-no-semantics -funparse -fopenmp %s | FileCheck %s
+! RUN: %flang_fc1 -fdebug-unparse-no-sema -fopenmp %s | FileCheck %s
 ! Check Unparsing of OpenMP Allocate directive
 
 program allocate_unparse

diff  --git a/flang/test/Parser/omp-atomic-unparse.f90 b/flang/test/Parser/omp-atomic-unparse.f90
index 10d1a61df07c4..f9d8ec5d5c681 100644
--- a/flang/test/Parser/omp-atomic-unparse.f90
+++ b/flang/test/Parser/omp-atomic-unparse.f90
@@ -1,4 +1,4 @@
-! RUN: %f18 -fdebug-no-semantics -funparse -fopenmp %s | FileCheck %s
+! RUN: %flang_fc1 -fdebug-unparse-no-sema -fopenmp %s | FileCheck %s
 
 program main
    implicit none

diff  --git a/flang/tools/f18/f18.cpp b/flang/tools/f18/f18.cpp
index 92d04ddd9b27c..9a24183aa8738 100644
--- a/flang/tools/f18/f18.cpp
+++ b/flang/tools/f18/f18.cpp
@@ -564,6 +564,13 @@ int main(int argc, char *const argv[]) {
       options.instrumentedParse = true;
     } else if (arg == "-fdebug-no-semantics") {
       driver.debugNoSemantics = true;
+    } else if (arg == "-fdebug-unparse-no-sema") {
+      driver.debugNoSemantics = true;
+      driver.dumpUnparse = true;
+    } else if (arg == "-fdebug-dump-parse-tree-no-sema") {
+      driver.debugNoSemantics = true;
+      driver.dumpParseTree = true;
+      driver.syntaxOnly = true;
     } else if (arg == "-funparse" || arg == "-fdebug-unparse") {
       driver.dumpUnparse = true;
     } else if (arg == "-funparse-with-symbols" ||


        


More information about the cfe-commits mailing list