diff --git a/include/swift/Driver/Job.h b/include/swift/Driver/Job.h index 1351cd73819..69a88d8790c 100644 --- a/include/swift/Driver/Job.h +++ b/include/swift/Driver/Job.h @@ -33,7 +33,6 @@ namespace driver { class Action; class InputAction; class Job; -class Tool; class CommandOutput { types::ID PrimaryOutputType; @@ -89,12 +88,9 @@ public: }; private: - /// The action which caused the creation of this Job. - const Action &Source; - - /// The tool which created this Job, and the conditions under which it must - /// be run. - llvm::PointerIntPair CreatorAndCondition; + /// The action which caused the creation of this Job, and the conditions + /// under which it must be run. + llvm::PointerIntPair SourceAndCondition; /// The list of other Jobs which are inputs to this Job. SmallVector Inputs; @@ -113,17 +109,16 @@ private: llvm::sys::TimeValue InputModTime = llvm::sys::TimeValue::MaxTime(); public: - Job(const Action &Source, const Tool &Creator, + Job(const Action &Source, SmallVectorImpl &&Inputs, std::unique_ptr Output, const char *Executable, llvm::opt::ArgStringList Arguments) - : Source(Source), CreatorAndCondition(&Creator, Condition::Always), + : SourceAndCondition(&Source, Condition::Always), Inputs(std::move(Inputs)), Output(std::move(Output)), Executable(Executable), Arguments(std::move(Arguments)) {} - const Action &getSource() const { return Source; } - const Tool &getCreator() const { return *CreatorAndCondition.getPointer(); } + const Action &getSource() const { return *SourceAndCondition.getPointer(); } const char *getExecutable() const { return Executable; } const llvm::opt::ArgStringList &getArguments() const { return Arguments; } @@ -132,10 +127,10 @@ public: const CommandOutput &getOutput() const { return *Output; } Condition getCondition() const { - return CreatorAndCondition.getInt(); + return SourceAndCondition.getInt(); } void setCondition(Condition Cond) { - CreatorAndCondition.setInt(Cond); + SourceAndCondition.setInt(Cond); } void setInputModTime(llvm::sys::TimeValue time) { diff --git a/include/swift/Driver/Tool.h b/include/swift/Driver/Tool.h deleted file mode 100644 index cde2084901e..00000000000 --- a/include/swift/Driver/Tool.h +++ /dev/null @@ -1,95 +0,0 @@ -//===--- Tool.h - Compilation Tools -----------------------------*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See http://swift.org/LICENSE.txt for license information -// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_DRIVER_TOOL_H -#define SWIFT_DRIVER_TOOL_H - -#include "swift/Basic/LLVM.h" -#include "swift/Driver/Util.h" -#include "llvm/Option/Option.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" - -#include -#include - -namespace llvm { -namespace opt { - class ArgList; -} -} - -namespace swift { -namespace driver { - class Compilation; - class CommandOutput; - class JobAction; - class Job; - class OutputInfo; - class ToolChain; - -class Tool { - /// The tool name, for debugging purposes. - std::string Name; - - /// The human readable name of the tool, for use in diagnostics. - std::string DiagName; - - /// The tool chain of which this tool is a part. - const ToolChain &TheToolChain; - -public: - Tool(StringRef Name, StringRef DiagName, const ToolChain &TC) - : Name(Name), DiagName(DiagName), TheToolChain(TC) {} - Tool(StringRef Name, const ToolChain &TC) - : Tool(Name, Name, TC) {} - - virtual ~Tool() = default; - - StringRef getName() const { return Name; } - - StringRef getNameForDiagnostics() const { return DiagName; } - - const ToolChain &getToolChain() const { return TheToolChain; } - - /// \brief Does this tool have "good" standardized diagnostic, or should the - /// driver add an additional "command failed" diagnostic on failure? - virtual bool hasGoodDiagnostics() const { return false; } - - /// Construct a Job to perform \p JA for the given input Jobs \p Inputs. - /// - /// \param Args The argument list for this tool chain. - /// \param OI information about the output which the driver will create, - /// which may influence the creation of this Job. - std::unique_ptr constructJob(const JobAction &JA, - SmallVectorImpl &&Inputs, - std::unique_ptr Output, - const ActionList &InputActions, - const llvm::opt::ArgList &Args, - const OutputInfo &OI) const; - -protected: - virtual llvm::opt::ArgStringList - constructArgumentList(const JobAction &JA, - ArrayRef Inputs, - const CommandOutput *Output, - const ActionList &InputActions, - const llvm::opt::ArgList &Args, - const OutputInfo &OI) const = 0; - - virtual const char *getPath(const llvm::opt::ArgList &Args, - const OutputInfo &OI) const = 0; -}; -} // end namespace driver -} // end namespace swift - -#endif diff --git a/include/swift/Driver/ToolChain.h b/include/swift/Driver/ToolChain.h index dc8eef6b327..17dcac55360 100644 --- a/include/swift/Driver/ToolChain.h +++ b/include/swift/Driver/ToolChain.h @@ -13,67 +13,109 @@ #ifndef SWIFT_DRIVER_TOOLCHAIN_H #define SWIFT_DRIVER_TOOLCHAIN_H -#include "swift/Basic/LLVM.h" #include "swift/Driver/Action.h" #include "swift/Driver/Types.h" -#include "llvm/Support/Program.h" +#include "swift/Basic/LLVM.h" +#include "llvm/Option/Option.h" #include "llvm/ADT/Triple.h" #include -namespace llvm { -namespace opt { - class ArgList; - class DerivedArgList; - class InputArgList; -} -} - namespace swift { namespace driver { + class CommandOutput; class Compilation; class Driver; - class Tool; + class Job; + class OutputInfo; +/// A ToolChain is responsible for turning abstract Actions into concrete, +/// runnable Jobs. +/// +/// The primary purpose of a ToolChain is built around the +/// \c constructInvocation family of methods. This is a set of callbacks +/// following the Visitor pattern for the various JobAction subclasses, which +/// returns an executable name and arguments for the Job to be run. The base +/// ToolChain knows how to perform most operations, but some (like linking) +/// require platform-specific knowledge, provided in subclasses. class ToolChain { const Driver &D; const llvm::Triple Triple; - - mutable std::unique_ptr Swift; - mutable std::unique_ptr MergeModule; - mutable std::unique_ptr LLDB; - mutable std::unique_ptr Linker; - mutable std::unique_ptr Dsymutil; - mutable std::unique_ptr AutolinkExtract; - - Tool *getSwift() const; - Tool *getMergeModule() const; - Tool *getLLDB() const; - Tool *getLinker() const; - Tool *getDsymutil() const; - Tool *getAutolinkExtract() const; + mutable llvm::StringMap ProgramLookupCache; protected: ToolChain(const Driver &D, const llvm::Triple &T) : D(D), Triple(T) {} - virtual std::unique_ptr buildLinker() const = 0; + /// A special name used to identify the Swift executable itself. + constexpr static const char * const SWIFT_EXECUTABLE_NAME = "swift"; + + /// Packs together the supplementary information about the job being created. + struct JobContext { + ArrayRef Inputs; + const CommandOutput &Output; + ArrayRef InputActions; + const llvm::opt::ArgList &Args; + const OutputInfo &OI; + }; + + virtual std::pair + constructInvocation(const CompileJobAction &job, + const JobContext &context) const; + virtual std::pair + constructInvocation(const BackendJobAction &job, + const JobContext &context) const; + virtual std::pair + constructInvocation(const MergeModuleJobAction &job, + const JobContext &context) const; + + virtual std::pair + constructInvocation(const REPLJobAction &job, + const JobContext &context) const; + + virtual std::pair + constructInvocation(const GenerateDSYMJobAction &job, + const JobContext &context) const; + virtual std::pair + constructInvocation(const AutolinkExtractJobAction &job, + const JobContext &context) const; + virtual std::pair + constructInvocation(const LinkJobAction &job, + const JobContext &context) const; + + /// Searches for the given executable in appropriate paths relative to the + /// Swift binary. + /// + /// This method caches its results. + /// + /// \sa findProgramRelativeToSwiftImpl + std::string findProgramRelativeToSwift(StringRef name) const; + + /// An override point for platform-specific subclasses to customize how to + /// do relative searches for programs. + /// + /// This method is invoked by findProgramRelativeToSwift(). + virtual std::string findProgramRelativeToSwiftImpl(StringRef name) const; public: virtual ~ToolChain() = default; - // Accessors - const Driver &getDriver() const { return D; } const llvm::Triple &getTriple() const { return Triple; } - /// Choose a tool to use to handle the action \p JA. - virtual Tool *selectTool(const JobAction &JA) const; + /// Construct a Job for the action \p JA, taking the given information into + /// account. + /// + /// This method dispatches to the various \c constructInvocation methods, + /// which may be overridden by platform-specific subclasses. + std::unique_ptr constructJob(const JobAction &JA, + SmallVectorImpl &&inputs, + std::unique_ptr output, + const ActionList &inputActions, + const llvm::opt::ArgList &args, + const OutputInfo &OI) const; /// Look up \p Name in the list of program search paths. - virtual std::string getProgramPath(StringRef Name) const; - - // Platform defaults information - + /// /// Return the default langauge type to use for the given extension. virtual types::ID lookupTypeForExtension(StringRef Ext) const; }; diff --git a/include/swift/Driver/Util.h b/include/swift/Driver/Util.h index b04c9a4a80f..ef5b7e7ea32 100644 --- a/include/swift/Driver/Util.h +++ b/include/swift/Driver/Util.h @@ -30,17 +30,6 @@ namespace driver { DynamicLibrary }; - /// Searches for an executable relative to the compiler itself. - /// - /// This first looks next to the compiler binary, then checks to see if the - /// compiler is in an Xcode toolchain and looks in the bin directory outside - /// the toolchain. - /// - /// \returns The path to the executable being searched for, or an empty string - /// if it cannot be found. - std::string findRelativeExecutable(StringRef compilerPath, - StringRef executableName); - } // end namespace driver } // end namespace swift diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 243af6ea45e..f183827f069 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -72,7 +72,7 @@ def driver_print_actions : Flag<["-"], "driver-print-actions">, def driver_print_output_file_map : Flag<["-"], "driver-print-output-file-map">, InternalDebugOpt, HelpText<"Dump the contents of the output file map">; def driver_print_bindings : Flag<["-"], "driver-print-bindings">, - InternalDebugOpt, HelpText<"Dump list of bindings">; + InternalDebugOpt, HelpText<"Dump list of job inputs and outputs">; def driver_print_jobs : Flag<["-"], "driver-print-jobs">, InternalDebugOpt, HelpText<"Dump list of jobs to execute">; def _HASH_HASH_HASH : Flag<["-"], "###">, Alias; diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt index eb852f76428..a8718746a0e 100644 --- a/lib/Driver/CMakeLists.txt +++ b/lib/Driver/CMakeLists.txt @@ -7,12 +7,9 @@ set(swiftDriver_sources Job.cpp OutputFileMap.cpp ParseableOutput.cpp - Tool.cpp - Tools.cpp ToolChain.cpp ToolChains.cpp Types.cpp - Util.cpp ) add_swift_library(swiftDriver diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp index b6f312f7f0b..437a17be7bb 100644 --- a/lib/Driver/Compilation.cpp +++ b/lib/Driver/Compilation.cpp @@ -23,7 +23,6 @@ #include "swift/Driver/Driver.h" #include "swift/Driver/Job.h" #include "swift/Driver/ParseableOutput.h" -#include "swift/Driver/Tool.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/TinyPtrVector.h" @@ -338,7 +337,7 @@ int Compilation::performJobsImpl() { } } - int Result = 0; + int Result = EXIT_SUCCESS; // Set up a callback which will be called immediately after a task has // started. This callback may be used to provide output indicating that the @@ -374,21 +373,23 @@ int Compilation::performJobsImpl() { llvm::errs() << Output; } - if (ReturnCode != 0) { + if (ReturnCode != EXIT_SUCCESS) { // The task failed, so return true without performing any further // dependency analysis. // Store this task's ReturnCode as our Result if we haven't stored // anything yet. - if (Result == 0) + if (Result == EXIT_SUCCESS) Result = ReturnCode; - if (!FinishedCmd->getCreator().hasGoodDiagnostics() || ReturnCode != 1) + if (!isa(FinishedCmd->getSource()) || + ReturnCode != EXIT_FAILURE) { Diags.diagnose(SourceLoc(), diag::error_command_failed, - FinishedCmd->getCreator().getNameForDiagnostics(), + FinishedCmd->getSource().getClassName(), ReturnCode); + } - return ContinueBuildingAfterErrors ? + return ContinueBuildingAfterErrors ? TaskFinishedResponse::ContinueExecution : TaskFinishedResponse::StopExecution; } @@ -455,7 +456,7 @@ int Compilation::performJobsImpl() { ErrorMsg); Diags.diagnose(SourceLoc(), diag::error_command_signalled, - SignalledCmd->getCreator().getNameForDiagnostics()); + SignalledCmd->getSource().getClassName()); // Since the task signalled, so unconditionally set result to -2. Result = -2; diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 5a54acec53d..d1eb953da39 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -16,7 +16,6 @@ #include "swift/Driver/Driver.h" -#include "Tools.h" #include "ToolChains.h" #include "swift/Strings.h" #include "swift/AST/DiagnosticEngine.h" @@ -1607,6 +1606,7 @@ Job *Driver::buildJobsForAction(Compilation &C, const Action *A, const ToolChain &TC, bool AtTopLevel, JobCacheMap &JobCache) const { assert(!isa(A) && "unexpected unprocessed input"); + const auto *JA = cast(A); // 1. See if we've already got this cached. std::pair Key(A, &TC); @@ -1630,13 +1630,7 @@ Job *Driver::buildJobsForAction(Compilation &C, const Action *A, } } - // 3. Select the right tool for the job. - const JobAction *JA = cast(A); - const Tool *T = TC.selectTool(*JA); - if (!T) - return nullptr; - - // 4. Determine the CommandOutput for the job. + // 3. Determine the CommandOutput for the job. StringRef BaseInput; if (!InputActions.empty()) { // Use the first InputAction as our BaseInput. @@ -1856,9 +1850,10 @@ Job *Driver::buildJobsForAction(Compilation &C, const Action *A, } // 5. Construct a Job which produces the right CommandOutput. - std::unique_ptr ownedJob = T->constructJob(*JA, std::move(InputJobs), - std::move(Output), - InputActions, C.getArgs(), OI); + std::unique_ptr ownedJob = TC.constructJob(*JA, std::move(InputJobs), + std::move(Output), + InputActions, C.getArgs(), + OI); Job *J = C.addJob(std::move(ownedJob)); // If we track dependencies for this job, we may be able to avoid running it. @@ -1877,8 +1872,8 @@ Job *Driver::buildJobsForAction(Compilation &C, const Action *A, JobCache[Key] = J; if (DriverPrintBindings) { - llvm::outs() << "# \"" << T->getToolChain().getTriple().str() - << "\" - \"" << T->getName() + llvm::outs() << "# \"" << TC.getTriple().str() + << "\" - \"" << llvm::sys::path::filename(J->getExecutable()) << "\", inputs: ["; interleave(InputActions.begin(), InputActions.end(), diff --git a/lib/Driver/FrontendUtil.cpp b/lib/Driver/FrontendUtil.cpp index 7e4026e865e..4960246f715 100644 --- a/lib/Driver/FrontendUtil.cpp +++ b/lib/Driver/FrontendUtil.cpp @@ -17,7 +17,6 @@ #include "swift/Driver/Compilation.h" #include "swift/Driver/Driver.h" #include "swift/Driver/Job.h" -#include "swift/Driver/Tool.h" #include "swift/Frontend/Frontend.h" using namespace swift; @@ -57,7 +56,7 @@ swift::driver::createCompilerInvocation(ArrayRef ArgList, } const Job *Cmd = *CompileCommands.begin(); - if (Cmd->getCreator().getName() != "swift") { + if (Cmd->getArguments().front() != "-frontend") { Diags.diagnose(SourceLoc(), diag::error_expected_frontend_command); return nullptr; } diff --git a/lib/Driver/Tool.cpp b/lib/Driver/Tool.cpp deleted file mode 100644 index df0c9e8c38c..00000000000 --- a/lib/Driver/Tool.cpp +++ /dev/null @@ -1,32 +0,0 @@ -//===--- Tool.cpp - Compilation Tools -------------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See http://swift.org/LICENSE.txt for license information -// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#include "swift/Driver/Tool.h" -#include "swift/Driver/Action.h" -#include "swift/Driver/Job.h" -#include "llvm/ADT/STLExtras.h" - -using namespace swift; -using namespace swift::driver; - -std::unique_ptr -Tool::constructJob(const JobAction &JA, - SmallVectorImpl &&inputs, - std::unique_ptr output, - const ActionList &inputActions, - const llvm::opt::ArgList &args, - const OutputInfo &OI) const { - auto arguments = constructArgumentList(JA, inputs, output.get(), - inputActions, args, OI); - return llvm::make_unique(JA, *this, std::move(inputs), std::move(output), - getPath(args, OI), std::move(arguments)); -} diff --git a/lib/Driver/ToolChain.cpp b/lib/Driver/ToolChain.cpp index a673a4238a2..1a074073a1b 100644 --- a/lib/Driver/ToolChain.cpp +++ b/lib/Driver/ToolChain.cpp @@ -9,80 +9,100 @@ // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// +// +/// \file This file defines the base implementation of the ToolChain class. +/// The platform-specific subclasses are implemented in ToolChains.cpp. +/// For organizational purposes, the platform-independent logic for +/// constructing job invocations is also located in ToolChains.cpp. +// +//===----------------------------------------------------------------------===// #include "swift/Driver/ToolChain.h" -#include "Tools.h" -#include "swift/Driver/Tool.h" +#include "swift/Driver/Driver.h" +#include "swift/Driver/Job.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Program.h" +#include "llvm/ADT/STLExtras.h" using namespace swift; using namespace swift::driver; using namespace llvm::opt; -template -static Tool *cacheTool(const ToolChain &TC, - const std::unique_ptr &tool) { - if (!tool) - const_cast &>(tool).reset(new T(TC)); - return tool.get(); -} +const char * const ToolChain::SWIFT_EXECUTABLE_NAME; -#define CACHE_TOOL(X) \ -Tool *ToolChain::get##X() const { \ - return cacheTool(*this, X); \ -} +std::unique_ptr +ToolChain::constructJob(const JobAction &JA, + SmallVectorImpl &&inputs, + std::unique_ptr output, + const ActionList &inputActions, + const llvm::opt::ArgList &args, + const OutputInfo &OI) const { + JobContext context{inputs, *output, inputActions, args, OI}; -CACHE_TOOL(Swift) -CACHE_TOOL(MergeModule) -CACHE_TOOL(LLDB) -CACHE_TOOL(Dsymutil) -CACHE_TOOL(AutolinkExtract) - -Tool *ToolChain::getLinker() const { - if (!Linker) - Linker = buildLinker(); - return Linker.get(); -} - -Tool *ToolChain::selectTool(const JobAction &JA) const { + const char *executableName; + llvm::opt::ArgStringList arguments; switch (JA.getKind()) { - case Action::CompileJob: - case Action::BackendJob: - return getSwift(); - case Action::MergeModuleJob: - return getMergeModule(); - case Action::LinkJob: - return getLinker(); - case Action::GenerateDSYMJob: - return getDsymutil(); - case Action::AutolinkExtractJob: - return getAutolinkExtract(); - case Action::REPLJob: - switch (cast(JA).getRequestedMode()) { - case REPLJobAction::Mode::Integrated: - return getSwift(); - case REPLJobAction::Mode::RequireLLDB: - return getLLDB(); - case REPLJobAction::Mode::PreferLLDB: - if (static_cast(getLLDB())->isPresentRelativeToDriver()) - return getLLDB(); - return getSwift(); - } +#define CASE(K) case Action::K: \ + std::tie(executableName, arguments) = \ + constructInvocation(cast(JA), context); \ + break; + CASE(CompileJob) + CASE(BackendJob) + CASE(MergeModuleJob) + CASE(LinkJob) + CASE(GenerateDSYMJob) + CASE(AutolinkExtractJob) + CASE(REPLJob) +#undef CASE case Action::Input: - llvm_unreachable("Invalid tool kind."); + llvm_unreachable("not a JobAction"); } - llvm_unreachable("Invalid tool kind."); + // Special-case the Swift frontend. + const char *executablePath = nullptr; + if (StringRef(SWIFT_EXECUTABLE_NAME) == executableName) { + executablePath = getDriver().getSwiftProgramPath().c_str(); + } else { + std::string relativePath = findProgramRelativeToSwift(executableName); + if (!relativePath.empty()) { + executablePath = args.MakeArgString(relativePath); + } else { + auto systemPath = llvm::sys::findProgramByName(executableName); + if (systemPath) { + executablePath = args.MakeArgString(systemPath.get()); + } else { + // For debugging purposes. + executablePath = executableName; + } + } + } + + return llvm::make_unique(JA, std::move(inputs), std::move(output), + executablePath, std::move(arguments)); } -std::string ToolChain::getProgramPath(StringRef Name) const { - // TODO: perform ToolChain-specific lookup +std::string +ToolChain::findProgramRelativeToSwift(StringRef executableName) const { + auto insertionResult = + ProgramLookupCache.insert(std::make_pair(executableName, "")); + if (insertionResult.second) { + std::string path = findProgramRelativeToSwiftImpl(executableName); + insertionResult.first->setValue(std::move(path)); + } + return insertionResult.first->getValue(); +} - auto P = llvm::sys::findProgramByName(Name); - if (!P.getError()) - return *P; - - return Name; +std::string +ToolChain::findProgramRelativeToSwiftImpl(StringRef executableName) const { + llvm::SmallString<128> path{getDriver().getSwiftProgramPath()}; + llvm::sys::path::remove_filename(path); + auto result = llvm::sys::findProgramByName(executableName, {path}); + if (result) + return result.get(); + return {}; } types::ID ToolChain::lookupTypeForExtension(StringRef Ext) const { diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index a279c62a7e4..ad8be6d15aa 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -1,4 +1,4 @@ -//===--- ToolChains.cpp - ToolChain Implementations -----------------------===// +//===--- ToolChains.cpp - Job invocations (general and per-plaftorm) ------===// // // This source file is part of the Swift.org open source project // @@ -12,25 +12,965 @@ #include "ToolChains.h" -#include "Tools.h" +#include "swift/Basic/Dwarf.h" +#include "swift/Basic/Fallthrough.h" +#include "swift/Basic/LLVM.h" +#include "swift/Basic/Platform.h" +#include "swift/Basic/Range.h" +#include "swift/Driver/Driver.h" +#include "swift/Driver/Job.h" +#include "swift/Frontend/Frontend.h" +#include "swift/Option/Options.h" +#include "swift/Config.h" +#include "clang/Basic/Version.h" +#include "clang/Driver/Util.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Program.h" using namespace swift; using namespace swift::driver; -using namespace swift::driver::toolchains; using namespace llvm::opt; -/// Darwin +/// The name of the Swift migrator binary. +static const char * const SWIFT_UPDATE_NAME = "swift-update"; -std::unique_ptr Darwin::buildLinker() const { - return std::unique_ptr(new tools::darwin::Linker(*this)); +static void addInputsOfType(ArgStringList &Arguments, + ArrayRef Inputs, + types::ID InputType) { + for (auto &Input : Inputs) { + if (Input->getType() != InputType) + continue; + Arguments.push_back(cast(Input)->getInputArg().getValue()); + } +} + +static void addInputsOfType(ArgStringList &Arguments, + ArrayRef Jobs, + types::ID InputType) { + for (const Job *Cmd : Jobs) { + auto &output = Cmd->getOutput().getAnyOutputForType(InputType); + if (!output.empty()) + Arguments.push_back(output.c_str()); + } +} + +static void addPrimaryInputsOfType(ArgStringList &Arguments, + ArrayRef Jobs, + types::ID InputType) { + for (const Job *Cmd : Jobs) { + auto &outputInfo = Cmd->getOutput(); + if (outputInfo.getPrimaryOutputType() == InputType) { + for (const std::string &Output : outputInfo.getPrimaryOutputFilenames()) { + Arguments.push_back(Output.c_str()); + } + } + } +} + +/// Handle arguments common to all invocations of the frontend (compilation, +/// module-merging, LLDB's REPL, etc). +static void addCommonFrontendArgs(const ToolChain &TC, + const OutputInfo &OI, + const CommandOutput &output, + const ArgList &inputArgs, + ArgStringList &arguments) { + arguments.push_back("-target"); + arguments.push_back(inputArgs.MakeArgString(TC.getTriple().str())); + const llvm::Triple &Triple = TC.getTriple(); + + // Enable address top-byte ignored in the ARM64 backend. + if (Triple.getArch() == llvm::Triple::aarch64) { + arguments.push_back("-Xllvm"); + arguments.push_back("-aarch64-use-tbi"); + } + + // Enable or disable ObjC interop appropriately for the platform + if (Triple.isOSDarwin()) { + arguments.push_back("-enable-objc-interop"); + } else { + arguments.push_back("-disable-objc-interop"); + } + + // Handle the CPU and its preferences. + if (auto arg = inputArgs.getLastArg(options::OPT_target_cpu)) + arg->render(inputArgs, arguments); + + if (!OI.SDKPath.empty()) { + arguments.push_back("-sdk"); + arguments.push_back(inputArgs.MakeArgString(OI.SDKPath)); + } + + inputArgs.AddAllArgs(arguments, options::OPT_I); + inputArgs.AddAllArgs(arguments, options::OPT_F); + + inputArgs.AddLastArg(arguments, options::OPT_AssertConfig); + inputArgs.AddLastArg(arguments, options::OPT_autolink_force_load); + inputArgs.AddLastArg(arguments, options::OPT_color_diagnostics); + inputArgs.AddLastArg(arguments, options::OPT_enable_app_extension); + inputArgs.AddLastArg(arguments, options::OPT_enable_testing); + inputArgs.AddLastArg(arguments, options::OPT_g_Group); + inputArgs.AddLastArg(arguments, options::OPT_import_objc_header); + inputArgs.AddLastArg(arguments, options::OPT_import_underlying_module); + inputArgs.AddLastArg(arguments, options::OPT_module_cache_path); + inputArgs.AddLastArg(arguments, options::OPT_module_link_name); + inputArgs.AddLastArg(arguments, options::OPT_nostdimport); + inputArgs.AddLastArg(arguments, options::OPT_parse_stdlib); + inputArgs.AddLastArg(arguments, options::OPT_resource_dir); + inputArgs.AddLastArg(arguments, options::OPT_solver_memory_threshold); + inputArgs.AddLastArg(arguments, options::OPT_profile_generate); + inputArgs.AddLastArg(arguments, options::OPT_profile_coverage_mapping); + + // Pass on any build config options + inputArgs.AddAllArgs(arguments, options::OPT_D); + + // Pass through the values passed to -Xfrontend. + inputArgs.AddAllArgValues(arguments, options::OPT_Xfrontend); + + // Pass through any subsystem flags. + inputArgs.AddAllArgs(arguments, options::OPT_Xllvm); + inputArgs.AddAllArgs(arguments, options::OPT_Xcc); + + const std::string &moduleDocOutputPath = + output.getAdditionalOutputForType(types::TY_SwiftModuleDocFile); + if (!moduleDocOutputPath.empty()) { + arguments.push_back("-emit-module-doc-path"); + arguments.push_back(moduleDocOutputPath.c_str()); + } + + if (llvm::sys::Process::StandardErrHasColors()) + arguments.push_back("-color-diagnostics"); +} + +std::pair +ToolChain::constructInvocation(const CompileJobAction &job, + const JobContext &context) const { + ArgStringList Arguments; + + if (context.OI.CompilerMode != OutputInfo::Mode::UpdateCode) + Arguments.push_back("-frontend"); + + // Determine the frontend mode option. + const char *FrontendModeOption = nullptr; + switch (context.OI.CompilerMode) { + case OutputInfo::Mode::StandardCompile: + case OutputInfo::Mode::SingleCompile: { + switch (context.Output.getPrimaryOutputType()) { + case types::TY_Object: + FrontendModeOption = "-c"; + break; + case types::TY_RawSIL: + FrontendModeOption = "-emit-silgen"; + break; + case types::TY_SIL: + FrontendModeOption = "-emit-sil"; + break; + case types::TY_RawSIB: + FrontendModeOption = "-emit-sibgen"; + break; + case types::TY_SIB: + FrontendModeOption = "-emit-sib"; + break; + case types::TY_LLVM_IR: + FrontendModeOption = "-emit-ir"; + break; + case types::TY_LLVM_BC: + FrontendModeOption = "-emit-bc"; + break; + case types::TY_Assembly: + FrontendModeOption = "-S"; + break; + case types::TY_SwiftModuleFile: + // Since this is our primary output, we need to specify the option here. + FrontendModeOption = "-emit-module"; + break; + case types::TY_Nothing: + // We were told to output nothing, so get the last mode option and use that. + if (const Arg *A = context.Args.getLastArg(options::OPT_modes_Group)) + FrontendModeOption = A->getSpelling().data(); + else + llvm_unreachable("We were told to perform a standard compile, " + "but no mode option was passed to the driver."); + break; + case types::TY_Swift: + case types::TY_dSYM: + case types::TY_AutolinkFile: + case types::TY_Dependencies: + case types::TY_SwiftModuleDocFile: + case types::TY_ClangModuleFile: + case types::TY_SerializedDiagnostics: + case types::TY_ObjCHeader: + case types::TY_Image: + case types::TY_SwiftDeps: + case types::TY_Remapping: + llvm_unreachable("Output type can never be primary output."); + case types::TY_INVALID: + llvm_unreachable("Invalid type ID"); + } + break; + } + case OutputInfo::Mode::Immediate: + FrontendModeOption = "-interpret"; + break; + case OutputInfo::Mode::REPL: + llvm_unreachable("REPL mode handled elsewhere"); + case OutputInfo::Mode::UpdateCode: + // Make sure that adding '-update-code' will permit accepting all arguments + // '-c' accepts. + FrontendModeOption = "-c"; + break; + } + + assert(FrontendModeOption != nullptr && "No frontend mode option specified!"); + + Arguments.push_back(FrontendModeOption); + + assert(context.Inputs.empty() && + "The Swift frontend does not expect to be fed any input Jobs!"); + + // Add input arguments. + switch (context.OI.CompilerMode) { + case OutputInfo::Mode::StandardCompile: + case OutputInfo::Mode::UpdateCode: { + assert(context.InputActions.size() == 1 && + "The Swift frontend expects exactly one input (the primary file)!"); + + auto *IA = cast(context.InputActions[0]); + const Arg &PrimaryInputArg = IA->getInputArg(); + bool FoundPrimaryInput = false; + + for (auto *A : make_range(context.Args.filtered_begin(options::OPT_INPUT), + context.Args.filtered_end())) { + // See if this input should be passed with -primary-file. + // FIXME: This will pick up non-source inputs too, like .o files. + if (!FoundPrimaryInput && PrimaryInputArg.getIndex() == A->getIndex()) { + Arguments.push_back("-primary-file"); + FoundPrimaryInput = true; + } + Arguments.push_back(A->getValue()); + } + break; + } + case OutputInfo::Mode::SingleCompile: + case OutputInfo::Mode::Immediate: { + for (const Action *A : context.InputActions) { + cast(A)->getInputArg().render(context.Args, Arguments); + } + break; + } + case OutputInfo::Mode::REPL: { + llvm_unreachable("REPL mode handled elsewhere"); + } + } + + if (context.Args.hasArg(options::OPT_parse_stdlib)) + Arguments.push_back("-disable-objc-attr-requires-foundation-module"); + + addCommonFrontendArgs(*this, context.OI, context.Output, context.Args, + Arguments); + + // Pass the optimization level down to the frontend. + context.Args.AddLastArg(Arguments, options::OPT_O_Group); + + if (context.Args.hasArg(options::OPT_parse_as_library) || + context.Args.hasArg(options::OPT_emit_library)) + Arguments.push_back("-parse-as-library"); + + context.Args.AddLastArg(Arguments, options::OPT_parse_sil); + + Arguments.push_back("-module-name"); + Arguments.push_back(context.Args.MakeArgString(context.OI.ModuleName)); + + // Mode-specific arguments. + switch (context.OI.CompilerMode) { + case OutputInfo::Mode::StandardCompile: + case OutputInfo::Mode::SingleCompile: + case OutputInfo::Mode::UpdateCode: + break; + case OutputInfo::Mode::Immediate: + case OutputInfo::Mode::REPL: + context.Args.AddAllArgs(Arguments, options::OPT_l, options::OPT_framework, + options::OPT_L); + break; + } + + const std::string &ModuleOutputPath = + context.Output.getAdditionalOutputForType(types::ID::TY_SwiftModuleFile); + if (!ModuleOutputPath.empty()) { + Arguments.push_back("-emit-module-path"); + Arguments.push_back(ModuleOutputPath.c_str()); + } + + const std::string &ObjCHeaderOutputPath = + context.Output.getAdditionalOutputForType(types::ID::TY_ObjCHeader); + if (!ObjCHeaderOutputPath.empty()) { + assert(context.OI.CompilerMode == OutputInfo::Mode::SingleCompile && + "The Swift tool should only emit an Obj-C header in single compile" + "mode!"); + + Arguments.push_back("-emit-objc-header-path"); + Arguments.push_back(ObjCHeaderOutputPath.c_str()); + } + + const std::string &SerializedDiagnosticsPath = + context.Output.getAdditionalOutputForType(types::TY_SerializedDiagnostics); + if (!SerializedDiagnosticsPath.empty()) { + Arguments.push_back("-serialize-diagnostics-path"); + Arguments.push_back(SerializedDiagnosticsPath.c_str()); + } + + const std::string &DependenciesPath = + context.Output.getAdditionalOutputForType(types::TY_Dependencies); + if (!DependenciesPath.empty()) { + Arguments.push_back("-emit-dependencies-path"); + Arguments.push_back(DependenciesPath.c_str()); + } + + const std::string &ReferenceDependenciesPath = + context.Output.getAdditionalOutputForType(types::TY_SwiftDeps); + if (!ReferenceDependenciesPath.empty()) { + Arguments.push_back("-emit-reference-dependencies-path"); + Arguments.push_back(ReferenceDependenciesPath.c_str()); + } + + const std::string &FixitsPath = + context.Output.getAdditionalOutputForType(types::TY_Remapping); + if (!FixitsPath.empty()) { + Arguments.push_back("-emit-fixits-path"); + Arguments.push_back(FixitsPath.c_str()); + } + + if (context.OI.numThreads > 0) { + Arguments.push_back("-num-threads"); + Arguments.push_back( + context.Args.MakeArgString(Twine(context.OI.numThreads))); + } + + // Add the output file argument if necessary. + if (context.Output.getPrimaryOutputType() != types::TY_Nothing) { + for (auto &FileName : context.Output.getPrimaryOutputFilenames()) { + Arguments.push_back("-o"); + Arguments.push_back(FileName.c_str()); + } + } + + if (context.Args.hasArg(options::OPT_embed_bitcode_marker)) + Arguments.push_back("-embed-bitcode-marker"); + + // The immediate arguments must be last. + if (context.OI.CompilerMode == OutputInfo::Mode::Immediate) + context.Args.AddLastArg(Arguments, options::OPT__DASH_DASH); + + auto program = SWIFT_EXECUTABLE_NAME; + if (context.OI.CompilerMode == OutputInfo::Mode::UpdateCode) + program = SWIFT_UPDATE_NAME; + + return std::make_pair(program, Arguments); +} + +std::pair +ToolChain::constructInvocation(const BackendJobAction &job, + const JobContext &context) const { + assert(context.Args.hasArg(options::OPT_embed_bitcode)); + ArgStringList Arguments; + + Arguments.push_back("-frontend"); + + // Determine the frontend mode option. + const char *FrontendModeOption = nullptr; + switch (context.OI.CompilerMode) { + case OutputInfo::Mode::StandardCompile: + case OutputInfo::Mode::SingleCompile: { + switch (context.Output.getPrimaryOutputType()) { + case types::TY_Object: + FrontendModeOption = "-c"; + break; + case types::TY_LLVM_IR: + FrontendModeOption = "-emit-ir"; + break; + case types::TY_LLVM_BC: + FrontendModeOption = "-emit-bc"; + break; + case types::TY_Assembly: + FrontendModeOption = "-S"; + break; + case types::TY_Nothing: + // We were told to output nothing, so get the last mode option and use that. + if (const Arg *A = context.Args.getLastArg(options::OPT_modes_Group)) + FrontendModeOption = A->getSpelling().data(); + else + llvm_unreachable("We were told to perform a standard compile, " + "but no mode option was passed to the driver."); + break; + + case types::TY_SwiftModuleFile: + case types::TY_RawSIL: + case types::TY_RawSIB: + case types::TY_SIL: + case types::TY_SIB: + llvm_unreachable("Cannot be output from backend job"); + case types::TY_Swift: + case types::TY_dSYM: + case types::TY_AutolinkFile: + case types::TY_Dependencies: + case types::TY_SwiftModuleDocFile: + case types::TY_ClangModuleFile: + case types::TY_SerializedDiagnostics: + case types::TY_ObjCHeader: + case types::TY_Image: + case types::TY_SwiftDeps: + case types::TY_Remapping: + llvm_unreachable("Output type can never be primary output."); + case types::TY_INVALID: + llvm_unreachable("Invalid type ID"); + } + break; + } + case OutputInfo::Mode::Immediate: + case OutputInfo::Mode::REPL: + case OutputInfo::Mode::UpdateCode: + llvm_unreachable("invalid mode for backend job"); + } + + assert(FrontendModeOption != nullptr && "No frontend mode option specified!"); + + Arguments.push_back(FrontendModeOption); + + // Add input arguments. + switch (context.OI.CompilerMode) { + case OutputInfo::Mode::StandardCompile: { + assert(context.Inputs.size() == 1 && "The backend expects one input!"); + Arguments.push_back("-primary-file"); + const Job *Cmd = context.Inputs.front(); + Arguments.push_back( + Cmd->getOutput().getPrimaryOutputFilename().c_str()); + break; + } + case OutputInfo::Mode::SingleCompile: { + assert(context.Inputs.size() == 1 && "The backend expects one input!"); + Arguments.push_back("-primary-file"); + const Job *Cmd = context.Inputs.front(); + + // In multi-threaded compilation, the backend job must select the correct + // output file of the compilation job. + auto OutNames = Cmd->getOutput().getPrimaryOutputFilenames(); + Arguments.push_back(OutNames[job.getInputIndex()].c_str()); + break; + } + case OutputInfo::Mode::Immediate: + case OutputInfo::Mode::REPL: + case OutputInfo::Mode::UpdateCode: + llvm_unreachable("invalid mode for backend job"); + } + + // Only white-listed flags below are allowed to be embedded. + Arguments.push_back("-target"); + Arguments.push_back(context.Args.MakeArgString(getTriple().str())); + + // Enable address top-byte ignored in the ARM64 backend. + if (getTriple().getArch() == llvm::Triple::aarch64) { + Arguments.push_back("-Xllvm"); + Arguments.push_back("-aarch64-use-tbi"); + } + + // Handle the CPU and its preferences. + if (auto arg = context.Args.getLastArg(options::OPT_target_cpu)) + arg->render(context.Args, Arguments); + + context.Args.AddLastArg(Arguments, options::OPT_parse_stdlib); + + // Pass the optimization level down to the frontend. + context.Args.AddLastArg(Arguments, options::OPT_O_Group); + + Arguments.push_back("-module-name"); + Arguments.push_back(context.Args.MakeArgString(context.OI.ModuleName)); + + // Add the output file argument if necessary. + if (context.Output.getPrimaryOutputType() != types::TY_Nothing) { + for (auto &FileName : context.Output.getPrimaryOutputFilenames()) { + Arguments.push_back("-o"); + Arguments.push_back(FileName.c_str()); + } + } + + // Add flags implied by -embed-bitcode. + Arguments.push_back("-embed-bitcode"); + // Disable all llvm IR level optimizations. + Arguments.push_back("-disable-llvm-optzns"); + + return std::make_pair(SWIFT_EXECUTABLE_NAME, Arguments); +} + +std::pair +ToolChain::constructInvocation(const MergeModuleJobAction &job, + const JobContext &context) const { + ArgStringList Arguments; + + if (context.OI.CompilerMode != OutputInfo::Mode::UpdateCode) + Arguments.push_back("-frontend"); + + // We just want to emit a module, so pass -emit-module without any other + // mode options. + Arguments.push_back("-emit-module"); + + size_t origLen = Arguments.size(); + (void)origLen; + addInputsOfType(Arguments, context.Inputs, types::TY_SwiftModuleFile); + addInputsOfType(Arguments, context.InputActions, types::TY_SwiftModuleFile); + assert(Arguments.size() - origLen >= + context.Inputs.size() + context.InputActions.size()); + assert((Arguments.size() - origLen == context.Inputs.size() || + !context.InputActions.empty()) && + "every input to MergeModule must generate a swiftmodule"); + + // Tell all files to parse as library, which is necessary to load them as + // serialized ASTs. + Arguments.push_back("-parse-as-library"); + + addCommonFrontendArgs(*this, context.OI, context.Output, context.Args, + Arguments); + + Arguments.push_back("-module-name"); + Arguments.push_back(context.Args.MakeArgString(context.OI.ModuleName)); + + assert(context.Output.getPrimaryOutputType() == types::TY_SwiftModuleFile && + "The MergeModule tool only produces swiftmodule files!"); + + const std::string &ObjCHeaderOutputPath = + context.Output.getAdditionalOutputForType(types::TY_ObjCHeader); + if (!ObjCHeaderOutputPath.empty()) { + Arguments.push_back("-emit-objc-header-path"); + Arguments.push_back(ObjCHeaderOutputPath.c_str()); + } + + Arguments.push_back("-o"); + Arguments.push_back( + context.Args.MakeArgString(context.Output.getPrimaryOutputFilename())); + + auto program = SWIFT_EXECUTABLE_NAME; + if (context.OI.CompilerMode == OutputInfo::Mode::UpdateCode) + program = SWIFT_UPDATE_NAME; + + return std::make_pair(program, Arguments); +} + +std::pair +ToolChain::constructInvocation(const REPLJobAction &job, + const JobContext &context) const { + assert(context.Inputs.empty()); + assert(context.InputActions.empty()); + + bool useLLDB; + + switch (job.getRequestedMode()) { + case REPLJobAction::Mode::Integrated: + useLLDB = false; + break; + case REPLJobAction::Mode::RequireLLDB: + useLLDB = true; + break; + case REPLJobAction::Mode::PreferLLDB: + useLLDB = !findProgramRelativeToSwift("lldb").empty(); + break; + } + + ArgStringList FrontendArgs; + addCommonFrontendArgs(*this, context.OI, context.Output, context.Args, + FrontendArgs); + context.Args.AddAllArgs(FrontendArgs, options::OPT_l, options::OPT_framework, + options::OPT_L); + + if (!useLLDB) { + FrontendArgs.insert(FrontendArgs.begin(), {"-frontend", "-repl"}); + FrontendArgs.push_back("-module-name"); + FrontendArgs.push_back(context.Args.MakeArgString(context.OI.ModuleName)); + return std::make_pair(SWIFT_EXECUTABLE_NAME, FrontendArgs); + } + + // Squash important frontend options into a single argument for LLDB. + std::string SingleArg = "--repl="; + { + llvm::raw_string_ostream os(SingleArg); + Job::printArguments(os, FrontendArgs); + } + + ArgStringList Arguments; + Arguments.push_back(context.Args.MakeArgString(std::move(SingleArg))); + + return std::make_pair("lldb", Arguments); +} + + +std::pair +ToolChain::constructInvocation(const GenerateDSYMJobAction &job, + const JobContext &context) const { + assert(context.Inputs.size() == 1); + assert(context.InputActions.empty()); + assert(context.Output.getPrimaryOutputType() == types::TY_dSYM); + + ArgStringList Arguments; + + StringRef inputPath = + context.Inputs.front()->getOutput().getPrimaryOutputFilename(); + Arguments.push_back(context.Args.MakeArgString(inputPath)); + + Arguments.push_back("-o"); + Arguments.push_back( + context.Args.MakeArgString(context.Output.getPrimaryOutputFilename())); + + return std::make_pair("dsymutil", Arguments); +} + +std::pair +ToolChain::constructInvocation(const AutolinkExtractJobAction &job, + const JobContext &context) const { + llvm_unreachable("autolink extraction not implemented for this toolchain"); +} + +std::pair +ToolChain::constructInvocation(const LinkJobAction &job, + const JobContext &context) const { + llvm_unreachable("linking not implemented for this toolchain"); +} + +std::string +toolchains::Darwin::findProgramRelativeToSwiftImpl(StringRef name) const { + StringRef swiftPath = getDriver().getSwiftProgramPath(); + StringRef swiftBinDir = llvm::sys::path::parent_path(swiftPath); + + // See if we're in an Xcode toolchain. + bool hasToolchain = false; + llvm::SmallString<128> path{swiftBinDir}; + llvm::sys::path::remove_filename(path); // bin + llvm::sys::path::remove_filename(path); // usr + if (llvm::sys::path::extension(path) == ".xctoolchain") { + hasToolchain = true; + llvm::sys::path::remove_filename(path); // *.xctoolchain + llvm::sys::path::remove_filename(path); // Toolchains + llvm::sys::path::append(path, "usr", "bin"); + } + + StringRef paths[] = { swiftBinDir, path }; + auto pathsRef = llvm::makeArrayRef(paths); + if (!hasToolchain) + pathsRef = pathsRef.drop_back(); + + auto result = llvm::sys::findProgramByName(name, pathsRef); + if (result) + return result.get(); + return {}; +} + +static void addVersionString(const ArgList &inputArgs, ArgStringList &arguments, + unsigned major, unsigned minor, unsigned micro) { + llvm::SmallString<8> buf; + llvm::raw_svector_ostream os{buf}; + os << major << '.' << minor << '.' << micro; + arguments.push_back(inputArgs.MakeArgString(os.str())); +} + +std::pair +toolchains::Darwin::constructInvocation(const LinkJobAction &job, + const JobContext &context) const { + assert(context.Output.getPrimaryOutputType() == types::TY_Image && + "Invalid linker output type."); + + const Driver &D = getDriver(); + const llvm::Triple &Triple = getTriple(); + + ArgStringList Arguments; + addPrimaryInputsOfType(Arguments, context.Inputs, types::TY_Object); + addInputsOfType(Arguments, context.InputActions, types::TY_Object); + + if (context.OI.DebugInfoKind == IRGenDebugInfoKind::Normal) { + size_t argCount = Arguments.size(); + if (context.OI.CompilerMode == OutputInfo::Mode::SingleCompile) + addInputsOfType(Arguments, context.Inputs, types::TY_SwiftModuleFile); + else + addPrimaryInputsOfType(Arguments, context.Inputs, + types::TY_SwiftModuleFile); + + if (Arguments.size() > argCount) { + assert(argCount + 1 == Arguments.size() && + "multiple swiftmodules found for -g"); + Arguments.insert(Arguments.end() - 1, "-add_ast_path"); + } + } + + switch (job.getKind()) { + case LinkKind::None: + llvm_unreachable("invalid link kind"); + case LinkKind::Executable: + // The default for ld; no extra flags necessary. + break; + case LinkKind::DynamicLibrary: + Arguments.push_back("-dylib"); + break; + } + + assert(Triple.isOSDarwin()); + bool wantsObjCRuntime = false; + if (Triple.isiOS()) + wantsObjCRuntime = Triple.isOSVersionLT(8); + else if (Triple.isWatchOS()) + wantsObjCRuntime = Triple.isOSVersionLT(2); + else if (Triple.isMacOSX()) + wantsObjCRuntime = Triple.isMacOSXVersionLT(10, 10); + + if (context.Args.hasFlag(options::OPT_link_objc_runtime, + options::OPT_no_link_objc_runtime, + /*default=*/wantsObjCRuntime)) { + llvm::SmallString<128> ARCLiteLib(D.getSwiftProgramPath()); + llvm::sys::path::remove_filename(ARCLiteLib); // 'swift' + llvm::sys::path::remove_filename(ARCLiteLib); // 'bin' + llvm::sys::path::append(ARCLiteLib, "lib", "arc", "libarclite_"); + ARCLiteLib += getPlatformNameForTriple(Triple); + ARCLiteLib += ".a"; + + Arguments.push_back("-force_load"); + Arguments.push_back(context.Args.MakeArgString(ARCLiteLib)); + + // Arclite depends on CoreFoundation. + Arguments.push_back("-framework"); + Arguments.push_back("CoreFoundation"); + } + + context.Args.AddAllArgValues(Arguments, options::OPT_Xlinker); + context.Args.AddAllArgs(Arguments, options::OPT_linker_option_Group); + context.Args.AddAllArgs(Arguments, options::OPT_F); + + if (context.Args.hasArg(options::OPT_enable_app_extension)) { + // Keep this string fixed in case the option used by the + // compiler itself changes. + Arguments.push_back("-application_extension"); + } + + if (context.Args.hasArg(options::OPT_embed_bitcode, + options::OPT_embed_bitcode_marker)) { + Arguments.push_back("-bitcode_bundle"); + } + + if (!context.OI.SDKPath.empty()) { + Arguments.push_back("-syslibroot"); + Arguments.push_back(context.Args.MakeArgString(context.OI.SDKPath)); + } + + Arguments.push_back("-lobjc"); + Arguments.push_back("-lSystem"); + + Arguments.push_back("-arch"); + Arguments.push_back(context.Args.MakeArgString(getTriple().getArchName())); + + // Add the runtime library link path, which is platform-specific and found + // relative to the compiler. + // FIXME: Duplicated from CompilerInvocation, but in theory the runtime + // library link path and the standard library module import path don't + // need to be the same. + llvm::SmallString<128> RuntimeLibPath; + + if (const Arg *A = context.Args.getLastArg(options::OPT_resource_dir)) { + RuntimeLibPath = A->getValue(); + } else { + RuntimeLibPath = D.getSwiftProgramPath(); + llvm::sys::path::remove_filename(RuntimeLibPath); // remove /swift + llvm::sys::path::remove_filename(RuntimeLibPath); // remove /bin + llvm::sys::path::append(RuntimeLibPath, "lib", "swift"); + } + llvm::sys::path::append(RuntimeLibPath, + getPlatformNameForTriple(getTriple())); + Arguments.push_back("-L"); + Arguments.push_back(context.Args.MakeArgString(RuntimeLibPath)); + + if (context.Args.hasArg(options::OPT_profile_generate)) { + SmallString<128> LibProfile(RuntimeLibPath); + llvm::sys::path::remove_filename(LibProfile); // remove platform name + llvm::sys::path::append(LibProfile, "clang", CLANG_VERSION_STRING); + + StringRef RT; + if (Triple.isiOS()) { +#if defined(SWIFT_ENABLE_TARGET_TVOS) + if (Triple.isTvOS()) + RT = "tvos"; + else +#endif // SWIFT_ENABLE_TARGET_TVOS + RT = "ios"; + } + else if (Triple.isWatchOS()) + RT = "watchos"; + else + RT = "osx"; + llvm::sys::path::append(LibProfile, "lib", "darwin", + "libclang_rt.profile_" + RT + ".a"); + Arguments.push_back(context.Args.MakeArgString(LibProfile)); + } + + // FIXME: We probably shouldn't be adding an rpath here unless we know ahead + // of time the standard library won't be copied. + Arguments.push_back("-rpath"); + Arguments.push_back(context.Args.MakeArgString(RuntimeLibPath)); + + // FIXME: Properly handle deployment targets. + assert(Triple.isiOS() || Triple.isWatchOS() || Triple.isMacOSX()); + if (Triple.isiOS()) { + bool isiOSSimulator = tripleIsiOSSimulator(Triple); +#if defined(SWIFT_ENABLE_TARGET_TVOS) + if (Triple.isTvOS()) { + if (isiOSSimulator) + Arguments.push_back("-tvos_simulator_version_min"); + else + Arguments.push_back("-tvos_version_min"); + } else +#endif // SWIFT_ENABLE_TARGET_TVOS + { + if (isiOSSimulator) + Arguments.push_back("-ios_simulator_version_min"); + else + Arguments.push_back("-iphoneos_version_min"); + } + unsigned major, minor, micro; + Triple.getiOSVersion(major, minor, micro); + addVersionString(context.Args, Arguments, major, minor, micro); + } else if (Triple.isWatchOS()) { + if (tripleIsWatchSimulator(Triple)) + Arguments.push_back("-watchos_simulator_version_min"); + else + Arguments.push_back("-watchos_version_min"); + unsigned major, minor, micro; + Triple.getOSVersion(major, minor, micro); + addVersionString(context.Args, Arguments, major, minor, micro); + } else { + Arguments.push_back("-macosx_version_min"); + unsigned major, minor, micro; + Triple.getMacOSXVersion(major, minor, micro); + addVersionString(context.Args, Arguments, major, minor, micro); + } + + Arguments.push_back("-no_objc_category_merging"); + + // This should be the last option, for convenience in checking output. + Arguments.push_back("-o"); + Arguments.push_back(context.Output.getPrimaryOutputFilename().c_str()); + + return std::make_pair("ld", Arguments); } #if defined(SWIFT_ENABLE_TARGET_LINUX) -/// Linux +std::pair +toolchains::Linux::constructInvocation(const AutolinkExtractJobAction &job, + const JobContext &context) const { + assert(context.Output.getPrimaryOutputType() == types::TY_AutolinkFile); -std::unique_ptr Linux::buildLinker() const { - return std::unique_ptr(new tools::linux::Linker(*this)); + ArgStringList Arguments; + addPrimaryInputsOfType(Arguments, context.Inputs, types::TY_Object); + addInputsOfType(Arguments, context.InputActions, types::TY_Object); + + Arguments.push_back("-o"); + Arguments.push_back( + context.Args.MakeArgString(context.Output.getPrimaryOutputFilename())); + + return std::make_pair("swift-autolink-extract", Arguments); +} + +std::pair +toolchains::Linux::constructInvocation(const LinkJobAction &job, + const JobContext &context) const { + const Driver &D = getDriver(); + + assert(context.Output.getPrimaryOutputType() == types::TY_Image && + "Invalid linker output type."); + + ArgStringList Arguments; + + switch (job.getKind()) { + case LinkKind::None: + llvm_unreachable("invalid link kind"); + case LinkKind::Executable: + // Default case, nothing extra needed + break; + case LinkKind::DynamicLibrary: + Arguments.push_back("-shared"); + break; + } + + addPrimaryInputsOfType(Arguments, context.Inputs, types::TY_Object); + addInputsOfType(Arguments, context.InputActions, types::TY_Object); + + context.Args.AddAllArgs(Arguments, options::OPT_Xlinker); + context.Args.AddAllArgs(Arguments, options::OPT_linker_option_Group); + context.Args.AddAllArgs(Arguments, options::OPT_F); + + if (!context.OI.SDKPath.empty()) { + Arguments.push_back("--sysroot"); + Arguments.push_back(context.Args.MakeArgString(context.OI.SDKPath)); + } + + // Add the runtime library link path, which is platform-specific and found + // relative to the compiler. + // FIXME: Duplicated from CompilerInvocation, but in theory the runtime + // library link path and the standard library module import path don't + // need to be the same. + llvm::SmallString<128> RuntimeLibPath; + + if (const Arg *A = context.Args.getLastArg(options::OPT_resource_dir)) { + RuntimeLibPath = A->getValue(); + } else { + RuntimeLibPath = D.getSwiftProgramPath(); + llvm::sys::path::remove_filename(RuntimeLibPath); // remove /swift + llvm::sys::path::remove_filename(RuntimeLibPath); // remove /bin + llvm::sys::path::append(RuntimeLibPath, "lib", "swift"); + } + llvm::sys::path::append(RuntimeLibPath, + getPlatformNameForTriple(getTriple())); + Arguments.push_back("-L"); + Arguments.push_back(context.Args.MakeArgString(RuntimeLibPath)); + + if (context.Args.hasArg(options::OPT_profile_generate)) { + SmallString<128> LibProfile(RuntimeLibPath); + llvm::sys::path::remove_filename(LibProfile); // remove platform name + llvm::sys::path::append(LibProfile, "clang", CLANG_VERSION_STRING); + + llvm::sys::path::append(LibProfile, "lib", getTriple().getOSName(), + Twine("libclang_rt.profile-") + + getTriple().getArchName() + + ".a"); + Arguments.push_back(context.Args.MakeArgString(LibProfile)); + } + + // FIXME: We probably shouldn't be adding an rpath here unless we know ahead + // of time the standard library won't be copied. + Arguments.push_back("-Xlinker"); + Arguments.push_back("-rpath"); + Arguments.push_back("-Xlinker"); + Arguments.push_back(context.Args.MakeArgString(RuntimeLibPath)); + + // Always add the stdlib + Arguments.push_back("-lswiftCore"); + + // Add any autolinking scripts to the arguments + for (const Job *Cmd : context.Inputs) { + auto &OutputInfo = Cmd->getOutput(); + if (OutputInfo.getPrimaryOutputType() == types::TY_AutolinkFile) + Arguments.push_back(context.Args.MakeArgString( + Twine("@") + OutputInfo.getPrimaryOutputFilename())); + } + + // Add the linker script that coalesces protocol conformance sections. + Arguments.push_back("-Xlinker"); + Arguments.push_back("-T"); + Arguments.push_back( + context.Args.MakeArgString(Twine(RuntimeLibPath) + "/x86_64/swift.ld")); + + // This should be the last option, for convenience in checking output. + Arguments.push_back("-o"); + Arguments.push_back(context.Output.getPrimaryOutputFilename().c_str()); + + return std::make_pair("clang++", Arguments); } #endif // SWIFT_ENABLE_TARGET_LINUX + diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index fe36408a37b..629ef3369c6 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -1,4 +1,4 @@ -//===--- ToolChains.h - ToolChain Implementations ---------------*- C++ -*-===// +//===--- ToolChains.h - Platform-specific ToolChain logic -------*- C++ -*-===// // // This source file is part of the Swift.org open source project // @@ -23,17 +23,29 @@ namespace toolchains { class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain { protected: - virtual std::unique_ptr buildLinker() const; + std::pair + constructInvocation(const LinkJobAction &job, + const JobContext &context) const override; + + std::string findProgramRelativeToSwiftImpl(StringRef name) const override; + public: Darwin(const Driver &D, const llvm::Triple &Triple) : ToolChain(D, Triple) {} ~Darwin() = default; + }; #if defined(SWIFT_ENABLE_TARGET_LINUX) class LLVM_LIBRARY_VISIBILITY Linux : public ToolChain { protected: - virtual std::unique_ptr buildLinker() const; + std::pair + constructInvocation(const AutolinkExtractJobAction &job, + const JobContext &context) const override; + std::pair + constructInvocation(const LinkJobAction &job, + const JobContext &context) const override; + public: Linux(const Driver &D, const llvm::Triple &Triple) : ToolChain(D, Triple) {} ~Linux() = default; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp deleted file mode 100644 index 2d770380340..00000000000 --- a/lib/Driver/Tools.cpp +++ /dev/null @@ -1,925 +0,0 @@ -//===--- Tools.cpp - Tools Implementations --------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See http://swift.org/LICENSE.txt for license information -// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#include "Tools.h" -#include "ToolChains.h" - -#include "swift/Basic/Dwarf.h" -#include "swift/Basic/Fallthrough.h" -#include "swift/Basic/LLVM.h" -#include "swift/Basic/Platform.h" -#include "swift/Basic/Range.h" -#include "swift/Driver/Driver.h" -#include "swift/Driver/Job.h" -#include "swift/Frontend/Frontend.h" -#include "swift/Option/Options.h" -#include "swift/Config.h" -#include "clang/Basic/Version.h" -#include "clang/Driver/Util.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/Option/Arg.h" -#include "llvm/Option/ArgList.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/Process.h" - -using namespace swift; -using namespace swift::driver; -using namespace swift::driver::tools; -using namespace llvm::opt; - -/// Swift Tool - -static void addInputsOfType(ArgStringList &Arguments, const ActionList &Inputs, - types::ID InputType) { - for (auto &Input : Inputs) { - if (Input->getType() != InputType) - continue; - Arguments.push_back(cast(Input)->getInputArg().getValue()); - } -} - -static void addInputsOfType(ArgStringList &Arguments, - ArrayRef Jobs, - types::ID InputType) { - for (const Job *Cmd : Jobs) { - auto &output = Cmd->getOutput().getAnyOutputForType(InputType); - if (!output.empty()) - Arguments.push_back(output.c_str()); - } -} - -static void addPrimaryInputsOfType(ArgStringList &Arguments, - ArrayRef Jobs, - types::ID InputType) { - for (const Job *Cmd : Jobs) { - auto &outputInfo = Cmd->getOutput(); - if (outputInfo.getPrimaryOutputType() == InputType) { - for (const std::string &Output : outputInfo.getPrimaryOutputFilenames()) { - Arguments.push_back(Output.c_str()); - } - } - } -} - -/// Handle arguments common to all invocations of the frontend (compilation, -/// module-merging, LLDB's REPL, etc). -static void addCommonFrontendArgs(const ToolChain &TC, - const OutputInfo &OI, - const CommandOutput *output, - const ArgList &inputArgs, - ArgStringList &arguments) { - arguments.push_back("-target"); - arguments.push_back(inputArgs.MakeArgString(TC.getTriple().str())); - const llvm::Triple &Triple = TC.getTriple(); - - // Enable address top-byte ignored in the ARM64 backend. - if (Triple.getArch() == llvm::Triple::aarch64) { - arguments.push_back("-Xllvm"); - arguments.push_back("-aarch64-use-tbi"); - } - - // Enable or disable ObjC interop appropriately for the platform - if (Triple.isOSDarwin()) { - arguments.push_back("-enable-objc-interop"); - } else { - arguments.push_back("-disable-objc-interop"); - } - - // Handle the CPU and its preferences. - if (auto arg = inputArgs.getLastArg(options::OPT_target_cpu)) - arg->render(inputArgs, arguments); - - if (!OI.SDKPath.empty()) { - arguments.push_back("-sdk"); - arguments.push_back(inputArgs.MakeArgString(OI.SDKPath)); - } - - inputArgs.AddAllArgs(arguments, options::OPT_I); - inputArgs.AddAllArgs(arguments, options::OPT_F); - - inputArgs.AddLastArg(arguments, options::OPT_AssertConfig); - inputArgs.AddLastArg(arguments, options::OPT_autolink_force_load); - inputArgs.AddLastArg(arguments, options::OPT_color_diagnostics); - inputArgs.AddLastArg(arguments, options::OPT_enable_app_extension); - inputArgs.AddLastArg(arguments, options::OPT_enable_testing); - inputArgs.AddLastArg(arguments, options::OPT_g_Group); - inputArgs.AddLastArg(arguments, options::OPT_import_objc_header); - inputArgs.AddLastArg(arguments, options::OPT_import_underlying_module); - inputArgs.AddLastArg(arguments, options::OPT_module_cache_path); - inputArgs.AddLastArg(arguments, options::OPT_module_link_name); - inputArgs.AddLastArg(arguments, options::OPT_nostdimport); - inputArgs.AddLastArg(arguments, options::OPT_parse_stdlib); - inputArgs.AddLastArg(arguments, options::OPT_resource_dir); - inputArgs.AddLastArg(arguments, options::OPT_solver_memory_threshold); - inputArgs.AddLastArg(arguments, options::OPT_profile_generate); - inputArgs.AddLastArg(arguments, options::OPT_profile_coverage_mapping); - - // Pass on any build config options - inputArgs.AddAllArgs(arguments, options::OPT_D); - - // Pass through the values passed to -Xfrontend. - inputArgs.AddAllArgValues(arguments, options::OPT_Xfrontend); - - // Pass through any subsystem flags. - inputArgs.AddAllArgs(arguments, options::OPT_Xllvm); - inputArgs.AddAllArgs(arguments, options::OPT_Xcc); - - const std::string &moduleDocOutputPath = - output->getAdditionalOutputForType(types::TY_SwiftModuleDocFile); - if (!moduleDocOutputPath.empty()) { - arguments.push_back("-emit-module-doc-path"); - arguments.push_back(moduleDocOutputPath.c_str()); - } - - if (llvm::sys::Process::StandardErrHasColors()) - arguments.push_back("-color-diagnostics"); -} - -/// Setup executable name and argument based on whether we should delegate -/// to 'swift -frontend' or to 'swift-update'. -/// \returns the executable name. -static const char *setupSwiftFrontendOrSwiftUpdate(const Tool &Tool, - const ArgList &Args, - const OutputInfo &OI) { - const std::string &Exec = - Tool.getToolChain().getDriver().getSwiftProgramPath(); - - if (OI.CompilerMode == OutputInfo::Mode::UpdateCode) { - SmallString<128> SwiftUpdatePath = llvm::sys::path::parent_path(Exec); - llvm::sys::path::append(SwiftUpdatePath, "swift-update"); - return Args.MakeArgString(SwiftUpdatePath.str()); - } - - return Exec.c_str(); -} - -const char *Swift::getPath(const llvm::opt::ArgList &Args, - const OutputInfo &OI) const { - return setupSwiftFrontendOrSwiftUpdate(*this, Args, OI); -} - -llvm::opt::ArgStringList -Swift::constructArgumentList(const JobAction &JA, - ArrayRef Inputs, - const CommandOutput *Output, - const ActionList &InputActions, - const llvm::opt::ArgList &Args, - const OutputInfo &OI) const { - ArgStringList Arguments; - - if (OI.CompilerMode != OutputInfo::Mode::UpdateCode) - Arguments.push_back("-frontend"); - - // Determine the frontend mode option. - const char *FrontendModeOption = nullptr; - switch (OI.CompilerMode) { - case OutputInfo::Mode::StandardCompile: - case OutputInfo::Mode::SingleCompile: { - switch (Output->getPrimaryOutputType()) { - case types::TY_Object: - FrontendModeOption = "-c"; - break; - case types::TY_RawSIL: - FrontendModeOption = "-emit-silgen"; - break; - case types::TY_SIL: - FrontendModeOption = "-emit-sil"; - break; - case types::TY_RawSIB: - FrontendModeOption = "-emit-sibgen"; - break; - case types::TY_SIB: - FrontendModeOption = "-emit-sib"; - break; - case types::TY_LLVM_IR: - FrontendModeOption = "-emit-ir"; - break; - case types::TY_LLVM_BC: - FrontendModeOption = "-emit-bc"; - break; - case types::TY_Assembly: - FrontendModeOption = "-S"; - break; - case types::TY_SwiftModuleFile: - // Since this is our primary output, we need to specify the option here. - FrontendModeOption = "-emit-module"; - break; - case types::TY_Nothing: - // We were told to output nothing, so get the last mode option and use that. - if (const Arg *A = Args.getLastArg(options::OPT_modes_Group)) - FrontendModeOption = A->getSpelling().data(); - else - llvm_unreachable("We were told to perform a standard compile, " - "but no mode option was passed to the driver."); - break; - case types::TY_Swift: - case types::TY_dSYM: - case types::TY_AutolinkFile: - case types::TY_Dependencies: - case types::TY_SwiftModuleDocFile: - case types::TY_ClangModuleFile: - case types::TY_SerializedDiagnostics: - case types::TY_ObjCHeader: - case types::TY_Image: - case types::TY_SwiftDeps: - case types::TY_Remapping: - llvm_unreachable("Output type can never be primary output."); - case types::TY_INVALID: - llvm_unreachable("Invalid type ID"); - } - break; - } - case OutputInfo::Mode::Immediate: - FrontendModeOption = "-interpret"; - break; - case OutputInfo::Mode::REPL: - FrontendModeOption = "-repl"; - break; - case OutputInfo::Mode::UpdateCode: - // Make sure that adding '-update-code' will permit accepting all arguments - // '-c' accepts. - FrontendModeOption = "-c"; - break; - } - - assert(FrontendModeOption != nullptr && "No frontend mode option specified!"); - - Arguments.push_back(FrontendModeOption); - - assert((Inputs.empty() || isa(JA)) && - "The Swift frontend does not expect to be fed any input Jobs!"); - - // Add input arguments. - switch (OI.CompilerMode) { - case OutputInfo::Mode::StandardCompile: - case OutputInfo::Mode::UpdateCode: { - if (isa(JA)) { - assert(Inputs.size() == 1 && "The Swift backend expects one input!"); - Arguments.push_back("-primary-file"); - const Job *Cmd = Inputs.front(); - Arguments.push_back( - Cmd->getOutput().getPrimaryOutputFilename().c_str()); - break; - } - - assert(InputActions.size() == 1 && - "The Swift frontend expects exactly one input (the primary file)!"); - - const InputAction *IA = dyn_cast(InputActions[0]); - assert(IA && "Only InputActions can be passed as inputs!"); - const Arg &PrimaryInputArg = IA->getInputArg(); - bool FoundPrimaryInput = false; - - for (const Arg *A : make_range(Args.filtered_begin(options::OPT_INPUT), - Args.filtered_end())) { - // See if this input should be passed with -primary-file. - // FIXME: This will pick up non-source inputs too, like .o files. - if (!FoundPrimaryInput && PrimaryInputArg.getIndex() == A->getIndex()) { - Arguments.push_back("-primary-file"); - FoundPrimaryInput = true; - } - Arguments.push_back(A->getValue()); - } - break; - } - case OutputInfo::Mode::SingleCompile: - if (isa(JA)) { - assert(Inputs.size() == 1 && "The Swift backend expects one input!"); - Arguments.push_back("-primary-file"); - const Job *Cmd = Inputs.front(); - - // In multi-threaded compilation, the backend job must select the correct - // output file of the compilation job. - auto OutNames = Cmd->getOutput().getPrimaryOutputFilenames(); - Arguments.push_back(OutNames[JA.getInputIndex()].c_str()); - break; - } - SWIFT_FALLTHROUGH; - case OutputInfo::Mode::Immediate: { - for (const Action *A : InputActions) { - const InputAction *IA = dyn_cast(A); - assert(IA && "Only InputActions can be passed as inputs!"); - - IA->getInputArg().render(Args, Arguments); - } - break; - } - case OutputInfo::Mode::REPL: { - assert(InputActions.empty() && "REPL mode accepts no inputs!"); - break; - } - } - - // Only white-listed flags below are allowed to be embedded. - if (Args.hasArg(options::OPT_embed_bitcode) && - isa(JA)) { - const llvm::Triple &Triple = getToolChain().getTriple(); - - Arguments.push_back("-target"); - Arguments.push_back(Args.MakeArgString(Triple.str())); - - // Enable address top-byte ignored in the ARM64 backend. - if (Triple.getArch() == llvm::Triple::aarch64) { - Arguments.push_back("-Xllvm"); - Arguments.push_back("-aarch64-use-tbi"); - } - - // Handle the CPU and its preferences. - if (auto arg = Args.getLastArg(options::OPT_target_cpu)) - arg->render(Args, Arguments); - - Args.AddLastArg(Arguments, options::OPT_parse_stdlib); - - // Pass the optimization level down to the frontend. - Args.AddLastArg(Arguments, options::OPT_O_Group); - - Arguments.push_back("-module-name"); - Arguments.push_back(Args.MakeArgString(OI.ModuleName)); - - // Add the output file argument if necessary. - if (Output->getPrimaryOutputType() != types::TY_Nothing) { - for (const std::string &FileName : Output->getPrimaryOutputFilenames()) { - Arguments.push_back("-o"); - Arguments.push_back(FileName.c_str()); - } - } - - // Add flags implied by -embed-bitcode. - Arguments.push_back("-embed-bitcode"); - // Disable all llvm IR level optimizations. - Arguments.push_back("-disable-llvm-optzns"); - - return Arguments; - } - - if (Args.hasArg(options::OPT_parse_stdlib)) - Arguments.push_back("-disable-objc-attr-requires-foundation-module"); - - addCommonFrontendArgs(getToolChain(), OI, Output, Args, Arguments); - - // Pass the optimization level down to the frontend. - Args.AddLastArg(Arguments, options::OPT_O_Group); - - if (Args.hasArg(options::OPT_parse_as_library) || - Args.hasArg(options::OPT_emit_library)) - Arguments.push_back("-parse-as-library"); - - Args.AddLastArg(Arguments, options::OPT_parse_sil); - - Arguments.push_back("-module-name"); - Arguments.push_back(Args.MakeArgString(OI.ModuleName)); - - // Mode-specific arguments. - switch (OI.CompilerMode) { - case OutputInfo::Mode::StandardCompile: - case OutputInfo::Mode::SingleCompile: - case OutputInfo::Mode::UpdateCode: - break; - case OutputInfo::Mode::Immediate: - case OutputInfo::Mode::REPL: - Args.AddAllArgs(Arguments, options::OPT_l, options::OPT_framework, - options::OPT_L); - break; - } - - const std::string &ModuleOutputPath = - Output->getAdditionalOutputForType(types::ID::TY_SwiftModuleFile); - if (!ModuleOutputPath.empty()) { - Arguments.push_back("-emit-module-path"); - Arguments.push_back(ModuleOutputPath.c_str()); - } - - const std::string &ObjCHeaderOutputPath = - Output->getAdditionalOutputForType(types::ID::TY_ObjCHeader); - if (!ObjCHeaderOutputPath.empty()) { - assert(OI.CompilerMode == OutputInfo::Mode::SingleCompile && - "The Swift tool should only emit an Obj-C header in single compile" - "mode!"); - - Arguments.push_back("-emit-objc-header-path"); - Arguments.push_back(ObjCHeaderOutputPath.c_str()); - } - - const std::string &SerializedDiagnosticsPath = - Output->getAdditionalOutputForType(types::TY_SerializedDiagnostics); - if (!SerializedDiagnosticsPath.empty()) { - Arguments.push_back("-serialize-diagnostics-path"); - Arguments.push_back(SerializedDiagnosticsPath.c_str()); - } - - const std::string &DependenciesPath = - Output->getAdditionalOutputForType(types::TY_Dependencies); - if (!DependenciesPath.empty()) { - Arguments.push_back("-emit-dependencies-path"); - Arguments.push_back(DependenciesPath.c_str()); - } - - const std::string &ReferenceDependenciesPath = - Output->getAdditionalOutputForType(types::TY_SwiftDeps); - if (!ReferenceDependenciesPath.empty()) { - Arguments.push_back("-emit-reference-dependencies-path"); - Arguments.push_back(ReferenceDependenciesPath.c_str()); - } - - const std::string &FixitsPath = - Output->getAdditionalOutputForType(types::TY_Remapping); - if (!FixitsPath.empty()) { - Arguments.push_back("-emit-fixits-path"); - Arguments.push_back(FixitsPath.c_str()); - } - - if (OI.numThreads > 0) { - Arguments.push_back("-num-threads"); - Arguments.push_back(Args.MakeArgString(Twine(OI.numThreads))); - } - - // Add the output file argument if necessary. - if (Output->getPrimaryOutputType() != types::TY_Nothing) { - for (const std::string &FileName : Output->getPrimaryOutputFilenames()) { - Arguments.push_back("-o"); - Arguments.push_back(FileName.c_str()); - } - } - - if (OI.CompilerMode == OutputInfo::Mode::Immediate) - Args.AddLastArg(Arguments, options::OPT__DASH_DASH); - - if (Args.hasArg(options::OPT_embed_bitcode_marker)) - Arguments.push_back("-embed-bitcode-marker"); - - return Arguments; -} - -const char *MergeModule::getPath(const llvm::opt::ArgList &Args, - const OutputInfo &OI) const { - return setupSwiftFrontendOrSwiftUpdate(*this, Args, OI); -} - -llvm::opt::ArgStringList -MergeModule::constructArgumentList(const JobAction &JA, - ArrayRef Inputs, - const CommandOutput *Output, - const ActionList &InputActions, - const llvm::opt::ArgList &Args, - const OutputInfo &OI) const { - ArgStringList Arguments; - - if (OI.CompilerMode != OutputInfo::Mode::UpdateCode) - Arguments.push_back("-frontend"); - - // We just want to emit a module, so pass -emit-module without any other - // mode options. - Arguments.push_back("-emit-module"); - - size_t origLen = Arguments.size(); - (void)origLen; - addInputsOfType(Arguments, Inputs, types::TY_SwiftModuleFile); - addInputsOfType(Arguments, InputActions, types::TY_SwiftModuleFile); - assert(Arguments.size() - origLen >= Inputs.size() + InputActions.size()); - assert((Arguments.size() - origLen == Inputs.size() || - !InputActions.empty()) && - "every input to MergeModule must generate a swiftmodule"); - - // Tell all files to parse as library, which is necessary to load them as - // serialized ASTs. - Arguments.push_back("-parse-as-library"); - - addCommonFrontendArgs(getToolChain(), OI, Output, Args, Arguments); - - Arguments.push_back("-module-name"); - Arguments.push_back(Args.MakeArgString(OI.ModuleName)); - - assert(Output->getPrimaryOutputType() == types::TY_SwiftModuleFile && - "The MergeModule tool only produces swiftmodule files!"); - - const std::string &ObjCHeaderOutputPath = - Output->getAdditionalOutputForType(types::TY_ObjCHeader); - if (!ObjCHeaderOutputPath.empty()) { - Arguments.push_back("-emit-objc-header-path"); - Arguments.push_back(ObjCHeaderOutputPath.c_str()); - } - - Arguments.push_back("-o"); - Arguments.push_back(Args.MakeArgString(Output->getPrimaryOutputFilename())); - - return Arguments; -} - -const char *ToolchainTool::getPath(const ArgList &Args, - const OutputInfo &OI) const { - if (!Bits.DidCheckRelativeToDriver) { - (void)isPresentRelativeToDriver(); - } - return NameOrPath.c_str(); -} - -bool ToolchainTool::isPresentRelativeToDriver() const { - if (!Bits.DidCheckRelativeToDriver) { - const Driver &D = getToolChain().getDriver(); - std::string RelativePath = - findRelativeExecutable(D.getSwiftProgramPath(), NameOrPath); - if (RelativePath.empty()) { - NameOrPath = getToolChain().getProgramPath(NameOrPath); - } else { - NameOrPath = std::move(RelativePath); - Bits.IsPresentRelativeToDriver = true; - } - Bits.DidCheckRelativeToDriver = true; - } - return Bits.IsPresentRelativeToDriver; -} - -llvm::opt::ArgStringList -LLDB::constructArgumentList(const JobAction &JA, - ArrayRef Inputs, - const CommandOutput *Output, - const ActionList &InputActions, - const llvm::opt::ArgList &Args, - const OutputInfo &OI) const { - assert(Inputs.empty()); - assert(InputActions.empty()); - - // Squash important frontend options into a single argument for LLDB. - ArgStringList FrontendArgs; - addCommonFrontendArgs(getToolChain(), OI, Output, Args, FrontendArgs); - Args.AddAllArgs(FrontendArgs, options::OPT_l, options::OPT_framework, - options::OPT_L); - - std::string SingleArg = "--repl="; - { - llvm::raw_string_ostream os(SingleArg); - Job::printArguments(os, FrontendArgs); - } - - ArgStringList Arguments; - Arguments.push_back(Args.MakeArgString(std::move(SingleArg))); - - return Arguments; -} - -llvm::opt::ArgStringList -Dsymutil::constructArgumentList(const JobAction &JA, - ArrayRef Inputs, - const CommandOutput *Output, - const ActionList &InputActions, - const llvm::opt::ArgList &Args, - const OutputInfo &OI) const { - assert(Inputs.size() == 1); - assert(InputActions.empty()); - assert(Output->getPrimaryOutputType() == types::TY_dSYM); - - ArgStringList Arguments; - - StringRef inputPath = Inputs.front()->getOutput().getPrimaryOutputFilename(); - Arguments.push_back(Args.MakeArgString(inputPath)); - - Arguments.push_back("-o"); - Arguments.push_back(Args.MakeArgString(Output->getPrimaryOutputFilename())); - - return Arguments; -} - -llvm::opt::ArgStringList -AutolinkExtract::constructArgumentList(const JobAction &JA, - ArrayRef Inputs, - const CommandOutput *Output, - const ActionList &InputActions, - const llvm::opt::ArgList &Args, - const OutputInfo &OI) const { - assert(Output->getPrimaryOutputType() == types::TY_AutolinkFile); - - ArgStringList Arguments; - addPrimaryInputsOfType(Arguments, Inputs, types::TY_Object); - addInputsOfType(Arguments, InputActions, types::TY_Object); - - Arguments.push_back("-o"); - Arguments.push_back(Args.MakeArgString(Output->getPrimaryOutputFilename())); - - return Arguments; -} - -/// Darwin Tools - -static void addVersionString(const ArgList &inputArgs, ArgStringList &arguments, - unsigned major, unsigned minor, unsigned micro) { - llvm::SmallString<8> buf; - llvm::raw_svector_ostream os{buf}; - os << major << '.' << minor << '.' << micro; - arguments.push_back(inputArgs.MakeArgString(os.str())); -} - -llvm::opt::ArgStringList -darwin::Linker::constructArgumentList(const JobAction &JA, - ArrayRef Inputs, - const CommandOutput *Output, - const ActionList &InputActions, - const llvm::opt::ArgList &Args, - const OutputInfo &OI) const { - assert(Output->getPrimaryOutputType() == types::TY_Image && - "Invalid linker output type."); - - auto &TC = static_cast(getToolChain()); - const Driver &D = TC.getDriver(); - const llvm::Triple &Triple = TC.getTriple(); - - ArgStringList Arguments; - addPrimaryInputsOfType(Arguments, Inputs, types::TY_Object); - addInputsOfType(Arguments, InputActions, types::TY_Object); - - if (OI.DebugInfoKind == IRGenDebugInfoKind::Normal) { - - size_t argCount = Arguments.size(); - if (OI.CompilerMode == OutputInfo::Mode::SingleCompile) - addInputsOfType(Arguments, Inputs, types::TY_SwiftModuleFile); - else - addPrimaryInputsOfType(Arguments, Inputs, types::TY_SwiftModuleFile); - - if (Arguments.size() > argCount) { - assert(argCount + 1 == Arguments.size() && - "multiple swiftmodules found for -g"); - Arguments.insert(Arguments.end() - 1, "-add_ast_path"); - } - } - - switch (cast(JA).getKind()) { - case LinkKind::None: - llvm_unreachable("invalid link kind"); - case LinkKind::Executable: - // The default for ld; no extra flags necessary. - break; - case LinkKind::DynamicLibrary: - Arguments.push_back("-dylib"); - break; - } - - assert(Triple.isOSDarwin()); - bool wantsObjCRuntime = false; - if (Triple.isiOS()) - wantsObjCRuntime = Triple.isOSVersionLT(8); - else if (Triple.isWatchOS()) - wantsObjCRuntime = Triple.isOSVersionLT(2); - else if (Triple.isMacOSX()) - wantsObjCRuntime = Triple.isMacOSXVersionLT(10, 10); - - if (Args.hasFlag(options::OPT_link_objc_runtime, - options::OPT_no_link_objc_runtime, - /*default=*/wantsObjCRuntime)) { - llvm::SmallString<128> ARCLiteLib(D.getSwiftProgramPath()); - llvm::sys::path::remove_filename(ARCLiteLib); // 'swift' - llvm::sys::path::remove_filename(ARCLiteLib); // 'bin' - llvm::sys::path::append(ARCLiteLib, "lib", "arc", "libarclite_"); - ARCLiteLib += getPlatformNameForTriple(Triple); - ARCLiteLib += ".a"; - - Arguments.push_back("-force_load"); - Arguments.push_back(Args.MakeArgString(ARCLiteLib)); - - // Arclite depends on CoreFoundation. - Arguments.push_back("-framework"); - Arguments.push_back("CoreFoundation"); - } - - Args.AddAllArgValues(Arguments, options::OPT_Xlinker); - Args.AddAllArgs(Arguments, options::OPT_linker_option_Group); - Args.AddAllArgs(Arguments, options::OPT_F); - - if (Args.hasArg(options::OPT_enable_app_extension)) { - // Keep this string fixed in case the option used by the - // compiler itself changes. - Arguments.push_back("-application_extension"); - } - - if (Args.hasArg(options::OPT_embed_bitcode, - options::OPT_embed_bitcode_marker)) { - Arguments.push_back("-bitcode_bundle"); - } - - if (!OI.SDKPath.empty()) { - Arguments.push_back("-syslibroot"); - Arguments.push_back(Args.MakeArgString(OI.SDKPath)); - } - - Arguments.push_back("-lobjc"); - Arguments.push_back("-lSystem"); - - Arguments.push_back("-arch"); - Arguments.push_back(Args.MakeArgString(TC.getTriple().getArchName())); - - // Add the runtime library link path, which is platform-specific and found - // relative to the compiler. - // FIXME: Duplicated from CompilerInvocation, but in theory the runtime - // library link path and the standard library module import path don't - // need to be the same. - llvm::SmallString<128> RuntimeLibPath; - - if (const Arg *A = Args.getLastArg(options::OPT_resource_dir)) { - RuntimeLibPath = A->getValue(); - } else { - RuntimeLibPath = D.getSwiftProgramPath(); - llvm::sys::path::remove_filename(RuntimeLibPath); // remove /swift - llvm::sys::path::remove_filename(RuntimeLibPath); // remove /bin - llvm::sys::path::append(RuntimeLibPath, "lib", "swift"); - } - llvm::sys::path::append(RuntimeLibPath, - getPlatformNameForTriple(TC.getTriple())); - Arguments.push_back("-L"); - Arguments.push_back(Args.MakeArgString(RuntimeLibPath)); - - if (Args.hasArg(options::OPT_profile_generate)) { - SmallString<128> LibProfile(RuntimeLibPath); - llvm::sys::path::remove_filename(LibProfile); // remove platform name - llvm::sys::path::append(LibProfile, "clang", CLANG_VERSION_STRING); - - StringRef RT; - if (Triple.isiOS()) { -#if defined(SWIFT_ENABLE_TARGET_TVOS) - if (Triple.isTvOS()) - RT = "tvos"; - else -#endif // SWIFT_ENABLE_TARGET_TVOS - RT = "ios"; - } - else if (Triple.isWatchOS()) - RT = "watchos"; - else - RT = "osx"; - llvm::sys::path::append(LibProfile, "lib", "darwin", - "libclang_rt.profile_" + RT + ".a"); - Arguments.push_back(Args.MakeArgString(LibProfile)); - } - - // FIXME: We probably shouldn't be adding an rpath here unless we know ahead - // of time the standard library won't be copied. - Arguments.push_back("-rpath"); - Arguments.push_back(Args.MakeArgString(RuntimeLibPath)); - - // FIXME: Properly handle deployment targets. - assert(Triple.isiOS() || Triple.isWatchOS() || Triple.isMacOSX()); - if (Triple.isiOS()) { - bool isiOSSimulator = tripleIsiOSSimulator(Triple); -#if defined(SWIFT_ENABLE_TARGET_TVOS) - if (Triple.isTvOS()) { - if (isiOSSimulator) - Arguments.push_back("-tvos_simulator_version_min"); - else - Arguments.push_back("-tvos_version_min"); - } else -#endif // SWIFT_ENABLE_TARGET_TVOS - { - if (isiOSSimulator) - Arguments.push_back("-ios_simulator_version_min"); - else - Arguments.push_back("-iphoneos_version_min"); - } - unsigned major, minor, micro; - Triple.getiOSVersion(major, minor, micro); - addVersionString(Args, Arguments, major, minor, micro); - } else if (Triple.isWatchOS()) { - if (tripleIsWatchSimulator(Triple)) - Arguments.push_back("-watchos_simulator_version_min"); - else - Arguments.push_back("-watchos_version_min"); - unsigned major, minor, micro; - Triple.getOSVersion(major, minor, micro); - addVersionString(Args, Arguments, major, minor, micro); - } else { - Arguments.push_back("-macosx_version_min"); - unsigned major, minor, micro; - Triple.getMacOSXVersion(major, minor, micro); - addVersionString(Args, Arguments, major, minor, micro); - } - - Arguments.push_back("-no_objc_category_merging"); - - // This should be the last option, for convenience in checking output. - Arguments.push_back("-o"); - Arguments.push_back(Output->getPrimaryOutputFilename().c_str()); - - return Arguments; -} - -#if defined(SWIFT_ENABLE_TARGET_LINUX) - -/// Linux Tools - -const char *linux::Linker::getPath(const llvm::opt::ArgList &Args, - const OutputInfo &OI) const { - // This avoids a bunch of issues trying to correctly guess parameters - // for ld for linux platforms. We know we have clang, we know it should - // be able to link, so use clang for now. - return Args.MakeArgString(getToolChain().getProgramPath("clang++")); -} - -llvm::opt::ArgStringList -linux::Linker::constructArgumentList(const JobAction &JA, - ArrayRef Inputs, - const CommandOutput *Output, - const ActionList &InputActions, - const llvm::opt::ArgList &Args, - const OutputInfo &OI) const { - const ToolChain &TC = getToolChain(); - const Driver &D = TC.getDriver(); - - assert(Output->getPrimaryOutputType() == types::TY_Image && - "Invalid linker output type."); - - ArgStringList Arguments; - - switch (cast(JA).getKind()) { - case LinkKind::None: - llvm_unreachable("invalid link kind"); - case LinkKind::Executable: - // Default case, nothing extra needed - break; - case LinkKind::DynamicLibrary: - Arguments.push_back("-shared"); - break; - } - - addPrimaryInputsOfType(Arguments, Inputs, types::TY_Object); - addInputsOfType(Arguments, InputActions, types::TY_Object); - - Args.AddAllArgs(Arguments, options::OPT_Xlinker); - Args.AddAllArgs(Arguments, options::OPT_linker_option_Group); - Args.AddAllArgs(Arguments, options::OPT_F); - - if (!OI.SDKPath.empty()) { - Arguments.push_back("--sysroot"); - Arguments.push_back(Args.MakeArgString(OI.SDKPath)); - } - - // Add the runtime library link path, which is platform-specific and found - // relative to the compiler. - // FIXME: Duplicated from CompilerInvocation, but in theory the runtime - // library link path and the standard library module import path don't - // need to be the same. - llvm::SmallString<128> RuntimeLibPath; - - if (const Arg *A = Args.getLastArg(options::OPT_resource_dir)) { - RuntimeLibPath = A->getValue(); - } else { - RuntimeLibPath = D.getSwiftProgramPath(); - llvm::sys::path::remove_filename(RuntimeLibPath); // remove /swift - llvm::sys::path::remove_filename(RuntimeLibPath); // remove /bin - llvm::sys::path::append(RuntimeLibPath, "lib", "swift"); - } - llvm::sys::path::append(RuntimeLibPath, - getPlatformNameForTriple(TC.getTriple())); - Arguments.push_back("-L"); - Arguments.push_back(Args.MakeArgString(RuntimeLibPath)); - - if (Args.hasArg(options::OPT_profile_generate)) { - SmallString<128> LibProfile(RuntimeLibPath); - llvm::sys::path::remove_filename(LibProfile); // remove platform name - llvm::sys::path::append(LibProfile, "clang", CLANG_VERSION_STRING); - - llvm::sys::path::append(LibProfile, "lib", TC.getTriple().getOSName(), - Twine("libclang_rt.profile-") + - TC.getTriple().getArchName() + - ".a"); - Arguments.push_back(Args.MakeArgString(LibProfile)); - } - - // FIXME: We probably shouldn't be adding an rpath here unless we know ahead - // of time the standard library won't be copied. - Arguments.push_back("-Xlinker"); - Arguments.push_back("-rpath"); - Arguments.push_back("-Xlinker"); - Arguments.push_back(Args.MakeArgString(RuntimeLibPath)); - - // Always add the stdlib - Arguments.push_back("-lswiftCore"); - - // Add any autolinking scripts to the arguments - for (const Job *Cmd : Inputs) { - auto &OutputInfo = Cmd->getOutput(); - if (OutputInfo.getPrimaryOutputType() == types::TY_AutolinkFile) - Arguments.push_back(Args.MakeArgString( - Twine("@") + OutputInfo.getPrimaryOutputFilename())); - } - - // Add the linker script that coalesces protocol conformance sections. - Arguments.push_back("-Xlinker"); - Arguments.push_back("-T"); - Arguments.push_back( - Args.MakeArgString(Twine(RuntimeLibPath) + "/x86_64/swift.ld")); - - // This should be the last option, for convenience in checking output. - Arguments.push_back("-o"); - Arguments.push_back(Output->getPrimaryOutputFilename().c_str()); - - return Arguments; -} - -#endif // SWIFT_ENABLE_TARGET_LINUX - diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h deleted file mode 100644 index a09e4367863..00000000000 --- a/lib/Driver/Tools.h +++ /dev/null @@ -1,185 +0,0 @@ -//===--- Tools.h - Tool Implementations -------------------------*- C++ -*-===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See http://swift.org/LICENSE.txt for license information -// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_DRIVER_TOOLS_H -#define SWIFT_DRIVER_TOOLS_H - -#include "swift/Basic/LLVM.h" -#include "swift/Driver/Tool.h" -#include "llvm/ADT/Triple.h" -#include "llvm/Option/Option.h" -#include "llvm/Support/Compiler.h" - -namespace swift { -namespace driver { - -namespace toolchains { - class Darwin; - class Linux; -} - -namespace tools { - -class LLVM_LIBRARY_VISIBILITY Swift : public Tool { -public: - explicit Swift(const ToolChain &TC) : Tool("swift", "swift frontend", TC) {} - - bool hasGoodDiagnostics() const override { return true; } - -protected: - const char *getPath(const llvm::opt::ArgList &Args, - const OutputInfo &OI) const override; - - llvm::opt::ArgStringList - constructArgumentList(const JobAction &JA, - ArrayRef Inputs, - const CommandOutput *Output, - const ActionList &InputActions, - const llvm::opt::ArgList &Args, - const OutputInfo &OI) const override; -}; - -class LLVM_LIBRARY_VISIBILITY MergeModule : public Tool { -public: - explicit MergeModule(const ToolChain &TC) - : Tool("merge-module", TC) {} - - bool hasGoodDiagnostics() const override { return true; } - -protected: - const char *getPath(const llvm::opt::ArgList &Args, - const OutputInfo &OI) const override; - - llvm::opt::ArgStringList - constructArgumentList(const JobAction &JA, - ArrayRef Inputs, - const CommandOutput *Output, - const ActionList &InputActions, - const llvm::opt::ArgList &Args, - const OutputInfo &OI) const override; -}; - -/// A ToolchainTool may be installed in a location relative to the driver -/// binary. The relative tool should be preferred over the one in the user's -/// \$PATH. -class LLVM_LIBRARY_VISIBILITY ToolchainTool : public Tool { - mutable std::string NameOrPath; - struct { - mutable unsigned DidCheckRelativeToDriver : 1; - mutable unsigned IsPresentRelativeToDriver : 1; - } Bits; - -protected: - ToolchainTool(StringRef BinaryName, StringRef ToolName, StringRef DiagName, - const ToolChain &TC) - : Tool(ToolName, DiagName, TC), NameOrPath(BinaryName), Bits() {} - ToolchainTool(StringRef Name, const ToolChain &TC) - : ToolchainTool(Name, Name, Name, TC) {} - - const char *getPath(const llvm::opt::ArgList &Args, - const OutputInfo &OI) const override; - -public: - bool isPresentRelativeToDriver() const; -}; - -class LLVM_LIBRARY_VISIBILITY LLDB : public ToolchainTool { -public: - explicit LLDB(const ToolChain &TC) - : ToolchainTool("lldb", "LLDB", "LLDB REPL", TC) {} - -protected: - llvm::opt::ArgStringList - constructArgumentList(const JobAction &JA, - ArrayRef Inputs, - const CommandOutput *Output, - const ActionList &InputActions, - const llvm::opt::ArgList &Args, - const OutputInfo &OI) const override; -}; - -class LLVM_LIBRARY_VISIBILITY Dsymutil : public ToolchainTool { -public: - explicit Dsymutil(const ToolChain &TC) : ToolchainTool("dsymutil", TC) {} - -protected: - llvm::opt::ArgStringList - constructArgumentList(const JobAction &JA, - ArrayRef Inputs, - const CommandOutput *Output, - const ActionList &InputActions, - const llvm::opt::ArgList &Args, - const OutputInfo &OI) const override; -}; - -class LLVM_LIBRARY_VISIBILITY AutolinkExtract : public ToolchainTool { -public: - explicit AutolinkExtract(const ToolChain &TC) - : ToolchainTool("swift-autolink-extract", TC) {} - -protected: - llvm::opt::ArgStringList - constructArgumentList(const JobAction &JA, - ArrayRef Inputs, - const CommandOutput *Output, - const ActionList &InputActions, - const llvm::opt::ArgList &Args, - const OutputInfo &OI) const override; -}; - -namespace darwin { - -class LLVM_LIBRARY_VISIBILITY Linker : public ToolchainTool { -public: - explicit Linker(const ToolChain &TC) - : ToolchainTool("ld", "darwin::Linker", "linker", TC) {} - -protected: - llvm::opt::ArgStringList - constructArgumentList(const JobAction &JA, - ArrayRef Inputs, - const CommandOutput *Output, - const ActionList &InputActions, - const llvm::opt::ArgList &Args, - const OutputInfo &OI) const override; -}; - -} // end namespace darwin - -namespace linux { - -class LLVM_LIBRARY_VISIBILITY Linker : public Tool { -public: - explicit Linker(const ToolChain &TC) - : Tool("linux::Linker", "linker", TC) {} - -protected: - const char *getPath(const llvm::opt::ArgList &Args, - const OutputInfo &OI) const override; - - llvm::opt::ArgStringList - constructArgumentList(const JobAction &JA, - ArrayRef Inputs, - const CommandOutput *Output, - const ActionList &InputActions, - const llvm::opt::ArgList &Args, - const OutputInfo &OI) const override; -}; - -} // end namespace linux - -} // end namespace tools - -} // end namespace driver -} // end namespace swift - -#endif diff --git a/lib/Driver/Util.cpp b/lib/Driver/Util.cpp deleted file mode 100644 index 66968848870..00000000000 --- a/lib/Driver/Util.cpp +++ /dev/null @@ -1,43 +0,0 @@ -//===--- Util.cpp - Common Driver Utilities -------------------------------===// -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See http://swift.org/LICENSE.txt for license information -// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors -// -//===----------------------------------------------------------------------===// - -#include "swift/Driver/Util.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Path.h" - -using namespace swift; - -std::string driver::findRelativeExecutable(StringRef compilerPath, - StringRef executableName) { - llvm::SmallString<128> path{compilerPath}; - llvm::sys::path::remove_filename(path); // swift - - // First try "bin/" (i.e. next to Swift). - llvm::sys::path::append(path, executableName); - if (llvm::sys::fs::exists(path.str())) - return path.str().str(); - - // Then see if we're in an Xcode toolchain. - llvm::sys::path::remove_filename(path); // - llvm::sys::path::remove_filename(path); // bin - llvm::sys::path::remove_filename(path); // usr - if (llvm::sys::path::extension(path) == ".xctoolchain") { - llvm::sys::path::remove_filename(path); // *.xctoolchain - llvm::sys::path::remove_filename(path); // Toolchains - llvm::sys::path::append(path, "usr", "bin", executableName); - if (llvm::sys::fs::exists(path.str())) - return path.str().str(); - } - - return {}; -} diff --git a/test/Driver/advanced_output_file_map.swift b/test/Driver/advanced_output_file_map.swift index f28d0d6b2fb..d561b261b63 100644 --- a/test/Driver/advanced_output_file_map.swift +++ b/test/Driver/advanced_output_file_map.swift @@ -22,6 +22,6 @@ // BINDINGS: # "x86_64-apple-macosx10.9" - "swift", inputs: ["{{.*}}/advanced_output_file_map.swift"], output: {object: "/build/obj/advanced_output_file_map.o", dependencies: "/build/d/advanced_output_file_map.d", swiftmodule: "/build/swiftmodule/advanced_output_file_map.swiftmodule", swiftdoc: "/build/swiftmodule/advanced_output_file_map_x.swiftdoc", diagnostics: "/build/dia/advanced_output_file_map.dia"} // BINDINGS: # "x86_64-apple-macosx10.9" - "swift", inputs: ["{{.*}}/Inputs/main.swift"], output: {object: "/build/obj/main.o", dependencies: "/build/d/main.d", swiftmodule: "/build/swiftmodule/main.swiftmodule", swiftdoc: "/build/swiftmodule/main_x.swiftdoc", diagnostics: "/build/dia/main.dia"} // BINDINGS: # "x86_64-apple-macosx10.9" - "swift", inputs: ["{{.*}}/Inputs/lib.swift"], output: {object: "/build/obj/lib.o", dependencies: "/build/d/lib.d", swiftmodule: "/build/swiftmodule/lib.swiftmodule", swiftdoc: "/build/swiftmodule/lib_x.swiftdoc", diagnostics: "/build/dia/lib.dia"} -// BINDINGS: # "x86_64-apple-macosx10.9" - "merge-module", inputs: ["/build/obj/advanced_output_file_map.o", "/build/obj/main.o", "/build/obj/lib.o"], output: {swiftmodule: "/build/OutputFileMap.swiftmodule", swiftdoc: "/build/OutputFileMap.swiftdoc"} -// BINDINGS: # "x86_64-apple-macosx10.9" - "darwin::Linker", inputs: ["/build/obj/advanced_output_file_map.o", "/build/obj/main.o", "/build/obj/lib.o", "/build/OutputFileMap.swiftmodule"], output: {image: "/build/advanced_output_file_map.out"} +// BINDINGS: # "x86_64-apple-macosx10.9" - "swift", inputs: ["/build/obj/advanced_output_file_map.o", "/build/obj/main.o", "/build/obj/lib.o"], output: {swiftmodule: "/build/OutputFileMap.swiftmodule", swiftdoc: "/build/OutputFileMap.swiftdoc"} +// BINDINGS: # "x86_64-apple-macosx10.9" - "ld", inputs: ["/build/obj/advanced_output_file_map.o", "/build/obj/main.o", "/build/obj/lib.o", "/build/OutputFileMap.swiftmodule"], output: {image: "/build/advanced_output_file_map.out"} // BINDINGS: # "x86_64-apple-macosx10.9" - "dsymutil", inputs: ["/build/advanced_output_file_map.out"], output: {dSYM: "/build/advanced_output_file_map.out.dSYM"} diff --git a/test/Driver/assert.swift b/test/Driver/assert.swift index 909925ca84a..95f78d52400 100644 --- a/test/Driver/assert.swift +++ b/test/Driver/assert.swift @@ -3,6 +3,6 @@ // REQUIRES: asserts -// CHECK: error: swift frontend command failed due to signal +// CHECK: error: compile command failed due to signal print("Hello, World") diff --git a/test/Driver/basic_output_file_map.swift b/test/Driver/basic_output_file_map.swift index e48aa047ddc..a7bbbde8408 100644 --- a/test/Driver/basic_output_file_map.swift +++ b/test/Driver/basic_output_file_map.swift @@ -10,4 +10,4 @@ // BINDINGS: # "x86_64-apple-macosx10.9" - "swift", inputs: ["{{.*}}/basic_output_file_map.swift"], output: {object: "/build/basic_output_file_map.o"} // BINDINGS: # "x86_64-apple-macosx10.9" - "swift", inputs: ["{{.*}}/Inputs/main.swift"], output: {object: "/build/main.o"} // BINDINGS: # "x86_64-apple-macosx10.9" - "swift", inputs: ["{{.*}}/Inputs/lib.swift"], output: {object: "/build/lib.o"} -// BINDINGS: # "x86_64-apple-macosx10.9" - "darwin::Linker", inputs: ["/build/basic_output_file_map.o", "/build/main.o", "/build/lib.o"], output: {image: "/build/basic_output_file_map.out"} +// BINDINGS: # "x86_64-apple-macosx10.9" - "ld", inputs: ["/build/basic_output_file_map.o", "/build/main.o", "/build/lib.o"], output: {image: "/build/basic_output_file_map.out"} diff --git a/test/Driver/bindings.swift b/test/Driver/bindings.swift index d0ab149e703..ffade5c0704 100644 --- a/test/Driver/bindings.swift +++ b/test/Driver/bindings.swift @@ -2,20 +2,20 @@ // RUN: %swiftc_driver -driver-print-bindings -target x86_64-apple-macosx10.9 %s 2>&1 | FileCheck %s -check-prefix=BASIC // BASIC: # "x86_64-apple-macosx10.9" - "swift", inputs: ["{{.*}}bindings.swift"], output: {object: "[[OBJECT:.*\.o]]"} -// BASIC: # "x86_64-apple-macosx10.9" - "darwin::Linker", inputs: ["[[OBJECT]]"], output: {image: "bindings"} +// BASIC: # "x86_64-apple-macosx10.9" - "ld", inputs: ["[[OBJECT]]"], output: {image: "bindings"} // RUN: %swiftc_driver -driver-print-bindings -target x86_64-apple-macosx10.9 - 2>&1 | FileCheck %s -check-prefix=STDIN // STDIN: # "x86_64-apple-macosx10.9" - "swift", inputs: ["-"], output: {object: "[[OBJECT:.*\.o]]"} -// STDIN: # "x86_64-apple-macosx10.9" - "darwin::Linker", inputs: ["[[OBJECT]]"], output: {image: "main"} +// STDIN: # "x86_64-apple-macosx10.9" - "ld", inputs: ["[[OBJECT]]"], output: {image: "main"} // RUN: %swiftc_driver -driver-print-bindings -target x86_64-apple-macosx10.9 %S/Inputs/invalid-module-name.swift 2>&1 | FileCheck %s -check-prefix=INVALID-NAME-SINGLE-FILE // INVALID-NAME-SINGLE-FILE: # "x86_64-apple-macosx10.9" - "swift", inputs: ["{{.*}}/Inputs/invalid-module-name.swift"], output: {object: "[[OBJECT:.*\.o]]"} -// INVALID-NAME-SINGLE-FILE: # "x86_64-apple-macosx10.9" - "darwin::Linker", inputs: ["[[OBJECT]]"], output: {image: "invalid-module-name"} +// INVALID-NAME-SINGLE-FILE: # "x86_64-apple-macosx10.9" - "ld", inputs: ["[[OBJECT]]"], output: {image: "invalid-module-name"} // RUN: %swiftc_driver -driver-print-bindings -target x86_64-apple-macosx10.9 -o NamedOutput %s 2>&1 | FileCheck %s -check-prefix=NAMEDIMG // RUN: %swiftc_driver -driver-print-bindings -target x86_64-apple-macosx10.9 -module-name NamedOutput %s 2>&1 | FileCheck %s -check-prefix=NAMEDIMG // NAMEDIMG: # "x86_64-apple-macosx10.9" - "swift", inputs: ["{{.*}}bindings.swift"], output: {object: "[[OBJECT:.*\.o]]"} -// NAMEDIMG: # "x86_64-apple-macosx10.9" - "darwin::Linker", inputs: ["[[OBJECT]]"], output: {image: "NamedOutput"} +// NAMEDIMG: # "x86_64-apple-macosx10.9" - "ld", inputs: ["[[OBJECT]]"], output: {image: "NamedOutput"} // RUN: %swiftc_driver -driver-print-bindings -target x86_64-apple-macosx10.9 -c %s 2>&1 | FileCheck %s -check-prefix=OBJ // OBJ: # "x86_64-apple-macosx10.9" - "swift", inputs: ["{{.*}}bindings.swift"], output: {object: "bindings.o"} @@ -46,9 +46,9 @@ // RUN: touch %t/a.o %t/b.o // RUN: %swiftc_driver -driver-print-bindings -target x86_64-apple-macosx10.9 %t/a.o %t/b.o -o main 2>&1 | FileCheck %s -check-prefix=LINK-ONLY // RUN: %swiftc_driver -driver-print-bindings -target x86_64-apple-macosx10.9 -g %t/a.o %t/b.o -o main 2>&1 | FileCheck %s -check-prefix=LINK-ONLY -// LINK-ONLY: # "x86_64-apple-macosx10.9" - "darwin::Linker", inputs: ["{{.*}}/a.o", "{{.*}}/b.o"], output: {image: "main"} +// LINK-ONLY: # "x86_64-apple-macosx10.9" - "ld", inputs: ["{{.*}}/a.o", "{{.*}}/b.o"], output: {image: "main"} // RUN: touch %t/a.swiftmodule %t/b.swiftmodule // RUN: %swiftc_driver -driver-print-bindings -target x86_64-apple-macosx10.9 -g %t/a.o %t/b.o %t/a.swiftmodule %t/b.swiftmodule -o main 2>&1 | FileCheck %s -check-prefix=DEBUG-LINK-ONLY -// DEBUG-LINK-ONLY: # "x86_64-apple-macosx10.9" - "merge-module", inputs: ["{{.*}}/a.swiftmodule", "{{.*}}/b.swiftmodule"], output: {swiftmodule: "[[MERGED:.+\.swiftmodule]]", swiftdoc: "{{.+}}.swiftdoc"} -// DEBUG-LINK-ONLY: # "x86_64-apple-macosx10.9" - "darwin::Linker", inputs: ["{{.*}}/a.o", "{{.*}}/b.o", "[[MERGED]]"], output: {image: "main"} +// DEBUG-LINK-ONLY: # "x86_64-apple-macosx10.9" - "swift", inputs: ["{{.*}}/a.swiftmodule", "{{.*}}/b.swiftmodule"], output: {swiftmodule: "[[MERGED:.+\.swiftmodule]]", swiftdoc: "{{.+}}.swiftdoc"} +// DEBUG-LINK-ONLY: # "x86_64-apple-macosx10.9" - "ld", inputs: ["{{.*}}/a.o", "{{.*}}/b.o", "[[MERGED]]"], output: {image: "main"} diff --git a/test/Driver/crash.swift b/test/Driver/crash.swift index 015be6a205e..79ba1cecb82 100644 --- a/test/Driver/crash.swift +++ b/test/Driver/crash.swift @@ -2,7 +2,7 @@ // RUN: not %swiftc_driver -emit-executable -o %t.exe %s -Xfrontend -debug-crash-after-parse 2>&1 | FileCheck %s -// CHECK: error: swift frontend command failed due to signal +// CHECK: error: compile command failed due to signal func anchor() {} anchor() diff --git a/test/Driver/driver-compile.swift b/test/Driver/driver-compile.swift index ec6a1db6631..caf76c6a309 100644 --- a/test/Driver/driver-compile.swift +++ b/test/Driver/driver-compile.swift @@ -35,8 +35,13 @@ // RUN: cp %s %t // RUN: not %swiftc_driver -driver-print-jobs -c -target x86_64-apple-macosx10.9 %s %t/driver-compile.swift 2>&1 | FileCheck -check-prefix DUPLICATE-NAME %s -// RUN: %swiftc_driver -driver-print-jobs -update-code -c -target x86_64-apple-macosx10.9 -emit-module -emit-module-path %t.mod %s 2>&1 > %t.upd.txt +// RUN: rm -rf %t && mkdir -p %t/DISTINCTIVE-PATH/usr/bin/ +// RUN: ln %swift_driver_plain %t/DISTINCTIVE-PATH/usr/bin/swiftc +// RUN: ln -s "swiftc" %t/DISTINCTIVE-PATH/usr/bin/swift-update +// RUN: %t/DISTINCTIVE-PATH/usr/bin/swiftc -driver-print-jobs -update-code -c -target x86_64-apple-macosx10.9 -emit-module -emit-module-path %t.mod %s 2>&1 > %t.upd.txt // RUN: FileCheck -check-prefix UPDATE-CODE %s < %t.upd.txt +// Clean up the test executable because hard links are expensive. +// RUN: rm -rf %t/DISTINCTIVE-PATH/usr/bin/swiftc // RUN: %swiftc_driver -driver-print-jobs -fixit-code -c -target x86_64-apple-macosx10.9 -emit-module -emit-module-path %t.mod %s 2>&1 > %t.upd.txt // RUN: FileCheck -check-prefix FIXIT-CODE %s < %t.upd.txt @@ -97,10 +102,10 @@ // DUPLICATE-NAME: error: filename "driver-compile.swift" used twice: '{{.*}}test/Driver/driver-compile.swift' and '{{.*}}driver-compile.swift' // DUPLICATE-NAME: note: filenames are used to distinguish private declarations with the same name -// UPDATE-CODE: bin/swift-update +// UPDATE-CODE: DISTINCTIVE-PATH/usr/bin/swift-update // UPDATE-CODE: -c{{ }} // UPDATE-CODE: -o {{.+}}.remap -// UPDATE-CODE: bin/swift-update +// UPDATE-CODE: DISTINCTIVE-PATH/usr/bin/swift-update // UPDATE-CODE: -emit-module{{ }} // UPDATE-CODE: -o {{.+}}.mod diff --git a/test/Driver/embed-bitcode.swift b/test/Driver/embed-bitcode.swift index 84e2bed9249..39e0f4f5d2c 100644 --- a/test/Driver/embed-bitcode.swift +++ b/test/Driver/embed-bitcode.swift @@ -1,12 +1,12 @@ // RUN: %target-swiftc_driver -driver-print-bindings -embed-bitcode %s 2>&1 | FileCheck -check-prefix=CHECK-%target-object-format %s // CHECK-macho: "swift", inputs: ["{{.*}}embed-bitcode.swift"], output: {llvm-bc: "[[BC:.*\.bc]]"} // CHECK-macho: "swift", inputs: ["[[BC]]"], output: {object: "[[OBJECT:.*\.o]]"} -// CHECK-macho: "darwin::Linker", inputs: ["[[OBJECT]]"], output: {image: "embed-bitcode"} +// CHECK-macho: "ld", inputs: ["[[OBJECT]]"], output: {image: "embed-bitcode"} // CHECK-elf: "swift", inputs: ["{{.*}}embed-bitcode.swift"], output: {llvm-bc: "[[BC:.*\.bc]]"} // CHECK-elf: "swift", inputs: ["[[BC]]"], output: {object: "[[OBJECT:.*\.o]]"} // CHECK-elf: "swift-autolink-extract", inputs: ["[[OBJECT]]"], output: {autolink: "[[AUTOLINK:.*\.autolink]]"} -// CHECK-elf: "linux::Linker", inputs: ["[[OBJECT]]", "[[AUTOLINK]]"], output: {image: "main"} +// CHECK-elf: "clang++", inputs: ["[[OBJECT]]", "[[AUTOLINK]]"], output: {image: "main"} // RUN: %target-swiftc_driver -embed-bitcode %s 2>&1 -### | FileCheck %s -check-prefix=CHECK-FRONT -check-prefix=CHECK-FRONT-%target-object-format // CHECK-FRONT: -frontend diff --git a/test/Driver/linker.swift b/test/Driver/linker.swift index f1254c90b1a..2618fb6a65c 100644 --- a/test/Driver/linker.swift +++ b/test/Driver/linker.swift @@ -144,6 +144,7 @@ // RUN: rm -rf %t // RUN: mkdir -p %t/DISTINCTIVE-PATH/usr/bin/ // RUN: touch %t/DISTINCTIVE-PATH/usr/bin/ld +// RUN: chmod +x %t/DISTINCTIVE-PATH/usr/bin/ld // RUN: ln %swift_driver_plain %t/DISTINCTIVE-PATH/usr/bin/swiftc // RUN: %t/DISTINCTIVE-PATH/usr/bin/swiftc %s -### | FileCheck -check-prefix=RELATIVE-LINKER %s diff --git a/test/Driver/options-repl.swift b/test/Driver/options-repl.swift index 547d00f5674..4abac0e8d3d 100644 --- a/test/Driver/options-repl.swift +++ b/test/Driver/options-repl.swift @@ -44,6 +44,7 @@ // RUN: rm -rf %t // RUN: mkdir -p %t/usr/bin/ // RUN: touch %t/usr/bin/lldb +// RUN: chmod +x %t/usr/bin/lldb // RUN: ln %swift_driver_plain %t/usr/bin/swift // RUN: %t/usr/bin/swift -repl -### | FileCheck -check-prefix=LLDB %s // RUN: %t/usr/bin/swift -### | FileCheck -check-prefix=LLDB %s