[flang][driver] Fix support for -x

Until now, `-x` wasn't really taken into account in Flang's compiler and
frontend drivers. `flang-new` and `flang-new -fc1` only recently gained
powers to consume inputs other than Fortran files and that's probably
why this hasn't been noticed yet.

This patch makes sure that `-x` is supported correctly and consistently
with Clang. To this end, verification is added when reading LLVM IR
files (i.e. IR modules are verified with `llvm::verifyModule`). This
way, LLVM IR parsing errors are correctly reported to Flang users. This
also aids testing.

With the new functionality, we can verify that `-x ir` breaks
compilation for e.g. Fortran files and vice-versa. Tests are updated
accordingly.

Differential Revision: https://reviews.llvm.org/D127207
This commit is contained in:
Andrzej Warzynski
2022-06-06 17:57:33 +00:00
parent ceb21fa4e4
commit 3e782ba21b
10 changed files with 103 additions and 20 deletions

View File

@@ -4166,7 +4166,8 @@ def why_load : Flag<["-"], "why_load">;
def whyload : Flag<["-"], "whyload">, Alias<why_load>;
def w : Flag<["-"], "w">, HelpText<"Suppress all warnings">, Flags<[CC1Option]>,
MarshallingInfoFlag<DiagnosticOpts<"IgnoreWarnings">>;
def x : JoinedOrSeparate<["-"], "x">, Flags<[NoXarchOption,CC1Option]>,
def x : JoinedOrSeparate<["-"], "x">,
Flags<[NoXarchOption,CC1Option,FlangOption,FC1Option]>,
HelpText<"Treat subsequent input files as having type <language>">,
MetaVarName<"<language>">;
def y : Joined<["-"], "y">;

View File

@@ -19,6 +19,14 @@ using namespace clang::driver::tools;
using namespace clang;
using namespace llvm::opt;
/// Add -x lang to \p CmdArgs for \p Input.
static void addDashXForInput(const ArgList &Args, const InputInfo &Input,
ArgStringList &CmdArgs) {
CmdArgs.push_back("-x");
// Map the driver type to the frontend type.
CmdArgs.push_back(types::getTypeName(Input.getType()));
}
void Flang::AddFortranDialectOptions(const ArgList &Args,
ArgStringList &CmdArgs) const {
Args.AddAllArgs(
@@ -126,6 +134,9 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
}
assert(Input.isFilename() && "Invalid input.");
addDashXForInput(Args, Input, CmdArgs);
CmdArgs.push_back(Input.getFilename());
const auto& D = C.getDriver();

View File

@@ -263,7 +263,10 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
llvm::StringRef xValue = a->getValue();
// Principal languages.
dashX = llvm::StringSwitch<InputKind>(xValue)
.Case("f90", Language::Fortran)
// Flang does not differentiate between pre-processed and not
// pre-processed inputs.
.Case("f95", Language::Fortran)
.Case("f95-cpp-input", Language::Fortran)
.Default(Language::Unknown);
// Some special cases cannot be combined with suffixes.

View File

@@ -41,6 +41,7 @@
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Passes/PassBuilder.h"
@@ -78,25 +79,36 @@ bool PrescanAndSemaDebugAction::beginSourceFileAction() {
bool CodeGenAction::beginSourceFileAction() {
llvmCtx = std::make_unique<llvm::LLVMContext>();
CompilerInstance &ci = this->getInstance();
// If the input is an LLVM file, just parse it and return.
if (this->getCurrentInput().getKind().getLanguage() == Language::LLVM_IR) {
llvm::SMDiagnostic err;
llvmModule = llvm::parseIRFile(getCurrentInput().getFile(), err, *llvmCtx);
if (!llvmModule || llvm::verifyModule(*llvmModule, &llvm::errs())) {
err.print("flang-new", llvm::errs());
unsigned diagID = ci.getDiagnostics().getCustomDiagID(
clang::DiagnosticsEngine::Error, "Could not parse IR");
ci.getDiagnostics().Report(diagID);
return false;
}
return (nullptr != llvmModule);
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");
if (getCurrentInput().getKind().getLanguage() != Language::Fortran) {
unsigned diagID = ci.getDiagnostics().getCustomDiagID(
clang::DiagnosticsEngine::Error,
"Invalid input type - expecting a Fortran file");
ci.getDiagnostics().Report(diagID);
return false;
}
bool res = runPrescan() && runParse() && runSemanticChecks() &&
generateRtTypeTables();
if (!res)
return res;
CompilerInstance &ci = this->getInstance();
// Load the MLIR dialects required by Flang
mlir::DialectRegistry registry;
mlirCtx = std::make_unique<mlir::MLIRContext>(registry);

View File

@@ -0,0 +1,26 @@
; Verify that reading from stdin works as expected - LLVM input
;----------
; RUN LINES
;----------
; Input type is implicit - assumed to be Fortran. As the input is provided via
; stdin, the file extension is not relevant here.
; RUN: cat %s | not %flang -S - -o -
; RUN: cat %s | not %flang_fc1 -S - -o -
; Input type is explicit
; RUN: cat %s | %flang -x ir -S - -o - | FileCheck %s
; RUN: cat %s | %flang_fc1 -x ir -S - -o - | FileCheck %s
;----------------
; EXPECTED OUTPUT
;----------------
; CHECK-LABEL: foo:
; CHECK: ret
;------
; INPUT
;------
define void @foo() {
ret void
}

View File

@@ -1,4 +1,4 @@
! Verify that reading from stdin works as expected
! Verify that reading from stdin works as expected - Fortran input
!--------------------------
! FLANG DRIVER (flang)

View File

@@ -20,7 +20,7 @@
!----------------
! Compiler invocation to generate the object file
! CHECK-LABEL: {{.*}} "-emit-obj"
! CHECK-SAME: "-o" "[[object_file:.*]]" {{.*}}Inputs/hello.f90
! CHECK-SAME: "-o" "[[object_file:.*\.o]]" {{.*}}Inputs/hello.f90
! Linker invocation to generate the executable
! CHECK-LABEL: "/usr/bin/ld"

View File

@@ -1,11 +0,0 @@
! Verify that parsing errors are correctly reported by the driver
! Focuses on actions inheriting from the following:
! * PrescanAndSemaAction (-fsyntax-only)
! * PrescanAndParseAction (-fdebug-unparse-no-sema)
! RUN: not %flang_fc1 -fdebug-unparse-no-sema %s 2>&1 | FileCheck %s --check-prefix=ERROR
! RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix=ERROR
! ERROR: Could not parse {{.*}}parse-error.f95
"This file will not parse"

View File

@@ -0,0 +1,23 @@
; This file is a valid LLVM IR file, but we force the driver to treat it as
; Fortran (with the `-x` flag). This way we verify that the driver
; correctly rejects invalid Fortran input.
;----------
; RUN LINES
;----------
; Input type is implicit (correctly assumed to be LLVM IR)
; RUN: %flang_fc1 -S %s -o -
; Input type is explicitly set as Fortran
; Verify that parsing errors are correctly reported by the driver
; Focuses on actions inheriting from the following:
; * PrescanAndSemaAction (-fsyntax-only)
; * PrescanAndParseAction (-fdebug-unparse-no-sema)
; RUN: not %flang_fc1 -fdebug-unparse-no-sema -x f95 %s 2>&1 | FileCheck %s --check-prefix=ERROR
; RUN: not %flang_fc1 -fsyntax-only %s -x f95 2>&1 | FileCheck %s --check-prefix=ERROR
; ERROR: Could not parse {{.*}}parse-error.f95
define void @foo() {
ret void
}

View File

@@ -0,0 +1,18 @@
! This file is a valid Fortran file, but we force the driver to treat it as an
! LLVM file (with the `-x` flag). This way we verify that the driver correctly
! rejects invalid LLVM IR input.
!----------
! RUN LINES
!----------
! Input type is implicit (correctly assumed to be Fortran)
! RUN: %flang_fc1 -S %s
! Input type is explicitly set as LLVM IR
! RUN: not %flang -S -x ir %s 2>&1 | FileCheck %s
!----------------
! EXPECTED OUTPUT
!----------------
! CHECK: error: Could not parse IR
end program