[flang][driver] Make `flang-new` always generate run-time type info

Currently, the driver generates the tables with "run-time type
information for derived types" only when specific actions are run.
However, the corresponding data might be required by the subsequent
compilation stages (e.g. lowering, code-gen) and should be generated
unconditionally. Note that this is only possible once the semantic
checks have been run.

Note that when generating these tables, extra semantic errors might be
generated. The driver will always report these and in most cases such
semantic errors will cause the driver to exit immediately. The only
exception are actions inheriting from `PrescanAndSemaDebugAction`.
Currently, there's only one such action: `DebugDumpAllAction`
(corresponds to `-fdebug-dump-all` command-line flag). I've updated the
comments for this action to clarify this.

This change will mostly affect lowering, which currently is only
available for most basic examples (e.g. empty programs). I wasn't able
to find a working case that would demonstrate the new behaviour. I
hope that this change is straightforward enough and am submitting it
without a test.

Differential Revision: https://reviews.llvm.org/D120051
This commit is contained in:
Andrzej Warzynski 2022-02-17 13:32:32 +00:00
parent 25d7b4fb44
commit 16a91a1cbe
5 changed files with 53 additions and 24 deletions

View File

@ -13,6 +13,7 @@
#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 "llvm/Support/raw_ostream.h"
@ -47,6 +48,8 @@ class CompilerInstance {
std::unique_ptr<Fortran::semantics::Semantics> semantics_;
std::unique_ptr<Fortran::semantics::RuntimeDerivedTypeTables> rtTyTables_;
/// The stream for diagnostics from Semantics
llvm::raw_ostream *semaOutputStream_ = &llvm::errs();
@ -129,6 +132,16 @@ public:
semantics_ = std::move(semantics);
}
void setRtTyTables(
std::unique_ptr<Fortran::semantics::RuntimeDerivedTypeTables> tables) {
rtTyTables_ = std::move(tables);
}
Fortran::semantics::RuntimeDerivedTypeTables &getRtTyTables() {
assert(rtTyTables_ && "Missing runtime derived type tables!");
return *rtTyTables_;
}
/// }
/// @name High-Level Operations
/// {

View File

@ -112,6 +112,10 @@ protected:
// Run semantic checks for the current input file. Return False if fatal
// errors are reported, True otherwise.
bool RunSemanticChecks();
// Generate run-time type information for derived types. This may lead to new
// semantic errors. Return False if fatal errors are reported, True
// otherwise.
bool GenerateRtTypeTables();
// Report fatal semantic errors. Return True if present, false otherwise.
bool reportFatalSemanticErrors();

View File

@ -133,7 +133,12 @@ class PluginParseTreeAction : public PrescanAndSemaAction {
// PrescanAndSemaDebug Actions
//
// These actions will parse the input, run the semantic checks and execute
// their actions regardless of whether any semantic errors are found.
// their actions _regardless of_ whether any semantic errors have been found.
// This can be useful when adding new languge feature and when you wish to
// investigate compiler output (e.g. the parse tree) despite any semantic
// errors.
//
// NOTE: Use with care and for development only!
//===----------------------------------------------------------------------===//
class PrescanAndSemaDebugAction : public FrontendAction {

View File

@ -180,6 +180,21 @@ bool FrontendAction::RunSemanticChecks() {
return true;
}
bool FrontendAction::GenerateRtTypeTables() {
instance().setRtTyTables(
std::make_unique<Fortran::semantics::RuntimeDerivedTypeTables>(
BuildRuntimeDerivedTypeTables(
instance().invocation().semanticsContext())));
// The runtime derived type information table builder may find additional
// semantic errors. Report them.
if (reportFatalSemanticErrors()) {
return false;
}
return true;
}
template <unsigned N>
bool FrontendAction::reportFatalErrors(const char (&message)[N]) {
if (!instance_->parsing().messages().empty() &&

View File

@ -47,12 +47,18 @@ bool PrescanAndParseAction::BeginSourceFileAction() {
}
bool PrescanAndSemaAction::BeginSourceFileAction() {
return RunPrescan() && RunParse() && RunSemanticChecks();
return RunPrescan() && RunParse() && RunSemanticChecks() &&
GenerateRtTypeTables();
}
bool PrescanAndSemaDebugAction::BeginSourceFileAction() {
// Semantic checks are made to succeed unconditionally.
return RunPrescan() && RunParse() && (RunSemanticChecks() || true);
// This is a "debug" action for development purposes. To facilitate this, the
// semantic checks are made to succeed unconditionally to prevent this action
// from exiting early (i.e. in the presence of semantic errors). We should
// never do this in actions intended for end-users or otherwise regular
// compiler workflows!
return RunPrescan() && RunParse() && (RunSemanticChecks() || true) &&
(GenerateRtTypeTables() || true);
}
bool CodeGenAction::BeginSourceFileAction() {
@ -218,25 +224,18 @@ void DebugUnparseWithSymbolsAction::ExecuteAction() {
void DebugDumpSymbolsAction::ExecuteAction() {
CompilerInstance &ci = this->instance();
auto &semantics = ci.semantics();
auto tables{Fortran::semantics::BuildRuntimeDerivedTypeTables(
instance().invocation().semanticsContext())};
// The runtime derived type information table builder may find and report
// semantic errors. So it is important that we report them _after_
// BuildRuntimeDerivedTypeTables is run.
reportFatalSemanticErrors();
if (!tables.schemata) {
if (!ci.getRtTyTables().schemata) {
unsigned DiagID =
ci.diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error,
"could not find module file for __fortran_type_info");
ci.diagnostics().Report(DiagID);
llvm::errs() << "\n";
return;
}
// Dump symbols
semantics.DumpSymbols(llvm::outs());
ci.semantics().DumpSymbols(llvm::outs());
}
void DebugDumpAllAction::ExecuteAction() {
@ -250,27 +249,20 @@ void DebugDumpAllAction::ExecuteAction() {
Fortran::parser::DumpTree(
llvm::outs(), parseTree, &ci.invocation().asFortran());
auto &semantics = ci.semantics();
auto tables{Fortran::semantics::BuildRuntimeDerivedTypeTables(
instance().invocation().semanticsContext())};
// The runtime derived type information table builder may find and report
// semantic errors. So it is important that we report them _after_
// BuildRuntimeDerivedTypeTables is run.
reportFatalSemanticErrors();
if (!tables.schemata) {
if (!ci.getRtTyTables().schemata) {
unsigned DiagID =
ci.diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error,
"could not find module file for __fortran_type_info");
ci.diagnostics().Report(DiagID);
llvm::errs() << "\n";
return;
}
// Dump symbols
llvm::outs() << "=====================";
llvm::outs() << " Flang: symbols dump ";
llvm::outs() << "=====================\n";
semantics.DumpSymbols(llvm::outs());
ci.semantics().DumpSymbols(llvm::outs());
}
void DebugDumpParseTreeNoSemaAction::ExecuteAction() {