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 mlir::applyPassManagerCLOptions(pm); 431 432 // Run the pass manager 433 if (!mlir::succeeded(pm.run(*mlirModule))) { 434 unsigned diagID = ci.diagnostics().getCustomDiagID( 435 clang::DiagnosticsEngine::Error, "Lowering to LLVM IR failed"); 436 ci.diagnostics().Report(diagID); 437 } 438 439 // Translate to LLVM IR 440 llvm::Optional<llvm::StringRef> moduleName = mlirModule->getName(); 441 llvmCtx = std::make_unique<llvm::LLVMContext>(); 442 llvmModule = mlir::translateModuleToLLVMIR( 443 *mlirModule, *llvmCtx, moduleName ? *moduleName : "FIRModule"); 444 445 if (!llvmModule) { 446 unsigned diagID = ci.diagnostics().getCustomDiagID( 447 clang::DiagnosticsEngine::Error, "failed to create the LLVM module"); 448 ci.diagnostics().Report(diagID); 449 return; 450 } 451 } 452 453 void EmitLLVMAction::ExecuteAction() { 454 CompilerInstance &ci = this->instance(); 455 GenerateLLVMIR(); 456 457 // If set, use the predefined outupt stream to print the generated module. 458 if (!ci.IsOutputStreamNull()) { 459 llvmModule->print( 460 ci.GetOutputStream(), /*AssemblyAnnotationWriter=*/nullptr); 461 return; 462 } 463 464 // No predefined output stream was set. Create an output file and dump the 465 // generated module there. 466 std::unique_ptr<llvm::raw_ostream> os = ci.CreateDefaultOutputFile( 467 /*Binary=*/false, /*InFile=*/GetCurrentFileOrBufferName(), "ll"); 468 if (!os) { 469 unsigned diagID = ci.diagnostics().getCustomDiagID( 470 clang::DiagnosticsEngine::Error, "failed to create the output file"); 471 ci.diagnostics().Report(diagID); 472 return; 473 } 474 llvmModule->print(*os, /*AssemblyAnnotationWriter=*/nullptr); 475 } 476 477 void EmitLLVMBitcodeAction::ExecuteAction() { 478 CompilerInstance &ci = this->instance(); 479 // Generate an LLVM module if it's not already present (it will already be 480 // present if the input file is an LLVM IR/BC file). 481 if (!llvmModule) 482 GenerateLLVMIR(); 483 484 // Create and configure `Target` 485 std::string error; 486 std::string theTriple = llvmModule->getTargetTriple(); 487 const llvm::Target *theTarget = 488 llvm::TargetRegistry::lookupTarget(theTriple, error); 489 assert(theTarget && "Failed to create Target"); 490 491 // Create and configure `TargetMachine` 492 std::unique_ptr<llvm::TargetMachine> TM( 493 theTarget->createTargetMachine(theTriple, /*CPU=*/"", 494 /*Features=*/"", llvm::TargetOptions(), llvm::None)); 495 assert(TM && "Failed to create TargetMachine"); 496 llvmModule->setDataLayout(TM->createDataLayout()); 497 498 // Generate an output file 499 std::unique_ptr<llvm::raw_ostream> os = ci.CreateDefaultOutputFile( 500 /*Binary=*/true, /*InFile=*/GetCurrentFileOrBufferName(), "bc"); 501 if (!os) { 502 unsigned diagID = ci.diagnostics().getCustomDiagID( 503 clang::DiagnosticsEngine::Error, "failed to create the output file"); 504 ci.diagnostics().Report(diagID); 505 return; 506 } 507 508 // Set-up the pass manager 509 llvm::ModulePassManager MPM; 510 llvm::ModuleAnalysisManager MAM; 511 llvm::PassBuilder PB(TM.get()); 512 PB.registerModuleAnalyses(MAM); 513 MPM.addPass(llvm::BitcodeWriterPass(*os)); 514 515 // Run the passes 516 MPM.run(*llvmModule, MAM); 517 } 518 519 void EmitMLIRAction::ExecuteAction() { 520 CompilerInstance &ci = this->instance(); 521 522 // Print the output. If a pre-defined output stream exists, dump the MLIR 523 // content there. 524 if (!ci.IsOutputStreamNull()) { 525 mlirModule->print(ci.GetOutputStream()); 526 return; 527 } 528 529 // ... otherwise, print to a file. 530 std::unique_ptr<llvm::raw_pwrite_stream> os{ci.CreateDefaultOutputFile( 531 /*Binary=*/true, /*InFile=*/GetCurrentFileOrBufferName(), "mlir")}; 532 if (!os) { 533 unsigned diagID = ci.diagnostics().getCustomDiagID( 534 clang::DiagnosticsEngine::Error, "failed to create the output file"); 535 ci.diagnostics().Report(diagID); 536 return; 537 } 538 539 mlirModule->print(*os); 540 } 541 542 void BackendAction::ExecuteAction() { 543 CompilerInstance &ci = this->instance(); 544 // Generate an LLVM module if it's not already present (it will already be 545 // present if the input file is an LLVM IR/BC file). 546 if (!llvmModule) 547 GenerateLLVMIR(); 548 549 // Create `Target` 550 std::string error; 551 const std::string &theTriple = llvmModule->getTargetTriple(); 552 const llvm::Target *theTarget = 553 llvm::TargetRegistry::lookupTarget(theTriple, error); 554 // TODO: Make this a diagnostic once `flang-new` can consume LLVM IR files 555 // (in which users could use unsupported triples) 556 assert(theTarget && "Failed to create Target"); 557 558 // Create `TargetMachine` 559 std::unique_ptr<llvm::TargetMachine> TM( 560 theTarget->createTargetMachine(theTriple, /*CPU=*/"", 561 /*Features=*/"", llvm::TargetOptions(), llvm::None)); 562 assert(TM && "Failed to create TargetMachine"); 563 llvmModule->setDataLayout(TM->createDataLayout()); 564 565 // If the output stream is a file, generate it and define the corresponding 566 // output stream. If a pre-defined output stream is available, we will use 567 // that instead. 568 // 569 // NOTE: `os` is a smart pointer that will be destroyed at the end of this 570 // method. However, it won't be written to until `CodeGenPasses` is 571 // destroyed. By defining `os` before `CodeGenPasses`, we make sure that the 572 // output stream won't be destroyed before it is written to. This only 573 // applies when an output file is used (i.e. there is no pre-defined output 574 // stream). 575 // TODO: Revisit once the new PM is ready (i.e. when `CodeGenPasses` is 576 // updated to use it). 577 std::unique_ptr<llvm::raw_pwrite_stream> os; 578 if (ci.IsOutputStreamNull()) { 579 // Get the output buffer/file 580 switch (action) { 581 case BackendActionTy::Backend_EmitAssembly: 582 os = ci.CreateDefaultOutputFile( 583 /*Binary=*/false, /*InFile=*/GetCurrentFileOrBufferName(), "s"); 584 break; 585 case BackendActionTy::Backend_EmitObj: 586 os = ci.CreateDefaultOutputFile( 587 /*Binary=*/true, /*InFile=*/GetCurrentFileOrBufferName(), "o"); 588 break; 589 } 590 if (!os) { 591 unsigned diagID = ci.diagnostics().getCustomDiagID( 592 clang::DiagnosticsEngine::Error, "failed to create the output file"); 593 ci.diagnostics().Report(diagID); 594 return; 595 } 596 } 597 598 // Create an LLVM code-gen pass pipeline. Currently only the legacy pass 599 // manager is supported. 600 // TODO: Switch to the new PM once it's available in the backend. 601 llvm::legacy::PassManager CodeGenPasses; 602 CodeGenPasses.add( 603 createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis())); 604 llvm::Triple triple(theTriple); 605 606 std::unique_ptr<llvm::TargetLibraryInfoImpl> TLII = 607 std::make_unique<llvm::TargetLibraryInfoImpl>(triple); 608 assert(TLII && "Failed to create TargetLibraryInfo"); 609 CodeGenPasses.add(new llvm::TargetLibraryInfoWrapperPass(*TLII)); 610 611 llvm::CodeGenFileType cgft = (action == BackendActionTy::Backend_EmitAssembly) 612 ? llvm::CodeGenFileType::CGFT_AssemblyFile 613 : llvm::CodeGenFileType::CGFT_ObjectFile; 614 if (TM->addPassesToEmitFile(CodeGenPasses, 615 ci.IsOutputStreamNull() ? *os : ci.GetOutputStream(), nullptr, 616 cgft)) { 617 unsigned diagID = 618 ci.diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, 619 "emission of this file type is not supported"); 620 ci.diagnostics().Report(diagID); 621 return; 622 } 623 624 // Run the code-gen passes 625 CodeGenPasses.run(*llvmModule); 626 } 627 628 void InitOnlyAction::ExecuteAction() { 629 CompilerInstance &ci = this->instance(); 630 unsigned DiagID = 631 ci.diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Warning, 632 "Use `-init-only` for testing purposes only"); 633 ci.diagnostics().Report(DiagID); 634 } 635 636 void PluginParseTreeAction::ExecuteAction() {} 637 638 void DebugDumpPFTAction::ExecuteAction() { 639 CompilerInstance &ci = this->instance(); 640 641 if (auto ast = Fortran::lower::createPFT( 642 *ci.parsing().parseTree(), ci.semantics().context())) { 643 Fortran::lower::dumpPFT(llvm::outs(), *ast); 644 return; 645 } 646 647 unsigned DiagID = ci.diagnostics().getCustomDiagID( 648 clang::DiagnosticsEngine::Error, "Pre FIR Tree is NULL."); 649 ci.diagnostics().Report(DiagID); 650 } 651 652 Fortran::parser::Parsing &PluginParseTreeAction::getParsing() { 653 return instance().parsing(); 654 } 655 656 std::unique_ptr<llvm::raw_pwrite_stream> 657 PluginParseTreeAction::createOutputFile(llvm::StringRef extension = "") { 658 659 std::unique_ptr<llvm::raw_pwrite_stream> OS{ 660 instance().CreateDefaultOutputFile( 661 /*Binary=*/false, /*InFile=*/GetCurrentFileOrBufferName(), 662 extension)}; 663 return OS; 664 } 665