forked from OSchip/llvm-project
[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
This commit is contained in:
parent
8675ef100f
commit
e81b340117
|
@ -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>,
|
||||
|
|
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" ||
|
||||
|
|
Loading…
Reference in New Issue