1 //===--- FrontendActions.cpp ----------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "flang/Frontend/FrontendActions.h"
10 #include "flang/Common/default-kinds.h"
11 #include "flang/Frontend/CompilerInstance.h"
12 #include "flang/Frontend/FrontendOptions.h"
13 #include "flang/Frontend/PreprocessorOptions.h"
14 #include "flang/Lower/Bridge.h"
15 #include "flang/Lower/PFTBuilder.h"
16 #include "flang/Lower/Support/Verifier.h"
17 #include "flang/Optimizer/Support/FIRContext.h"
18 #include "flang/Optimizer/Support/InitFIR.h"
19 #include "flang/Optimizer/Support/KindMapping.h"
20 #include "flang/Optimizer/Support/Utils.h"
21 #include "flang/Parser/dump-parse-tree.h"
22 #include "flang/Parser/parsing.h"
23 #include "flang/Parser/provenance.h"
24 #include "flang/Parser/source.h"
25 #include "flang/Parser/unparse.h"
26 #include "flang/Semantics/runtime-type-info.h"
27 #include "flang/Semantics/semantics.h"
28 #include "flang/Semantics/unparse-with-symbols.h"
29 
30 #include "mlir/IR/Dialect.h"
31 #include "mlir/Pass/PassManager.h"
32 #include "mlir/Target/LLVMIR/ModuleTranslation.h"
33 #include "llvm/ADT/StringRef.h"
34 #include "llvm/Analysis/TargetLibraryInfo.h"
35 #include "llvm/Analysis/TargetTransformInfo.h"
36 #include "llvm/Bitcode/BitcodeWriterPass.h"
37 #include "llvm/IR/LegacyPassManager.h"
38 #include "llvm/MC/TargetRegistry.h"
39 #include "llvm/Passes/PassBuilder.h"
40 #include "llvm/Support/ErrorHandling.h"
41 #include "llvm/Target/TargetMachine.h"
42 #include <clang/Basic/Diagnostic.h>
43 #include <memory>
44 
45 using namespace Fortran::frontend;
46 
47 //===----------------------------------------------------------------------===//
48 // Custom BeginSourceFileAction
49 //===----------------------------------------------------------------------===//
50 bool PrescanAction::BeginSourceFileAction() { return RunPrescan(); }
51 
52 bool PrescanAndParseAction::BeginSourceFileAction() {
53   return RunPrescan() && RunParse();
54 }
55 
56 bool PrescanAndSemaAction::BeginSourceFileAction() {
57   return RunPrescan() && RunParse() && RunSemanticChecks() &&
58       GenerateRtTypeTables();
59 }
60 
61 bool PrescanAndSemaDebugAction::BeginSourceFileAction() {
62   // This is a "debug" action for development purposes. To facilitate this, the
63   // semantic checks are made to succeed unconditionally to prevent this action
64   // from exiting early (i.e. in the presence of semantic errors). We should
65   // never do this in actions intended for end-users or otherwise regular
66   // compiler workflows!
67   return RunPrescan() && RunParse() && (RunSemanticChecks() || true) &&
68       (GenerateRtTypeTables() || true);
69 }
70 
71 bool CodeGenAction::BeginSourceFileAction() {
72   bool res = RunPrescan() && RunParse() && RunSemanticChecks();
73   if (!res)
74     return res;
75 
76   CompilerInstance &ci = this->instance();
77 
78   // Load the MLIR dialects required by Flang
79   mlir::DialectRegistry registry;
80   mlirCtx = std::make_unique<mlir::MLIRContext>(registry);
81   fir::support::registerNonCodegenDialects(registry);
82   fir::support::loadNonCodegenDialects(*mlirCtx);
83 
84   // Create a LoweringBridge
85   const common::IntrinsicTypeDefaultKinds &defKinds =
86       ci.invocation().semanticsContext().defaultKinds();
87   fir::KindMapping kindMap(mlirCtx.get(),
88       llvm::ArrayRef<fir::KindTy>{fir::fromDefaultKinds(defKinds)});
89   lower::LoweringBridge lb = Fortran::lower::LoweringBridge::create(*mlirCtx,
90       defKinds, ci.invocation().semanticsContext().intrinsics(),
91       ci.parsing().allCooked(), ci.invocation().targetOpts().triple, kindMap);
92 
93   // Create a parse tree and lower it to FIR
94   Fortran::parser::Program &parseTree{*ci.parsing().parseTree()};
95   lb.lower(parseTree, ci.invocation().semanticsContext());
96   mlirModule = std::make_unique<mlir::ModuleOp>(lb.getModule());
97 
98   // Run the default passes.
99   mlir::PassManager pm(mlirCtx.get(), mlir::OpPassManager::Nesting::Implicit);
100   pm.enableVerifier(/*verifyPasses=*/true);
101   pm.addPass(std::make_unique<Fortran::lower::VerifierPass>());
102 
103   if (mlir::failed(pm.run(*mlirModule))) {
104     unsigned diagID =
105         ci.diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error,
106             "verification of lowering to FIR failed");
107     ci.diagnostics().Report(diagID);
108     return false;
109   }
110 
111   return true;
112 }
113 
114 //===----------------------------------------------------------------------===//
115 // Custom ExecuteAction
116 //===----------------------------------------------------------------------===//
117 void InputOutputTestAction::ExecuteAction() {
118   CompilerInstance &ci = instance();
119 
120   // Create a stream for errors
121   std::string buf;
122   llvm::raw_string_ostream error_stream{buf};
123 
124   // Read the input file
125   Fortran::parser::AllSources &allSources{ci.allSources()};
126   std::string path{GetCurrentFileOrBufferName()};
127   const Fortran::parser::SourceFile *sf;
128   if (path == "-")
129     sf = allSources.ReadStandardInput(error_stream);
130   else
131     sf = allSources.Open(path, error_stream, std::optional<std::string>{"."s});
132   llvm::ArrayRef<char> fileContent = sf->content();
133 
134   // Output file descriptor to receive the contents of the input file.
135   std::unique_ptr<llvm::raw_ostream> os;
136 
137   // Copy the contents from the input file to the output file
138   if (!ci.IsOutputStreamNull()) {
139     // An output stream (outputStream_) was set earlier
140     ci.WriteOutputStream(fileContent.data());
141   } else {
142     // No pre-set output stream - create an output file
143     os = ci.CreateDefaultOutputFile(
144         /*binary=*/true, GetCurrentFileOrBufferName(), "txt");
145     if (!os)
146       return;
147     (*os) << fileContent.data();
148   }
149 }
150 
151 void PrintPreprocessedAction::ExecuteAction() {
152   std::string buf;
153   llvm::raw_string_ostream outForPP{buf};
154 
155   // Format or dump the prescanner's output
156   CompilerInstance &ci = this->instance();
157   if (ci.invocation().preprocessorOpts().noReformat) {
158     ci.parsing().DumpCookedChars(outForPP);
159   } else {
160     ci.parsing().EmitPreprocessedSource(
161         outForPP, !ci.invocation().preprocessorOpts().noLineDirectives);
162   }
163 
164   // Print diagnostics from the prescanner
165   ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources());
166 
167   // If a pre-defined output stream exists, dump the preprocessed content there
168   if (!ci.IsOutputStreamNull()) {
169     // Send the output to the pre-defined output buffer.
170     ci.WriteOutputStream(outForPP.str());
171     return;
172   }
173 
174   // Create a file and save the preprocessed output there
175   std::unique_ptr<llvm::raw_pwrite_stream> os{ci.CreateDefaultOutputFile(
176       /*Binary=*/true, /*InFile=*/GetCurrentFileOrBufferName())};
177   if (!os) {
178     return;
179   }
180 
181   (*os) << outForPP.str();
182 }
183 
184 void DebugDumpProvenanceAction::ExecuteAction() {
185   this->instance().parsing().DumpProvenance(llvm::outs());
186 }
187 
188 void ParseSyntaxOnlyAction::ExecuteAction() {
189 }
190 
191 void DebugUnparseNoSemaAction::ExecuteAction() {
192   auto &invoc = this->instance().invocation();
193   auto &parseTree{instance().parsing().parseTree()};
194 
195   // TODO: Options should come from CompilerInvocation
196   Unparse(llvm::outs(), *parseTree,
197       /*encoding=*/Fortran::parser::Encoding::UTF_8,
198       /*capitalizeKeywords=*/true, /*backslashEscapes=*/false,
199       /*preStatement=*/nullptr,
200       invoc.useAnalyzedObjectsForUnparse() ? &invoc.asFortran() : nullptr);
201 }
202 
203 void DebugUnparseAction::ExecuteAction() {
204   auto &invoc = this->instance().invocation();
205   auto &parseTree{instance().parsing().parseTree()};
206 
207   CompilerInstance &ci = this->instance();
208   auto os{ci.CreateDefaultOutputFile(
209       /*Binary=*/false, /*InFile=*/GetCurrentFileOrBufferName())};
210 
211   // TODO: Options should come from CompilerInvocation
212   Unparse(*os, *parseTree,
213       /*encoding=*/Fortran::parser::Encoding::UTF_8,
214       /*capitalizeKeywords=*/true, /*backslashEscapes=*/false,
215       /*preStatement=*/nullptr,
216       invoc.useAnalyzedObjectsForUnparse() ? &invoc.asFortran() : nullptr);
217 
218   // Report fatal semantic errors
219   reportFatalSemanticErrors();
220 }
221 
222 void DebugUnparseWithSymbolsAction::ExecuteAction() {
223   auto &parseTree{*instance().parsing().parseTree()};
224 
225   Fortran::semantics::UnparseWithSymbols(
226       llvm::outs(), parseTree, /*encoding=*/Fortran::parser::Encoding::UTF_8);
227 
228   // Report fatal semantic errors
229   reportFatalSemanticErrors();
230 }
231 
232 void DebugDumpSymbolsAction::ExecuteAction() {
233   CompilerInstance &ci = this->instance();
234 
235   if (!ci.getRtTyTables().schemata) {
236     unsigned DiagID =
237         ci.diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error,
238             "could not find module file for __fortran_type_info");
239     ci.diagnostics().Report(DiagID);
240     llvm::errs() << "\n";
241     return;
242   }
243 
244   // Dump symbols
245   ci.semantics().DumpSymbols(llvm::outs());
246 }
247 
248 void DebugDumpAllAction::ExecuteAction() {
249   CompilerInstance &ci = this->instance();
250 
251   // Dump parse tree
252   auto &parseTree{instance().parsing().parseTree()};
253   llvm::outs() << "========================";
254   llvm::outs() << " Flang: parse tree dump ";
255   llvm::outs() << "========================\n";
256   Fortran::parser::DumpTree(
257       llvm::outs(), parseTree, &ci.invocation().asFortran());
258 
259   if (!ci.getRtTyTables().schemata) {
260     unsigned DiagID =
261         ci.diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error,
262             "could not find module file for __fortran_type_info");
263     ci.diagnostics().Report(DiagID);
264     llvm::errs() << "\n";
265     return;
266   }
267 
268   // Dump symbols
269   llvm::outs() << "=====================";
270   llvm::outs() << " Flang: symbols dump ";
271   llvm::outs() << "=====================\n";
272   ci.semantics().DumpSymbols(llvm::outs());
273 }
274 
275 void DebugDumpParseTreeNoSemaAction::ExecuteAction() {
276   auto &parseTree{instance().parsing().parseTree()};
277 
278   // Dump parse tree
279   Fortran::parser::DumpTree(
280       llvm::outs(), parseTree, &this->instance().invocation().asFortran());
281 }
282 
283 void DebugDumpParseTreeAction::ExecuteAction() {
284   auto &parseTree{instance().parsing().parseTree()};
285 
286   // Dump parse tree
287   Fortran::parser::DumpTree(
288       llvm::outs(), parseTree, &this->instance().invocation().asFortran());
289 
290   // Report fatal semantic errors
291   reportFatalSemanticErrors();
292 }
293 
294 void DebugMeasureParseTreeAction::ExecuteAction() {
295   CompilerInstance &ci = this->instance();
296 
297   // Parse. In case of failure, report and return.
298   ci.parsing().Parse(llvm::outs());
299 
300   if (!ci.parsing().messages().empty() &&
301       (ci.invocation().warnAsErr() ||
302           ci.parsing().messages().AnyFatalError())) {
303     unsigned diagID = ci.diagnostics().getCustomDiagID(
304         clang::DiagnosticsEngine::Error, "Could not parse %0");
305     ci.diagnostics().Report(diagID) << GetCurrentFileOrBufferName();
306 
307     ci.parsing().messages().Emit(
308         llvm::errs(), this->instance().allCookedSources());
309     return;
310   }
311 
312   // Report the diagnostics from parsing
313   ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources());
314 
315   auto &parseTree{*ci.parsing().parseTree()};
316 
317   // Measure the parse tree
318   MeasurementVisitor visitor;
319   Fortran::parser::Walk(parseTree, visitor);
320   llvm::outs() << "Parse tree comprises " << visitor.objects
321                << " objects and occupies " << visitor.bytes
322                << " total bytes.\n";
323 }
324 
325 void DebugPreFIRTreeAction::ExecuteAction() {
326   CompilerInstance &ci = this->instance();
327   // Report and exit if fatal semantic errors are present
328   if (reportFatalSemanticErrors()) {
329     return;
330   }
331 
332   auto &parseTree{*ci.parsing().parseTree()};
333 
334   // Dump pre-FIR tree
335   if (auto ast{Fortran::lower::createPFT(
336           parseTree, ci.invocation().semanticsContext())}) {
337     Fortran::lower::dumpPFT(llvm::outs(), *ast);
338   } else {
339     unsigned diagID = ci.diagnostics().getCustomDiagID(
340         clang::DiagnosticsEngine::Error, "Pre FIR Tree is NULL.");
341     ci.diagnostics().Report(diagID);
342   }
343 }
344 
345 void DebugDumpParsingLogAction::ExecuteAction() {
346   CompilerInstance &ci = this->instance();
347 
348   ci.parsing().Parse(llvm::errs());
349   ci.parsing().DumpParsingLog(llvm::outs());
350 }
351 
352 void GetDefinitionAction::ExecuteAction() {
353   CompilerInstance &ci = this->instance();
354 
355   // Report and exit if fatal semantic errors are present
356   if (reportFatalSemanticErrors()) {
357     return;
358   }
359 
360   parser::AllCookedSources &cs = ci.allCookedSources();
361   unsigned diagID = ci.diagnostics().getCustomDiagID(
362       clang::DiagnosticsEngine::Error, "Symbol not found");
363 
364   auto gdv = ci.invocation().frontendOpts().getDefVals;
365   auto charBlock{cs.GetCharBlockFromLineAndColumns(
366       gdv.line, gdv.startColumn, gdv.endColumn)};
367   if (!charBlock) {
368     ci.diagnostics().Report(diagID);
369     return;
370   }
371 
372   llvm::outs() << "String range: >" << charBlock->ToString() << "<\n";
373 
374   auto *symbol{ci.invocation()
375                    .semanticsContext()
376                    .FindScope(*charBlock)
377                    .FindSymbol(*charBlock)};
378   if (!symbol) {
379     ci.diagnostics().Report(diagID);
380     return;
381   }
382 
383   llvm::outs() << "Found symbol name: " << symbol->name().ToString() << "\n";
384 
385   auto sourceInfo{cs.GetSourcePositionRange(symbol->name())};
386   if (!sourceInfo) {
387     llvm_unreachable(
388         "Failed to obtain SourcePosition."
389         "TODO: Please, write a test and replace this with a diagnostic!");
390     return;
391   }
392 
393   llvm::outs() << "Found symbol name: " << symbol->name().ToString() << "\n";
394   llvm::outs() << symbol->name().ToString() << ": "
395                << sourceInfo->first.file.path() << ", "
396                << sourceInfo->first.line << ", " << sourceInfo->first.column
397                << "-" << sourceInfo->second.column << "\n";
398 }
399 
400 void GetSymbolsSourcesAction::ExecuteAction() {
401   CompilerInstance &ci = this->instance();
402 
403   // Report and exit if fatal semantic errors are present
404   if (reportFatalSemanticErrors()) {
405     return;
406   }
407 
408   ci.semantics().DumpSymbolsSources(llvm::outs());
409 }
410 
411 #include "flang/Tools/CLOptions.inc"
412 
413 // Lower the previously generated MLIR module into an LLVM IR module
414 void CodeGenAction::GenerateLLVMIR() {
415   assert(mlirModule && "The MLIR module has not been generated yet.");
416 
417   CompilerInstance &ci = this->instance();
418 
419   fir::support::loadDialects(*mlirCtx);
420   fir::support::registerLLVMTranslation(*mlirCtx);
421 
422   // Set-up the MLIR pass manager
423   mlir::PassManager pm(mlirCtx.get(), mlir::OpPassManager::Nesting::Implicit);
424 
425   pm.addPass(std::make_unique<Fortran::lower::VerifierPass>());
426   pm.enableVerifier(/*verifyPasses=*/true);
427 
428   // Create the pass pipeline
429   fir::createMLIRToLLVMPassPipeline(pm);
430 
431   // Run the pass manager
432   if (!mlir::succeeded(pm.run(*mlirModule))) {
433     unsigned diagID = ci.diagnostics().getCustomDiagID(
434         clang::DiagnosticsEngine::Error, "Lowering to LLVM IR failed");
435     ci.diagnostics().Report(diagID);
436   }
437 
438   // Translate to LLVM IR
439   llvm::Optional<llvm::StringRef> moduleName = mlirModule->getName();
440   llvmCtx = std::make_unique<llvm::LLVMContext>();
441   llvmModule = mlir::translateModuleToLLVMIR(
442       *mlirModule, *llvmCtx, moduleName ? *moduleName : "FIRModule");
443 
444   if (!llvmModule) {
445     unsigned diagID = ci.diagnostics().getCustomDiagID(
446         clang::DiagnosticsEngine::Error, "failed to create the LLVM module");
447     ci.diagnostics().Report(diagID);
448     return;
449   }
450 }
451 
452 void EmitLLVMAction::ExecuteAction() {
453   CompilerInstance &ci = this->instance();
454   GenerateLLVMIR();
455 
456   // If set, use the predefined outupt stream to print the generated module.
457   if (!ci.IsOutputStreamNull()) {
458     llvmModule->print(
459         ci.GetOutputStream(), /*AssemblyAnnotationWriter=*/nullptr);
460     return;
461   }
462 
463   // No predefined output stream was set. Create an output file and dump the
464   // generated module there.
465   std::unique_ptr<llvm::raw_ostream> os = ci.CreateDefaultOutputFile(
466       /*Binary=*/false, /*InFile=*/GetCurrentFileOrBufferName(), "ll");
467   if (!os) {
468     unsigned diagID = ci.diagnostics().getCustomDiagID(
469         clang::DiagnosticsEngine::Error, "failed to create the output file");
470     ci.diagnostics().Report(diagID);
471     return;
472   }
473   llvmModule->print(*os, /*AssemblyAnnotationWriter=*/nullptr);
474 }
475 
476 void EmitLLVMBitcodeAction::ExecuteAction() {
477   CompilerInstance &ci = this->instance();
478   // Generate an LLVM module if it's not already present (it will already be
479   // present if the input file is an LLVM IR/BC file).
480   if (!llvmModule)
481     GenerateLLVMIR();
482 
483   // Create and configure `Target`
484   std::string error;
485   std::string theTriple = llvmModule->getTargetTriple();
486   const llvm::Target *theTarget =
487       llvm::TargetRegistry::lookupTarget(theTriple, error);
488   assert(theTarget && "Failed to create Target");
489 
490   // Create and configure `TargetMachine`
491   std::unique_ptr<llvm::TargetMachine> TM(
492       theTarget->createTargetMachine(theTriple, /*CPU=*/"",
493           /*Features=*/"", llvm::TargetOptions(), llvm::None));
494   assert(TM && "Failed to create TargetMachine");
495   llvmModule->setDataLayout(TM->createDataLayout());
496 
497   // Generate an output file
498   std::unique_ptr<llvm::raw_ostream> os = ci.CreateDefaultOutputFile(
499       /*Binary=*/true, /*InFile=*/GetCurrentFileOrBufferName(), "bc");
500   if (!os) {
501     unsigned diagID = ci.diagnostics().getCustomDiagID(
502         clang::DiagnosticsEngine::Error, "failed to create the output file");
503     ci.diagnostics().Report(diagID);
504     return;
505   }
506 
507   // Set-up the pass manager
508   llvm::ModulePassManager MPM;
509   llvm::ModuleAnalysisManager MAM;
510   llvm::PassBuilder PB(TM.get());
511   PB.registerModuleAnalyses(MAM);
512   MPM.addPass(llvm::BitcodeWriterPass(*os));
513 
514   // Run the passes
515   MPM.run(*llvmModule, MAM);
516 }
517 
518 void EmitMLIRAction::ExecuteAction() {
519   CompilerInstance &ci = this->instance();
520 
521   // Print the output. If a pre-defined output stream exists, dump the MLIR
522   // content there.
523   if (!ci.IsOutputStreamNull()) {
524     mlirModule->print(ci.GetOutputStream());
525     return;
526   }
527 
528   // ... otherwise, print to a file.
529   std::unique_ptr<llvm::raw_pwrite_stream> os{ci.CreateDefaultOutputFile(
530       /*Binary=*/true, /*InFile=*/GetCurrentFileOrBufferName(), "mlir")};
531   if (!os) {
532     unsigned diagID = ci.diagnostics().getCustomDiagID(
533         clang::DiagnosticsEngine::Error, "failed to create the output file");
534     ci.diagnostics().Report(diagID);
535     return;
536   }
537 
538   mlirModule->print(*os);
539 }
540 
541 void BackendAction::ExecuteAction() {
542   CompilerInstance &ci = this->instance();
543   // Generate an LLVM module if it's not already present (it will already be
544   // present if the input file is an LLVM IR/BC file).
545   if (!llvmModule)
546     GenerateLLVMIR();
547 
548   // Create `Target`
549   std::string error;
550   const std::string &theTriple = llvmModule->getTargetTriple();
551   const llvm::Target *theTarget =
552       llvm::TargetRegistry::lookupTarget(theTriple, error);
553   // TODO: Make this a diagnostic once `flang-new` can consume LLVM IR files
554   // (in which users could use unsupported triples)
555   assert(theTarget && "Failed to create Target");
556 
557   // Create `TargetMachine`
558   std::unique_ptr<llvm::TargetMachine> TM(
559       theTarget->createTargetMachine(theTriple, /*CPU=*/"",
560           /*Features=*/"", llvm::TargetOptions(), llvm::None));
561   assert(TM && "Failed to create TargetMachine");
562   llvmModule->setDataLayout(TM->createDataLayout());
563 
564   // If the output stream is a file, generate it and define the corresponding
565   // output stream. If a pre-defined output stream is available, we will use
566   // that instead.
567   //
568   // NOTE: `os` is a smart pointer that will be destroyed at the end of this
569   // method. However, it won't be written to until `CodeGenPasses` is
570   // destroyed. By defining `os` before `CodeGenPasses`, we make sure that the
571   // output stream won't be destroyed before it is written to. This only
572   // applies when an output file is used (i.e. there is no pre-defined output
573   // stream).
574   // TODO: Revisit once the new PM is ready (i.e. when `CodeGenPasses` is
575   // updated to use it).
576   std::unique_ptr<llvm::raw_pwrite_stream> os;
577   if (ci.IsOutputStreamNull()) {
578     // Get the output buffer/file
579     switch (action) {
580     case BackendActionTy::Backend_EmitAssembly:
581       os = ci.CreateDefaultOutputFile(
582           /*Binary=*/false, /*InFile=*/GetCurrentFileOrBufferName(), "s");
583       break;
584     case BackendActionTy::Backend_EmitObj:
585       os = ci.CreateDefaultOutputFile(
586           /*Binary=*/true, /*InFile=*/GetCurrentFileOrBufferName(), "o");
587       break;
588     }
589     if (!os) {
590       unsigned diagID = ci.diagnostics().getCustomDiagID(
591           clang::DiagnosticsEngine::Error, "failed to create the output file");
592       ci.diagnostics().Report(diagID);
593       return;
594     }
595   }
596 
597   // Create an LLVM code-gen pass pipeline. Currently only the legacy pass
598   // manager is supported.
599   // TODO: Switch to the new PM once it's available in the backend.
600   llvm::legacy::PassManager CodeGenPasses;
601   CodeGenPasses.add(
602       createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
603   llvm::Triple triple(theTriple);
604 
605   std::unique_ptr<llvm::TargetLibraryInfoImpl> TLII =
606       std::make_unique<llvm::TargetLibraryInfoImpl>(triple);
607   assert(TLII && "Failed to create TargetLibraryInfo");
608   CodeGenPasses.add(new llvm::TargetLibraryInfoWrapperPass(*TLII));
609 
610   llvm::CodeGenFileType cgft = (action == BackendActionTy::Backend_EmitAssembly)
611       ? llvm::CodeGenFileType::CGFT_AssemblyFile
612       : llvm::CodeGenFileType::CGFT_ObjectFile;
613   if (TM->addPassesToEmitFile(CodeGenPasses,
614           ci.IsOutputStreamNull() ? *os : ci.GetOutputStream(), nullptr,
615           cgft)) {
616     unsigned diagID =
617         ci.diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error,
618             "emission of this file type is not supported");
619     ci.diagnostics().Report(diagID);
620     return;
621   }
622 
623   // Run the code-gen passes
624   CodeGenPasses.run(*llvmModule);
625 }
626 
627 void InitOnlyAction::ExecuteAction() {
628   CompilerInstance &ci = this->instance();
629   unsigned DiagID =
630       ci.diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Warning,
631           "Use `-init-only` for testing purposes only");
632   ci.diagnostics().Report(DiagID);
633 }
634 
635 void PluginParseTreeAction::ExecuteAction() {}
636 
637 void DebugDumpPFTAction::ExecuteAction() {
638   CompilerInstance &ci = this->instance();
639 
640   if (auto ast = Fortran::lower::createPFT(
641           *ci.parsing().parseTree(), ci.semantics().context())) {
642     Fortran::lower::dumpPFT(llvm::outs(), *ast);
643     return;
644   }
645 
646   unsigned DiagID = ci.diagnostics().getCustomDiagID(
647       clang::DiagnosticsEngine::Error, "Pre FIR Tree is NULL.");
648   ci.diagnostics().Report(DiagID);
649 }
650