diff options
author | Faris Rehman <faris.rehman@arm.com> | 2021-02-17 18:53:05 +0000 |
---|---|---|
committer | Faris Rehman <faris.rehman@arm.com> | 2021-02-19 11:27:54 +0000 |
commit | 529f71811b0475995f2d9cf766f18d897eec574c (patch) | |
tree | 38a91175d41a58a35a1caffc1abae6fe8513d861 | |
parent | aa44815f849f2928f998499b163c8c3230a73c95 (diff) | |
download | llvm-529f71811b0475995f2d9cf766f18d897eec574c.zip llvm-529f71811b0475995f2d9cf766f18d897eec574c.tar.gz llvm-529f71811b0475995f2d9cf766f18d897eec574c.tar.bz2 |
[flang][driver] Add debug measure-parse-tree and pre-fir-tree options
Add the following options:
* -fdebug-measure-parse-tree
* -fdebug-pre-fir-tree
Summary of changes:
- Add 2 new frontend actions: DebugMeasureParseTreeAction and DebugPreFIRTreeAction
- Add MeasurementVisitor to FrontendActions.h
- Make reportFatalSemanticErrors return true if there are any fatal errors
- Port most of the `-fdebug-pre-fir-tree` tests to use the new driver if built, otherwise use f18.
Differential Revision: https://reviews.llvm.org/D96884
-rw-r--r-- | clang/include/clang/Driver/Options.td | 4 | ||||
-rw-r--r-- | flang/include/flang/Frontend/FrontendActions.h | 19 | ||||
-rw-r--r-- | flang/include/flang/Frontend/FrontendOptions.h | 9 | ||||
-rw-r--r-- | flang/lib/Frontend/CMakeLists.txt | 1 | ||||
-rw-r--r-- | flang/lib/Frontend/CompilerInvocation.cpp | 6 | ||||
-rw-r--r-- | flang/lib/Frontend/FrontendActions.cpp | 62 | ||||
-rw-r--r-- | flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp | 6 | ||||
-rw-r--r-- | flang/test/Flang-Driver/debug-measure-parse-tree.f90 | 26 | ||||
-rw-r--r-- | flang/test/Flang-Driver/driver-help.f90 | 3 | ||||
-rw-r--r-- | flang/test/Lower/pre-fir-tree01.f90 | 2 | ||||
-rw-r--r-- | flang/test/Lower/pre-fir-tree02.f90 | 2 | ||||
-rw-r--r-- | flang/test/Lower/pre-fir-tree03.f90 | 2 | ||||
-rw-r--r-- | flang/test/Lower/pre-fir-tree05.f90 | 2 |
13 files changed, 138 insertions, 6 deletions
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 17eb0ad..ade330b 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4288,6 +4288,10 @@ def fdebug_dump_parse_tree : Flag<["-"], "fdebug-dump-parse-tree">, Group<Action HelpText<"Dump the parse tree">; def fdebug_dump_provenance : Flag<["-"], "fdebug-dump-provenance">, Group<Action_Group>, HelpText<"Dump provenance">; +def fdebug_measure_parse_tree : Flag<["-"], "fdebug-measure-parse-tree">, Group<Action_Group>, + HelpText<"Measure the parse tree">; +def fdebug_pre_fir_tree : Flag<["-"], "fdebug-pre-fir-tree">, Group<Action_Group>, + HelpText<"Dump the pre-FIR tree">; } diff --git a/flang/include/flang/Frontend/FrontendActions.h b/flang/include/flang/Frontend/FrontendActions.h index ebcb695..f6dfdd2 100644 --- a/flang/include/flang/Frontend/FrontendActions.h +++ b/flang/include/flang/Frontend/FrontendActions.h @@ -15,6 +15,17 @@ 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 //===----------------------------------------------------------------------===// @@ -43,6 +54,10 @@ class DebugDumpProvenanceAction : public PrescanAction { void ExecuteAction() override; }; +class DebugMeasureParseTreeAction : public PrescanAction { + void ExecuteAction() override; +}; + //===----------------------------------------------------------------------===// // PrescanAndSema Actions //===----------------------------------------------------------------------===// @@ -77,6 +92,10 @@ class DebugDumpParseTreeAction : public PrescanAndSemaAction { void ExecuteAction() override; }; +class DebugPreFIRTreeAction : public PrescanAndSemaAction { + void ExecuteAction() override; +}; + class ParseSyntaxOnlyAction : public PrescanAndSemaAction { void ExecuteAction() override; }; diff --git a/flang/include/flang/Frontend/FrontendOptions.h b/flang/include/flang/Frontend/FrontendOptions.h index a26e1e3..98a717df 100644 --- a/flang/include/flang/Frontend/FrontendOptions.h +++ b/flang/include/flang/Frontend/FrontendOptions.h @@ -48,7 +48,14 @@ enum ActionKind { DebugDumpParseTree, /// Dump provenance - DebugDumpProvenance + DebugDumpProvenance, + + /// Parse then output the number of objects in the parse tree and the overall + /// size + DebugMeasureParseTree, + + /// Parse, run semantics and then output the pre-FIR tree + DebugPreFIRTree /// TODO: RunPreprocessor, EmitLLVM, EmitLLVMOnly, /// EmitCodeGenOnly, EmitAssembly, (...) diff --git a/flang/lib/Frontend/CMakeLists.txt b/flang/lib/Frontend/CMakeLists.txt index 53c2518..abaa77f 100644 --- a/flang/lib/Frontend/CMakeLists.txt +++ b/flang/lib/Frontend/CMakeLists.txt @@ -16,6 +16,7 @@ add_flang_library(flangFrontend FortranSemantics FortranEvaluate FortranCommon + FortranLower clangBasic clangDriver diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index ecc0fda..822bf26 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -125,6 +125,12 @@ static InputKind ParseFrontendArgs(FrontendOptions &opts, case clang::driver::options::OPT_fdebug_dump_provenance: opts.programAction_ = DebugDumpProvenance; break; + case clang::driver::options::OPT_fdebug_measure_parse_tree: + opts.programAction_ = DebugMeasureParseTree; + break; + case clang::driver::options::OPT_fdebug_pre_fir_tree: + opts.programAction_ = DebugPreFIRTree; + break; // TODO: // case calng::driver::options::OPT_emit_llvm: diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index 91e19a7..b7e4f91 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -10,6 +10,7 @@ #include "flang/Common/default-kinds.h" #include "flang/Frontend/CompilerInstance.h" #include "flang/Frontend/FrontendOptions.h" +#include "flang/Lower/PFTBuilder.h" #include "flang/Parser/dump-parse-tree.h" #include "flang/Parser/parsing.h" #include "flang/Parser/provenance.h" @@ -23,13 +24,22 @@ using namespace Fortran::frontend; -void reportFatalSemanticErrors(const Fortran::semantics::Semantics &semantics, +/// Report fatal semantic errors if present. +/// +/// \param semantics The semantics instance +/// \param diags The diagnostics engine instance +/// \param bufferName The file or buffer name +/// +/// \return True if fatal semantic errors are present, false if not +bool reportFatalSemanticErrors(const Fortran::semantics::Semantics &semantics, clang::DiagnosticsEngine &diags, const llvm::StringRef &bufferName) { if (semantics.AnyFatalError()) { unsigned DiagID = diags.getCustomDiagID( clang::DiagnosticsEngine::Error, "Semantic errors in %0"); diags.Report(DiagID) << bufferName; + return true; } + return false; } bool PrescanAction::BeginSourceFileAction(CompilerInstance &c1) { @@ -247,6 +257,56 @@ void DebugDumpParseTreeAction::ExecuteAction() { GetCurrentFileOrBufferName()); } +void DebugMeasureParseTreeAction::ExecuteAction() { + CompilerInstance &ci = this->instance(); + + // 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; + } + + // Report the diagnostics from parsing + ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources()); + + auto &parseTree{*ci.parsing().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"; +} + +void DebugPreFIRTreeAction::ExecuteAction() { + CompilerInstance &ci = this->instance(); + // Report and exit if fatal semantic errors are present + if (reportFatalSemanticErrors( + semantics(), ci.diagnostics(), GetCurrentFileOrBufferName())) { + return; + } + + auto &parseTree{*ci.parsing().parseTree()}; + + // Dump pre-FIR tree + if (auto ast{Fortran::lower::createPFT( + parseTree, ci.invocation().semanticsContext())}) { + Fortran::lower::dumpPFT(llvm::outs(), *ast); + } else { + unsigned diagID = ci.diagnostics().getCustomDiagID( + clang::DiagnosticsEngine::Error, "Pre FIR Tree is NULL."); + ci.diagnostics().Report(diagID); + } +} + void EmitObjAction::ExecuteAction() { CompilerInstance &ci = this->instance(); unsigned DiagID = ci.diagnostics().getCustomDiagID( diff --git a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index aec968b..c5f7bb2 100644 --- a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -52,6 +52,12 @@ static std::unique_ptr<FrontendAction> CreateFrontendBaseAction( case DebugDumpProvenance: return std::make_unique<DebugDumpProvenanceAction>(); break; + case DebugMeasureParseTree: + return std::make_unique<DebugMeasureParseTreeAction>(); + break; + case DebugPreFIRTree: + return std::make_unique<DebugPreFIRTreeAction>(); + break; default: break; // TODO: diff --git a/flang/test/Flang-Driver/debug-measure-parse-tree.f90 b/flang/test/Flang-Driver/debug-measure-parse-tree.f90 new file mode 100644 index 0000000..fd43468 --- /dev/null +++ b/flang/test/Flang-Driver/debug-measure-parse-tree.f90 @@ -0,0 +1,26 @@ +! Ensure argument -fdebug-measure-parse-tree works as expected. + +! REQUIRES: new-flang-driver + +!-------------------------- +! FLANG DRIVER (flang-new) +!-------------------------- +! RUN: not %flang-new -fdebug-measure-parse-tree %s 2>&1 | FileCheck %s --check-prefix=FLANG + +!---------------------------------------- +! FRONTEND FLANG DRIVER (flang-new -fc1) +!---------------------------------------- +! RUN: %flang-new -fc1 -fdebug-measure-parse-tree %s 2>&1 | FileCheck %s --check-prefix=FRONTEND + +!---------------------------------- +! EXPECTED OUTPUT WITH `flang-new` +!---------------------------------- +! FLANG:warning: argument unused during compilation: '-fdebug-measure-parse-tree' + +!--------------------------------------- +! EXPECTED OUTPUT WITH `flang-new -fc1` +!--------------------------------------- +! FRONTEND:Parse tree comprises {{[0-9]+}} objects and occupies {{[0-9]+}} total bytes. + +program A +end diff --git a/flang/test/Flang-Driver/driver-help.f90 b/flang/test/Flang-Driver/driver-help.f90 index fd05331..b4072c1 100644 --- a/flang/test/Flang-Driver/driver-help.f90 +++ b/flang/test/Flang-Driver/driver-help.f90 @@ -59,6 +59,9 @@ ! HELP-FC1-NEXT: -fdebug-dump-parse-tree Dump the parse tree ! HELP-FC1-NEXT: -fdebug-dump-provenance Dump provenance ! HELP-FC1-NEXT: -fdebug-dump-symbols Dump symbols after the semantic analysis +! HELP-FC1-NEXT: -fdebug-measure-parse-tree +! HELP-FC1-NEXT: Measure the parse tree +! HELP-FC1-NEXT: -fdebug-pre-fir-tree Dump the pre-FIR tree ! 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/Lower/pre-fir-tree01.f90 b/flang/test/Lower/pre-fir-tree01.f90 index 5e59ff7..23f9fd1 100644 --- a/flang/test/Lower/pre-fir-tree01.f90 +++ b/flang/test/Lower/pre-fir-tree01.f90 @@ -1,4 +1,4 @@ -! RUN: %f18 -fdebug-pre-fir-tree -fsyntax-only %s | FileCheck %s +! RUN: %flang_fc1 -fsyntax-only -fdebug-pre-fir-tree %s | FileCheck %s ! Test structure of the Pre-FIR tree diff --git a/flang/test/Lower/pre-fir-tree02.f90 b/flang/test/Lower/pre-fir-tree02.f90 index 1db4960..9e16c4e 100644 --- a/flang/test/Lower/pre-fir-tree02.f90 +++ b/flang/test/Lower/pre-fir-tree02.f90 @@ -1,4 +1,4 @@ -! RUN: %f18 -fdebug-pre-fir-tree -fsyntax-only %s | FileCheck %s +! RUN: %flang_fc1 -fsyntax-only -fdebug-pre-fir-tree %s | FileCheck %s ! Test Pre-FIR Tree captures all the intended nodes from the parse-tree ! Coarray and OpenMP related nodes are tested in other files. diff --git a/flang/test/Lower/pre-fir-tree03.f90 b/flang/test/Lower/pre-fir-tree03.f90 index efc923a..19cf098 100644 --- a/flang/test/Lower/pre-fir-tree03.f90 +++ b/flang/test/Lower/pre-fir-tree03.f90 @@ -1,4 +1,4 @@ -! RUN: %f18 -fdebug-pre-fir-tree -fsyntax-only -fopenmp %s | FileCheck %s +! RUN: %flang_fc1 -fsyntax-only -fdebug-pre-fir-tree -fopenmp %s | FileCheck %s ! Test Pre-FIR Tree captures OpenMP related constructs diff --git a/flang/test/Lower/pre-fir-tree05.f90 b/flang/test/Lower/pre-fir-tree05.f90 index 3acc38b..fb57663 100644 --- a/flang/test/Lower/pre-fir-tree05.f90 +++ b/flang/test/Lower/pre-fir-tree05.f90 @@ -1,4 +1,4 @@ -! RUN: %f18 -fdebug-pre-fir-tree -fsyntax-only -fopenacc %s | FileCheck %s +! RUN: %flang_fc1 -fsyntax-only -fdebug-pre-fir-tree -fopenacc %s | FileCheck %s ! Test structure of the Pre-FIR tree with OpenACC construct |