1 //===- bbc.cpp - Burnside Bridge Compiler -----------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
11 //===----------------------------------------------------------------------===//
13 /// This is a tool for translating Fortran sources to the FIR dialect of MLIR.
15 //===----------------------------------------------------------------------===//
17 #include "flang/Common/Fortran-features.h"
18 #include "flang/Common/LangOptions.h"
19 #include "flang/Common/OpenMP-features.h"
20 #include "flang/Common/Version.h"
21 #include "flang/Common/default-kinds.h"
22 #include "flang/Frontend/CodeGenOptions.h"
23 #include "flang/Frontend/TargetOptions.h"
24 #include "flang/Lower/Bridge.h"
25 #include "flang/Lower/PFTBuilder.h"
26 #include "flang/Lower/Support/Verifier.h"
27 #include "flang/Optimizer/Dialect/Support/FIRContext.h"
28 #include "flang/Optimizer/Dialect/Support/KindMapping.h"
29 #include "flang/Optimizer/Support/InitFIR.h"
30 #include "flang/Optimizer/Support/InternalNames.h"
31 #include "flang/Optimizer/Support/Utils.h"
32 #include "flang/Optimizer/Transforms/Passes.h"
33 #include "flang/Parser/characters.h"
34 #include "flang/Parser/dump-parse-tree.h"
35 #include "flang/Parser/message.h"
36 #include "flang/Parser/parse-tree-visitor.h"
37 #include "flang/Parser/parse-tree.h"
38 #include "flang/Parser/parsing.h"
39 #include "flang/Parser/provenance.h"
40 #include "flang/Parser/unparse.h"
41 #include "flang/Semantics/expression.h"
42 #include "flang/Semantics/runtime-type-info.h"
43 #include "flang/Semantics/semantics.h"
44 #include "flang/Semantics/unparse-with-symbols.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"
74 //===----------------------------------------------------------------------===//
75 // Some basic command-line options
76 //===----------------------------------------------------------------------===//
78 static llvm::cl::opt
<std::string
> inputFilename(llvm::cl::Positional
,
80 llvm::cl::desc("<input file>"));
82 static llvm::cl::opt
<std::string
>
83 outputFilename("o", llvm::cl::desc("Specify the output filename"),
84 llvm::cl::value_desc("filename"));
86 static llvm::cl::list
<std::string
>
87 includeDirs("I", llvm::cl::desc("include module search paths"));
89 static llvm::cl::alias
includeAlias("module-directory",
90 llvm::cl::desc("module search directory"),
91 llvm::cl::aliasopt(includeDirs
));
93 static llvm::cl::list
<std::string
>
94 intrinsicIncludeDirs("J", llvm::cl::desc("intrinsic module search paths"));
96 static llvm::cl::alias
97 intrinsicIncludeAlias("intrinsic-module-directory",
98 llvm::cl::desc("intrinsic module directory"),
99 llvm::cl::aliasopt(intrinsicIncludeDirs
));
101 static llvm::cl::opt
<std::string
>
102 moduleDir("module", llvm::cl::desc("module output directory (default .)"),
103 llvm::cl::init("."));
105 static llvm::cl::opt
<std::string
>
106 moduleSuffix("module-suffix", llvm::cl::desc("module file suffix override"),
107 llvm::cl::init(".mod"));
109 static llvm::cl::opt
<bool>
111 llvm::cl::desc("Dump the FIR created by lowering and exit"),
112 llvm::cl::init(false));
114 static 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));
119 static llvm::cl::opt
<bool> warnStdViolation("Mstandard",
120 llvm::cl::desc("emit warnings"),
121 llvm::cl::init(false));
123 static llvm::cl::opt
<bool> warnIsError("Werror",
124 llvm::cl::desc("warnings are errors"),
125 llvm::cl::init(false));
127 static llvm::cl::opt
<bool> dumpSymbols("dump-symbols",
128 llvm::cl::desc("dump the symbol table"),
129 llvm::cl::init(false));
131 static llvm::cl::opt
<bool> pftDumpTest(
133 llvm::cl::desc("parse the input, create a PFT, dump it, and exit"),
134 llvm::cl::init(false));
136 static llvm::cl::opt
<bool> enableOpenMP("fopenmp",
137 llvm::cl::desc("enable openmp"),
138 llvm::cl::init(false));
140 static llvm::cl::opt
<bool>
141 enableOpenMPDevice("fopenmp-is-target-device",
142 llvm::cl::desc("enable openmp device compilation"),
143 llvm::cl::init(false));
145 static llvm::cl::opt
<bool>
146 enableOpenMPGPU("fopenmp-is-gpu",
147 llvm::cl::desc("enable openmp GPU target codegen"),
148 llvm::cl::init(false));
150 static llvm::cl::opt
<bool> enableOpenMPForceUSM(
152 llvm::cl::desc("force openmp unified shared memory mode"),
153 llvm::cl::init(false));
155 static llvm::cl::list
<std::string
> targetTriplesOpenMP(
157 llvm::cl::desc("comma-separated list of OpenMP offloading triples"),
158 llvm::cl::CommaSeparated
);
160 // A simplified subset of the OpenMP RTL Flags from Flang, only the primary
161 // positive options are available, no negative options e.g. fopen_assume* vs
163 static llvm::cl::opt
<uint32_t>
164 setOpenMPVersion("fopenmp-version",
165 llvm::cl::desc("OpenMP standard version"),
168 static llvm::cl::opt
<uint32_t> setOpenMPTargetDebug(
169 "fopenmp-target-debug",
170 llvm::cl::desc("Enable debugging in the OpenMP offloading device RTL"),
173 static llvm::cl::opt
<bool> setOpenMPThreadSubscription(
174 "fopenmp-assume-threads-oversubscription",
175 llvm::cl::desc("Assume work-shared loops do not have more "
176 "iterations than participating threads."),
177 llvm::cl::init(false));
179 static llvm::cl::opt
<bool> setOpenMPTeamSubscription(
180 "fopenmp-assume-teams-oversubscription",
181 llvm::cl::desc("Assume distributed loops do not have more iterations than "
182 "participating teams."),
183 llvm::cl::init(false));
185 static llvm::cl::opt
<bool> setOpenMPNoThreadState(
186 "fopenmp-assume-no-thread-state",
188 "Assume that no thread in a parallel region will modify an ICV."),
189 llvm::cl::init(false));
191 static llvm::cl::opt
<bool> setOpenMPNoNestedParallelism(
192 "fopenmp-assume-no-nested-parallelism",
193 llvm::cl::desc("Assume that no thread in a parallel region will encounter "
194 "a parallel region."),
195 llvm::cl::init(false));
197 static llvm::cl::opt
<bool>
198 setNoGPULib("nogpulib",
199 llvm::cl::desc("Do not link device library for CUDA/HIP device "
201 llvm::cl::init(false));
203 static llvm::cl::opt
<bool> enableOpenACC("fopenacc",
204 llvm::cl::desc("enable openacc"),
205 llvm::cl::init(false));
207 static llvm::cl::opt
<bool> enableNoPPCNativeVecElemOrder(
208 "fno-ppc-native-vector-element-order",
209 llvm::cl::desc("no PowerPC native vector element order."),
210 llvm::cl::init(false));
212 static llvm::cl::opt
<bool> useHLFIR("hlfir",
213 llvm::cl::desc("Lower to high level FIR"),
214 llvm::cl::init(true));
216 static llvm::cl::opt
<bool> enableCUDA("fcuda",
217 llvm::cl::desc("enable CUDA Fortran"),
218 llvm::cl::init(false));
220 static llvm::cl::opt
<std::string
>
221 enableGPUMode("gpu", llvm::cl::desc("Enable GPU Mode managed|unified"),
224 static llvm::cl::opt
<bool> fixedForm("ffixed-form",
225 llvm::cl::desc("enable fixed form"),
226 llvm::cl::init(false));
227 static llvm::cl::opt
<std::string
>
228 targetTripleOverride("target",
229 llvm::cl::desc("Override host target triple"),
232 static llvm::cl::opt
<bool> integerWrapAround(
234 llvm::cl::desc("Treat signed integer overflow as two's complement"),
235 llvm::cl::init(false));
237 // TODO: integrate this option with the above
238 static llvm::cl::opt
<bool>
239 setNSW("integer-overflow",
240 llvm::cl::desc("add nsw flag to internal operations"),
241 llvm::cl::init(false));
243 #define FLANG_EXCLUDE_CODEGEN
244 #include "flang/Optimizer/Passes/CommandLineOpts.h"
245 #include "flang/Optimizer/Passes/Pipelines.h"
247 //===----------------------------------------------------------------------===//
249 using ProgramName
= std::string
;
251 // Print the module with the "module { ... }" wrapper, preventing
252 // information loss from attribute information appended to the module
253 static void printModule(mlir::ModuleOp mlirModule
, llvm::raw_ostream
&out
) {
254 out
<< mlirModule
<< '\n';
257 static void registerAllPasses() {
258 fir::support::registerMLIRPassesForFortranTools();
259 fir::registerOptTransformPasses();
262 /// Create a target machine that is at least sufficient to get data-layout
263 /// information required by flang semantics and lowering. Note that it may not
264 /// contain all the CPU feature information to get optimized assembly generation
265 /// from LLVM IR. Drivers that needs to generate assembly from LLVM IR should
266 /// create a target machine according to their specific options.
267 static std::unique_ptr
<llvm::TargetMachine
>
268 createTargetMachine(llvm::StringRef targetTriple
, std::string
&error
) {
269 std::string triple
{targetTriple
};
271 triple
= llvm::sys::getDefaultTargetTriple();
273 const llvm::Target
*theTarget
=
274 llvm::TargetRegistry::lookupTarget(triple
, error
);
277 return std::unique_ptr
<llvm::TargetMachine
>{
278 theTarget
->createTargetMachine(triple
, /*CPU=*/"",
279 /*Features=*/"", llvm::TargetOptions(),
280 /*Reloc::Model=*/std::nullopt
)};
283 /// Build and execute the OpenMPFIRPassPipeline with its own instance
284 /// of the pass manager, allowing it to be invoked as soon as it's
285 /// required without impacting the main pass pipeline that may be invoked
286 /// more than once for verification.
287 static llvm::LogicalResult
runOpenMPPasses(mlir::ModuleOp mlirModule
) {
288 mlir::PassManager
pm(mlirModule
->getName(),
289 mlir::OpPassManager::Nesting::Implicit
);
290 fir::createOpenMPFIRPassPipeline(pm
, enableOpenMPDevice
);
291 (void)mlir::applyPassManagerCLOptions(pm
);
292 if (mlir::failed(pm
.run(mlirModule
))) {
293 llvm::errs() << "FATAL: failed to correctly apply OpenMP pass pipeline";
294 return mlir::failure();
296 return mlir::success();
299 //===----------------------------------------------------------------------===//
300 // Translate Fortran input to FIR, a dialect of MLIR.
301 //===----------------------------------------------------------------------===//
303 static llvm::LogicalResult
convertFortranSourceToMLIR(
304 std::string path
, Fortran::parser::Options options
,
305 const ProgramName
&programPrefix
,
306 Fortran::semantics::SemanticsContext
&semanticsContext
,
307 const mlir::PassPipelineCLParser
&passPipeline
,
308 const llvm::TargetMachine
&targetMachine
) {
310 // prep for prescan and parse
311 Fortran::parser::Parsing parsing
{semanticsContext
.allCookedSources()};
312 parsing
.Prescan(path
, options
);
313 if (!parsing
.messages().empty() && (parsing
.messages().AnyFatalError())) {
314 llvm::errs() << programPrefix
<< "could not scan " << path
<< '\n';
315 parsing
.messages().Emit(llvm::errs(), parsing
.allCooked());
316 return mlir::failure();
319 // parse the input Fortran
320 parsing
.Parse(llvm::outs());
321 if (!parsing
.consumedWholeFile()) {
322 parsing
.messages().Emit(llvm::errs(), parsing
.allCooked());
323 parsing
.EmitMessage(llvm::errs(), parsing
.finalRestingPlace(),
324 "parser FAIL (final position)",
325 "error: ", llvm::raw_ostream::RED
);
326 return mlir::failure();
327 } else if ((!parsing
.messages().empty() &&
328 (parsing
.messages().AnyFatalError())) ||
329 !parsing
.parseTree().has_value()) {
330 parsing
.messages().Emit(llvm::errs(), parsing
.allCooked());
331 llvm::errs() << programPrefix
<< "could not parse " << path
<< '\n';
332 return mlir::failure();
334 semanticsContext
.messages().Annex(std::move(parsing
.messages()));
338 auto &parseTree
= *parsing
.parseTree();
339 Fortran::semantics::Semantics
semantics(semanticsContext
, parseTree
);
341 semantics
.EmitMessages(llvm::errs());
342 if (semantics
.AnyFatalError()) {
343 llvm::errs() << programPrefix
<< "semantic errors in " << path
<< '\n';
344 return mlir::failure();
346 Fortran::semantics::RuntimeDerivedTypeTables tables
;
347 if (!semantics
.AnyFatalError()) {
349 Fortran::semantics::BuildRuntimeDerivedTypeTables(semanticsContext
);
350 if (!tables
.schemata
)
351 llvm::errs() << programPrefix
352 << "could not find module file for __fortran_type_info\n";
356 semantics
.DumpSymbols(llvm::outs());
357 return mlir::success();
361 if (auto ast
= Fortran::lower::createPFT(parseTree
, semanticsContext
)) {
362 Fortran::lower::dumpPFT(llvm::outs(), *ast
);
363 return mlir::success();
365 llvm::errs() << "Pre FIR Tree is NULL.\n";
366 return mlir::failure();
369 // translate to FIR dialect of MLIR
370 mlir::DialectRegistry registry
;
371 fir::support::registerNonCodegenDialects(registry
);
372 fir::support::addFIRExtensions(registry
);
373 mlir::MLIRContext
ctx(registry
);
374 fir::support::loadNonCodegenDialects(ctx
);
375 auto &defKinds
= semanticsContext
.defaultKinds();
376 fir::KindMapping
kindMap(
377 &ctx
, llvm::ArrayRef
<fir::KindTy
>{fir::fromDefaultKinds(defKinds
)});
378 std::string targetTriple
= targetMachine
.getTargetTriple().normalize();
379 // Use default lowering options for bbc.
380 Fortran::lower::LoweringOptions loweringOptions
{};
381 loweringOptions
.setNoPPCNativeVecElemOrder(enableNoPPCNativeVecElemOrder
);
382 loweringOptions
.setLowerToHighLevelFIR(useHLFIR
|| emitHLFIR
);
383 loweringOptions
.setIntegerWrapAround(integerWrapAround
);
384 loweringOptions
.setNSWOnLoopVarInc(setNSW
);
385 std::vector
<Fortran::lower::EnvironmentDefault
> envDefaults
= {};
386 Fortran::frontend::TargetOptions targetOpts
;
387 Fortran::frontend::CodeGenOptions cgOpts
;
388 auto burnside
= Fortran::lower::LoweringBridge::create(
389 ctx
, semanticsContext
, defKinds
, semanticsContext
.intrinsics(),
390 semanticsContext
.targetCharacteristics(), parsing
.allCooked(),
391 targetTriple
, kindMap
, loweringOptions
, envDefaults
,
392 semanticsContext
.languageFeatures(), targetMachine
, targetOpts
, cgOpts
);
393 mlir::ModuleOp mlirModule
= burnside
.getModule();
395 if (enableOpenMPGPU
&& !enableOpenMPDevice
) {
396 llvm::errs() << "FATAL: -fopenmp-is-gpu can only be set if "
397 "-fopenmp-is-target-device is also set";
398 return mlir::failure();
400 // Construct offloading target triples vector.
401 std::vector
<llvm::Triple
> targetTriples
;
402 targetTriples
.reserve(targetTriplesOpenMP
.size());
403 for (llvm::StringRef s
: targetTriplesOpenMP
)
404 targetTriples
.emplace_back(s
);
406 auto offloadModuleOpts
= OffloadModuleOpts(
407 setOpenMPTargetDebug
, setOpenMPTeamSubscription
,
408 setOpenMPThreadSubscription
, setOpenMPNoThreadState
,
409 setOpenMPNoNestedParallelism
, enableOpenMPDevice
, enableOpenMPGPU
,
410 enableOpenMPForceUSM
, setOpenMPVersion
, "", targetTriples
, setNoGPULib
);
411 setOffloadModuleInterfaceAttributes(mlirModule
, offloadModuleOpts
);
412 setOpenMPVersionAttribute(mlirModule
, setOpenMPVersion
);
414 burnside
.lower(parseTree
, semanticsContext
);
416 std::string outputName
= outputFilename
;
417 if (!outputName
.size())
418 outputName
= llvm::sys::path::stem(inputFilename
).str().append(".mlir");
419 llvm::raw_fd_ostream
out(outputName
, ec
);
421 return mlir::emitError(mlir::UnknownLoc::get(&ctx
),
422 "could not open output file ")
425 // WARNING: This pipeline must be run immediately after the lowering to
426 // ensure that the FIR is correct with respect to OpenMP operations/
429 if (mlir::failed(runOpenMPPasses(mlirModule
)))
430 return mlir::failure();
432 // Otherwise run the default passes.
433 mlir::PassManager
pm(mlirModule
->getName(),
434 mlir::OpPassManager::Nesting::Implicit
);
435 pm
.enableVerifier(/*verifyPasses=*/true);
436 (void)mlir::applyPassManagerCLOptions(pm
);
437 if (passPipeline
.hasAnyOccurrences()) {
438 // run the command-line specified pipeline
439 hlfir::registerHLFIRPasses();
440 (void)passPipeline
.addToPipeline(pm
, [&](const llvm::Twine
&msg
) {
441 mlir::emitError(mlir::UnknownLoc::get(&ctx
)) << msg
;
442 return mlir::failure();
444 } else if (emitFIR
|| emitHLFIR
) {
445 // --emit-fir: Build the IR, verify it, and dump the IR if the IR passes
446 // verification. Use --dump-module-on-failure to dump invalid IR.
447 pm
.addPass(std::make_unique
<Fortran::lower::VerifierPass
>());
448 if (mlir::failed(pm
.run(mlirModule
))) {
449 llvm::errs() << "FATAL: verification of lowering to FIR failed";
450 return mlir::failure();
453 if (emitFIR
&& useHLFIR
) {
454 // lower HLFIR to FIR
455 fir::createHLFIRToFIRPassPipeline(pm
, enableOpenMP
,
456 llvm::OptimizationLevel::O2
);
457 if (mlir::failed(pm
.run(mlirModule
))) {
458 llvm::errs() << "FATAL: lowering from HLFIR to FIR failed";
459 return mlir::failure();
463 printModule(mlirModule
, out
);
464 return mlir::success();
466 // run the default canned pipeline
467 pm
.addPass(std::make_unique
<Fortran::lower::VerifierPass
>());
469 // Add O2 optimizer pass pipeline.
470 MLIRToLLVMPassPipelineConfig
config(llvm::OptimizationLevel::O2
);
472 config
.EnableOpenMP
= true;
473 config
.NSWOnLoopVarInc
= setNSW
;
474 fir::registerDefaultInlinerPass(config
);
475 fir::createDefaultFIROptimizerPassPipeline(pm
, config
);
478 if (mlir::succeeded(pm
.run(mlirModule
))) {
479 // Emit MLIR and do not lower to LLVM IR.
480 printModule(mlirModule
, out
);
481 return mlir::success();
483 // Something went wrong. Try to dump the MLIR module.
484 llvm::errs() << "oops, pass manager reported failure\n";
485 return mlir::failure();
488 int main(int argc
, char **argv
) {
489 [[maybe_unused
]] llvm::InitLLVM
y(argc
, argv
);
490 llvm::InitializeAllTargets();
491 llvm::InitializeAllTargetMCs();
494 mlir::registerMLIRContextCLOptions();
495 mlir::registerAsmPrinterCLOptions();
496 mlir::registerPassManagerCLOptions();
497 mlir::PassPipelineCLParser
passPipe("", "Compiler passes to run");
498 llvm::cl::ParseCommandLineOptions(argc
, argv
, "Burnside Bridge Compiler\n");
500 ProgramName programPrefix
;
501 programPrefix
= argv
[0] + ": "s
;
503 if (includeDirs
.size() == 0) {
504 includeDirs
.push_back(".");
505 // Default Fortran modules should be installed in include/flang (a sibling
506 // to the bin) directory.
507 intrinsicIncludeDirs
.push_back(
508 llvm::sys::path::parent_path(
509 llvm::sys::path::parent_path(
510 llvm::sys::fs::getMainExecutable(argv
[0], nullptr)))
515 Fortran::parser::Options options
;
516 options
.predefinitions
.emplace_back("__flang__"s
, "1"s
);
517 options
.predefinitions
.emplace_back("__flang_major__"s
,
518 std::string
{FLANG_VERSION_MAJOR_STRING
});
519 options
.predefinitions
.emplace_back("__flang_minor__"s
,
520 std::string
{FLANG_VERSION_MINOR_STRING
});
521 options
.predefinitions
.emplace_back(
522 "__flang_patchlevel__"s
, std::string
{FLANG_VERSION_PATCHLEVEL_STRING
});
524 Fortran::common::LangOptions langOpts
;
525 langOpts
.NoGPULib
= setNoGPULib
;
526 langOpts
.OpenMPVersion
= setOpenMPVersion
;
527 langOpts
.OpenMPIsTargetDevice
= enableOpenMPDevice
;
528 langOpts
.OpenMPIsGPU
= enableOpenMPGPU
;
529 langOpts
.OpenMPForceUSM
= enableOpenMPForceUSM
;
530 langOpts
.OpenMPTargetDebug
= setOpenMPTargetDebug
;
531 langOpts
.OpenMPThreadSubscription
= setOpenMPThreadSubscription
;
532 langOpts
.OpenMPTeamSubscription
= setOpenMPTeamSubscription
;
533 langOpts
.OpenMPNoThreadState
= setOpenMPNoThreadState
;
534 langOpts
.OpenMPNoNestedParallelism
= setOpenMPNoNestedParallelism
;
535 std::transform(targetTriplesOpenMP
.begin(), targetTriplesOpenMP
.end(),
536 std::back_inserter(langOpts
.OMPTargetTriples
),
537 [](const std::string
&str
) { return llvm::Triple(str
); });
539 // enable parsing of OpenMP
541 options
.features
.Enable(Fortran::common::LanguageFeature::OpenMP
);
542 Fortran::common::setOpenMPMacro(setOpenMPVersion
, options
.predefinitions
);
545 // enable parsing of OpenACC
547 options
.features
.Enable(Fortran::common::LanguageFeature::OpenACC
);
548 options
.predefinitions
.emplace_back("_OPENACC", "202211");
551 // enable parsing of CUDA Fortran
553 options
.features
.Enable(Fortran::common::LanguageFeature::CUDA
);
556 if (enableGPUMode
== "managed") {
557 options
.features
.Enable(Fortran::common::LanguageFeature::CudaManaged
);
558 } else if (enableGPUMode
== "unified") {
559 options
.features
.Enable(Fortran::common::LanguageFeature::CudaUnified
);
563 options
.isFixedForm
= fixedForm
;
566 Fortran::common::IntrinsicTypeDefaultKinds defaultKinds
;
567 Fortran::parser::AllSources allSources
;
568 Fortran::parser::AllCookedSources
allCookedSources(allSources
);
569 Fortran::semantics::SemanticsContext semanticsContext
{
570 defaultKinds
, options
.features
, langOpts
, allCookedSources
};
571 semanticsContext
.set_moduleDirectory(moduleDir
)
572 .set_moduleFileSuffix(moduleSuffix
)
573 .set_searchDirectories(includeDirs
)
574 .set_intrinsicModuleDirectories(intrinsicIncludeDirs
)
575 .set_warnOnNonstandardUsage(warnStdViolation
)
576 .set_warningsAreErrors(warnIsError
);
579 // Create host target machine.
580 std::unique_ptr
<llvm::TargetMachine
> targetMachine
=
581 createTargetMachine(targetTripleOverride
, error
);
582 if (!targetMachine
) {
583 llvm::errs() << "failed to create target machine: " << error
<< "\n";
584 return mlir::failed(mlir::failure());
586 std::string compilerVersion
= Fortran::common::getFlangToolFullVersion("bbc");
587 std::string compilerOptions
= "";
588 Fortran::tools::setUpTargetCharacteristics(
589 semanticsContext
.targetCharacteristics(), *targetMachine
, {},
590 compilerVersion
, compilerOptions
);
593 convertFortranSourceToMLIR(inputFilename
, options
, programPrefix
,
594 semanticsContext
, passPipe
, *targetMachine
));