brintos

brintos / llvm-project-archived public Read only

0
0
Text · 27.1 KiB · 8b12da3 Raw
678 lines · cpp
1//===- bbc.cpp - Burnside Bridge Compiler -----------------------*- C++ -*-===//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-exception6//7//===----------------------------------------------------------------------===//8//9// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/10//11//===----------------------------------------------------------------------===//12///13/// This is a tool for translating Fortran sources to the FIR dialect of MLIR.14///15//===----------------------------------------------------------------------===//16 17#include "flang/Frontend/CodeGenOptions.h"18#include "flang/Frontend/TargetOptions.h"19#include "flang/Lower/Bridge.h"20#include "flang/Lower/PFTBuilder.h"21#include "flang/Lower/Support/Verifier.h"22#include "flang/Optimizer/Dialect/Support/FIRContext.h"23#include "flang/Optimizer/Dialect/Support/KindMapping.h"24#include "flang/Optimizer/Support/InitFIR.h"25#include "flang/Optimizer/Support/InternalNames.h"26#include "flang/Optimizer/Support/Utils.h"27#include "flang/Optimizer/Transforms/Passes.h"28#include "flang/Parser/characters.h"29#include "flang/Parser/dump-parse-tree.h"30#include "flang/Parser/message.h"31#include "flang/Parser/parse-tree-visitor.h"32#include "flang/Parser/parse-tree.h"33#include "flang/Parser/parsing.h"34#include "flang/Parser/provenance.h"35#include "flang/Parser/unparse.h"36#include "flang/Semantics/expression.h"37#include "flang/Semantics/runtime-type-info.h"38#include "flang/Semantics/semantics.h"39#include "flang/Semantics/unparse-with-symbols.h"40#include "flang/Support/Fortran-features.h"41#include "flang/Support/LangOptions.h"42#include "flang/Support/OpenMP-features.h"43#include "flang/Support/Version.h"44#include "flang/Support/default-kinds.h"45#include "flang/Tools/CrossToolHelpers.h"46#include "flang/Tools/TargetSetup.h"47#include "flang/Version.inc"48#include "mlir/Dialect/OpenMP/OpenMPDialect.h"49#include "mlir/IR/AsmState.h"50#include "mlir/IR/BuiltinOps.h"51#include "mlir/IR/MLIRContext.h"52#include "mlir/Parser/Parser.h"53#include "mlir/Pass/Pass.h"54#include "mlir/Pass/PassManager.h"55#include "mlir/Pass/PassRegistry.h"56#include "mlir/Transforms/GreedyPatternRewriteDriver.h"57#include "mlir/Transforms/Passes.h"58#include "llvm/MC/TargetRegistry.h"59#include "llvm/Passes/OptimizationLevel.h"60#include "llvm/Support/CommandLine.h"61#include "llvm/Support/ErrorOr.h"62#include "llvm/Support/FileSystem.h"63#include "llvm/Support/InitLLVM.h"64#include "llvm/Support/MemoryBuffer.h"65#include "llvm/Support/Path.h"66#include "llvm/Support/SourceMgr.h"67#include "llvm/Support/TargetSelect.h"68#include "llvm/Support/ToolOutputFile.h"69#include "llvm/Support/raw_ostream.h"70#include "llvm/TargetParser/Host.h"71#include "llvm/TargetParser/Triple.h"72#include <memory>73 74//===----------------------------------------------------------------------===//75// Some basic command-line options76//===----------------------------------------------------------------------===//77 78static llvm::cl::opt<std::string> inputFilename(llvm::cl::Positional,79                                                llvm::cl::Required,80                                                llvm::cl::desc("<input file>"));81 82static llvm::cl::opt<std::string>83    outputFilename("o", llvm::cl::desc("Specify the output filename"),84                   llvm::cl::value_desc("filename"));85 86static llvm::cl::list<std::string>87    includeDirs("I", llvm::cl::desc("include module search paths"));88 89static llvm::cl::alias includeAlias("module-directory",90                                    llvm::cl::desc("module search directory"),91                                    llvm::cl::aliasopt(includeDirs));92 93static llvm::cl::list<std::string>94    intrinsicIncludeDirs("J", llvm::cl::desc("intrinsic module search paths"));95 96static llvm::cl::alias97    intrinsicIncludeAlias("intrinsic-module-directory",98                          llvm::cl::desc("intrinsic module directory"),99                          llvm::cl::aliasopt(intrinsicIncludeDirs));100 101static llvm::cl::opt<std::string>102    moduleDir("module", llvm::cl::desc("module output directory (default .)"),103              llvm::cl::init("."));104 105static llvm::cl::opt<std::string>106    moduleSuffix("module-suffix", llvm::cl::desc("module file suffix override"),107                 llvm::cl::init(".mod"));108 109static llvm::cl::opt<bool>110    emitFIR("emit-fir",111            llvm::cl::desc("Dump the FIR created by lowering and exit"),112            llvm::cl::init(false));113 114static llvm::cl::opt<bool>115    emitHLFIR("emit-hlfir",116              llvm::cl::desc("Dump the HLFIR created by lowering and exit"),117              llvm::cl::init(false));118 119static llvm::cl::opt<bool> warnStdViolation("Mstandard",120                                            llvm::cl::desc("emit warnings"),121                                            llvm::cl::init(false));122 123static llvm::cl::opt<bool> warnIsError("Werror",124                                       llvm::cl::desc("warnings are errors"),125                                       llvm::cl::init(false));126 127static llvm::cl::opt<bool> dumpSymbols("dump-symbols",128                                       llvm::cl::desc("dump the symbol table"),129                                       llvm::cl::init(false));130 131static llvm::cl::opt<bool> pftDumpTest(132    "pft-test",133    llvm::cl::desc("parse the input, create a PFT, dump it, and exit"),134    llvm::cl::init(false));135 136static llvm::cl::opt<bool> enableOpenMP("fopenmp",137                                        llvm::cl::desc("enable openmp"),138                                        llvm::cl::init(false));139 140static llvm::cl::opt<bool>141    enableOpenMPDevice("fopenmp-is-target-device",142                       llvm::cl::desc("enable openmp device compilation"),143                       llvm::cl::init(false));144 145static llvm::cl::opt<std::string> enableDoConcurrentToOpenMPConversion(146    "fdo-concurrent-to-openmp",147    llvm::cl::desc(148        "Try to map `do concurrent` loops to OpenMP [none|host|device]"),149    llvm::cl::init("none"));150 151static llvm::cl::opt<bool>152    enableOpenMPGPU("fopenmp-is-gpu",153                    llvm::cl::desc("enable openmp GPU target codegen"),154                    llvm::cl::init(false));155 156static llvm::cl::opt<bool> enableOpenMPForceUSM(157    "fopenmp-force-usm",158    llvm::cl::desc("force openmp unified shared memory mode"),159    llvm::cl::init(false));160 161static llvm::cl::list<std::string> targetTriplesOpenMP(162    "fopenmp-targets",163    llvm::cl::desc("comma-separated list of OpenMP offloading triples"),164    llvm::cl::CommaSeparated);165 166// A simplified subset of the OpenMP RTL Flags from Flang, only the primary167// positive options are available, no negative options e.g. fopen_assume* vs168// fno_open_assume*169static llvm::cl::opt<uint32_t>170    setOpenMPVersion("fopenmp-version",171                     llvm::cl::desc("OpenMP standard version"),172                     llvm::cl::init(31));173 174static llvm::cl::opt<uint32_t> setOpenMPTargetDebug(175    "fopenmp-target-debug",176    llvm::cl::desc("Enable debugging in the OpenMP offloading device RTL"),177    llvm::cl::init(0));178 179static llvm::cl::opt<bool> setOpenMPThreadSubscription(180    "fopenmp-assume-threads-oversubscription",181    llvm::cl::desc("Assume work-shared loops do not have more "182                   "iterations than participating threads."),183    llvm::cl::init(false));184 185static llvm::cl::opt<bool> setOpenMPTeamSubscription(186    "fopenmp-assume-teams-oversubscription",187    llvm::cl::desc("Assume distributed loops do not have more iterations than "188                   "participating teams."),189    llvm::cl::init(false));190 191static llvm::cl::opt<bool> setOpenMPNoThreadState(192    "fopenmp-assume-no-thread-state",193    llvm::cl::desc(194        "Assume that no thread in a parallel region will modify an ICV."),195    llvm::cl::init(false));196 197static llvm::cl::opt<bool> setOpenMPNoNestedParallelism(198    "fopenmp-assume-no-nested-parallelism",199    llvm::cl::desc("Assume that no thread in a parallel region will encounter "200                   "a parallel region."),201    llvm::cl::init(false));202 203static llvm::cl::opt<bool>204    setNoGPULib("nogpulib",205                llvm::cl::desc("Do not link device library for CUDA/HIP device "206                               "compilation"),207                llvm::cl::init(false));208 209static llvm::cl::opt<bool> enableOpenACC("fopenacc",210                                         llvm::cl::desc("enable openacc"),211                                         llvm::cl::init(false));212 213static llvm::cl::opt<bool> enableNoPPCNativeVecElemOrder(214    "fno-ppc-native-vector-element-order",215    llvm::cl::desc("no PowerPC native vector element order."),216    llvm::cl::init(false));217 218static llvm::cl::opt<bool> useHLFIR("hlfir",219                                    llvm::cl::desc("Lower to high level FIR"),220                                    llvm::cl::init(true));221 222static llvm::cl::opt<bool> enableCUDA("fcuda",223                                      llvm::cl::desc("enable CUDA Fortran"),224                                      llvm::cl::init(false));225 226static llvm::cl::opt<bool>227    enableDoConcurrentOffload("fdoconcurrent-offload",228                              llvm::cl::desc("enable do concurrent offload"),229                              llvm::cl::init(false));230 231static llvm::cl::opt<bool>232    disableCUDAWarpFunction("fcuda-disable-warp-function",233                            llvm::cl::desc("Disable CUDA Warp Function"),234                            llvm::cl::init(false));235 236static llvm::cl::opt<std::string>237    enableGPUMode("gpu", llvm::cl::desc("Enable GPU Mode managed|unified"),238                  llvm::cl::init(""));239 240static llvm::cl::opt<bool> fixedForm("ffixed-form",241                                     llvm::cl::desc("enable fixed form"),242                                     llvm::cl::init(false));243static llvm::cl::opt<std::string>244    targetTripleOverride("target",245                         llvm::cl::desc("Override host target triple"),246                         llvm::cl::init(""));247 248static llvm::cl::opt<bool> integerWrapAround(249    "fwrapv",250    llvm::cl::desc("Treat signed integer overflow as two's complement"),251    llvm::cl::init(false));252 253static llvm::cl::opt<bool> initGlobalZero(254    "finit-global-zero",255    llvm::cl::desc("Zero initialize globals without default initialization"),256    llvm::cl::init(true));257 258static llvm::cl::opt<bool>259    reallocateLHS("frealloc-lhs",260                  llvm::cl::desc("Follow Fortran 2003 rules for (re)allocating "261                                 "the LHS of the intrinsic assignment"),262                  llvm::cl::init(true));263 264static llvm::cl::opt<bool> stackRepackArrays(265    "fstack-repack-arrays",266    llvm::cl::desc("Allocate temporary arrays for -frepack-arrays "267                   "in stack memory"),268    llvm::cl::init(false));269 270static llvm::cl::opt<bool>271    repackArrays("frepack-arrays",272                 llvm::cl::desc("Pack non-contiguous assummed shape arrays "273                                "into contiguous memory"),274                 llvm::cl::init(false));275 276static llvm::cl::opt<bool>277    repackArraysWhole("frepack-arrays-continuity-whole",278                      llvm::cl::desc("Repack arrays that are non-contiguous "279                                     "in any dimension. If set to false, "280                                     "only the arrays non-contiguous in the "281                                     "leading dimension will be repacked"),282                      llvm::cl::init(true));283 284static llvm::cl::opt<std::string> complexRange(285    "complex-range",286    llvm::cl::desc("Controls the various implementations for complex "287                   "multiplication and division [full|improved|basic]"),288    llvm::cl::init(""));289 290#define FLANG_EXCLUDE_CODEGEN291#include "flang/Optimizer/Passes/CommandLineOpts.h"292#include "flang/Optimizer/Passes/Pipelines.h"293 294//===----------------------------------------------------------------------===//295 296using ProgramName = std::string;297 298// Print the module with the "module { ... }" wrapper, preventing299// information loss from attribute information appended to the module300static void printModule(mlir::ModuleOp mlirModule, llvm::raw_ostream &out) {301  out << mlirModule << '\n';302}303 304static void registerAllPasses() {305  fir::support::registerMLIRPassesForFortranTools();306  fir::registerOptTransformPasses();307}308 309/// Create a target machine that is at least sufficient to get data-layout310/// information required by flang semantics and lowering. Note that it may not311/// contain all the CPU feature information to get optimized assembly generation312/// from LLVM IR. Drivers that needs to generate assembly from LLVM IR should313/// create a target machine according to their specific options.314static std::unique_ptr<llvm::TargetMachine>315createTargetMachine(llvm::StringRef targetTriple, std::string &error) {316  std::string triple{targetTriple};317  if (triple.empty())318    triple = llvm::sys::getDefaultTargetTriple();319  llvm::Triple parsedTriple(triple);320 321  const llvm::Target *theTarget =322      llvm::TargetRegistry::lookupTarget(parsedTriple, error);323  if (!theTarget)324    return nullptr;325  return std::unique_ptr<llvm::TargetMachine>{326      theTarget->createTargetMachine(parsedTriple, /*CPU=*/"",327                                     /*Features=*/"", llvm::TargetOptions(),328                                     /*Reloc::Model=*/std::nullopt)};329}330 331/// Build and execute the OpenMPFIRPassPipeline with its own instance332/// of the pass manager, allowing it to be invoked as soon as it's333/// required without impacting the main pass pipeline that may be invoked334/// more than once for verification.335static llvm::LogicalResult runOpenMPPasses(mlir::ModuleOp mlirModule) {336  mlir::PassManager pm(mlirModule->getName(),337                       mlir::OpPassManager::Nesting::Implicit);338  using DoConcurrentMappingKind =339      Fortran::frontend::CodeGenOptions::DoConcurrentMappingKind;340 341  fir::OpenMPFIRPassPipelineOpts opts;342  opts.isTargetDevice = enableOpenMPDevice;343  opts.doConcurrentMappingKind =344      llvm::StringSwitch<DoConcurrentMappingKind>(345          enableDoConcurrentToOpenMPConversion)346          .Case("host", DoConcurrentMappingKind::DCMK_Host)347          .Case("device", DoConcurrentMappingKind::DCMK_Device)348          .Default(DoConcurrentMappingKind::DCMK_None);349 350  fir::createOpenMPFIRPassPipeline(pm, opts);351  (void)mlir::applyPassManagerCLOptions(pm);352  if (mlir::failed(pm.run(mlirModule))) {353    llvm::errs() << "FATAL: failed to correctly apply OpenMP pass pipeline";354    return mlir::failure();355  }356  return mlir::success();357}358 359//===----------------------------------------------------------------------===//360// Translate Fortran input to FIR, a dialect of MLIR.361//===----------------------------------------------------------------------===//362 363static llvm::LogicalResult convertFortranSourceToMLIR(364    std::string path, Fortran::parser::Options options,365    const ProgramName &programPrefix,366    Fortran::semantics::SemanticsContext &semanticsContext,367    const mlir::PassPipelineCLParser &passPipeline,368    const llvm::TargetMachine &targetMachine) {369 370  // prep for prescan and parse371  Fortran::parser::Parsing parsing{semanticsContext.allCookedSources()};372  parsing.Prescan(path, options);373  if (!parsing.messages().empty() && (parsing.messages().AnyFatalError())) {374    llvm::errs() << programPrefix << "could not scan " << path << '\n';375    parsing.messages().Emit(llvm::errs(), parsing.allCooked());376    return mlir::failure();377  }378 379  // parse the input Fortran380  parsing.Parse(llvm::outs());381  if (!parsing.consumedWholeFile()) {382    parsing.messages().Emit(llvm::errs(), parsing.allCooked());383    parsing.EmitMessage(llvm::errs(), parsing.finalRestingPlace(),384                        "parser FAIL (final position)",385                        "error: ", llvm::raw_ostream::RED);386    return mlir::failure();387  } else if ((!parsing.messages().empty() &&388              (parsing.messages().AnyFatalError())) ||389             !parsing.parseTree().has_value()) {390    parsing.messages().Emit(llvm::errs(), parsing.allCooked());391    llvm::errs() << programPrefix << "could not parse " << path << '\n';392    return mlir::failure();393  } else {394    semanticsContext.messages().Annex(std::move(parsing.messages()));395  }396 397  // run semantics398  auto &parseTree = *parsing.parseTree();399  Fortran::semantics::Semantics semantics(semanticsContext, parseTree);400  semantics.Perform();401  semantics.EmitMessages(llvm::errs());402  if (semantics.AnyFatalError()) {403    llvm::errs() << programPrefix << "semantic errors in " << path << '\n';404    return mlir::failure();405  }406  Fortran::semantics::RuntimeDerivedTypeTables tables;407  if (!semantics.AnyFatalError()) {408    tables =409        Fortran::semantics::BuildRuntimeDerivedTypeTables(semanticsContext);410    if (!tables.schemata)411      llvm::errs() << programPrefix412                   << "could not find module file for __fortran_type_info\n";413  }414 415  if (dumpSymbols) {416    semantics.DumpSymbols(llvm::outs());417    return mlir::success();418  }419 420  if (pftDumpTest) {421    if (auto ast = Fortran::lower::createPFT(parseTree, semanticsContext)) {422      Fortran::lower::dumpPFT(llvm::outs(), *ast);423      return mlir::success();424    }425    llvm::errs() << "Pre FIR Tree is NULL.\n";426    return mlir::failure();427  }428 429  // translate to FIR dialect of MLIR430  mlir::DialectRegistry registry;431  fir::support::registerNonCodegenDialects(registry);432  fir::support::addFIRExtensions(registry);433  mlir::MLIRContext ctx(registry);434  fir::support::loadNonCodegenDialects(ctx);435  auto &defKinds = semanticsContext.defaultKinds();436  fir::KindMapping kindMap(437      &ctx, llvm::ArrayRef<fir::KindTy>{fir::fromDefaultKinds(defKinds)});438  std::string targetTriple = targetMachine.getTargetTriple().normalize();439  // Use default lowering options for bbc.440  Fortran::lower::LoweringOptions loweringOptions{};441  loweringOptions.setNoPPCNativeVecElemOrder(enableNoPPCNativeVecElemOrder);442  loweringOptions.setLowerToHighLevelFIR(useHLFIR || emitHLFIR);443  loweringOptions.setIntegerWrapAround(integerWrapAround);444  loweringOptions.setInitGlobalZero(initGlobalZero);445  loweringOptions.setReallocateLHS(reallocateLHS);446  loweringOptions.setStackRepackArrays(stackRepackArrays);447  loweringOptions.setRepackArrays(repackArrays);448  loweringOptions.setRepackArraysWhole(repackArraysWhole);449  loweringOptions.setSkipExternalRttiDefinition(skipExternalRttiDefinition);450  if (enableCUDA)451    loweringOptions.setCUDARuntimeCheck(true);452  if (complexRange == "improved" || complexRange == "basic")453    loweringOptions.setComplexDivisionToRuntime(false);454  std::vector<Fortran::lower::EnvironmentDefault> envDefaults = {};455  Fortran::frontend::TargetOptions targetOpts;456  Fortran::frontend::CodeGenOptions cgOpts;457  auto burnside = Fortran::lower::LoweringBridge::create(458      ctx, semanticsContext, defKinds, semanticsContext.intrinsics(),459      semanticsContext.targetCharacteristics(), parsing.allCooked(),460      targetTriple, kindMap, loweringOptions, envDefaults,461      semanticsContext.languageFeatures(), targetMachine, targetOpts, cgOpts);462  mlir::ModuleOp mlirModule = burnside.getModule();463  if (enableOpenMP) {464    if (enableOpenMPGPU && !enableOpenMPDevice) {465      llvm::errs() << "FATAL: -fopenmp-is-gpu can only be set if "466                      "-fopenmp-is-target-device is also set";467      return mlir::failure();468    }469    // Construct offloading target triples vector.470    std::vector<llvm::Triple> targetTriples;471    targetTriples.reserve(targetTriplesOpenMP.size());472    for (llvm::StringRef s : targetTriplesOpenMP)473      targetTriples.emplace_back(s);474 475    auto offloadModuleOpts = OffloadModuleOpts(476        setOpenMPTargetDebug, setOpenMPTeamSubscription,477        setOpenMPThreadSubscription, setOpenMPNoThreadState,478        setOpenMPNoNestedParallelism, enableOpenMPDevice, enableOpenMPGPU,479        enableOpenMPForceUSM, setOpenMPVersion, "", targetTriples, setNoGPULib);480    setOffloadModuleInterfaceAttributes(mlirModule, offloadModuleOpts);481    setOpenMPVersionAttribute(mlirModule, setOpenMPVersion);482  }483  burnside.lower(parseTree, semanticsContext);484  std::error_code ec;485  std::string outputName = outputFilename;486  if (!outputName.size())487    outputName = llvm::sys::path::stem(inputFilename).str().append(".mlir");488  llvm::raw_fd_ostream out(outputName, ec);489  if (ec)490    return mlir::emitError(mlir::UnknownLoc::get(&ctx),491                           "could not open output file ")492           << outputName;493 494  // WARNING: This pipeline must be run immediately after the lowering to495  // ensure that the FIR is correct with respect to OpenMP operations/496  // attributes.497  if (enableOpenMP)498    if (mlir::failed(runOpenMPPasses(mlirModule)))499      return mlir::failure();500 501  // Otherwise run the default passes.502  mlir::PassManager pm(mlirModule->getName(),503                       mlir::OpPassManager::Nesting::Implicit);504  pm.enableVerifier(/*verifyPasses=*/true);505  (void)mlir::applyPassManagerCLOptions(pm);506  if (passPipeline.hasAnyOccurrences()) {507    // run the command-line specified pipeline508    hlfir::registerHLFIRPasses();509    (void)passPipeline.addToPipeline(pm, [&](const llvm::Twine &msg) {510      mlir::emitError(mlir::UnknownLoc::get(&ctx)) << msg;511      return mlir::failure();512    });513  } else if (emitFIR || emitHLFIR) {514    // --emit-fir: Build the IR, verify it, and dump the IR if the IR passes515    // verification. Use --dump-module-on-failure to dump invalid IR.516    pm.addPass(std::make_unique<Fortran::lower::VerifierPass>());517    if (mlir::failed(pm.run(mlirModule))) {518      llvm::errs() << "FATAL: verification of lowering to FIR failed";519      return mlir::failure();520    }521 522    if (emitFIR && useHLFIR) {523      // lower HLFIR to FIR524      fir::EnableOpenMP enableOmp =525          enableOpenMP ? fir::EnableOpenMP::Full : fir::EnableOpenMP::None;526      fir::createHLFIRToFIRPassPipeline(pm, enableOmp,527                                        llvm::OptimizationLevel::O2);528      if (mlir::failed(pm.run(mlirModule))) {529        llvm::errs() << "FATAL: lowering from HLFIR to FIR failed";530        return mlir::failure();531      }532    }533 534    printModule(mlirModule, out);535    return mlir::success();536  } else {537    // run the default canned pipeline538    pm.addPass(std::make_unique<Fortran::lower::VerifierPass>());539 540    // Add O2 optimizer pass pipeline.541    MLIRToLLVMPassPipelineConfig config(llvm::OptimizationLevel::O2);542    config.SkipConvertComplexPow = targetMachine.getTargetTriple().isAMDGCN();543    if (enableOpenMP)544      config.EnableOpenMP = true;545    config.NSWOnLoopVarInc = !integerWrapAround;546    fir::registerDefaultInlinerPass(config);547    fir::createDefaultFIROptimizerPassPipeline(pm, config);548  }549 550  if (mlir::succeeded(pm.run(mlirModule))) {551    // Emit MLIR and do not lower to LLVM IR.552    printModule(mlirModule, out);553    return mlir::success();554  }555  // Something went wrong. Try to dump the MLIR module.556  llvm::errs() << "oops, pass manager reported failure\n";557  return mlir::failure();558}559 560int main(int argc, char **argv) {561  [[maybe_unused]] llvm::InitLLVM y(argc, argv);562  llvm::InitializeAllTargets();563  llvm::InitializeAllTargetMCs();564  registerAllPasses();565 566  mlir::registerMLIRContextCLOptions();567  mlir::registerAsmPrinterCLOptions();568  mlir::registerPassManagerCLOptions();569  mlir::PassPipelineCLParser passPipe("", "Compiler passes to run");570  llvm::cl::ParseCommandLineOptions(argc, argv, "Burnside Bridge Compiler\n");571 572  ProgramName programPrefix;573  programPrefix = argv[0] + ": "s;574 575  if (includeDirs.size() == 0) {576    includeDirs.push_back(".");577    // Default Fortran modules should be installed in include/flang (a sibling578    // to the bin) directory.579    intrinsicIncludeDirs.push_back(580        llvm::sys::path::parent_path(581            llvm::sys::path::parent_path(582                llvm::sys::fs::getMainExecutable(argv[0], nullptr)))583            .str() +584        "/include/flang");585  }586 587  Fortran::parser::Options options;588  options.predefinitions.emplace_back("__flang__"s, "1"s);589  options.predefinitions.emplace_back("__flang_major__"s,590                                      std::string{FLANG_VERSION_MAJOR_STRING});591  options.predefinitions.emplace_back("__flang_minor__"s,592                                      std::string{FLANG_VERSION_MINOR_STRING});593  options.predefinitions.emplace_back(594      "__flang_patchlevel__"s, std::string{FLANG_VERSION_PATCHLEVEL_STRING});595 596  Fortran::common::LangOptions langOpts;597  langOpts.NoGPULib = setNoGPULib;598  langOpts.OpenMPVersion = setOpenMPVersion;599  langOpts.OpenMPIsTargetDevice = enableOpenMPDevice;600  langOpts.OpenMPIsGPU = enableOpenMPGPU;601  langOpts.OpenMPForceUSM = enableOpenMPForceUSM;602  langOpts.OpenMPTargetDebug = setOpenMPTargetDebug;603  langOpts.OpenMPThreadSubscription = setOpenMPThreadSubscription;604  langOpts.OpenMPTeamSubscription = setOpenMPTeamSubscription;605  langOpts.OpenMPNoThreadState = setOpenMPNoThreadState;606  langOpts.OpenMPNoNestedParallelism = setOpenMPNoNestedParallelism;607  std::transform(targetTriplesOpenMP.begin(), targetTriplesOpenMP.end(),608                 std::back_inserter(langOpts.OMPTargetTriples),609                 [](const std::string &str) { return llvm::Triple(str); });610 611  // enable parsing of OpenMP612  if (enableOpenMP) {613    options.features.Enable(Fortran::common::LanguageFeature::OpenMP);614    Fortran::common::setOpenMPMacro(setOpenMPVersion, options.predefinitions);615  }616 617  // enable parsing of OpenACC618  if (enableOpenACC) {619    options.features.Enable(Fortran::common::LanguageFeature::OpenACC);620    options.predefinitions.emplace_back("_OPENACC", "202211");621  }622 623  // enable parsing of CUDA Fortran624  if (enableCUDA) {625    options.features.Enable(Fortran::common::LanguageFeature::CUDA);626  }627 628  if (enableDoConcurrentOffload) {629    options.features.Enable(630        Fortran::common::LanguageFeature::DoConcurrentOffload);631  }632 633  if (disableCUDAWarpFunction) {634    options.features.Enable(635        Fortran::common::LanguageFeature::CudaWarpMatchFunction, false);636  }637 638  if (enableGPUMode == "managed") {639    options.features.Enable(Fortran::common::LanguageFeature::CudaManaged);640  } else if (enableGPUMode == "unified") {641    options.features.Enable(Fortran::common::LanguageFeature::CudaUnified);642  }643 644  if (fixedForm) {645    options.isFixedForm = fixedForm;646  }647 648  Fortran::common::IntrinsicTypeDefaultKinds defaultKinds;649  Fortran::parser::AllSources allSources;650  Fortran::parser::AllCookedSources allCookedSources(allSources);651  Fortran::semantics::SemanticsContext semanticsContext{652      defaultKinds, options.features, langOpts, allCookedSources};653  semanticsContext.set_moduleDirectory(moduleDir)654      .set_moduleFileSuffix(moduleSuffix)655      .set_searchDirectories(includeDirs)656      .set_intrinsicModuleDirectories(intrinsicIncludeDirs)657      .set_warnOnNonstandardUsage(warnStdViolation)658      .set_warningsAreErrors(warnIsError);659 660  std::string error;661  // Create host target machine.662  std::unique_ptr<llvm::TargetMachine> targetMachine =663      createTargetMachine(targetTripleOverride, error);664  if (!targetMachine) {665    llvm::errs() << "failed to create target machine: " << error << "\n";666    return mlir::failed(mlir::failure());667  }668  std::string compilerVersion = Fortran::common::getFlangToolFullVersion("bbc");669  std::string compilerOptions = "";670  Fortran::tools::setUpTargetCharacteristics(671      semanticsContext.targetCharacteristics(), *targetMachine, {},672      compilerVersion, compilerOptions);673 674  return mlir::failed(675      convertFortranSourceToMLIR(inputFilename, options, programPrefix,676                                 semanticsContext, passPipe, *targetMachine));677}678