[clang] 38101b4 - [flang][driver] Add support for -S and implement -c/-emit-obj

Andrzej Warzynski via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 9 07:49:35 PST 2022


Author: Andrzej Warzynski
Date: 2022-03-09T15:48:09Z
New Revision: 38101b4e95aa4983b7acf1e6351309db9ce5761b

URL: https://github.com/llvm/llvm-project/commit/38101b4e95aa4983b7acf1e6351309db9ce5761b
DIFF: https://github.com/llvm/llvm-project/commit/38101b4e95aa4983b7acf1e6351309db9ce5761b.diff

LOG: [flang][driver] Add support for -S and implement -c/-emit-obj

This patch adds support for:
  * `-S` in Flang's compiler and frontend drivers,
and implements:
  * `-emit-obj` in Flang's frontend driver and `-c` in Flang's compiler
    driver (this is consistent with Clang).
(these options were already available before, but only as placeholders).
The semantics of these options in Clang and Flang are identical.

The `EmitObjAction` frontend action is renamed as `BackendAction`. This
new name more accurately reflects the fact that this action will
primarily run the code-gen/backend pipeline in LLVM. It also makes more
sense as an action implementing both `-emit-obj` and `-S` (originally,
it was just `-emit-obj`).

`tripleName` from FirContext.cpp is deleted and, when a target triple is
required, `mlir::LLVM::LLVMDialect::getTargetTripleAttrName()` is used
instead. In practice, this means that `fir.triple` is replaced with
`llvm.target_triple`. The former was effectively ignored. The latter is
used when lowering from the LLVM dialect in MLIR to LLVM IR (i.e. it's
embedded in the generated LLVM IR module). The driver can then re-use
it when configuring the backend. With this change, the LLVM IR files
generated by e.g. `tco` will from now on contain the correct target
triple.

The code-gen.f90 test is replaced with code-gen-x86.f90 and
code-gen-aarch64.f90. With 2 seperate files we can verify that
`--target` is correctly taken into account. LIT configuration is updated
to enable e.g.:
```
! REQUIRES: aarch64-registered-target
```

Differential Revision: https://reviews.llvm.org/D120568

Added: 
    flang/test/Driver/code-gen-aarch64.f90
    flang/test/Driver/code-gen-x86.f90
    flang/test/Driver/emit-asm-aarch64.f90
    flang/test/Driver/emit-asm-x86.f90

Modified: 
    clang/include/clang/Driver/Options.td
    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/ExecuteCompilerInvocation.cpp
    flang/lib/Optimizer/Support/FIRContext.cpp
    flang/test/CMakeLists.txt
    flang/test/Driver/driver-help-hidden.f90
    flang/test/Driver/driver-help.f90
    flang/test/Driver/syntax-only.f90
    flang/test/Fir/target-rewrite-triple.fir
    flang/test/lit.cfg.py
    flang/test/lit.site.cfg.py.in
    flang/tools/flang-driver/fc1_main.cpp
    flang/unittests/Frontend/CMakeLists.txt
    flang/unittests/Frontend/FrontendActionTest.cpp

Removed: 
    flang/test/Driver/code-gen.f90


################################################################################
diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 3d49e6b165b38..fa54d4a7689cd 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -750,7 +750,7 @@ def Rpass_analysis_EQ : Joined<["-"], "Rpass-analysis=">, Group<R_value_Group>,
            "name matches the given POSIX regular expression">;
 def R_Joined : Joined<["-"], "R">, Group<R_Group>, Flags<[CC1Option, CoreOption]>,
   MetaVarName<"<remark>">, HelpText<"Enable the specified remark">;
-def S : Flag<["-"], "S">, Flags<[NoXarchOption,CC1Option]>, Group<Action_Group>,
+def S : Flag<["-"], "S">, Flags<[NoXarchOption,CC1Option,FlangOption,FC1Option]>, Group<Action_Group>,
   HelpText<"Only run preprocess and compilation steps">;
 def Tbss : JoinedOrSeparate<["-"], "Tbss">, Group<T_Group>,
   MetaVarName<"<addr>">, HelpText<"Set starting address of BSS to <addr>">;

diff  --git a/flang/include/flang/Frontend/FrontendActions.h b/flang/include/flang/Frontend/FrontendActions.h
index 0cb6d6301c066..34cabea590485 100644
--- a/flang/include/flang/Frontend/FrontendActions.h
+++ b/flang/include/flang/Frontend/FrontendActions.h
@@ -192,8 +192,19 @@ class EmitLLVMAction : public CodeGenAction {
   void ExecuteAction() override;
 };
 
-class EmitObjAction : public CodeGenAction {
+class BackendAction : public CodeGenAction {
+public:
+  enum class BackendActionTy {
+    Backend_EmitAssembly, ///< Emit native assembly files
+    Backend_EmitObj ///< Emit native object files
+  };
+
+  BackendAction(BackendActionTy act) : action{act} {};
+
+private:
   void ExecuteAction() override;
+
+  BackendActionTy action;
 };
 
 } // namespace Fortran::frontend

diff  --git a/flang/include/flang/Frontend/FrontendOptions.h b/flang/include/flang/Frontend/FrontendOptions.h
index c396822819ac6..b299c87ef15f1 100644
--- a/flang/include/flang/Frontend/FrontendOptions.h
+++ b/flang/include/flang/Frontend/FrontendOptions.h
@@ -40,6 +40,9 @@ enum ActionKind {
   /// Emit a .o file.
   EmitObj,
 
+  /// Emit a .s file.
+  EmitAssembly,
+
   /// Parse, unparse the parse-tree and output a Fortran source file
   DebugUnparse,
 

diff  --git a/flang/lib/Frontend/CMakeLists.txt b/flang/lib/Frontend/CMakeLists.txt
index 4f54ab7d7ce70..a68e0e9a74634 100644
--- a/flang/lib/Frontend/CMakeLists.txt
+++ b/flang/lib/Frontend/CMakeLists.txt
@@ -27,6 +27,8 @@ add_flang_library(flangFrontend
   FortranLower
   clangBasic
   clangDriver
+  LLVMAnalysis
+  LLVMTarget
   FIRDialect
   FIRSupport
   FIRBuilder

diff  --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index a1d730959f5fc..d1b0d0e532cd9 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -153,6 +153,9 @@ static bool ParseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
     case clang::driver::options::OPT_emit_obj:
       opts.programAction = EmitObj;
       break;
+    case clang::driver::options::OPT_S:
+      opts.programAction = EmitAssembly;
+      break;
     case clang::driver::options::OPT_fdebug_unparse:
       opts.programAction = DebugUnparse;
       break;

diff  --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index c72460f159e12..e30f6af7d489a 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -31,7 +31,13 @@
 #include "mlir/Pass/PassManager.h"
 #include "mlir/Target/LLVMIR/ModuleTranslation.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Passes/PassBuilder.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Target/TargetMachine.h"
 #include <clang/Basic/Diagnostic.h>
 #include <memory>
 
@@ -417,7 +423,6 @@ void CodeGenAction::GenerateLLVMIR() {
 
   pm.addPass(std::make_unique<Fortran::lower::VerifierPass>());
   pm.enableVerifier(/*verifyPasses=*/true);
-  mlir::PassPipelineCLParser passPipeline("", "Compiler passes to run");
 
   // Create the pass pipeline
   fir::createMLIRToLLVMPassPipeline(pm);
@@ -490,11 +495,90 @@ void EmitMLIRAction::ExecuteAction() {
   mlirModule->print(*os);
 }
 
-void EmitObjAction::ExecuteAction() {
+void BackendAction::ExecuteAction() {
   CompilerInstance &ci = this->instance();
-  unsigned DiagID = ci.diagnostics().getCustomDiagID(
-      clang::DiagnosticsEngine::Error, "code-generation is not available yet");
-  ci.diagnostics().Report(DiagID);
+  // Generate an LLVM module if it's not already present (it will already be
+  // present if the input file is an LLVM IR/BC file).
+  if (!llvmModule)
+    GenerateLLVMIR();
+
+  // Create `Target`
+  std::string error;
+  const std::string &theTriple = llvmModule->getTargetTriple();
+  const llvm::Target *theTarget =
+      llvm::TargetRegistry::lookupTarget(theTriple, error);
+  // TODO: Make this a diagnostic once `flang-new` can consume LLVM IR files
+  // (in which users could use unsupported triples)
+  assert(theTarget && "Failed to create Target");
+
+  // Create `TargetMachine`
+  std::unique_ptr<llvm::TargetMachine> TM;
+  TM.reset(theTarget->createTargetMachine(theTriple, /*CPU=*/"",
+      /*Features=*/"", llvm::TargetOptions(), llvm::None));
+  assert(TM && "Failed to create TargetMachine");
+  llvmModule->setDataLayout(TM->createDataLayout());
+
+  // If the output stream is a file, generate it and define the corresponding
+  // output stream. If a pre-defined output stream is available, we will use
+  // that instead.
+  //
+  // NOTE: `os` is a smart pointer that will be destroyed at the end of this
+  // method. However, it won't be written to until `CodeGenPasses` is
+  // destroyed. By defining `os` before `CodeGenPasses`, we make sure that the
+  // output stream won't be destroyed before it is written to. This only
+  // applies when an output file is used (i.e. there is no pre-defined output
+  // stream).
+  // TODO: Revisit once the new PM is ready (i.e. when `CodeGenPasses` is
+  // updated to use it).
+  std::unique_ptr<llvm::raw_pwrite_stream> os;
+  if (ci.IsOutputStreamNull()) {
+    // Get the output buffer/file
+    switch (action) {
+    case BackendActionTy::Backend_EmitAssembly:
+      os = ci.CreateDefaultOutputFile(
+          /*Binary=*/false, /*InFile=*/GetCurrentFileOrBufferName(), "s");
+      break;
+    case BackendActionTy::Backend_EmitObj:
+      os = ci.CreateDefaultOutputFile(
+          /*Binary=*/true, /*InFile=*/GetCurrentFileOrBufferName(), "o");
+      break;
+    }
+    if (!os) {
+      unsigned diagID = ci.diagnostics().getCustomDiagID(
+          clang::DiagnosticsEngine::Error, "failed to create the output file");
+      ci.diagnostics().Report(diagID);
+      return;
+    }
+  }
+
+  // Create an LLVM code-gen pass pipeline. Currently only the legacy pass
+  // manager is supported.
+  // TODO: Switch to the new PM once it's available in the backend.
+  llvm::legacy::PassManager CodeGenPasses;
+  CodeGenPasses.add(
+      createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis()));
+  llvm::Triple triple(theTriple);
+
+  std::unique_ptr<llvm::TargetLibraryInfoImpl> TLII =
+      std::make_unique<llvm::TargetLibraryInfoImpl>(triple);
+  assert(TLII && "Failed to create TargetLibraryInfo");
+  CodeGenPasses.add(new llvm::TargetLibraryInfoWrapperPass(*TLII));
+
+  llvm::CodeGenFileType cgft = (action == BackendActionTy::Backend_EmitAssembly)
+      ? llvm::CodeGenFileType::CGFT_AssemblyFile
+      : llvm::CodeGenFileType::CGFT_ObjectFile;
+  if (TM->addPassesToEmitFile(CodeGenPasses,
+          ci.IsOutputStreamNull() ? *os : ci.GetOutputStream(), nullptr,
+          cgft)) {
+    unsigned diagID =
+        ci.diagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error,
+            "emission of this file type is not supported");
+    ci.diagnostics().Report(diagID);
+    return;
+  }
+
+  // Run the code-gen passes
+  CodeGenPasses.run(*llvmModule);
 }
 
 void InitOnlyAction::ExecuteAction() {

diff  --git a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index d97833b376980..4e8c22550c406 100644
--- a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -38,7 +38,11 @@ static std::unique_ptr<FrontendAction> CreateFrontendBaseAction(
   case EmitLLVM:
     return std::make_unique<EmitLLVMAction>();
   case EmitObj:
-    return std::make_unique<EmitObjAction>();
+    return std::make_unique<BackendAction>(
+        BackendAction::BackendActionTy::Backend_EmitObj);
+  case EmitAssembly:
+    return std::make_unique<BackendAction>(
+        BackendAction::BackendActionTy::Backend_EmitAssembly);
   case DebugUnparse:
     return std::make_unique<DebugUnparseAction>();
   case DebugUnparseNoSema:

diff  --git a/flang/lib/Optimizer/Support/FIRContext.cpp b/flang/lib/Optimizer/Support/FIRContext.cpp
index 890364a0f1473..80dfa1c65d15a 100644
--- a/flang/lib/Optimizer/Support/FIRContext.cpp
+++ b/flang/lib/Optimizer/Support/FIRContext.cpp
@@ -12,19 +12,20 @@
 
 #include "flang/Optimizer/Support/FIRContext.h"
 #include "flang/Optimizer/Support/KindMapping.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/BuiltinOps.h"
 #include "llvm/Support/Host.h"
 
-static constexpr const char *tripleName = "fir.triple";
-
 void fir::setTargetTriple(mlir::ModuleOp mod, llvm::StringRef triple) {
   auto target = fir::determineTargetTriple(triple);
-  mod->setAttr(tripleName, mlir::StringAttr::get(mod.getContext(), target));
+  mod->setAttr(mlir::LLVM::LLVMDialect::getTargetTripleAttrName(),
+               mlir::StringAttr::get(mod.getContext(), target));
 }
 
 llvm::Triple fir::getTargetTriple(mlir::ModuleOp mod) {
-  if (auto target = mod->getAttrOfType<mlir::StringAttr>(tripleName))
+  if (auto target = mod->getAttrOfType<mlir::StringAttr>(
+          mlir::LLVM::LLVMDialect::getTargetTripleAttrName()))
     return llvm::Triple(target.getValue());
   return llvm::Triple(llvm::sys::getDefaultTargetTriple());
 }

diff  --git a/flang/test/CMakeLists.txt b/flang/test/CMakeLists.txt
index e2725d2c7182e..282426ec66d1a 100644
--- a/flang/test/CMakeLists.txt
+++ b/flang/test/CMakeLists.txt
@@ -46,7 +46,7 @@ set(FLANG_TEST_PARAMS
   flang_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py)
 
 set(FLANG_TEST_DEPENDS
-  flang-new llvm-config FileCheck count not module_files fir-opt tco bbc
+  flang-new llvm-config FileCheck count not module_files fir-opt tco bbc llvm-objdump
 )
 
 if (FLANG_INCLUDE_TESTS)

diff  --git a/flang/test/Driver/code-gen-aarch64.f90 b/flang/test/Driver/code-gen-aarch64.f90
new file mode 100644
index 0000000000000..aabfabb735fcb
--- /dev/null
+++ b/flang/test/Driver/code-gen-aarch64.f90
@@ -0,0 +1,31 @@
+! Test -emit-obj (X86)
+
+! REQUIRES: aarch64-registered-target, x86-registered-target
+
+!-------------
+! RUN COMMANDS
+!-------------
+! RUN: rm -f %t.o
+! RUN: %flang_fc1 -emit-obj -triple aarch64-unknown-linux-gnu %s -o %t.o
+! RUN: llvm-objdump --triple aarch64-unknown-linux-gnu --disassemble-all %t.o | FileCheck %s --check-prefix=CORRECT_TRIPLE
+! RUN: rm -f %t.o
+! RUN: %flang -c --target=aarch64-unknown-linux-gnu %s -o %t.o
+! RUN: llvm-objdump --triple aarch64-unknown-linux-gnu --disassemble-all %t.o | FileCheck %s --check-prefix=CORRECT_TRIPLE
+
+! RUN: %flang -c --target=aarch64-unknown-linux-gnu %s -o %t.o
+! RUN: llvm-objdump --triple x86_64-unknown-linux-gnu --disassemble-all %t.o | FileCheck %s --check-prefix=INCORRECT_TRIPLE
+
+!----------------
+! EXPECTED OUTPUT
+!----------------
+! CORRECT_TRIPLE-LABEL: <_QQmain>:
+! CORRECT_TRIPLE-NEXT:  	ret
+
+! When incorrect triple is used to disassemble, there won't be a ret instruction at all.
+! INCORRECT_TRIPLE-LABEL: <_QQmain>:
+! INCORRECT_TRIPLE-NOT:  	ret
+
+!------
+! INPUT
+!------
+end program

diff  --git a/flang/test/Driver/code-gen-x86.f90 b/flang/test/Driver/code-gen-x86.f90
new file mode 100644
index 0000000000000..e6306774346ef
--- /dev/null
+++ b/flang/test/Driver/code-gen-x86.f90
@@ -0,0 +1,32 @@
+! Test -emit-obj (X86)
+
+! REQUIRES: x86-registered-target, aarch64-registered-target
+! UNSUPPORTED: darwin, macos
+
+!-------------
+! RUN COMMANDS
+!-------------
+! RUN: rm -f %t.o
+! RUN: %flang_fc1 -triple x86_64-unknown-linux-gnu -emit-obj %s -o %t.o
+! RUN: llvm-objdump --triple x86_64-unknown-linux-gnu --disassemble-all %t.o | FileCheck %s --check-prefix=CORRECT_TRIPLE
+! RUN: rm -f %t.o
+! RUN: %flang --target=x86_64-unknown-linux-gnu -c %s -o %t.o
+! RUN: llvm-objdump --triple x86_64-unknown-linux-gnu --disassemble-all %t.o | FileCheck %s --check-prefix=CORRECT_TRIPLE
+
+! RUN: %flang -c --target=x86_64-unknown-linux-gnu %s -o %t.o
+! RUN: llvm-objdump --triple aarch64-unknown-linux-gnu --disassemble-all %t.o | FileCheck %s --check-prefix=INCORRECT_TRIPLE
+
+!----------------
+! EXPECTED OUTPUT
+!----------------
+! CORRECT_TRIPLE-LABEL: <_QQmain>:
+! CORRECT_TRIPLE-NEXT:  	retq
+
+! When incorrect triple is used to disassemble, there won't be a ret(q) instruction at all.
+! INCORRECT_TRIPLE-LABEL: <_QQmain>:
+! INCORRECT_TRIPLE-NOT:  	ret
+
+!------
+! INPUT
+!------
+end program

diff  --git a/flang/test/Driver/code-gen.f90 b/flang/test/Driver/code-gen.f90
deleted file mode 100644
index 53ee40d3d9cf8..0000000000000
--- a/flang/test/Driver/code-gen.f90
+++ /dev/null
@@ -1,19 +0,0 @@
-! Although code-generation is not yet available, we do have frontend actions
-! that correspond to `-c` and `-emit-obj`. For now these actions are just a
-! placeholder and running them leads to a driver error. This test makes sure
-! that these actions are indeed run (rather than `-c` or `-emit-obj` being
-! rejected earlier).
-! TODO: Replace this file with a proper test once code-generation is available.
-
-!-----------
-! RUN LINES
-!-----------
-! RUN: not %flang %s 2>&1 | FileCheck %s --check-prefix=ERROR
-! RUN: not %flang -c %s 2>&1 | FileCheck %s --check-prefix=ERROR
-! RUN: not %flang -emit-obj %s 2>&1 | FileCheck %s --check-prefix=ERROR
-! RUN: not %flang -fc1 -emit-obj %s 2>&1 | FileCheck %s --check-prefix=ERROR
-
-!-----------------------
-! EXPECTED OUTPUT
-!-----------------------
-! ERROR: code-generation is not available yet

diff  --git a/flang/test/Driver/driver-help-hidden.f90 b/flang/test/Driver/driver-help-hidden.f90
index 5aed6f25ae52f..150900a281e85 100644
--- a/flang/test/Driver/driver-help-hidden.f90
+++ b/flang/test/Driver/driver-help-hidden.f90
@@ -55,6 +55,7 @@
 ! CHECK-NEXT: -print-target-triple    Print the normalized target triple
 ! CHECK-NEXT: -P                     Disable linemarker output in -E mode
 ! CHECK-NEXT: -std=<value>           Language standard to compile for
+! CHECK-NEXT: -S                     Only run preprocess and compilation steps
 ! CHECK-NEXT: --target=<value>        Generate code for the given target
 ! CHECK-NEXT: -U <macro>             Undefine macro <macro>
 ! CHECK-NEXT: --version Print version information

diff  --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90
index 560c67537ef64..fd192203e4f35 100644
--- a/flang/test/Driver/driver-help.f90
+++ b/flang/test/Driver/driver-help.f90
@@ -55,6 +55,7 @@
 ! HELP-NEXT: -print-target-triple    Print the normalized target triple
 ! HELP-NEXT: -P                     Disable linemarker output in -E mode
 ! HELP-NEXT: -std=<value>           Language standard to compile for
+! HELP-NEXT: -S                     Only run preprocess and compilation steps
 ! HELP-NEXT: --target=<value>       Generate code for the given target
 ! HELP-NEXT: -U <macro>             Undefine macro <macro>
 ! HELP-NEXT: --version              Print version information
@@ -128,6 +129,7 @@
 ! HELP-FC1-NEXT: -plugin <name>         Use the named plugin action instead of the default action (use "help" to list available options)
 ! HELP-FC1-NEXT: -P                     Disable linemarker output in -E mode
 ! HELP-FC1-NEXT: -std=<value>           Language standard to compile for
+! HELP-FC1-NEXT: -S                     Only run preprocess and compilation steps
 ! HELP-FC1-NEXT: -test-io               Run the InputOuputTest action. Use for development and testing only.
 ! HELP-FC1-NEXT: -triple <value>        Specify target triple (e.g. i686-apple-darwin9)
 ! HELP-FC1-NEXT: -U <macro>             Undefine macro <macro>

diff  --git a/flang/test/Driver/emit-asm-aarch64.f90 b/flang/test/Driver/emit-asm-aarch64.f90
new file mode 100644
index 0000000000000..4c849859a68a9
--- /dev/null
+++ b/flang/test/Driver/emit-asm-aarch64.f90
@@ -0,0 +1,21 @@
+! Test -S (AArch64)
+
+! REQUIRES: aarch64-registered-target
+
+!-------------
+! RUN COMMANDS
+!-------------
+! RUN: %flang_fc1 -S -triple aarch64-unknown-linux-gnu %s -o - | FileCheck %s
+! RUN: %flang -S -target aarch64-unknown-linux-gnu %s -o - | FileCheck %s
+
+!----------------
+! EXPECTED OUTPUT
+!----------------
+! CHECK-LABEL: _QQmain:
+! CHECK-NEXT: .Lfunc_begin0:
+! CHECK: ret
+
+!------
+! INPUT
+!------
+end program

diff  --git a/flang/test/Driver/emit-asm-x86.f90 b/flang/test/Driver/emit-asm-x86.f90
new file mode 100644
index 0000000000000..c79406c4244d0
--- /dev/null
+++ b/flang/test/Driver/emit-asm-x86.f90
@@ -0,0 +1,21 @@
+! Test -S (X86)
+
+! REQUIRES: x86-registered-target
+
+!-------------
+! RUN COMMANDS
+!-------------
+! RUN: %flang_fc1 -S -triple x86_64-unknown-linux-gnu %s -o - | FileCheck %s
+! RUN: %flang -S -target x86_64-unknown-linux-gnu %s -o - | FileCheck %s
+
+!----------------
+! EXPECTED OUTPUT
+!----------------
+! CHECK-LABEL: _QQmain:
+! CHECK-NEXT: .Lfunc_begin0:
+! CHECK: ret
+
+!------
+! INPUT
+!------
+end program

diff  --git a/flang/test/Driver/syntax-only.f90 b/flang/test/Driver/syntax-only.f90
index a97abee23001a..df831e09684fb 100644
--- a/flang/test/Driver/syntax-only.f90
+++ b/flang/test/Driver/syntax-only.f90
@@ -13,14 +13,15 @@
 ! 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
+! RUN: rm -rf %t/non-existent-dir/
+! RUN: not %flang -c %s -o %t/non-existent-dir/syntax-only.o 2>&1 | FileCheck %s --check-prefix=NO_FSYNTAX_ONLY
+! RUN: not %flang_fc1 -emit-obj %s -o %t/non-existent-dir/syntax-only.o 2>&1 | FileCheck %s --check-prefix=NO_FSYNTAX_ONLY
 
 !-----------------
 ! EXPECTED OUTPUT
 !-----------------
 ! CHECK-NOT: error
-! NO_FSYNTAX_ONLY: error: code-generation is not available yet
+! NO_FSYNTAX_ONLY: error: failed to create the output file
 
 !-------
 ! INPUT

diff  --git a/flang/test/Fir/target-rewrite-triple.fir b/flang/test/Fir/target-rewrite-triple.fir
index ccaf4fa68b5b5..b9e61b310398e 100644
--- a/flang/test/Fir/target-rewrite-triple.fir
+++ b/flang/test/Fir/target-rewrite-triple.fir
@@ -1,10 +1,10 @@
 // RUN: fir-opt --target-rewrite %s | FileCheck %s --check-prefix=UNCHANGED
 // RUN: fir-opt --target-rewrite="target=x86_64-unknown-linux-gnu" %s | FileCheck %s --check-prefix=CHANGED
 
-// UNCHANGED: fir.triple = "aarch64-unknown-linux-gnu"
-// CHANGED: fir.triple = "x86_64-unknown-linux-gnu"
-// CHANGED-NOT: fir.triple = "aarch64-unknown-linux-gnu"
-module attributes {fir.triple = "aarch64-unknown-linux-gnu"}  {
+// UNCHANGED: llvm.target_triple = "aarch64-unknown-linux-gnu"
+// CHANGED: llvm.target_triple = "x86_64-unknown-linux-gnu"
+// CHANGED-NOT: llvm.target_triple = "aarch64-unknown-linux-gnu"
+module attributes {llvm.target_triple = "aarch64-unknown-linux-gnu"}  {
   func @dummyfunc() -> () {
     return
   }

diff  --git a/flang/test/lit.cfg.py b/flang/test/lit.cfg.py
index 3942198454620..9578ab9fff62c 100644
--- a/flang/test/lit.cfg.py
+++ b/flang/test/lit.cfg.py
@@ -39,6 +39,11 @@
 llvm_config.feature_config(
     [('--assertion-mode', {'ON': 'asserts'})])
 
+# Targets
+config.targets = frozenset(config.targets_to_build.split())
+for arch in config.targets_to_build.split():
+    config.available_features.add(arch.lower() + '-registered-target')
+
 # excludes: A list of directories to exclude from the testsuite. The 'Inputs'
 # subdirectories contain auxiliary inputs for various tests in their parent
 # directories.

diff  --git a/flang/test/lit.site.cfg.py.in b/flang/test/lit.site.cfg.py.in
index 378602dd71568..5619dd62b1f24 100644
--- a/flang/test/lit.site.cfg.py.in
+++ b/flang/test/lit.site.cfg.py.in
@@ -18,6 +18,7 @@ config.python_executable = "@PYTHON_EXECUTABLE@"
 config.flang_standalone_build = @FLANG_STANDALONE_BUILD@
 config.has_plugins = @LLVM_ENABLE_PLUGINS@
 config.cc = "@CMAKE_C_COMPILER@"
+config.targets_to_build = "@TARGETS_TO_BUILD@"
 
 # Support substitution of the tools_dir with user parameters. This is
 # used when we can't determine the tool dir at configuration time.

diff  --git a/flang/tools/flang-driver/fc1_main.cpp b/flang/tools/flang-driver/fc1_main.cpp
index ecdceb9ba1cd0..ff9d3c79bb38e 100644
--- a/flang/tools/flang-driver/fc1_main.cpp
+++ b/flang/tools/flang-driver/fc1_main.cpp
@@ -20,6 +20,7 @@
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/OptTable.h"
+#include "llvm/Support/TargetSelect.h"
 
 #include <cstdio>
 
@@ -48,6 +49,11 @@ int fc1_main(llvm::ArrayRef<const char *> argv, const char *argv0) {
   bool success =
       CompilerInvocation::CreateFromArgs(flang->invocation(), argv, diags);
 
+  // Initialize targets first, so that --version shows registered targets.
+  llvm::InitializeAllTargets();
+  llvm::InitializeAllTargetMCs();
+  llvm::InitializeAllAsmPrinters();
+
   diagsBuffer->FlushDiagnostics(flang->diagnostics());
 
   if (!success)

diff  --git a/flang/unittests/Frontend/CMakeLists.txt b/flang/unittests/Frontend/CMakeLists.txt
index b78adf3f50229..739412c7888c4 100644
--- a/flang/unittests/Frontend/CMakeLists.txt
+++ b/flang/unittests/Frontend/CMakeLists.txt
@@ -1,3 +1,7 @@
+set(LLVM_LINK_COMPONENTS
+  ${LLVM_TARGETS_TO_BUILD}
+)
+
 add_flang_unittest(FlangFrontendTests
   CompilerInstanceTest.cpp
   FrontendActionTest.cpp

diff  --git a/flang/unittests/Frontend/FrontendActionTest.cpp b/flang/unittests/Frontend/FrontendActionTest.cpp
index 81a57be1fad01..b88f1ab8710f0 100644
--- a/flang/unittests/Frontend/FrontendActionTest.cpp
+++ b/flang/unittests/Frontend/FrontendActionTest.cpp
@@ -11,6 +11,7 @@
 #include "flang/Frontend/FrontendOptions.h"
 #include "flang/FrontendTool/Utils.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/raw_ostream.h"
 
 #include "gtest/gtest.h"
@@ -188,4 +189,35 @@ TEST_F(FrontendActionTest, EmitLLVM) {
   EXPECT_TRUE(llvm::StringRef(outputFileBuffer.data())
                   .contains("define void @_QQmain()"));
 }
+
+TEST_F(FrontendActionTest, EmitAsm) {
+  // Populate the input file with the pre-defined input and flush it.
+  *(inputFileOs_) << "end program";
+  inputFileOs_.reset();
+
+  // Set-up the action kind.
+  compInst_.invocation().frontendOpts().programAction = EmitAssembly;
+  compInst_.invocation().preprocessorOpts().noReformat = true;
+
+  // Initialise LLVM backend
+  llvm::InitializeAllTargets();
+  llvm::InitializeAllTargetMCs();
+  llvm::InitializeAllAsmPrinters();
+
+  // Set-up the output stream. We are using output buffer wrapped as an output
+  // stream, as opposed to an actual file (or a file descriptor).
+  llvm::SmallVector<char, 256> outputFileBuffer;
+  std::unique_ptr<llvm::raw_pwrite_stream> outputFileStream(
+      new llvm::raw_svector_ostream(outputFileBuffer));
+  compInst_.set_outputStream(std::move(outputFileStream));
+
+  // Execute the action.
+  bool success = ExecuteCompilerInvocation(&compInst_);
+
+  // Validate the expected output.
+  EXPECT_TRUE(success);
+  EXPECT_TRUE(!outputFileBuffer.empty());
+
+  EXPECT_TRUE(llvm::StringRef(outputFileBuffer.data()).contains("_QQmain"));
+}
 } // namespace


        


More information about the cfe-commits mailing list