Skip to content

Commit

Permalink
[ClassicFlang][Driver] Reduce downstream delta
Browse files Browse the repository at this point in the history
This commit is motivated by reducing the merge burden by shrinking the
diff between llvm upstream and classic-flang-llvm-project.

Outside of Flang, Fortran code is fed through the Compile phase, and
the appropriate tooling is picked up through ToolChain::SelectTool.

Classic Flang introduced a FortranFrontend, but these days this seems
unnecessary. Fortran can go through the same machinery as everything else.

* Use the Preprocess phase to preprocess Fortran code. This phase is
  always combined with the Compile phase.

* Use the Compile phase to lower Fortran code to LLVM IR, and use the
  Backend phase to compile and optimize the IR. These phases are never
  combined.

* Remove FortranFrontendJobClass.

* Remove FortranFrontend tool (instead it's just the Flang tool, which
  in Classic Flang mode is Classic Flang).

* Update tests which inspect the output of the Classic Flang tooling,
  and ensures that the driver does the right thing for various types of
  inputs.

Based on a patch from Peter Waller <peter.waller@arm.com>.
  • Loading branch information
bryanpkc committed Oct 13, 2020
1 parent da9edce commit 3b88c71
Show file tree
Hide file tree
Showing 16 changed files with 123 additions and 104 deletions.
11 changes: 0 additions & 11 deletions clang/include/clang/Driver/Action.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ class Action {
AnalyzeJobClass,
MigrateJobClass,
CompileJobClass,
FortranFrontendJobClass,
BackendJobClass,
AssembleJobClass,
LinkJobClass,
Expand Down Expand Up @@ -455,16 +454,6 @@ class MigrateJobAction : public JobAction {
}
};

class FortranFrontendJobAction : public JobAction {
void anchor() override;
public:
FortranFrontendJobAction(Action *Input, types::ID OutputType);

static bool classof(const Action *A) {
return A->getKind() == FortranFrontendJobClass;
}
};

class CompileJobAction : public JobAction {
void anchor() override;

Expand Down
1 change: 0 additions & 1 deletion clang/include/clang/Driver/Phases.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ namespace phases {
enum ID {
Preprocess,
Precompile,
FortranFrontend,
Compile,
Backend,
Assemble,
Expand Down
2 changes: 0 additions & 2 deletions clang/include/clang/Driver/ToolChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ class ToolChain {

mutable std::unique_ptr<Tool> Clang;
mutable std::unique_ptr<Tool> Flang;
mutable std::unique_ptr<Tool> FortranFrontend;
mutable std::unique_ptr<Tool> Assemble;
mutable std::unique_ptr<Tool> Link;
mutable std::unique_ptr<Tool> IfsMerge;
Expand All @@ -144,7 +143,6 @@ class ToolChain {

Tool *getClang() const;
Tool *getFlang() const;
Tool *getFortranFrontend() const;
Tool *getAssemble() const;
Tool *getLink() const;
Tool *getIfsMerge() const;
Expand Down
8 changes: 4 additions & 4 deletions clang/include/clang/Driver/Types.def
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ TYPE("ada", Ada, INVALID, nullptr, phases
TYPE("assembler", PP_Asm, INVALID, "s", phases::Assemble, phases::Link)
TYPE("assembler-with-cpp", Asm, PP_Asm, "S", phases::Preprocess, phases::Assemble, phases::Link)
#ifdef ENABLE_CLASSIC_FLANG
TYPE("f77", PP_F_FixedForm, INVALID, "f", phases::FortranFrontend, phases::Backend, phases::Assemble, phases::Link)
TYPE("f77-cpp-input", F_FixedForm, PP_F_FixedForm, "F", phases::FortranFrontend, phases::Backend, phases::Assemble, phases::Link)
TYPE("f95", PP_F_FreeForm, INVALID, "f95", phases::FortranFrontend, phases::Backend, phases::Assemble, phases::Link)
TYPE("f95-cpp-input", F_FreeForm, PP_F_FreeForm, "F95", phases::FortranFrontend, phases::Backend, phases::Assemble, phases::Link)
TYPE("f77", PP_F_FixedForm, INVALID, "f", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("f77-cpp-input", F_FixedForm, PP_F_FixedForm, "F", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("f95", PP_F_FreeForm, INVALID, "f95", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("f95-cpp-input", F_FreeForm, PP_F_FreeForm, "F95", phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
#else
TYPE("f95", PP_Fortran, INVALID, nullptr, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
TYPE("f95-cpp-input", Fortran, PP_Fortran, nullptr, phases::Preprocess, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
Expand Down
7 changes: 0 additions & 7 deletions clang/lib/Driver/Action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ const char *Action::getClassName(ActionClass AC) {
case HeaderModulePrecompileJobClass: return "header-module-precompiler";
case AnalyzeJobClass: return "analyzer";
case MigrateJobClass: return "migrator";
case FortranFrontendJobClass: return "fortran-frontend";
case CompileJobClass: return "compiler";
case BackendJobClass: return "backend";
case AssembleJobClass: return "assembler";
Expand Down Expand Up @@ -346,12 +345,6 @@ void MigrateJobAction::anchor() {}
MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType)
: JobAction(MigrateJobClass, Input, OutputType) {}

void FortranFrontendJobAction::anchor() {}

FortranFrontendJobAction::FortranFrontendJobAction(Action *Input,
types::ID OutputType)
: JobAction(FortranFrontendJobClass, Input, OutputType) {}

void CompileJobAction::anchor() {}

CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)
Expand Down
52 changes: 18 additions & 34 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,42 +271,18 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL,

// -{E,EP,P,M,MM} only run the preprocessor.
if (CCCIsCPP() || (PhaseArg = DAL.getLastArg(options::OPT_E)) ||
#ifdef ENABLE_CLASSIC_FLANG
(PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
#endif
(PhaseArg = DAL.getLastArg(options::OPT__SLASH_EP)) ||
(PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM)) ||
(PhaseArg = DAL.getLastArg(options::OPT__SLASH_P))) {
#ifdef ENABLE_CLASSIC_FLANG
// -fsyntax-only or -E stops Fortran compilation after FortranFrontend
if (IsFlangMode() && (DAL.getLastArg(options::OPT_E) ||
DAL.getLastArg(options::OPT_fsyntax_only))) {
FinalPhase = phases::FortranFrontend;

// if not Fortran, fsyntax_only implies 'Compile' is the FinalPhase
} else if (DAL.getLastArg(options::OPT_fsyntax_only)) {
FinalPhase = phases::Compile;

// everything else has 'Preprocess' as its FinalPhase
} else {
FinalPhase = phases::Preprocess;
}
#else
FinalPhase = phases::Preprocess;
#endif

// --precompile only runs up to precompilation.
} else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile))) {
FinalPhase = phases::Precompile;

#ifdef ENABLE_CLASSIC_FLANG
// -{analyze,emit-ast} only run up to the compiler.
} else if ((PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) ||
#else
// -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
} else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
(PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) ||
#endif
(PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) ||
(PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) ||
(PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) ||
Expand Down Expand Up @@ -3306,10 +3282,13 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args,
if (InputArg->isClaimed())
continue;

// Fortran input is preprocessed using the frontend.
if (InitialPhase == phases::FortranFrontend &&
#ifdef ENABLE_CLASSIC_FLANG
// If the input is detected as already preprocessed (e.g. has the .f95
// extension), and the user specifies -E, preprocess the file anyway.
if (IsFlangMode() && InitialPhase == phases::Compile &&
FinalPhase == phases::Preprocess)
continue;
#endif

// Claim here to avoid the more general unused warning.
InputArg->claim();
Expand Down Expand Up @@ -3677,13 +3656,6 @@ Action *Driver::ConstructPhaseAction(
ModName);
return C.MakeAction<PrecompileJobAction>(Input, OutputTy);
}
case phases::FortranFrontend: {
if (Args.hasArg(options::OPT_fsyntax_only))
return C.MakeAction<FortranFrontendJobAction>(Input,
types::TY_Nothing);
return C.MakeAction<FortranFrontendJobAction>(Input,
types::TY_LLVM_IR);
}
case phases::Compile: {
if (Args.hasArg(options::OPT_fsyntax_only))
return C.MakeAction<CompileJobAction>(Input, types::TY_Nothing);
Expand All @@ -3702,6 +3674,10 @@ Action *Driver::ConstructPhaseAction(
return C.MakeAction<CompileJobAction>(Input, types::TY_ModuleFile);
if (Args.hasArg(options::OPT_verify_pch))
return C.MakeAction<VerifyPCHJobAction>(Input, types::TY_Nothing);
#ifdef ENABLE_CLASSIC_FLANG
if (IsFlangMode())
return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_IR);
#endif
return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC);
}
case phases::Backend: {
Expand Down Expand Up @@ -4041,6 +4017,10 @@ class ToolSelector final {
if (!T)
return nullptr;

// Classic Flang is not integrated with the backend.
if (C.getDriver().IsFlangMode() && !T->hasIntegratedAssembler())
return nullptr;

if (T->canEmitIR() && ((SaveTemps && !InputIsBitcode) || EmbedBitcode))
return nullptr;

Expand Down Expand Up @@ -5015,7 +4995,11 @@ bool Driver::ShouldUseFlangCompiler(const JobAction &JA) const {
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)
#ifndef ENABLE_CLASSIC_FLANG
&& !isa<BackendJobAction>(JA)
#endif
)
return false;

return true;
Expand Down
1 change: 0 additions & 1 deletion clang/lib/Driver/Phases.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ const char *phases::getPhaseName(ID Id) {
switch (Id) {
case Preprocess: return "preprocessor";
case Precompile: return "precompiler";
case FortranFrontend: return "fortran-frontend";
case Compile: return "compiler";
case Backend: return "backend";
case Assemble: return "assembler";
Expand Down
17 changes: 4 additions & 13 deletions clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,11 @@ Tool *ToolChain::getClang() const {

Tool *ToolChain::getFlang() const {
if (!Flang)
#ifdef ENABLE_CLASSIC_FLANG
Flang.reset(new tools::ClassicFlang(*this));
#else
Flang.reset(new tools::Flang(*this));
#endif
return Flang.get();
}

Expand All @@ -277,16 +281,6 @@ Tool *ToolChain::getAssemble() const {
return Assemble.get();
}

Tool *ToolChain::getFortranFrontend() const {
#ifdef ENABLE_CLASSIC_FLANG
if (!FortranFrontend)
FortranFrontend.reset(new tools::ClassicFlang(*this));
return FortranFrontend.get();
#else
llvm_unreachable("Fortran is not supported by this toolchain");
#endif
}

Tool *ToolChain::getClangAs() const {
if (!Assemble)
Assemble.reset(new tools::ClangAs(*this));
Expand Down Expand Up @@ -352,9 +346,6 @@ Tool *ToolChain::getTool(Action::ActionClass AC) const {

case Action::OffloadWrapperJobClass:
return getOffloadWrapper();

case Action::FortranFrontendJobClass:
return getFortranFrontend();
}

llvm_unreachable("Invalid tool kind.");
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/ClassicFlang.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class LLVM_LIBRARY_VISIBILITY ClassicFlang : public Tool {

bool hasGoodDiagnostics() const override { return true; }
bool hasIntegratedAssembler() const override { return false; }
bool hasIntegratedCPP() const override { return false; }
bool hasIntegratedCPP() const override { return true; }

void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/Types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ void types::getCompilationPhases(const clang::driver::Driver &Driver,
llvm::copy_if(PhaseList, std::back_inserter(P),
[&](phases::ID Phase) {
return (Phase <= phases::Preprocess ||
(Phase == phases::FortranFrontend &&
(Phase == phases::Compile &&
Driver.IsFlangMode()));
});
#else
Expand Down
12 changes: 12 additions & 0 deletions clang/test/Driver/flang/classic-flang-must-preprocess.F
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
! REQUIRES: classic_flang

! Check that the driver invokes flang1 correctly for fixed-form Fortran code
! which requires preprocessing.

! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -c %s -### 2>&1 \
! RUN: | FileCheck %s
! CHECK: "flang1"
! CHECK-SAME: "-preprocess"
! CHECK-SAME: "-nofreeform"
! CHECK-NEXT: "flang2"
! CHECK-NEXT: {{clang.* "-cc1"}}
12 changes: 12 additions & 0 deletions clang/test/Driver/flang/classic-flang-must-preprocess.F95
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
! REQUIRES: classic_flang

! Check that the driver invokes flang1 correctly for free-form Fortran code
! which requires preprocessing.

! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -c %s -### 2>&1 \
! RUN: | FileCheck %s
! CHECK: "flang1"
! CHECK-SAME: "-preprocess"
! CHECK-SAME: "-freeform"
! CHECK-NEXT: "flang2"
! CHECK-NEXT: {{clang.* "-cc1"}}
26 changes: 26 additions & 0 deletions clang/test/Driver/flang/classic-flang.f
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
! REQUIRES: classic_flang

! Check that the driver invokes flang1 correctly for preprocessed fixed-form
! Fortran code.

! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -c %s -### 2>&1 \
! RUN: | FileCheck %s
! CHECK: "flang1"
! CHECK-NOT: "-preprocess"
! CHECK-SAME: "-nofreeform"
! CHECK-NEXT: "flang2"
! CHECK-NEXT: {{clang.* "-cc1"}}

! Check that the driver invokes flang1 correctly when preprocessing is
! explicitly requested.

! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -E %s -### 2>&1 \
! RUN: | FileCheck --check-prefix=CHECK-PREPROCESS %s
! CHECK-PREPROCESS: "flang1"
! CHECK-PREPROCESS-SAME: "-preprocess"
! CHECK-PREPROCESS-SAME: "-es"
! CHECK-PREPROCESS-SAME: "-pp"
! CHECK-PREPROCESS-NOT: "flang1"
! CHECK-PREPROCESS-NOT: "flang2"
! CHECK-PREPROCESS-NOT: {{clang.* "-cc1"}}
! CHECK-PREPROCESS-NOT: {{clang.* "-cc1as"}}
43 changes: 43 additions & 0 deletions clang/test/Driver/flang/classic-flang.f95
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
! REQUIRES: classic_flang

! Check that the driver invokes flang1 correctly for preprocessed free-form
! Fortran code. Also check that the backend is invoked correctly.

! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -c %s -### 2>&1 \
! RUN: | FileCheck --check-prefix=CHECK-OBJECT %s
! CHECK-OBJECT: "flang1"
! CHECK-OBJECT-NOT: "-preprocess"
! CHECK-OBJECT-SAME: "-freeform"
! CHECK-OBJECT-NEXT: "flang2"
! CHECK-OBJECT-SAME: "-asm" [[LLFILE:.*.ll]]
! CHECK-OBJECT-NEXT: {{clang.* "-cc1"}}
! CHECK-OBJECT-SAME: "-o" "classic-flang.o"
! CHECK-OBJECT-SAME: "-x" "ir"
! CHECK-OBJECT-SAME: [[LLFILE]]

! Check that the driver invokes flang1 correctly when preprocessing is
! explicitly requested.

! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -E %s -### 2>&1 \
! RUN: | FileCheck --check-prefix=CHECK-PREPROCESS %s
! CHECK-PREPROCESS: "flang1"
! CHECK-PREPROCESS-SAME: "-preprocess"
! CHECK-PREPROCESS-SAME: "-es"
! CHECK-PREPROCESS-SAME: "-pp"
! CHECK-PREPROCESS-NOT: "flang1"
! CHECK-PREPROCESS-NOT: "flang2"
! CHECK-PREPROCESS-NOT: {{clang.* "-cc1"}}
! CHECK-PREPROCESS-NOT: {{clang.* "-cc1as"}}

! Check that the backend job (clang -cc1) is not combined into the compile job
! (flang2) even if -integrated-as is specified.

! RUN: %clang --driver-mode=flang -target x86_64-unknown-linux-gnu -integrated-as -S %s -### 2>&1 \
! RUN: | FileCheck --check-prefix=CHECK-ASM %s
! CHECK-ASM: "flang1"
! CHECK-ASM-NEXT: "flang2"
! CHECK-ASM-SAME: "-asm" [[LLFILE:.*.ll]]
! CHECK-ASM-NEXT: {{clang.* "-cc1"}}
! CHECK-ASM-SAME: "-o" "classic-flang.s"
! CHECK-ASM-SAME: "-x" "ir"
! CHECK-ASM-SAME: [[LLFILE]]
28 changes: 0 additions & 28 deletions clang/test/Driver/flang/classic_flang.f95

This file was deleted.

3 changes: 2 additions & 1 deletion clang/test/Driver/lit.local.cfg
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
config.suffixes = ['.c', '.cpp', '.h', '.m', '.mm', '.S', '.s', '.f90', '.F90', '.f95',
config.suffixes = ['.c', '.cpp', '.h', '.m', '.mm', '.S', '.s',
'.f', '.F', '.f90', '.F90', '.f95', '.F95',
'.cu', '.rs', '.cl', '.hip']
config.substitutions = list(config.substitutions)
config.substitutions.insert(0,
Expand Down

0 comments on commit 3b88c71

Please sign in to comment.