//===--- ParserActions.cpp ------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ // //===----------------------------------------------------------------------===// #include "flang/Frontend/ParserActions.h" #include "flang/Frontend/CompilerInstance.h" #include "flang/Lower/Bridge.h" #include "flang/Lower/PFTBuilder.h" #include "flang/Parser/dump-parse-tree.h" #include "flang/Parser/parsing.h" #include "flang/Parser/provenance.h" #include "flang/Parser/source.h" #include "flang/Parser/unparse.h" #include "flang/Semantics/unparse-with-symbols.h" #include "llvm/Support/raw_ostream.h" namespace Fortran::frontend { parser::AllCookedSources &getAllCooked(CompilerInstance &ci) { return ci.getParsing().allCooked(); } void parseAndLowerTree(CompilerInstance &ci, lower::LoweringBridge &lb) { parser::Program &parseTree{*ci.getParsing().parseTree()}; lb.lower(parseTree, ci.getSemanticsContext()); } void dumpTree(CompilerInstance &ci) { auto &parseTree{ci.getParsing().parseTree()}; llvm::outs() << "========================"; llvm::outs() << " Flang: parse tree dump "; llvm::outs() << "========================\n"; parser::DumpTree(llvm::outs(), parseTree, &ci.getInvocation().getAsFortran()); } void dumpProvenance(CompilerInstance &ci) { ci.getParsing().DumpProvenance(llvm::outs()); } void dumpPreFIRTree(CompilerInstance &ci) { auto &parseTree{*ci.getParsing().parseTree()}; if (auto ast{lower::createPFT(parseTree, ci.getSemanticsContext())}) { lower::dumpPFT(llvm::outs(), *ast); } else { unsigned diagID = ci.getDiagnostics().getCustomDiagID( clang::DiagnosticsEngine::Error, "Pre FIR Tree is NULL."); ci.getDiagnostics().Report(diagID); } } void formatOrDumpPrescanner(std::string &buf, llvm::raw_string_ostream &outForPP, CompilerInstance &ci) { if (ci.getInvocation().getPreprocessorOpts().showMacros) { ci.getParsing().EmitPreprocessorMacros(outForPP); } else if (ci.getInvocation().getPreprocessorOpts().noReformat) { ci.getParsing().DumpCookedChars(outForPP); } else { ci.getParsing().EmitPreprocessedSource( outForPP, !ci.getInvocation().getPreprocessorOpts().noLineDirectives); } // Print getDiagnostics from the prescanner ci.getParsing().messages().Emit(llvm::errs(), ci.getAllCookedSources()); } struct MeasurementVisitor { template bool Pre(const A &) { return true; } template void Post(const A &) { ++objects; bytes += sizeof(A); } size_t objects{0}, bytes{0}; }; void debugMeasureParseTree(CompilerInstance &ci, llvm::StringRef filename) { // Parse. In case of failure, report and return. ci.getParsing().Parse(llvm::outs()); if ((ci.getParsing().parseTree().has_value() && !ci.getParsing().consumedWholeFile()) || (!ci.getParsing().messages().empty() && (ci.getInvocation().getWarnAsErr() || ci.getParsing().messages().AnyFatalError()))) { unsigned diagID = ci.getDiagnostics().getCustomDiagID( clang::DiagnosticsEngine::Error, "Could not parse %0"); ci.getDiagnostics().Report(diagID) << filename; ci.getParsing().messages().Emit(llvm::errs(), ci.getAllCookedSources()); return; } // Report the getDiagnostics from parsing ci.getParsing().messages().Emit(llvm::errs(), ci.getAllCookedSources()); auto &parseTree{ci.getParsing().parseTree()}; MeasurementVisitor visitor; parser::Walk(parseTree, visitor); llvm::outs() << "Parse tree comprises " << visitor.objects << " objects and occupies " << visitor.bytes << " total bytes.\n"; } void debugUnparseNoSema(CompilerInstance &ci, llvm::raw_ostream &out) { auto &invoc = ci.getInvocation(); auto &parseTree{ci.getParsing().parseTree()}; // TODO: Options should come from CompilerInvocation Unparse(out, *parseTree, ci.getInvocation().getLangOpts(), /*encoding=*/parser::Encoding::UTF_8, /*capitalizeKeywords=*/true, /*backslashEscapes=*/false, /*preStatement=*/nullptr, invoc.getUseAnalyzedObjectsForUnparse() ? &invoc.getAsFortran() : nullptr); } void debugUnparseWithSymbols(CompilerInstance &ci) { auto &parseTree{*ci.getParsing().parseTree()}; semantics::UnparseWithSymbols(llvm::outs(), parseTree, ci.getInvocation().getLangOpts(), /*encoding=*/parser::Encoding::UTF_8); } void debugUnparseWithModules(CompilerInstance &ci) { auto &parseTree{*ci.getParsing().parseTree()}; semantics::UnparseWithModules(llvm::outs(), ci.getSemantics().context(), parseTree, /*encoding=*/parser::Encoding::UTF_8); } void debugDumpParsingLog(CompilerInstance &ci) { ci.getParsing().Parse(llvm::errs()); ci.getParsing().DumpParsingLog(llvm::outs()); } } // namespace Fortran::frontend