[flang-commits] [flang] b9f3b7f - [flang][driver] Add support for consuming LLVM IR/BC files

Andrzej Warzynski via flang-commits flang-commits at lists.llvm.org
Thu May 5 08:12:23 PDT 2022


Author: Andrzej Warzynski
Date: 2022-05-05T15:11:50Z
New Revision: b9f3b7f89a4cb4cf541b7116d9389c73690f78fa

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

LOG: [flang][driver] Add support for consuming LLVM IR/BC files

This change makes sure that Flang's driver recognises LLVM IR and BC as
supported file formats. To this end, `isFortran` is extended and renamed
as `isSupportedByFlang` (the latter better reflects the new
functionality).

New tests are added to verify that the target triple is correctly
overridden by the frontend driver's default value or the value specified
with `-triple`. Strictly speaking, this is not a functionality that's
new in this patch (it was added in D124664). This patch simply enables
us to write such tests and hence I'm including them here.

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

Added: 
    flang/test/Driver/emit-asm-from-llvm-bc.ll
    flang/test/Driver/emit-asm-from-llvm.ll
    flang/test/Driver/missing-triple.ll
    flang/test/Driver/override-triple.ll

Modified: 
    clang/include/clang/Driver/Types.h
    clang/lib/Driver/Driver.cpp
    clang/lib/Driver/Types.cpp
    flang/lib/Frontend/CMakeLists.txt
    flang/lib/Frontend/FrontendActions.cpp
    flang/lib/Frontend/FrontendOptions.cpp
    flang/test/lit.cfg.py

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Driver/Types.h b/clang/include/clang/Driver/Types.h
index 4aecf7ee1e5286..fc5dd7bbfd6f55 100644
--- a/clang/include/clang/Driver/Types.h
+++ b/clang/include/clang/Driver/Types.h
@@ -66,6 +66,9 @@ namespace types {
   /// isAcceptedByClang - Can clang handle this input type.
   bool isAcceptedByClang(ID Id);
 
+  /// isAcceptedByFlang - Can flang handle this input type.
+  bool isAcceptedByFlang(ID Id);
+
   /// isDerivedFromC - Is the input derived from C.
   ///
   /// That is, does the lexer follow the rules of
@@ -92,9 +95,6 @@ namespace types {
   /// isOpenCL - Is this an "OpenCL" input.
   bool isOpenCL(ID Id);
 
-  /// isFortran - Is this a Fortran input.
-  bool isFortran(ID Id);
-
   /// isSrcFile - Is this a source file, i.e. something that still has to be
   /// preprocessed. The logic behind this is the same that decides if the first
   /// compilation phase is a preprocessing one.

diff  --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 8f71634a7fc03c..5bba896d8c3784 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -6050,11 +6050,12 @@ bool Driver::ShouldUseClangCompiler(const JobAction &JA) const {
 bool Driver::ShouldUseFlangCompiler(const JobAction &JA) const {
   // Say "no" if there is not exactly one input of a type flang understands.
   if (JA.size() != 1 ||
-      !types::isFortran((*JA.input_begin())->getType()))
+      !types::isAcceptedByFlang((*JA.input_begin())->getType()))
     return false;
 
   // And say "no" if this is not a kind of action flang understands.
-  if (!isa<PreprocessJobAction>(JA) && !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA))
+  if (!isa<PreprocessJobAction>(JA) && !isa<CompileJobAction>(JA) &&
+      !isa<BackendJobAction>(JA))
     return false;
 
   return true;

diff  --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp
index 1115e8c7710cf2..66da6fe97059a0 100644
--- a/clang/lib/Driver/Types.cpp
+++ b/clang/lib/Driver/Types.cpp
@@ -159,6 +159,20 @@ bool types::isAcceptedByClang(ID Id) {
   }
 }
 
+bool types::isAcceptedByFlang(ID Id) {
+  switch (Id) {
+  default:
+    return false;
+
+  case TY_Fortran:
+  case TY_PP_Fortran:
+    return true;
+  case TY_LLVM_IR:
+  case TY_LLVM_BC:
+    return true;
+  }
+}
+
 bool types::isDerivedFromC(ID Id) {
   switch (Id) {
   default:
@@ -272,16 +286,6 @@ bool types::isHIP(ID Id) {
   }
 }
 
-bool types::isFortran(ID Id) {
-  switch (Id) {
-  default:
-    return false;
-
-  case TY_Fortran: case TY_PP_Fortran:
-    return true;
-  }
-}
-
 bool types::isSrcFile(ID Id) {
   return Id != TY_Object && getPreprocessedType(Id) != TY_INVALID;
 }

diff  --git a/flang/lib/Frontend/CMakeLists.txt b/flang/lib/Frontend/CMakeLists.txt
index 8e186616fb8180..476dff0a76cfac 100644
--- a/flang/lib/Frontend/CMakeLists.txt
+++ b/flang/lib/Frontend/CMakeLists.txt
@@ -40,6 +40,7 @@ add_flang_library(flangFrontend
   LINK_COMPONENTS
   Passes
   Analysis
+  IRReader
   Option
   Support
   Target

diff  --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 3965c490227164..2ff121d2a241cb 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -73,6 +73,19 @@ bool PrescanAndSemaDebugAction::BeginSourceFileAction() {
 }
 
 bool CodeGenAction::BeginSourceFileAction() {
+  llvmCtx = std::make_unique<llvm::LLVMContext>();
+
+  // If the input is an LLVM file, just parse it and return.
+  if (this->currentInput().kind().GetLanguage() == Language::LLVM_IR) {
+    llvm::SMDiagnostic err;
+    llvmModule = llvm::parseIRFile(currentInput().file(), err, *llvmCtx);
+
+    return (nullptr != llvmModule);
+  }
+
+  // Otherwise, generate an MLIR module from the input Fortran source
+  assert(currentInput().kind().GetLanguage() == Language::Fortran &&
+         "Invalid input type - expecting a Fortran file");
   bool res = RunPrescan() && RunParse() && RunSemanticChecks();
   if (!res)
     return res;
@@ -448,7 +461,6 @@ void CodeGenAction::GenerateLLVMIR() {
 
   // Translate to LLVM IR
   llvm::Optional<llvm::StringRef> moduleName = mlirModule->getName();
-  llvmCtx = std::make_unique<llvm::LLVMContext>();
   llvmModule = mlir::translateModuleToLLVMIR(
       *mlirModule, *llvmCtx, moduleName ? *moduleName : "FIRModule");
 

diff  --git a/flang/lib/Frontend/FrontendOptions.cpp b/flang/lib/Frontend/FrontendOptions.cpp
index 886baa39ee571e..fe62175a5e395a 100644
--- a/flang/lib/Frontend/FrontendOptions.cpp
+++ b/flang/lib/Frontend/FrontendOptions.cpp
@@ -35,5 +35,9 @@ InputKind FrontendOptions::GetInputKindForExtension(llvm::StringRef extension) {
   if (isFixedFormSuffix(extension) || isFreeFormSuffix(extension)) {
     return Language::Fortran;
   }
+
+  if (extension == "bc" || extension == "ll")
+    return Language::LLVM_IR;
+
   return Language::Unknown;
 }

diff  --git a/flang/test/Driver/emit-asm-from-llvm-bc.ll b/flang/test/Driver/emit-asm-from-llvm-bc.ll
new file mode 100644
index 00000000000000..51d2d48cdac3b0
--- /dev/null
+++ b/flang/test/Driver/emit-asm-from-llvm-bc.ll
@@ -0,0 +1,30 @@
+; Verify that the driver can consume LLVM BC files. The expected assembly is
+; fairly generic (tested on AArch64 and X86_64), but we may need to tweak when
+; testing on other platforms. Note that the actual output doesn't matter as
+; long as it's in Assembly format.
+
+;-------------
+; RUN COMMANDS
+;-------------
+; RUN: rm -f %t.bc
+; RUN: %flang_fc1 -emit-llvm-bc %s -o %t.bc
+; RUN: %flang_fc1 -S -o - %t.bc | FileCheck %s
+; RUN: rm -f %t.bc
+
+; RUN: rm -f %t.bc
+; RUN: %flang -c -emit-llvm %s -o %t.bc
+; RUN: %flang -S -o - %t.bc | FileCheck %s
+; RUN: rm -f %t.bc
+
+;----------------
+; EXPECTED OUTPUT
+;----------------
+; CHECK-LABEL: foo:
+; CHECK: ret
+
+;------
+; INPUT
+;------
+define void @foo() {
+  ret void
+}

diff  --git a/flang/test/Driver/emit-asm-from-llvm.ll b/flang/test/Driver/emit-asm-from-llvm.ll
new file mode 100644
index 00000000000000..ba3f0d1f3d1359
--- /dev/null
+++ b/flang/test/Driver/emit-asm-from-llvm.ll
@@ -0,0 +1,23 @@
+; Verify that the driver can consume LLVM IR files. The expected assembly is
+; fairly generic (verified on AArch64 and X86_64), but we may need to tweak when
+; testing on other platforms. Note that the actual output doesn't matter
+; as long as it's in Assembly format.
+
+;-------------
+; RUN COMMANDS
+;-------------
+; RUN: %flang_fc1 -S %s -o - | FileCheck %s
+; RUN: %flang -S  %s -o - | FileCheck %s
+
+;----------------
+; EXPECTED OUTPUT
+;----------------
+; CHECK-LABEL: foo:
+; CHECK: ret
+
+;------
+; INPUT
+;------
+define void @foo() {
+  ret void
+}

diff  --git a/flang/test/Driver/missing-triple.ll b/flang/test/Driver/missing-triple.ll
new file mode 100644
index 00000000000000..d3de54f8c689e5
--- /dev/null
+++ b/flang/test/Driver/missing-triple.ll
@@ -0,0 +1,21 @@
+; Verify that the module triple is overridden by the driver - even when the
+; module triple is missing.
+; NOTE: At the time of writing, the tested behaviour was consistent with Clang
+
+;-------------
+; RUN COMMANDS
+;-------------
+; RUN: %flang_fc1 -S %s -o - 2>&1 | FileCheck %s
+; RUN: %flang -S  %s -o - 2>&1 | FileCheck %s
+
+;----------------
+; EXPECTED OUTPUT
+;----------------
+; CHECK: warning: overriding the module target triple with {{.*}}
+
+;------
+; INPUT
+;------
+define void @foo() {
+  ret void
+}

diff  --git a/flang/test/Driver/override-triple.ll b/flang/test/Driver/override-triple.ll
new file mode 100644
index 00000000000000..dc9863b79bde50
--- /dev/null
+++ b/flang/test/Driver/override-triple.ll
@@ -0,0 +1,25 @@
+; Verify that the module triple is overridden by the driver - even in the presence
+; of a module triple.
+; NOTE: At the time of writing, the tested behaviour was consistent with Clang
+
+;-------------
+; RUN COMMANDS
+;-------------
+; RUN: %flang_fc1 -S %s -o - 2>&1 | FileCheck %s
+; RUN: %flang -S  %s -o - 2>&1 | FileCheck %s
+
+;----------------
+; EXPECTED OUTPUT
+;----------------
+; CHECK: warning: overriding the module target triple with {{.*}}
+
+;------
+; INPUT
+;------
+; For the triple to be overridden by the driver, it needs to be 
diff erent to the host triple.
+; Use a random string to guarantee that.
+target triple = "invalid-triple"
+
+define void @foo() {
+  ret void
+}

diff  --git a/flang/test/lit.cfg.py b/flang/test/lit.cfg.py
index 9578ab9fff62c4..0248dab966cfa0 100644
--- a/flang/test/lit.cfg.py
+++ b/flang/test/lit.cfg.py
@@ -27,7 +27,8 @@
 # suffixes: A list of file extensions to treat as test files.
 config.suffixes = ['.c', '.cpp', '.f', '.F', '.ff', '.FOR', '.for', '.f77', '.f90', '.F90',
                    '.ff90', '.f95', '.F95', '.ff95', '.fpp', '.FPP', '.cuf'
-                   '.CUF', '.f18', '.F18', '.fir', '.f03', '.F03', '.f08', '.F08']
+                   '.CUF', '.f18', '.F18', '.fir', '.f03', '.F03', '.f08',
+                   '.F08', '.ll']
 
 config.substitutions.append(('%PATH%', config.environment['PATH']))
 config.substitutions.append(('%llvmshlibdir', config.llvm_shlib_dir))


        


More information about the flang-commits mailing list