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

Reply via email to