Skip to content

Commit 2cfe75f

Browse files
authored
Merge pull request #1008 from banach-space/andrzej/generate_fir
[flang][driver] Add support for `-emit-fir`
2 parents 6005fdf + 5edb129 commit 2cfe75f

File tree

12 files changed

+162
-0
lines changed

12 files changed

+162
-0
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4467,6 +4467,10 @@ def fintrinsic_modules_path : Separate<["-"], "fintrinsic-modules-path">, Group
44674467
HelpText<"Specify where to find the compiled intrinsic modules">,
44684468
DocBrief<[{This option specifies the location of pre-compiled intrinsic modules,
44694469
if they are not in the default location expected by the compiler.}]>;
4470+
4471+
def emit_mlir : Flag<["-"], "emit-mlir">, Group<Action_Group>,
4472+
HelpText<"Build the parse tree, then lower it to MLIR and dump">;
4473+
def emit_fir : Flag<["-"], "emit-fir">, Alias<emit_mlir>;
44704474
}
44714475

44724476
def J : JoinedOrSeparate<["-"], "J">,

flang/include/flang/Frontend/CompilerInstance.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,13 @@ class CompilerInstance {
250250
void WriteOutputStream(const std::string &message) {
251251
*outputStream_ << message;
252252
}
253+
254+
/// Get the user specified output stream.
255+
llvm::raw_pwrite_stream &GetOutputStream() {
256+
assert(outputStream_ &&
257+
"Compiler instance has no user-specified output stream!");
258+
return *outputStream_;
259+
}
253260
};
254261

255262
} // end namespace Fortran::frontend

flang/include/flang/Frontend/FrontendActions.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,19 @@ class ParseSyntaxOnlyAction : public PrescanAndSemaAction {
127127
void ExecuteAction() override;
128128
};
129129

130+
//===----------------------------------------------------------------------===//
131+
// CodeGen Actions
132+
//===----------------------------------------------------------------------===//
133+
class CodeGenAction : public FrontendAction {
134+
135+
void ExecuteAction() override = 0;
136+
bool BeginSourceFileAction() override;
137+
};
138+
139+
class EmitMLIRAction : public CodeGenAction {
140+
void ExecuteAction() override;
141+
};
142+
130143
} // namespace Fortran::frontend
131144

132145
#endif // LLVM_FLANG_FRONTEND_FRONTENDACTIONS_H

flang/include/flang/Frontend/FrontendOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ enum ActionKind {
3131
/// -fsyntax-only
3232
ParseSyntaxOnly,
3333

34+
/// Emit a .mlir file
35+
EmitMLIR,
36+
3437
/// Emit a .o file.
3538
EmitObj,
3639

flang/lib/Frontend/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
2+
13
add_flang_library(flangFrontend
24
CompilerInstance.cpp
35
CompilerInvocation.cpp
@@ -19,6 +21,11 @@ add_flang_library(flangFrontend
1921
FortranLower
2022
clangBasic
2123
clangDriver
24+
FIRDialect
25+
FIRAnalysis
26+
FIRSupport
27+
FIRBuilder
28+
${dialect_libs}
2229

2330
LINK_COMPONENTS
2431
Option

flang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ static bool ParseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
123123
case clang::driver::options::OPT_fsyntax_only:
124124
opts.programAction = ParseSyntaxOnly;
125125
break;
126+
case clang::driver::options::OPT_emit_mlir:
127+
opts.programAction = EmitMLIR;
128+
break;
126129
case clang::driver::options::OPT_emit_obj:
127130
opts.programAction = EmitObj;
128131
break;

flang/lib/Frontend/FrontendActions.cpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,19 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "flang/Frontend/FrontendActions.h"
10+
#include "mlir/IR/Dialect.h"
11+
#include "mlir/Pass/PassManager.h"
12+
#include "mlir/Support/LogicalResult.h"
1013
#include "flang/Common/default-kinds.h"
1114
#include "flang/Frontend/CompilerInstance.h"
1215
#include "flang/Frontend/FrontendOptions.h"
1316
#include "flang/Frontend/PreprocessorOptions.h"
17+
#include "flang/Lower/Bridge.h"
1418
#include "flang/Lower/PFTBuilder.h"
19+
#include "flang/Lower/Support/Verifier.h"
20+
#include "flang/Optimizer/Dialect/FIRType.h"
21+
#include "flang/Optimizer/Support/InitFIR.h"
22+
#include "flang/Optimizer/Support/KindMapping.h"
1523
#include "flang/Parser/dump-parse-tree.h"
1624
#include "flang/Parser/parsing.h"
1725
#include "flang/Parser/provenance.h"
@@ -22,6 +30,7 @@
2230
#include "flang/Semantics/unparse-with-symbols.h"
2331
#include "llvm/ADT/StringRef.h"
2432
#include "llvm/Support/ErrorHandling.h"
33+
#include "llvm/Support/raw_ostream.h"
2534
#include <clang/Basic/Diagnostic.h>
2635
#include <memory>
2736

@@ -40,6 +49,10 @@ bool PrescanAndSemaAction::BeginSourceFileAction() {
4049
return RunPrescan() & RunParse() && RunSemanticChecks();
4150
}
4251

52+
bool CodeGenAction::BeginSourceFileAction() {
53+
return RunPrescan() & RunParse() && RunSemanticChecks();
54+
}
55+
4356
//===----------------------------------------------------------------------===//
4457
// Custom ExecuteAction
4558
//===----------------------------------------------------------------------===//
@@ -351,6 +364,77 @@ void GetSymbolsSourcesAction::ExecuteAction() {
351364
ci.semantics().DumpSymbolsSources(llvm::outs());
352365
}
353366

367+
// Translate front-end KINDs for use in the IR and code gen. Extracted from
368+
// bbc.cpp.
369+
static std::vector<fir::KindTy>
370+
fromDefaultKinds(const Fortran::common::IntrinsicTypeDefaultKinds &defKinds) {
371+
return {static_cast<fir::KindTy>(defKinds.GetDefaultKind(
372+
Fortran::common::TypeCategory::Character)),
373+
static_cast<fir::KindTy>(
374+
defKinds.GetDefaultKind(Fortran::common::TypeCategory::Complex)),
375+
static_cast<fir::KindTy>(defKinds.doublePrecisionKind()),
376+
static_cast<fir::KindTy>(
377+
defKinds.GetDefaultKind(Fortran::common::TypeCategory::Integer)),
378+
static_cast<fir::KindTy>(
379+
defKinds.GetDefaultKind(Fortran::common::TypeCategory::Logical)),
380+
static_cast<fir::KindTy>(
381+
defKinds.GetDefaultKind(Fortran::common::TypeCategory::Real))};
382+
}
383+
384+
void EmitMLIRAction::ExecuteAction() {
385+
CompilerInstance &ci = this->instance();
386+
387+
// Load the MLIR dialects required by Flang
388+
mlir::DialectRegistry registry;
389+
mlir::MLIRContext ctx(registry);
390+
fir::support::registerNonCodegenDialects(registry);
391+
fir::support::loadNonCodegenDialects(ctx);
392+
393+
// Create a LoweringBridge
394+
auto &defKinds = ci.invocation().semanticsContext().defaultKinds();
395+
fir::KindMapping kindMap(
396+
&ctx, llvm::ArrayRef<fir::KindTy>{fromDefaultKinds(defKinds)});
397+
auto lb = Fortran::lower::LoweringBridge::create(ctx, defKinds,
398+
ci.invocation().semanticsContext().intrinsics(), ci.parsing().allCooked(),
399+
"", kindMap);
400+
401+
// Create a parse tree and lower it to FIR
402+
auto &parseTree{*ci.parsing().parseTree()};
403+
lb.lower(parseTree, ci.invocation().semanticsContext());
404+
405+
// Run the default passes.
406+
mlir::PassManager pm(&ctx, mlir::OpPassManager::Nesting::Implicit);
407+
pm.enableVerifier(/*verifyPasses=*/true);
408+
pm.addPass(std::make_unique<Fortran::lower::VerifierPass>());
409+
mlir::ModuleOp mlirModule = lb.getModule();
410+
if (mlir::failed(pm.run(mlirModule))) {
411+
unsigned diagID =
412+
ci.diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error,
413+
"verification of lowering to FIR failed");
414+
ci.diagnostics().Report(diagID);
415+
return;
416+
}
417+
418+
// Print the output. If a pre-defined output stream exists, dump the MLIR
419+
// content there.
420+
if (!ci.IsOutputStreamNull()) {
421+
mlirModule.print(ci.GetOutputStream());
422+
return;
423+
}
424+
425+
// ... otherwise, print to a file.
426+
auto os{ci.CreateDefaultOutputFile(
427+
/*Binary=*/true, /*InFile=*/GetCurrentFileOrBufferName(), "mlir")};
428+
if (!os) {
429+
unsigned diagID = ci.diagnostics().getCustomDiagID(
430+
clang::DiagnosticsEngine::Error, "failed to create the output file");
431+
ci.diagnostics().Report(diagID);
432+
return;
433+
}
434+
435+
mlirModule.print(*os);
436+
}
437+
354438
void EmitObjAction::ExecuteAction() {
355439
CompilerInstance &ci = this->instance();
356440
unsigned DiagID = ci.diagnostics().getCustomDiagID(

flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ static std::unique_ptr<FrontendAction> CreateFrontendBaseAction(
3232
return std::make_unique<PrintPreprocessedAction>();
3333
case ParseSyntaxOnly:
3434
return std::make_unique<ParseSyntaxOnlyAction>();
35+
case EmitMLIR:
36+
return std::make_unique<EmitMLIRAction>();
3537
case EmitObj:
3638
return std::make_unique<EmitObjAction>();
3739
case DebugUnparse:

flang/test/Driver/driver-help-hidden.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
! CHECK-NEXT: -cpp Enable predefined and command line preprocessor macros
2323
! CHECK-NEXT: -c Only run preprocess, compile, and assemble steps
2424
! CHECK-NEXT: -D <macro>=<value> Define <macro> to <value> (or 1 if <value> omitted)
25+
! CHECK-NEXT: -emit-mlir Build the parse tree, then lower it to MLIR and dump
2526
! CHECK-NEXT: -E Only run the preprocessor
2627
! CHECK-NEXT: -falternative-parameter-statement
2728
! CHECK-NEXT: Enable the old style PARAMETER statement

flang/test/Driver/driver-help.f90

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
! HELP-NEXT: -cpp Enable predefined and command line preprocessor macros
2323
! HELP-NEXT: -c Only run preprocess, compile, and assemble steps
2424
! HELP-NEXT: -D <macro>=<value> Define <macro> to <value> (or 1 if <value> omitted)
25+
! HELP-NEXT: -emit-mlir Build the parse tree, then lower it to MLIR and dump
2526
! HELP-NEXT: -E Only run the preprocessor
2627
! HELP-NEXT: -falternative-parameter-statement
2728
! HELP-NEXT: Enable the old style PARAMETER statement
@@ -65,6 +66,7 @@
6566
! HELP-FC1-NEXT:OPTIONS:
6667
! HELP-FC1-NEXT: -cpp Enable predefined and command line preprocessor macros
6768
! HELP-FC1-NEXT: -D <macro>=<value> Define <macro> to <value> (or 1 if <value> omitted)
69+
! HELP-FC1-NEXT: -emit-mlir Build the parse tree, then lower it to MLIR and dump
6870
! HELP-FC1-NEXT: -emit-obj Emit native object files
6971
! HELP-FC1-NEXT: -E Only run the preprocessor
7072
! HELP-FC1-NEXT: -falternative-parameter-statement

0 commit comments

Comments
 (0)