diff --git a/clang/include/clang/Driver/Types.h b/clang/include/clang/Driver/Types.h --- a/clang/include/clang/Driver/Types.h +++ b/clang/include/clang/Driver/Types.h @@ -11,12 +11,14 @@ #include "clang/Driver/Phases.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Option/ArgList.h" namespace llvm { class StringRef; } namespace clang { namespace driver { +class Driver; namespace types { enum ID { TY_INVALID, @@ -100,6 +102,9 @@ void getCompilationPhases( ID Id, llvm::SmallVectorImpl &Phases); + void getCompilationPhases(const clang::driver::Driver &Driver, + llvm::opt::DerivedArgList &DAL, ID Id, + llvm::SmallVectorImpl &Phases); /// lookupCXXTypeForCType - Lookup CXX input type that corresponds to given /// C type (used for clang++ emulation of g++ behaviour) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -3217,10 +3217,9 @@ HeaderModulePrecompileJobAction *HeaderModuleAction = nullptr; ActionList LinkerInputs; - phases::ID FinalPhase; { Arg *FinalPhaseArg; - FinalPhase = getFinalPhase(Args, &FinalPhaseArg); + phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg); if (FinalPhase == phases::Link) { if (Args.hasArg(options::OPT_emit_llvm)) @@ -3323,10 +3322,13 @@ const Arg *InputArg = I.second; llvm::SmallVector PL; - types::getCompilationPhases(InputType, PL); - if (PL[0] > FinalPhase) + types::getCompilationPhases(*this, Args, InputType, PL); + if (!PL.size()) continue; + llvm::SmallVector FullPL; + types::getCompilationPhases(InputType, FullPL); + // Build the pipeline for this file. Action *Current = C.MakeAction(*InputArg, InputType); @@ -3337,13 +3339,9 @@ for (phases::ID Phase : PL) { - // We are done if this step is past what the user requested. - if (Phase > FinalPhase) - break; - // Add any offload action the host action depends on. Current = OffloadBuilder.addDeviceDependencesToHostAction( - Current, InputArg, Phase, FinalPhase, PL); + Current, InputArg, Phase, PL.back(), FullPL); if (!Current) break; diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp --- a/clang/lib/Driver/Types.cpp +++ b/clang/lib/Driver/Types.cpp @@ -6,10 +6,14 @@ // //===----------------------------------------------------------------------===// +#include "clang/Driver/Driver.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Types.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Option/Arg.h" #include #include @@ -293,6 +297,59 @@ assert(P.size() <= phases::MaxNumberOfPhases && "Too many phases in list"); } +void types::getCompilationPhases(const clang::driver::Driver &Driver, + llvm::opt::DerivedArgList &DAL, ID Id, + llvm::SmallVectorImpl &P) { + llvm::SmallVector PhaseList; + types::getCompilationPhases(Id, PhaseList); + + if (Driver.CCCIsCPP() || DAL.getLastArg(options::OPT_E) || + DAL.getLastArg(options::OPT__SLASH_EP) || + DAL.getLastArg(options::OPT_M, options::OPT_MM) || + DAL.getLastArg(options::OPT__SLASH_P)) { + // Filter to compiler mode. When the compiler is run as a preprocessor then + // compilation is not an option. + // -S runs the compiler in Assembly listing mode. + for (auto Phase : PhaseList) + if (Phase <= phases::Preprocess) + P.push_back(Phase); + } else if (DAL.getLastArg(options::OPT__precompile)) { + // --precompile only runs up to precompilation. + // This is a clang extension and is not compatible with GCC. + for (auto Phase : PhaseList) + if (Phase <= phases::Precompile) + P.push_back(Phase); + } else if (DAL.getLastArg(options::OPT_fsyntax_only) || + DAL.getLastArg(options::OPT_print_supported_cpus) || + DAL.getLastArg(options::OPT_module_file_info) || + DAL.getLastArg(options::OPT_verify_pch) || + DAL.getLastArg(options::OPT_rewrite_objc) || + DAL.getLastArg(options::OPT_rewrite_legacy_objc) || + DAL.getLastArg(options::OPT__migrate) || + DAL.getLastArg(options::OPT_emit_iterface_stubs) || + DAL.getLastArg(options::OPT__analyze, + options::OPT__analyze_auto) || + DAL.getLastArg(options::OPT_emit_ast)) { + // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler. + for (auto Phase : PhaseList) + if (Phase <= phases::Compile) + P.push_back(Phase); + } else if (DAL.getLastArg(options::OPT_S) || + DAL.getLastArg(options::OPT_emit_llvm)) { + for (auto Phase : PhaseList) + if (Phase <= phases::Backend) + P.push_back(Phase); + } else if (DAL.getLastArg(options::OPT_c)) { + for (auto Phase : PhaseList) + if (Phase <= phases::Assemble) + P.push_back(Phase); + } else { + // Generally means, do every phase until Link. + for (auto Phase : PhaseList) + P.push_back(Phase); + } +} + ID types::lookupCXXTypeForCType(ID Id) { switch (Id) { default: