diff --git a/clang/include/clang/Driver/Action.h b/clang/include/clang/Driver/Action.h --- a/clang/include/clang/Driver/Action.h +++ b/clang/include/clang/Driver/Action.h @@ -65,6 +65,7 @@ BackendJobClass, AssembleJobClass, LinkJobClass, + IfsMergeJobClass, LipoJobClass, DsymutilJobClass, VerifyDebugInfoJobClass, @@ -485,6 +486,17 @@ } }; +class IfsMergeJobAction : public JobAction { + void anchor() override; + +public: + IfsMergeJobAction(ActionList &Inputs, types::ID Type); + + static bool classof(const Action *A) { + return A->getKind() == IfsMergeJobClass; + } +}; + class LinkJobAction : public JobAction { void anchor() override; diff --git a/clang/include/clang/Driver/Phases.h b/clang/include/clang/Driver/Phases.h --- a/clang/include/clang/Driver/Phases.h +++ b/clang/include/clang/Driver/Phases.h @@ -20,7 +20,8 @@ Compile, Backend, Assemble, - Link + Link, + IfsMerge }; enum { diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -136,11 +136,13 @@ mutable std::unique_ptr Clang; mutable std::unique_ptr Assemble; mutable std::unique_ptr Link; + mutable std::unique_ptr IfsMerge; mutable std::unique_ptr OffloadBundler; Tool *getClang() const; Tool *getAssemble() const; Tool *getLink() const; + Tool *getIfsMerge() const; Tool *getClangAs() const; Tool *getOffloadBundler() const; diff --git a/clang/include/clang/Driver/Types.def b/clang/include/clang/Driver/Types.def --- a/clang/include/clang/Driver/Types.def +++ b/clang/include/clang/Driver/Types.def @@ -84,7 +84,7 @@ // Misc. TYPE("ast", AST, INVALID, "ast", phases::Compile, phases::Backend, phases::Assemble, phases::Link) -TYPE("ifs", IFS, INVALID, "ifs", phases::Compile, phases::Backend, phases::Assemble, phases::Link) +TYPE("ifs", IFS, INVALID, "ifs", phases::Compile, phases::IfsMerge) TYPE("pcm", ModuleFile, INVALID, "pcm", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("plist", Plist, INVALID, "plist", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("rewritten-objc", RewrittenObjC,INVALID, "cpp", phases::Compile, phases::Backend, phases::Assemble, phases::Link) diff --git a/clang/lib/Driver/Action.cpp b/clang/lib/Driver/Action.cpp --- a/clang/lib/Driver/Action.cpp +++ b/clang/lib/Driver/Action.cpp @@ -31,6 +31,7 @@ case CompileJobClass: return "compiler"; case BackendJobClass: return "backend"; case AssembleJobClass: return "assembler"; + case IfsMergeJobClass: return "interface-stub-merger"; case LinkJobClass: return "linker"; case LipoJobClass: return "lipo"; case DsymutilJobClass: return "dsymutil"; @@ -357,6 +358,11 @@ AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType) : JobAction(AssembleJobClass, Input, OutputType) {} +void IfsMergeJobAction::anchor() {} + +IfsMergeJobAction::IfsMergeJobAction(ActionList &Inputs, types::ID Type) + : JobAction(IfsMergeJobClass, Inputs, Type) {} + void LinkJobAction::anchor() {} LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type) diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -66,6 +66,7 @@ ToolChains/WebAssembly.cpp ToolChains/XCore.cpp ToolChains/PPCLinux.cpp + ToolChains/InterfaceStubs.cpp Types.cpp XRayArgs.cpp 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 @@ -3317,6 +3317,7 @@ // Construct the actions to perform. HeaderModulePrecompileJobAction *HeaderModuleAction = nullptr; ActionList LinkerInputs; + ActionList MergerInputs; handleArguments(C, Args, Inputs, Actions, YcArg, YuArg); @@ -3330,7 +3331,10 @@ continue; llvm::SmallVector FullPL; - types::getCompilationPhases(InputType, FullPL); + types::getCompilationPhases( + (Args.getLastArg(options::OPT_emit_iterface_stubs) ? types::TY_IFS + : InputType), + FullPL); // Build the pipeline for this file. Action *Current = C.MakeAction(*InputArg, InputType); @@ -3356,6 +3360,14 @@ break; } + // Queue linker inputs. + if (Phase == phases::IfsMerge) { + assert(Phase == PL.back() && "merging must be final compilation step."); + MergerInputs.push_back(Current); + Current = nullptr; + break; + } + // Each precompiled header file after a module file action is a module // header of that same module file, rather than being compiled to a // separate PCH. @@ -3405,6 +3417,13 @@ Actions.push_back(LA); } + // Add a link action if necessary. + if (!MergerInputs.empty()) { + Action *LA = C.MakeAction(MergerInputs, types::TY_Image); + LA = OffloadBuilder.processHostLinkAction(LA); + Actions.push_back(LA); + } + // If --print-supported-cpus, -mcpu=? or -mtune=? is specified, build a custom // Compile phase that prints out supported cpu models and quits. if (Arg *A = Args.getLastArg(options::OPT_print_supported_cpus)) { @@ -3440,6 +3459,7 @@ // Build the appropriate action. switch (Phase) { case phases::Link: + case phases::IfsMerge: llvm_unreachable("link action invalid here."); case phases::Preprocess: { types::ID OutputTy; diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -10,6 +10,7 @@ #include "InputInfo.h" #include "ToolChains/Arch/ARM.h" #include "ToolChains/Clang.h" +#include "ToolChains/InterfaceStubs.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Sanitizers.h" #include "clang/Config/config.h" @@ -279,6 +280,12 @@ return Link.get(); } +Tool *ToolChain::getIfsMerge() const { + if (!IfsMerge) + IfsMerge.reset(new tools::ifstool::Merger(*this)); + return IfsMerge.get(); +} + Tool *ToolChain::getOffloadBundler() const { if (!OffloadBundler) OffloadBundler.reset(new tools::OffloadBundler(*this)); @@ -290,6 +297,9 @@ case Action::AssembleJobClass: return getAssemble(); + case Action::IfsMergeJobClass: + return getIfsMerge(); + case Action::LinkJobClass: return getLink(); diff --git a/clang/lib/Driver/ToolChains/InterfaceStubs.h b/clang/lib/Driver/ToolChains/InterfaceStubs.h new file mode 100644 --- /dev/null +++ b/clang/lib/Driver/ToolChains/InterfaceStubs.h @@ -0,0 +1,40 @@ +//===--- InterfaceStubs.cpp - Base InterfaceStubs Implementations C++ ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_IFS_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_IFS_H + +#include "clang/Driver/Tool.h" +#include "clang/Driver/ToolChain.h" +#include + +using namespace clang; +using namespace llvm::opt; + +namespace clang { +namespace driver { +namespace tools { +namespace ifstool { +class LLVM_LIBRARY_VISIBILITY Merger : public Tool { +public: + Merger(const ToolChain &TC) : Tool("IFS::Merger", "merger", TC) {} + + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return false; } + + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; +} // end namespace ifstool +} // end namespace tools +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_IFS_H diff --git a/clang/lib/Driver/ToolChains/InterfaceStubs.cpp b/clang/lib/Driver/ToolChains/InterfaceStubs.cpp new file mode 100644 --- /dev/null +++ b/clang/lib/Driver/ToolChains/InterfaceStubs.cpp @@ -0,0 +1,42 @@ +//===--- InterfaceStubs.cpp - Base InterfaceStubs Implementations C++ ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "InterfaceStubs.h" +#include "CommonArgs.h" +#include "clang/Config/config.h" // for GCC_INSTALL_PREFIX +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/Tool.h" +#include "clang/Driver/ToolChain.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/TargetParser.h" +#include "llvm/Support/VirtualFileSystem.h" +#include + +using namespace clang::driver; +using namespace clang; +using namespace llvm::opt; + +void tools::ifstool::Merger::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + llvm::errs() << "Construct merger job\n"; + SmallVector CmdArgs; + const char *Exec = "/bin/echo"; + // CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + for (auto Input : Inputs) + CmdArgs.push_back(Input.getFilename()); + C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs)); +} 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 @@ -319,6 +319,17 @@ llvm::copy_if(PhaseList, std::back_inserter(P), [](phases::ID Phase) { return Phase <= phases::Precompile; }); + // Treat Interface Stubs like its own compilation mode. + else if (DAL.getLastArg(options::OPT_emit_iterface_stubs)) { + llvm::SmallVector IfsModePhaseList; + types::getCompilationPhases(types::TY_IFS, IfsModePhaseList); + llvm::copy_if( + IfsModePhaseList, std::back_inserter(P), [&DAL](phases::ID Phase) { + return Phase <= ((DAL.getLastArg(options::OPT_c)) ? phases::Compile + : phases::IfsMerge); + }); + } + // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler. else if (DAL.getLastArg(options::OPT_fsyntax_only) || DAL.getLastArg(options::OPT_print_supported_cpus) || @@ -327,7 +338,6 @@ 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)) llvm::copy_if(PhaseList, std::back_inserter(P),