diff --git a/flang/include/flang/Frontend/FrontendOptions.h b/flang/include/flang/Frontend/FrontendOptions.h --- a/flang/include/flang/Frontend/FrontendOptions.h +++ b/flang/include/flang/Frontend/FrontendOptions.h @@ -115,12 +115,17 @@ enum class Language : uint8_t { Unknown, + /// MLIR: we accept this so that we can run the optimizer on it, and compile + /// it to LLVM IR, assembly or object code. + MLIR, + /// LLVM IR: we accept this so that we can run the optimizer on it, /// and compile it to assembly or object code. LLVM_IR, /// @{ Languages that the frontend can parse and compile. Fortran, + ///@} }; // Source file layout diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -270,6 +270,8 @@ if (dashX.isUnknown()) dashX = llvm::StringSwitch(xValue) .Case("ir", Language::LLVM_IR) + .Case("fir", Language::MLIR) + .Case("mlir", Language::MLIR) .Default(Language::Unknown); if (dashX.isUnknown()) diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -34,6 +34,7 @@ #include "mlir/IR/Dialect.h" #include "mlir/Pass/PassManager.h" #include "mlir/Target/LLVMIR/ModuleTranslation.h" +#include "mlir/Parser/Parser.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticFrontend.h" #include "llvm/ADT/StringRef.h" @@ -87,6 +88,30 @@ return (nullptr != llvmModule); } + // Load the MLIR dialects required by Flang + mlir::DialectRegistry registry; + mlirCtx = std::make_unique(registry); + fir::support::registerNonCodegenDialects(registry); + fir::support::loadNonCodegenDialects(*mlirCtx); + fir::support::loadDialects(*mlirCtx); + fir::support::registerLLVMTranslation(*mlirCtx); + + // If the input is an MLIR file, just parse it and return. + if (this->getCurrentInput().getKind().getLanguage() == Language::MLIR) { + llvm::SourceMgr sourceMgr; + llvm::ErrorOr> fileOrErr = + llvm::MemoryBuffer::getFileOrSTDIN(getCurrentInput().getFile()); + sourceMgr.AddNewSourceBuffer(std::move(*fileOrErr), llvm::SMLoc()); + mlir::OwningOpRef module = + mlir::parseSourceFile(sourceMgr, mlirCtx.get()); + + if (!module || mlir::failed(module->verifyInvariants())) + return false; + + mlirModule = std::make_unique(module.release()); + return true; + } + // Otherwise, generate an MLIR module from the input Fortran source assert(getCurrentInput().getKind().getLanguage() == Language::Fortran && "Invalid input type - expecting a Fortran file"); @@ -96,12 +121,6 @@ CompilerInstance &ci = this->getInstance(); - // Load the MLIR dialects required by Flang - mlir::DialectRegistry registry; - mlirCtx = std::make_unique(registry); - fir::support::registerNonCodegenDialects(registry); - fir::support::loadNonCodegenDialects(*mlirCtx); - // Create a LoweringBridge const common::IntrinsicTypeDefaultKinds &defKinds = ci.getInvocation().getSemanticsContext().defaultKinds(); diff --git a/flang/lib/Frontend/FrontendOptions.cpp b/flang/lib/Frontend/FrontendOptions.cpp --- a/flang/lib/Frontend/FrontendOptions.cpp +++ b/flang/lib/Frontend/FrontendOptions.cpp @@ -42,6 +42,8 @@ if (extension == "bc" || extension == "ll") return Language::LLVM_IR; + if (extension == "fir" || extension == "mlir") + return Language::MLIR; return Language::Unknown; } diff --git a/flang/test/Fir/addrof.fir b/flang/test/Fir/addrof.fir --- a/flang/test/Fir/addrof.fir +++ b/flang/test/Fir/addrof.fir @@ -1,4 +1,5 @@ // RUN: tco %s | FileCheck %s +// RUN: %flang_fc1 -emit-llvm %s -o - | FileCheck %s // CHECK: @var_x = external global i32 fir.global @var_x : !fir.int<4> {} diff --git a/flang/test/Fir/alloc.fir b/flang/test/Fir/alloc.fir --- a/flang/test/Fir/alloc.fir +++ b/flang/test/Fir/alloc.fir @@ -1,4 +1,5 @@ // RUN: tco %s | FileCheck %s +// RUN: %flang_fc1 -emit-llvm %s -o - | FileCheck %s // UNSUPPORTED: system-windows diff --git a/flang/test/Fir/arrayset.fir b/flang/test/Fir/arrayset.fir --- a/flang/test/Fir/arrayset.fir +++ b/flang/test/Fir/arrayset.fir @@ -1,4 +1,5 @@ // RUN: tco %s | FileCheck %s +// RUN: %flang_fc1 -emit-llvm %s -o - | FileCheck %s // CHECK-LABEL: define void @x([10 x float]* %0) func.func @x(%arr : !fir.ref>) { diff --git a/flang/test/Fir/boxchar.fir b/flang/test/Fir/boxchar.fir --- a/flang/test/Fir/boxchar.fir +++ b/flang/test/Fir/boxchar.fir @@ -1,4 +1,5 @@ // RUN: tco --target=x86_64-unknown-linux-gnu %s | FileCheck %s +// RUN: %flang_fc1 -emit-llvm -triple x86_64-unknown-linux-gnu %s -o - | FileCheck %s // Test of building and passing boxchar. diff --git a/flang/test/Fir/embox.fir b/flang/test/Fir/embox.fir --- a/flang/test/Fir/embox.fir +++ b/flang/test/Fir/embox.fir @@ -1,4 +1,5 @@ // RUN: tco %s | FileCheck %s +// RUN: %flang_fc1 -mmlir -disable-external-name-interop -emit-llvm %s -o -| FileCheck %s // CHECK-LABEL: define void @_QPtest_callee({ i32*, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }* %0) diff --git a/flang/test/Fir/global-initialization.fir b/flang/test/Fir/global-initialization.fir --- a/flang/test/Fir/global-initialization.fir +++ b/flang/test/Fir/global-initialization.fir @@ -1,4 +1,4 @@ -// RUN: tco --fir-to-llvm-ir %s | FileCheck %s +// RUN: fir-opt --fir-to-llvm-ir %s | FileCheck %s fir.global internal @_QEmask : !fir.array<32xi32> { %c0_i32 = arith.constant 1 : i32 diff --git a/flang/test/Fir/global.fir b/flang/test/Fir/global.fir --- a/flang/test/Fir/global.fir +++ b/flang/test/Fir/global.fir @@ -1,4 +1,5 @@ // RUN: tco %s | FileCheck %s +// RUN: %flang_fc1 -emit-llvm %s -o - | FileCheck %s // CHECK: @g_i0 = global i32 0 fir.global @g_i0 : i32 { diff --git a/flang/test/Fir/ignore-missing-type-descriptor.fir b/flang/test/Fir/ignore-missing-type-descriptor.fir --- a/flang/test/Fir/ignore-missing-type-descriptor.fir +++ b/flang/test/Fir/ignore-missing-type-descriptor.fir @@ -3,6 +3,7 @@ // having to care with providing an ABI compliant derived type descriptor object. // Missing derived type descriptor pointers are replaced by null pointers. // RUN: tco --ignore-missing-type-desc -o - %s | FileCheck %s +// RUN: %flang_fc1 -emit-llvm -mmlir --ignore-missing-type-desc -o - %s | FileCheck %s !some_freestyle_type = !fir.type diff --git a/flang/test/Fir/inline.fir b/flang/test/Fir/inline.fir --- a/flang/test/Fir/inline.fir +++ b/flang/test/Fir/inline.fir @@ -1,4 +1,5 @@ // RUN: tco --target=x86_64-unknown-linux-gnu --inline-all %s -o - | FileCheck %s +// RUN: %flang_fc1 -triple x86_64-unknown-linux-gnu -mmlir --inline-all -emit-llvm %s -o - | FileCheck %s // CHECK-LABEL: @add func.func @add(%a : i32, %b : i32) -> i32 { diff --git a/flang/test/Fir/optional.fir b/flang/test/Fir/optional.fir --- a/flang/test/Fir/optional.fir +++ b/flang/test/Fir/optional.fir @@ -1,4 +1,5 @@ // RUN: tco %s | FileCheck %s +// RUN: %flang_fc1 -emit-llvm %s -o - | FileCheck %s // Test fir.is_present and fir.absent codegen diff --git a/flang/test/Fir/peephole.fir b/flang/test/Fir/peephole.fir --- a/flang/test/Fir/peephole.fir +++ b/flang/test/Fir/peephole.fir @@ -1,4 +1,5 @@ // RUN: tco %s | FileCheck %s +// RUN: %flang_fc1 -emit-llvm %s -o - | FileCheck %s // Test peephole optimizations diff --git a/flang/test/Fir/rebox-susbtring.fir b/flang/test/Fir/rebox-susbtring.fir --- a/flang/test/Fir/rebox-susbtring.fir +++ b/flang/test/Fir/rebox-susbtring.fir @@ -1,6 +1,6 @@ // Test translation to llvm IR of fir.rebox with substring array sections. -// RUN: tco -o - -cg-rewrite --fir-to-llvm-ir -cse %s | FileCheck %s +// RUN: fir-opt -o - -cg-rewrite --fir-to-llvm-ir -cse %s | FileCheck %s // Test a fir.rebox with a substring on a character array with constant // length (like c(:)(2:*) where c is a fir.box array with constant length). diff --git a/flang/test/Fir/rebox.fir b/flang/test/Fir/rebox.fir --- a/flang/test/Fir/rebox.fir +++ b/flang/test/Fir/rebox.fir @@ -1,4 +1,5 @@ // RUN: tco %s | FileCheck %s +// RUN: %flang_fc1 -emit-llvm %s -o - | FileCheck %s // Test applying slice on fir.box // subroutine foo(x) diff --git a/flang/test/Fir/select.fir b/flang/test/Fir/select.fir --- a/flang/test/Fir/select.fir +++ b/flang/test/Fir/select.fir @@ -1,6 +1,7 @@ // Test lowering FIR to LLVM IR of fir.select{|_rank|_case} // RUN: tco %s | FileCheck %s +// RUN: %flang_fc1 -emit-llvm %s -o - | FileCheck %s // CHECK-LABEL: @f func.func @f(%a : i32) -> i32 { diff --git a/flang/test/Fir/widechar.fir b/flang/test/Fir/widechar.fir --- a/flang/test/Fir/widechar.fir +++ b/flang/test/Fir/widechar.fir @@ -1,4 +1,5 @@ // RUN: tco %s | FileCheck %s +// RUN: %flang_fc1 -emit-llvm %s -o - | FileCheck %s // CHECK-LABEL: @character_literal1 func.func @character_literal1() -> !fir.char<1,13> { diff --git a/flang/test/Lower/common-block.f90 b/flang/test/Lower/common-block.f90 --- a/flang/test/Lower/common-block.f90 +++ b/flang/test/Lower/common-block.f90 @@ -1,4 +1,5 @@ ! RUN: bbc %s -o - | tco | FileCheck %s +! RUN: %flang -emit-llvm -S -mmlir -disable-external-name-interop %s -o - | FileCheck %s ! CHECK: @_QB = common global [8 x i8] zeroinitializer ! CHECK: @_QBrien = common global [1 x i8] zeroinitializer diff --git a/flang/test/Lower/complex-part.f90 b/flang/test/Lower/complex-part.f90 --- a/flang/test/Lower/complex-part.f90 +++ b/flang/test/Lower/complex-part.f90 @@ -1,4 +1,5 @@ ! RUN: bbc %s -o - | tco | FileCheck %s +! RUN: %flang -emit-llvm -S -mmlir -disable-external-name-interop %s -o - | FileCheck %s COMPLEX c c%RE = 3.14 diff --git a/flang/test/Lower/forall/character-1.f90 b/flang/test/Lower/forall/character-1.f90 --- a/flang/test/Lower/forall/character-1.f90 +++ b/flang/test/Lower/forall/character-1.f90 @@ -1,4 +1,5 @@ ! RUN: bbc %s -o - | tco | FileCheck %s +! RUN: %flang -emit-llvm -S -mmlir -disable-external-name-interop %s -o - | FileCheck %s ! Test from Fortran source through to LLVM IR. ! UNSUPPORTED: system-windows @@ -23,7 +24,7 @@ ! CHECK: %[[elesize:.*]] = getelementptr { {{.*}}, [1 x [3 x i64]] }, { {{.*}}, [1 x [3 x i64]] }* %[[arg]], i32 0, i32 1 ! CHECK: %[[esval:.*]] = load i64, i64* %[[elesize]] ! CHECK: %[[mul:.*]] = mul i64 1, %[[esval]] -! CHECK: %[[mul2:.*]] = mul i64 %[[mul]], %[[extval]], !dbg !18 +! CHECK: %[[mul2:.*]] = mul i64 %[[mul]], %[[extval]] ! CHECK: %[[buff:.*]] = call i8* @malloc(i64 %[[mul2]]) ! CHECK: %[[to:.*]] = getelementptr i8, i8* %[[buff]], i64 % ! CHECK: call void @llvm.memmove.p0i8.p0i8.i64(i8* %[[to]], i8* %{{.*}}, i64 %{{.*}}, i1 false)