awarzynski updated this revision to Diff 406398. awarzynski added a comment.
Remove `auto`, update comment Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D118985/new/ https://reviews.llvm.org/D118985 Files: clang/include/clang/Driver/Options.td flang/include/flang/Frontend/CompilerInstance.h flang/include/flang/Frontend/FrontendActions.h flang/include/flang/Frontend/FrontendOptions.h flang/lib/Frontend/CMakeLists.txt flang/lib/Frontend/CompilerInvocation.cpp flang/lib/Frontend/FrontendActions.cpp flang/lib/FrontendTool/CMakeLists.txt flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp flang/test/Driver/driver-help.f90 flang/test/Driver/emit-mlir.f90 flang/test/Driver/syntax-only.f90
Index: flang/test/Driver/syntax-only.f90 =================================================================== --- flang/test/Driver/syntax-only.f90 +++ flang/test/Driver/syntax-only.f90 @@ -1,24 +1,28 @@ -! Verify that the compiler driver correctly processes `-fsyntax-only`. By -! default it will try to run code-generation, but that's not supported yet. We -! don't need to test the frontend driver here - it runs `-fsyntax-only` by -! default. +! Verify that the driver correctly processes `-fsyntax-only`. +! +! By default, the compiler driver (`flang`) will create actions/phases to +! generate machine code (i.e. object files). The `-fsyntax-only` flag is a +! "phase-control" flag that controls this behavior and makes the driver stop +! once the semantic checks have been run. The frontend driver (`flang -fc1`) +! runs `-fsyntax-only` by default (i.e. that's the default action), so the flag +! can be skipped. !----------- ! RUN LINES !----------- -! RUN: not %flang -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix=FSYNTAX_ONLY +! RUN: %flang -fsyntax-only %s 2>&1 | FileCheck %s --allow-empty +! RUN: %flang_fc1 %s 2>&1 | FileCheck %s --allow-empty + ! RUN: not %flang %s 2>&1 | FileCheck %s --check-prefix=NO_FSYNTAX_ONLY +! RUN: not %flang_fc1 -emit-obj %s 2>&1 | FileCheck %s --check-prefix=NO_FSYNTAX_ONLY !----------------- ! EXPECTED OUTPUT !----------------- -! FSYNTAX_ONLY: IF statement is not allowed in IF statement -! FSYNTAX_ONLY_NEXT: Semantic errors in {{.*}}syntax-only.f90 - +! CHECK-NOT: error ! NO_FSYNTAX_ONLY: error: code-generation is not available yet !------- ! INPUT !------- -IF (A > 0.0) IF (B < 0.0) A = LOG (A) -END +end program Index: flang/test/Driver/emit-mlir.f90 =================================================================== --- /dev/null +++ flang/test/Driver/emit-mlir.f90 @@ -0,0 +1,21 @@ +! The `-emit-mlir` option + +!------------- +! RUN COMMANDS +!------------- +! RUN: %flang_fc1 -emit-mlir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +!---------------- +! EXPECTED OUTPUT +!---------------- +! CHECK: module attributes { +! CHECK-LABEL: func @_QQmain() { +! CHECK-NEXT: return +! CHECK-NEXT: } +! CHECK-NEXT: } + +!------ +! INPUT +!------ +end program Index: flang/test/Driver/driver-help.f90 =================================================================== --- flang/test/Driver/driver-help.f90 +++ flang/test/Driver/driver-help.f90 @@ -65,6 +65,7 @@ ! HELP-FC1-NEXT:OPTIONS: ! HELP-FC1-NEXT: -cpp Enable predefined and command line preprocessor macros ! HELP-FC1-NEXT: -D <macro>=<value> Define <macro> to <value> (or 1 if <value> omitted) +! HELP-FC1-NEXT: -emit-mlir Build the parse tree, then lower it to MLIR ! HELP-FC1-NEXT: -emit-obj Emit native object files ! HELP-FC1-NEXT: -E Only run the preprocessor ! HELP-FC1-NEXT: -falternative-parameter-statement Index: flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp =================================================================== --- flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -33,6 +33,8 @@ return std::make_unique<PrintPreprocessedAction>(); case ParseSyntaxOnly: return std::make_unique<ParseSyntaxOnlyAction>(); + case EmitMLIR: + return std::make_unique<EmitMLIRAction>(); case EmitObj: return std::make_unique<EmitObjAction>(); case DebugUnparse: Index: flang/lib/FrontendTool/CMakeLists.txt =================================================================== --- flang/lib/FrontendTool/CMakeLists.txt +++ flang/lib/FrontendTool/CMakeLists.txt @@ -2,6 +2,9 @@ ExecuteCompilerInvocation.cpp DEPENDS + # This makes sure that the MLIR dependencies of flangFrontend (which are + # transitively required here) are generated before this target is build. + flangFrontend clangBasic LINK_LIBS Index: flang/lib/Frontend/FrontendActions.cpp =================================================================== --- flang/lib/Frontend/FrontendActions.cpp +++ flang/lib/Frontend/FrontendActions.cpp @@ -11,7 +11,12 @@ #include "flang/Frontend/CompilerInstance.h" #include "flang/Frontend/FrontendOptions.h" #include "flang/Frontend/PreprocessorOptions.h" +#include "flang/Lower/Bridge.h" #include "flang/Lower/PFTBuilder.h" +#include "flang/Lower/Support/Verifier.h" +#include "flang/Optimizer/Support/InitFIR.h" +#include "flang/Optimizer/Support/KindMapping.h" +#include "flang/Optimizer/Support/Utils.h" #include "flang/Parser/dump-parse-tree.h" #include "flang/Parser/parsing.h" #include "flang/Parser/provenance.h" @@ -20,6 +25,9 @@ #include "flang/Semantics/runtime-type-info.h" #include "flang/Semantics/semantics.h" #include "flang/Semantics/unparse-with-symbols.h" + +#include "mlir/IR/Dialect.h" +#include "mlir/Pass/PassManager.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" #include <clang/Basic/Diagnostic.h> @@ -45,6 +53,49 @@ return RunPrescan() && RunParse() && (RunSemanticChecks() || true); } +bool CodeGenAction::BeginSourceFileAction() { + bool res = RunPrescan() && RunParse() && RunSemanticChecks(); + if (!res) + return res; + + CompilerInstance &ci = this->instance(); + + // Load the MLIR dialects required by Flang + mlir::DialectRegistry registry; + mlirCtx = std::make_unique<mlir::MLIRContext>(registry); + fir::support::registerNonCodegenDialects(registry); + fir::support::loadNonCodegenDialects(*mlirCtx); + + // Create a LoweringBridge + const common::IntrinsicTypeDefaultKinds &defKinds = + ci.invocation().semanticsContext().defaultKinds(); + fir::KindMapping kindMap(mlirCtx.get(), + llvm::ArrayRef<fir::KindTy>{fir::fromDefaultKinds(defKinds)}); + lower::LoweringBridge lb = Fortran::lower::LoweringBridge::create(*mlirCtx, + defKinds, ci.invocation().semanticsContext().intrinsics(), + ci.parsing().allCooked(), "", kindMap); + + // Create a parse tree and lower it to FIR + Fortran::parser::Program &parseTree{*ci.parsing().parseTree()}; + lb.lower(parseTree, ci.invocation().semanticsContext()); + mlirModule = std::make_unique<mlir::ModuleOp>(lb.getModule()); + + // Run the default passes. + mlir::PassManager pm(mlirCtx.get(), mlir::OpPassManager::Nesting::Implicit); + pm.enableVerifier(/*verifyPasses=*/true); + pm.addPass(std::make_unique<Fortran::lower::VerifierPass>()); + + if (mlir::failed(pm.run(*mlirModule))) { + unsigned diagID = + ci.diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, + "verification of lowering to FIR failed"); + ci.diagnostics().Report(diagID); + return false; + } + + return true; +} + //===----------------------------------------------------------------------===// // Custom ExecuteAction //===----------------------------------------------------------------------===// @@ -356,6 +407,29 @@ ci.semantics().DumpSymbolsSources(llvm::outs()); } +void EmitMLIRAction::ExecuteAction() { + CompilerInstance &ci = this->instance(); + + // Print the output. If a pre-defined output stream exists, dump the MLIR + // content there. + if (!ci.IsOutputStreamNull()) { + mlirModule->print(ci.GetOutputStream()); + return; + } + + // ... otherwise, print to a file. + std::unique_ptr<llvm::raw_pwrite_stream> os{ci.CreateDefaultOutputFile( + /*Binary=*/true, /*InFile=*/GetCurrentFileOrBufferName(), "mlir")}; + if (!os) { + unsigned diagID = ci.diagnostics().getCustomDiagID( + clang::DiagnosticsEngine::Error, "failed to create the output file"); + ci.diagnostics().Report(diagID); + return; + } + + mlirModule->print(*os); +} + void EmitObjAction::ExecuteAction() { CompilerInstance &ci = this->instance(); unsigned DiagID = ci.diagnostics().getCustomDiagID( Index: flang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- flang/lib/Frontend/CompilerInvocation.cpp +++ flang/lib/Frontend/CompilerInvocation.cpp @@ -134,6 +134,9 @@ case clang::driver::options::OPT_fsyntax_only: opts.programAction = ParseSyntaxOnly; break; + case clang::driver::options::OPT_emit_mlir: + opts.programAction = EmitMLIR; + break; case clang::driver::options::OPT_emit_obj: opts.programAction = EmitObj; break; Index: flang/lib/Frontend/CMakeLists.txt =================================================================== --- flang/lib/Frontend/CMakeLists.txt +++ flang/lib/Frontend/CMakeLists.txt @@ -1,3 +1,5 @@ +get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS) + add_flang_library(flangFrontend CompilerInstance.cpp CompilerInvocation.cpp @@ -10,6 +12,10 @@ DEPENDS clangBasic + FIRBuilder + FIRDialect + FIRSupport + ${dialect_libs} LINK_LIBS FortranParser @@ -19,6 +25,15 @@ FortranLower clangBasic clangDriver + FIRDialect + FIRSupport + FIRBuilder + FIRCodeGen + FIRTransforms + MLIRTransforms + MLIRLLVMToLLVMIRTranslation + MLIRSCFToControlFlow + ${dialect_libs} LINK_COMPONENTS Option Index: flang/include/flang/Frontend/FrontendOptions.h =================================================================== --- flang/include/flang/Frontend/FrontendOptions.h +++ flang/include/flang/Frontend/FrontendOptions.h @@ -31,6 +31,9 @@ /// -fsyntax-only ParseSyntaxOnly, + /// Emit a .mlir file + EmitMLIR, + /// Emit a .o file. EmitObj, Index: flang/include/flang/Frontend/FrontendActions.h =================================================================== --- flang/include/flang/Frontend/FrontendActions.h +++ flang/include/flang/Frontend/FrontendActions.h @@ -11,6 +11,8 @@ #include "flang/Frontend/FrontendAction.h" #include "flang/Semantics/semantics.h" + +#include "mlir/IR/BuiltinOps.h" #include <memory> namespace Fortran::frontend { @@ -34,10 +36,6 @@ void ExecuteAction() override; }; -class EmitObjAction : public FrontendAction { - void ExecuteAction() override; -}; - class InitOnlyAction : public FrontendAction { void ExecuteAction() override; }; @@ -146,6 +144,35 @@ void ExecuteAction() override; }; +//===----------------------------------------------------------------------===// +// CodeGen Actions +//===----------------------------------------------------------------------===// +/// Abstract base class for actions that generate code (MLIR, LLVM IR, assembly +/// and machine code). Every action that inherits from this class will at +/// least run the prescanning, parsing, semantic checks and lower the parse +/// tree to an MLIR module. +class CodeGenAction : public FrontendAction { + + void ExecuteAction() override = 0; + /// Runs prescan, parsing, sema and lowers to MLIR. + bool BeginSourceFileAction() override; + +protected: + /// @name MLIR + /// { + std::unique_ptr<mlir::ModuleOp> mlirModule; + std::unique_ptr<mlir::MLIRContext> mlirCtx; + /// } +}; + +class EmitMLIRAction : public CodeGenAction { + void ExecuteAction() override; +}; + +class EmitObjAction : public CodeGenAction { + void ExecuteAction() override; +}; + } // namespace Fortran::frontend #endif // LLVM_FLANG_FRONTEND_FRONTENDACTIONS_H Index: flang/include/flang/Frontend/CompilerInstance.h =================================================================== --- flang/include/flang/Frontend/CompilerInstance.h +++ flang/include/flang/Frontend/CompilerInstance.h @@ -250,6 +250,13 @@ void WriteOutputStream(const std::string &message) { *outputStream_ << message; } + + /// Get the user specified output stream. + llvm::raw_pwrite_stream &GetOutputStream() { + assert(outputStream_ && + "Compiler instance has no user-specified output stream!"); + return *outputStream_; + } }; } // end namespace Fortran::frontend Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -4747,6 +4747,10 @@ HelpText<"Dump the cooked character stream in -E mode">; defm analyzed_objects_for_unparse : OptOutFC1FFlag<"analyzed-objects-for-unparse", "", "Do not use the analyzed objects when unparsing">; +def emit_mlir : Flag<["-"], "emit-mlir">, Group<Action_Group>, + HelpText<"Build the parse tree, then lower it to MLIR">; +def emit_fir : Flag<["-"], "emit-fir">, Alias<emit_mlir>; + } //===----------------------------------------------------------------------===//
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits