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