10
10
#include " mlir/IR/Dialect.h"
11
11
#include " mlir/Pass/PassManager.h"
12
12
#include " mlir/Support/LogicalResult.h"
13
+ #include " mlir/Target/LLVMIR/ModuleTranslation.h"
13
14
#include " flang/Common/default-kinds.h"
14
15
#include " flang/Frontend/CompilerInstance.h"
15
16
#include " flang/Frontend/FrontendOptions.h"
16
17
#include " flang/Frontend/PreprocessorOptions.h"
17
18
#include " flang/Lower/Bridge.h"
18
19
#include " flang/Lower/PFTBuilder.h"
19
20
#include " flang/Lower/Support/Verifier.h"
21
+ #include " flang/Optimizer/CodeGen/CodeGen.h"
20
22
#include " flang/Optimizer/Dialect/FIRType.h"
23
+ #include " flang/Optimizer/Support//Utils.h"
24
+ #include " flang/Optimizer/Support/FIRContext.h"
21
25
#include " flang/Optimizer/Support/InitFIR.h"
22
26
#include " flang/Optimizer/Support/KindMapping.h"
27
+ #include " flang/Optimizer/Transforms/Passes.h"
23
28
#include " flang/Parser/dump-parse-tree.h"
24
29
#include " flang/Parser/parsing.h"
25
30
#include " flang/Parser/provenance.h"
32
37
#include " llvm/Support/ErrorHandling.h"
33
38
#include " llvm/Support/raw_ostream.h"
34
39
#include < clang/Basic/Diagnostic.h>
35
- #include < memory>
36
40
37
41
using namespace Fortran ::frontend;
38
42
@@ -55,7 +59,45 @@ bool PrescanAndSemaDebugAction::BeginSourceFileAction() {
55
59
}
56
60
57
61
bool CodeGenAction::BeginSourceFileAction () {
58
- return RunPrescan () & RunParse () && RunSemanticChecks ();
62
+ bool res = RunPrescan () && RunParse () && RunSemanticChecks ();
63
+ if (!res)
64
+ return res;
65
+
66
+ CompilerInstance &ci = this ->instance ();
67
+
68
+ // Load the MLIR dialects required by Flang
69
+ mlir::DialectRegistry registry;
70
+ ci.setMlirCtx (std::make_unique<mlir::MLIRContext>(registry));
71
+ fir::support::registerNonCodegenDialects (registry);
72
+ fir::support::loadNonCodegenDialects (ci.mlirCtx ());
73
+
74
+ // Create a LoweringBridge
75
+ auto &defKinds = ci.invocation ().semanticsContext ().defaultKinds ();
76
+ fir::KindMapping kindMap (&ci.mlirCtx (),
77
+ llvm::ArrayRef<fir::KindTy>{fir::fromDefaultKinds (defKinds)});
78
+ auto lb = Fortran::lower::LoweringBridge::create (ci.mlirCtx (), defKinds,
79
+ ci.invocation ().semanticsContext ().intrinsics (), ci.parsing ().allCooked (),
80
+ " " , kindMap);
81
+
82
+ // Create a parse tree and lower it to FIR
83
+ auto &parseTree{*ci.parsing ().parseTree ()};
84
+ lb.lower (parseTree, ci.invocation ().semanticsContext ());
85
+ ci.setMlirModule (std::make_unique<mlir::ModuleOp>(lb.getModule ()));
86
+
87
+ // Run the default passes.
88
+ mlir::PassManager pm (&ci.mlirCtx (), mlir::OpPassManager::Nesting::Implicit);
89
+ pm.enableVerifier (/* verifyPasses=*/ true );
90
+ pm.addPass (std::make_unique<Fortran::lower::VerifierPass>());
91
+
92
+ if (mlir::failed (pm.run (ci.mlirModule ()))) {
93
+ unsigned diagID =
94
+ ci.diagnostics ().getCustomDiagID (clang::DiagnosticsEngine::Error,
95
+ " verification of lowering to FIR failed" );
96
+ ci.diagnostics ().Report (diagID);
97
+ return false ;
98
+ }
99
+
100
+ return true ;
59
101
}
60
102
61
103
// ===----------------------------------------------------------------------===//
@@ -369,61 +411,13 @@ void GetSymbolsSourcesAction::ExecuteAction() {
369
411
ci.semantics ().DumpSymbolsSources (llvm::outs ());
370
412
}
371
413
372
- // Translate front-end KINDs for use in the IR and code gen. Extracted from
373
- // bbc.cpp.
374
- static std::vector<fir::KindTy>
375
- fromDefaultKinds (const Fortran::common::IntrinsicTypeDefaultKinds &defKinds) {
376
- return {static_cast <fir::KindTy>(defKinds.GetDefaultKind (
377
- Fortran::common::TypeCategory::Character)),
378
- static_cast <fir::KindTy>(
379
- defKinds.GetDefaultKind (Fortran::common::TypeCategory::Complex)),
380
- static_cast <fir::KindTy>(defKinds.doublePrecisionKind ()),
381
- static_cast <fir::KindTy>(
382
- defKinds.GetDefaultKind (Fortran::common::TypeCategory::Integer)),
383
- static_cast <fir::KindTy>(
384
- defKinds.GetDefaultKind (Fortran::common::TypeCategory::Logical)),
385
- static_cast <fir::KindTy>(
386
- defKinds.GetDefaultKind (Fortran::common::TypeCategory::Real))};
387
- }
388
-
389
414
void EmitMLIRAction::ExecuteAction () {
390
415
CompilerInstance &ci = this ->instance ();
391
416
392
- // Load the MLIR dialects required by Flang
393
- mlir::DialectRegistry registry;
394
- mlir::MLIRContext ctx (registry);
395
- fir::support::registerNonCodegenDialects (registry);
396
- fir::support::loadNonCodegenDialects (ctx);
397
-
398
- // Create a LoweringBridge
399
- auto &defKinds = ci.invocation ().semanticsContext ().defaultKinds ();
400
- fir::KindMapping kindMap (
401
- &ctx, llvm::ArrayRef<fir::KindTy>{fromDefaultKinds (defKinds)});
402
- auto lb = Fortran::lower::LoweringBridge::create (ctx, defKinds,
403
- ci.invocation ().semanticsContext ().intrinsics (), ci.parsing ().allCooked (),
404
- " " , kindMap);
405
-
406
- // Create a parse tree and lower it to FIR
407
- auto &parseTree{*ci.parsing ().parseTree ()};
408
- lb.lower (parseTree, ci.invocation ().semanticsContext ());
409
-
410
- // Run the default passes.
411
- mlir::PassManager pm (&ctx, mlir::OpPassManager::Nesting::Implicit);
412
- pm.enableVerifier (/* verifyPasses=*/ true );
413
- pm.addPass (std::make_unique<Fortran::lower::VerifierPass>());
414
- mlir::ModuleOp mlirModule = lb.getModule ();
415
- if (mlir::failed (pm.run (mlirModule))) {
416
- unsigned diagID =
417
- ci.diagnostics ().getCustomDiagID (clang::DiagnosticsEngine::Error,
418
- " verification of lowering to FIR failed" );
419
- ci.diagnostics ().Report (diagID);
420
- return ;
421
- }
422
-
423
417
// Print the output. If a pre-defined output stream exists, dump the MLIR
424
418
// content there.
425
419
if (!ci.IsOutputStreamNull ()) {
426
- mlirModule.print (ci.GetOutputStream ());
420
+ ci. mlirModule () .print (ci.GetOutputStream ());
427
421
return ;
428
422
}
429
423
@@ -437,7 +431,77 @@ void EmitMLIRAction::ExecuteAction() {
437
431
return ;
438
432
}
439
433
440
- mlirModule.print (*os);
434
+ ci.mlirModule ().print (*os);
435
+ }
436
+
437
+ #include " flang/Tools/CLOptions.inc"
438
+
439
+ void EmitLLVMAction::ExecuteAction () {
440
+ CompilerInstance &ci = this ->instance ();
441
+ auto mlirMod = ci.mlirModule ();
442
+
443
+ auto &ctx = ci.mlirCtx ();
444
+ fir::support::loadDialects (ctx);
445
+ fir::support::registerLLVMTranslation (ctx);
446
+
447
+ // Set-up the pass manager
448
+ fir::setTargetTriple (mlirMod, " native" );
449
+ auto &defKinds = ci.invocation ().semanticsContext ().defaultKinds ();
450
+ fir::KindMapping kindMap (&ci.mlirCtx (),
451
+ llvm::ArrayRef<fir::KindTy>{fir::fromDefaultKinds (defKinds)});
452
+ fir::setKindMapping (mlirMod, kindMap);
453
+ mlir::PassManager pm (&ci.mlirCtx (), mlir::OpPassManager::Nesting::Implicit);
454
+
455
+ pm.addPass (std::make_unique<Fortran::lower::VerifierPass>());
456
+ pm.enableVerifier (/* verifyPasses=*/ true );
457
+ mlir::PassPipelineCLParser passPipeline (" " , " Compiler passes to run" );
458
+
459
+ // Create the pass pipeline
460
+ fir::createMLIRToLLVMPassPipeline (pm);
461
+
462
+ // Run the pass manager
463
+ if (!mlir::succeeded (pm.run (mlirMod))) {
464
+ unsigned diagID = ci.diagnostics ().getCustomDiagID (
465
+ clang::DiagnosticsEngine::Error, " Lowering to LLVM IR failed" );
466
+ ci.diagnostics ().Report (diagID);
467
+ }
468
+
469
+ // Translate to LLVM IR
470
+ auto optName = mlirMod.getName ();
471
+ llvm::LLVMContext llvmCtx;
472
+ auto llvmModule = (mlir::translateModuleToLLVMIR (
473
+ mlirMod, llvmCtx, optName ? *optName : " FIRModule" ));
474
+
475
+ if (!llvmModule) {
476
+ unsigned diagID = ci.diagnostics ().getCustomDiagID (
477
+ clang::DiagnosticsEngine::Error, " failed to create the LLVM module" );
478
+ ci.diagnostics ().Report (diagID);
479
+ return ;
480
+ }
481
+
482
+ // Print the generated LLVM IR. If there is no pre-defined output stream to
483
+ // print to, create an output file.
484
+ std::unique_ptr<llvm::raw_ostream> os;
485
+ if (ci.IsOutputStreamNull ()) {
486
+ // Lower from the LLVM dialect to LLVM IR
487
+ os = ci.CreateDefaultOutputFile (
488
+ /* Binary=*/ true , /* InFile=*/ GetCurrentFileOrBufferName (), " ll" );
489
+ if (!os) {
490
+ unsigned diagID = ci.diagnostics ().getCustomDiagID (
491
+ clang::DiagnosticsEngine::Error, " failed to create the output file" );
492
+ ci.diagnostics ().Report (diagID);
493
+ return ;
494
+ }
495
+ }
496
+
497
+ if (!ci.IsOutputStreamNull ()) {
498
+ llvmModule->print (
499
+ ci.GetOutputStream (), /* AssemblyAnnotationWriter=*/ nullptr );
500
+ } else {
501
+ llvmModule->print (*os, /* AssemblyAnnotationWriter=*/ nullptr );
502
+ }
503
+
504
+ return ;
441
505
}
442
506
443
507
void EmitObjAction::ExecuteAction () {
0 commit comments