diff --git a/include/swift/Driver/Action.h b/include/swift/Driver/Action.h index 02801d8aece66..bb45411e3de1b 100644 --- a/include/swift/Driver/Action.h +++ b/include/swift/Driver/Action.h @@ -328,16 +328,20 @@ class GeneratePCHJobAction : public JobAction { class DynamicLinkJobAction : public JobAction { virtual void anchor(); LinkKind Kind; + bool ShouldPerformLTO; public: - DynamicLinkJobAction(ArrayRef Inputs, LinkKind K) + DynamicLinkJobAction(ArrayRef Inputs, LinkKind K, + bool ShouldPerformLTO) : JobAction(Action::Kind::DynamicLinkJob, Inputs, file_types::TY_Image), - Kind(K) { + Kind(K), ShouldPerformLTO(ShouldPerformLTO) { assert(Kind != LinkKind::None && Kind != LinkKind::StaticLibrary); } LinkKind getKind() const { return Kind; } + bool shouldPerformLTO() const { return ShouldPerformLTO; } + static bool classof(const Action *A) { return A->getKind() == Action::Kind::DynamicLinkJob; } diff --git a/include/swift/Driver/Driver.h b/include/swift/Driver/Driver.h index 5e055359d6346..018b2a468812b 100644 --- a/include/swift/Driver/Driver.h +++ b/include/swift/Driver/Driver.h @@ -101,6 +101,14 @@ class OutputInfo { /// The output type which should be used for compile actions. file_types::ID CompilerOutputType = file_types::ID::TY_INVALID; + enum class LTOKind { + None, + LLVMThin, + LLVMFull, + }; + + LTOKind LTOVariant = LTOKind::None; + /// Describes if and how the output of compile actions should be /// linked together. LinkKind LinkAction = LinkKind::None; diff --git a/lib/Driver/DarwinToolChains.cpp b/lib/Driver/DarwinToolChains.cpp index a7153dc064e52..34fcf626d2b51 100644 --- a/lib/Driver/DarwinToolChains.cpp +++ b/lib/Driver/DarwinToolChains.cpp @@ -202,6 +202,19 @@ static bool findXcodeClangPath(llvm::SmallVectorImpl &path) { return !path.empty(); } +static bool findXcodeClangLibPath(const Twine &libName, + llvm::SmallVectorImpl &path) { + assert(path.empty()); + + if (!findXcodeClangPath(path)) { + return false; + } + llvm::sys::path::remove_filename(path); // 'clang' + llvm::sys::path::remove_filename(path); // 'bin' + llvm::sys::path::append(path, "lib", libName); + return true; +} + static void addVersionString(const ArgList &inputArgs, ArgStringList &arguments, unsigned major, unsigned minor, unsigned micro) { llvm::SmallString<8> buf; @@ -239,12 +252,15 @@ toolchains::Darwin::addLinkerInputArgs(InvocationInfo &II, Arguments.push_back("-filelist"); Arguments.push_back(context.getTemporaryFilePath("inputs", "LinkFileList")); II.FilelistInfos.push_back( - {Arguments.back(), file_types::TY_Object, + {Arguments.back(), context.OI.CompilerOutputType, FilelistInfo::WhichFiles::InputJobsAndSourceInputActions}); } else { addPrimaryInputsOfType(Arguments, context.Inputs, context.Args, file_types::TY_Object); + addPrimaryInputsOfType(Arguments, context.Inputs, context.Args, + file_types::TY_LLVM_BC); addInputsOfType(Arguments, context.InputActions, file_types::TY_Object); + addInputsOfType(Arguments, context.InputActions, file_types::TY_LLVM_BC); } @@ -274,11 +290,7 @@ static void findARCLiteLibPath(const toolchains::Darwin &TC, // If we don't have a 'lib/arc/' directory, find the "arclite" library // relative to the Clang in the active Xcode. ARCLiteLib.clear(); - if (findXcodeClangPath(ARCLiteLib)) { - llvm::sys::path::remove_filename(ARCLiteLib); // 'clang' - llvm::sys::path::remove_filename(ARCLiteLib); // 'bin' - llvm::sys::path::append(ARCLiteLib, "lib", "arc"); - } + findXcodeClangLibPath("arc", ARCLiteLib); } } @@ -307,6 +319,15 @@ toolchains::Darwin::addArgsToLinkARCLite(ArgStringList &Arguments, } } +void toolchains::Darwin::addLTOLibArgs(ArgStringList &Arguments, + const JobContext &context) const { + llvm::SmallString<128> LTOLibPath; + if (findXcodeClangLibPath("libLTO.dylib", LTOLibPath)) { + Arguments.push_back("-lto_library"); + Arguments.push_back(context.Args.MakeArgString(LTOLibPath)); + } +} + void toolchains::Darwin::addSanitizerArgs(ArgStringList &Arguments, const DynamicLinkJobAction &job, @@ -761,6 +782,10 @@ toolchains::Darwin::constructInvocation(const DynamicLinkJobAction &job, addArgsToLinkARCLite(Arguments, context); + if (job.shouldPerformLTO()) { + addLTOLibArgs(Arguments, context); + } + for (const Arg *arg : context.Args.filtered(options::OPT_F, options::OPT_Fsystem)) { Arguments.push_back("-F"); @@ -828,14 +853,17 @@ toolchains::Darwin::constructInvocation(const StaticLinkJobAction &job, if (context.shouldUseInputFileList()) { Arguments.push_back("-filelist"); Arguments.push_back(context.getTemporaryFilePath("inputs", "LinkFileList")); - II.FilelistInfos.push_back({Arguments.back(), file_types::TY_Object, + II.FilelistInfos.push_back({Arguments.back(), context.OI.CompilerOutputType, FilelistInfo::WhichFiles::InputJobs}); } else { addPrimaryInputsOfType(Arguments, context.Inputs, context.Args, file_types::TY_Object); + addPrimaryInputsOfType(Arguments, context.Inputs, context.Args, + file_types::TY_LLVM_BC); } addInputsOfType(Arguments, context.InputActions, file_types::TY_Object); + addInputsOfType(Arguments, context.InputActions, file_types::TY_LLVM_BC); Arguments.push_back("-o"); diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 4f38b90bd1b2b..5064d5544e3b7 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1433,12 +1433,29 @@ static bool isSDKTooOld(StringRef sdkPath, const llvm::Triple &target) { void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args, const bool BatchMode, const InputFileList &Inputs, OutputInfo &OI) const { + + if (const Arg *A = Args.getLastArg(options::OPT_lto)) { + auto LTOVariant = + llvm::StringSwitch>(A->getValue()) + .Case("llvm-thin", OutputInfo::LTOKind::LLVMThin) + .Case("llvm-full", OutputInfo::LTOKind::LLVMFull) + .Default(llvm::None); + if (LTOVariant) + OI.LTOVariant = LTOVariant.getValue(); + else + Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value, + A->getAsString(Args), A->getValue()); + } + + auto CompilerOutputType = OI.LTOVariant != OutputInfo::LTOKind::None + ? file_types::TY_LLVM_BC + : file_types::TY_Object; // By default, the driver does not link its output; this will be updated // appropriately below if linking is required. OI.CompilerOutputType = driverKind == DriverKind::Interactive ? file_types::TY_Nothing - : file_types::TY_Object; + : CompilerOutputType; if (const Arg *A = Args.getLastArg(options::OPT_num_threads)) { if (BatchMode) { @@ -1468,14 +1485,14 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args, diag::error_static_emit_executable_disallowed); OI.LinkAction = LinkKind::Executable; - OI.CompilerOutputType = file_types::TY_Object; + OI.CompilerOutputType = CompilerOutputType; break; case options::OPT_emit_library: OI.LinkAction = Args.hasArg(options::OPT_static) ? LinkKind::StaticLibrary : LinkKind::DynamicLibrary; - OI.CompilerOutputType = file_types::TY_Object; + OI.CompilerOutputType = CompilerOutputType; break; case options::OPT_static: @@ -2119,15 +2136,16 @@ void Driver::buildActions(SmallVectorImpl &TopLevelActions, MergeModuleAction = C.createAction(AllModuleInputs); } + bool shouldPerformLTO = OI.LTOVariant != OutputInfo::LTOKind::None; if (OI.shouldLink() && !AllLinkerInputs.empty()) { JobAction *LinkAction = nullptr; if (OI.LinkAction == LinkKind::StaticLibrary) { - LinkAction = C.createAction(AllLinkerInputs, - OI.LinkAction); + LinkAction = + C.createAction(AllLinkerInputs, OI.LinkAction); } else { - LinkAction = C.createAction(AllLinkerInputs, - OI.LinkAction); + LinkAction = C.createAction( + AllLinkerInputs, OI.LinkAction, shouldPerformLTO); } // On ELF platforms there's no built in autolinking mechanism, so we @@ -2149,9 +2167,10 @@ void Driver::buildActions(SmallVectorImpl &TopLevelActions, AutolinkExtractInputs.push_back(A); } const bool AutolinkExtractRequired = - (Triple.getObjectFormat() == llvm::Triple::ELF && !Triple.isPS4()) || - Triple.getObjectFormat() == llvm::Triple::Wasm || - Triple.isOSCygMing(); + ((Triple.getObjectFormat() == llvm::Triple::ELF && !Triple.isPS4()) || + Triple.getObjectFormat() == llvm::Triple::Wasm || + Triple.isOSCygMing()) && + !shouldPerformLTO; if (!AutolinkExtractInputs.empty() && AutolinkExtractRequired) { auto *AutolinkExtractAction = C.createAction(AutolinkExtractInputs); diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 3e158c76274cf..ea33335ccbe10 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -128,6 +128,19 @@ static bool addOutputsOfType(ArgStringList &Arguments, return Added; } +static void addLTOArgs(const OutputInfo &OI, ArgStringList &arguments) { + switch (OI.LTOVariant) { + case OutputInfo::LTOKind::None: + break; + case OutputInfo::LTOKind::LLVMThin: + arguments.push_back("-lto=llvm-thin"); + break; + case OutputInfo::LTOKind::LLVMFull: + arguments.push_back("-lto=llvm-full"); + break; + } +} + void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, const CommandOutput &output, const ArgList &inputArgs, @@ -284,6 +297,8 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI, arguments.push_back(inputArgs.MakeArgString(workingDirectory)); } + addLTOArgs(OI, arguments); + // -g implies -enable-anonymous-context-mangled-names, because the extra // metadata aids debugging. if (inputArgs.hasArg(options::OPT_g)) { diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index 29a04c1b243a8..946a8e70bc446 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -48,6 +48,9 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain { void addDeploymentTargetArgs(llvm::opt::ArgStringList &Arguments, const JobContext &context) const; + void addLTOLibArgs(llvm::opt::ArgStringList &Arguments, + const JobContext &context) const; + void addCommonFrontendArgs( const OutputInfo &OI, const CommandOutput &output, const llvm::opt::ArgList &inputArgs, diff --git a/lib/Driver/UnixToolChains.cpp b/lib/Driver/UnixToolChains.cpp index 14a5e88a54de0..102905f371509 100644 --- a/lib/Driver/UnixToolChains.cpp +++ b/lib/Driver/UnixToolChains.cpp @@ -72,7 +72,10 @@ ToolChain::InvocationInfo toolchains::GenericUnix::constructInvocation( addPrimaryInputsOfType(Arguments, context.Inputs, context.Args, file_types::TY_Object); + addPrimaryInputsOfType(Arguments, context.Inputs, context.Args, + file_types::TY_LLVM_BC); addInputsOfType(Arguments, context.InputActions, file_types::TY_Object); + addInputsOfType(Arguments, context.InputActions, file_types::TY_LLVM_BC); Arguments.push_back("-o"); Arguments.push_back( @@ -165,9 +168,18 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, // Select the linker to use. std::string Linker; + if (context.OI.LTOVariant != OutputInfo::LTOKind::None) { + // Force to use lld for LTO on Unix-like platform (not including Darwin) + // because we don't support gold LTO or something else except for lld LTO + // at this time. + Linker = "lld"; + } + if (const Arg *A = context.Args.getLastArg(options::OPT_use_ld)) { Linker = A->getValue(); - } else { + } + + if (Linker.empty()) { Linker = getDefaultLinker(); } if (!Linker.empty()) { @@ -218,6 +230,17 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, Arguments.push_back("-pie"); } + switch (context.OI.LTOVariant) { + case OutputInfo::LTOKind::LLVMThin: + Arguments.push_back("-flto=thin"); + break; + case OutputInfo::LTOKind::LLVMFull: + Arguments.push_back("-flto=full"); + break; + case OutputInfo::LTOKind::None: + break; + } + bool staticExecutable = false; bool staticStdlib = false; @@ -253,7 +276,10 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, addPrimaryInputsOfType(Arguments, context.Inputs, context.Args, file_types::TY_Object); + addPrimaryInputsOfType(Arguments, context.Inputs, context.Args, + file_types::TY_LLVM_BC); addInputsOfType(Arguments, context.InputActions, file_types::TY_Object); + addInputsOfType(Arguments, context.InputActions, file_types::TY_LLVM_BC); for (const Arg *arg : context.Args.filtered(options::OPT_F, options::OPT_Fsystem)) { @@ -368,7 +394,8 @@ toolchains::GenericUnix::constructInvocation(const StaticLinkJobAction &job, ArgStringList Arguments; // Configure the toolchain. - const char *AR = "ar"; + const char *AR = + context.OI.LTOVariant != OutputInfo::LTOKind::None ? "llvm-ar" : "ar"; Arguments.push_back("crs"); Arguments.push_back( @@ -376,7 +403,10 @@ toolchains::GenericUnix::constructInvocation(const StaticLinkJobAction &job, addPrimaryInputsOfType(Arguments, context.Inputs, context.Args, file_types::TY_Object); + addPrimaryInputsOfType(Arguments, context.Inputs, context.Args, + file_types::TY_LLVM_BC); addInputsOfType(Arguments, context.InputActions, file_types::TY_Object); + addInputsOfType(Arguments, context.InputActions, file_types::TY_LLVM_BC); InvocationInfo II{AR, Arguments}; diff --git a/lib/Driver/WindowsToolChains.cpp b/lib/Driver/WindowsToolChains.cpp index 749f0c902a80c..4f50c22c3c935 100644 --- a/lib/Driver/WindowsToolChains.cpp +++ b/lib/Driver/WindowsToolChains.cpp @@ -76,6 +76,24 @@ toolchains::Windows::constructInvocation(const DynamicLinkJobAction &job, if (const Arg *A = context.Args.getLastArg(options::OPT_use_ld)) { Linker = A->getValue(); } + + switch (context.OI.LTOVariant) { + case OutputInfo::LTOKind::LLVMThin: + Arguments.push_back("-flto=thin"); + break; + case OutputInfo::LTOKind::LLVMFull: + Arguments.push_back("-flto=full"); + break; + case OutputInfo::LTOKind::None: + break; + } + + if (Linker.empty() && context.OI.LTOVariant != OutputInfo::LTOKind::None) { + // Force to use lld for LTO on Windows because we don't support link LTO or + // something else except for lld LTO at this time. + Linker = "lld"; + } + if (!Linker.empty()) Arguments.push_back(context.Args.MakeArgString("-fuse-ld=" + Linker)); @@ -143,7 +161,10 @@ toolchains::Windows::constructInvocation(const DynamicLinkJobAction &job, addPrimaryInputsOfType(Arguments, context.Inputs, context.Args, file_types::TY_Object); + addPrimaryInputsOfType(Arguments, context.Inputs, context.Args, + file_types::TY_LLVM_BC); addInputsOfType(Arguments, context.InputActions, file_types::TY_Object); + addInputsOfType(Arguments, context.InputActions, file_types::TY_LLVM_BC); for (const Arg *arg : context.Args.filtered(options::OPT_F, options::OPT_Fsystem)) { diff --git a/test/Driver/filelists.swift b/test/Driver/filelists.swift index 9c7d9ea3efddc..732f4914e580b 100644 --- a/test/Driver/filelists.swift +++ b/test/Driver/filelists.swift @@ -70,3 +70,28 @@ // CHECK-LINK: Handled link + +// Ensure that filelist accepts bitcode files produced by frontend when LTO + +// RUN: %empty-directory(%t) +// RUN: echo "int dummy;" >%t/a.cpp +// RUN: %target-clang -c %t/a.cpp -o %t/a.o +// RUN: %swiftc_driver -save-temps -driver-print-jobs %S/../Inputs/empty.swift %t/a.o -lto=llvm-full -target x86_64-apple-macosx10.9 -driver-filelist-threshold=0 -o filelist 2>&1 | tee %t/forFilelistCapture | %FileCheck -check-prefix FILELIST %s +// RUN: tail -2 %t/forFilelistCapture | head -1 | sed 's/.*-output-filelist //' | sed 's/ .*//' > %t/output-filelist +// RUN: tail -1 %t/forFilelistCapture | sed 's/.*-filelist //' | sed 's/ .*//' > %t/input-filelist +// RUN: cat $(cat %t/output-filelist) | %FileCheck -check-prefix OUTPUT-FILELIST-CONTENTS %s +// RUN: cat $(cat %t/input-filelist) | %FileCheck -check-prefix INPUT-FILELIST-CONTENTS %s + +// FILELIST: swift +// FILELIST-DAG: -emit-bc +// FILELIST-DAG: -lto=llvm-full +// FILELIST-DAG: -output-filelist + +// FILELIST: ld +// FILELIST-NOT: .o +// FILELIST-NOT: .bc +// FILELIST: -filelist + +// OUTPUT-FILELIST-CONTENTS: {{.*\.bc}} +// INPUT-FILELIST-CONTENTS: {{.*\.bc}} +// INPUT-FILELIST-CONTENTS: a.o diff --git a/test/Driver/link-time-opt-darwin-ld-lib.swift b/test/Driver/link-time-opt-darwin-ld-lib.swift new file mode 100644 index 0000000000000..b3998e24d2b78 --- /dev/null +++ b/test/Driver/link-time-opt-darwin-ld-lib.swift @@ -0,0 +1,26 @@ +// REQUIRES: OS=macosx + +// Check that ld gets "-lto_library" + +// RUN: %swiftc_driver -driver-print-jobs %S/../Inputs/empty.swift -lto=llvm-thin -target x86_64-apple-macosx10.9 | %FileCheck %s --check-prefix=CHECK-SIMPLE-THIN --check-prefix=CHECK-SIMPLE-THIN-macosx + +// CHECK-SIMPLE-THIN: swift +// CHECK-SIMPLE-THIN-DAG: -emit-bc +// CHECK-SIMPLE-THIN-DAG: -lto=llvm-thin +// CHECK-SIMPLE-THIN-DAG: -o [[OBJECTFILE:.*\.bc]] + +// CHECK-SIMPLE-THIN-macosx: ld +// CHECK-SIMPLE-THIN-macosx-DAG: -lto_library {{.+}}/lib/libLTO.dylib +// CHECK-SIMPLE-THIN-macosx-DAG: [[OBJECTFILE]] + + +// RUN: %swiftc_driver -driver-print-jobs %S/../Inputs/empty.swift -lto=llvm-full -target x86_64-apple-macosx10.9 | %FileCheck %s --check-prefix=CHECK-SIMPLE-FULL --check-prefix=CHECK-SIMPLE-FULL-macosx + +// CHECK-SIMPLE-FULL: swift +// CHECK-SIMPLE-FULL-DAG: -emit-bc +// CHECK-SIMPLE-FULL-DAG: -lto=llvm-full +// CHECK-SIMPLE-FULL-DAG: -o [[OBJECTFILE:.*\.bc]] + +// CHECK-SIMPLE-FULL-macosx: ld +// CHECK-SIMPLE-FULL-macosx-DAG: -lto_library {{.+}}/lib/libLTO.dylib +// CHECK-SIMPLE-FULL-macosx-DAG: [[OBJECTFILE]] diff --git a/test/Driver/link-time-opt.swift b/test/Driver/link-time-opt.swift new file mode 100644 index 0000000000000..b0684b2425a9d --- /dev/null +++ b/test/Driver/link-time-opt.swift @@ -0,0 +1,82 @@ +// REQUIRES: lld_lto + +// RUN: %swiftc_driver -driver-print-jobs %S/../Inputs/empty.swift -lto=llvm-thin -target x86_64-unknown-linux-gnu | %FileCheck %s --check-prefix=CHECK-SIMPLE-THIN --check-prefix=CHECK-SIMPLE-THIN-linux-gnu +// RUN: %swiftc_driver -driver-print-jobs %S/../Inputs/empty.swift -lto=llvm-thin -target x86_64-unknown-windows-msvc | %FileCheck %s --check-prefix=CHECK-SIMPLE-THIN --check-prefix=CHECK-SIMPLE-THIN-windows-msvc + +// CHECK-SIMPLE-THIN: swift +// CHECK-SIMPLE-THIN-DAG: -emit-bc +// CHECK-SIMPLE-THIN-DAG: -lto=llvm-thin +// CHECK-SIMPLE-THIN-DAG: -o [[BITCODEFILE:.*\.bc]] + +// CHECK-SIMPLE-THIN-windows-msvc: clang +// CHECK-SIMPLE-THIN-windows-msvc-DAG: -fuse-ld=lld +// CHECK-SIMPLE-THIN-windows-msvc-DAG: -flto=thin +// CHECK-SIMPLE-THIN-windows-msvc-DAG: [[BITCODEFILE]] + +// CHECK-SIMPLE-THIN-linux-gnu: clang +// CHECK-SIMPLE-THIN-linux-gnu-DAG: -flto=thin +// CHECK-SIMPLE-THIN-linux-gnu-DAG: -fuse-ld=lld +// CHECK-SIMPLE-THIN-linux-gnu-DAG: [[BITCODEFILE]] +// CHECK-SIMPLE-THIN-linux-gnu-NOT: swift-autolink-extract + + + +// RUN: %swiftc_driver -driver-print-jobs %S/../Inputs/empty.swift -lto=llvm-full -target x86_64-unknown-linux-gnu | %FileCheck %s --check-prefix=CHECK-SIMPLE-FULL --check-prefix=CHECK-SIMPLE-FULL-linux-gnu +// RUN: %swiftc_driver -driver-print-jobs %S/../Inputs/empty.swift -lto=llvm-full -target x86_64-unknown-windows-msvc | %FileCheck %s --check-prefix=CHECK-SIMPLE-FULL --check-prefix=CHECK-SIMPLE-FULL-windows-msvc + +// CHECK-SIMPLE-FULL: swift +// CHECK-SIMPLE-FULL-DAG: -emit-bc +// CHECK-SIMPLE-FULL-DAG: -lto=llvm-full +// CHECK-SIMPLE-FULL-DAG: -o [[BITCODEFILE:.*\.bc]] + +// CHECK-SIMPLE-FULL-windows-msvc: clang +// CHECK-SIMPLE-FULL-windows-msvc-DAG: -fuse-ld=lld +// CHECK-SIMPLE-FULL-windows-msvc-DAG: -flto=full +// CHECK-SIMPLE-FULL-windows-msvc-DAG: [[BITCODEFILE]] + +// CHECK-SIMPLE-FULL-linux-gnu: clang +// CHECK-SIMPLE-FULL-linux-gnu-DAG: -flto=full +// CHECK-SIMPLE-FULL-linux-gnu-DAG: -fuse-ld=lld +// CHECK-SIMPLE-FULL-linux-gnu-DAG: [[BITCODEFILE]] +// CHECK-SIMPLE-FULL-linux-gnu-NOT: swift-autolink-extract + + + +// RUN: %swiftc_driver -driver-print-jobs %S/../Inputs/empty.swift -lto=llvm-thin -static -emit-library -target x86_64-apple-macosx10.9 | %FileCheck %s --check-prefix=CHECK-STATIC-LIB-THIN --check-prefix=CHECK-STATIC-LIB-THIN-macosx +// RUN: %swiftc_driver -driver-print-jobs %S/../Inputs/empty.swift -lto=llvm-thin -static -emit-library -target x86_64-unknown-linux-gnu | %FileCheck %s --check-prefix=CHECK-STATIC-LIB-THIN --check-prefix=CHECK-STATIC-LIB-THIN-linux-gnu + +// CHECK-STATIC-LIB-THIN: swift +// CHECK-STATIC-LIB-THIN-DAG: -emit-bc +// CHECK-STATIC-LIB-THIN-DAG: -lto=llvm-thin +// CHECK-STATIC-LIB-THIN-DAG: -o [[BITCODEFILE:.*\.bc]] + +// CHECK-STATIC-LIB-THIN-macosx: libtool +// CHECK-STATIC-LIB-THIN-macosx-DAG: [[BITCODEFILE]] + +// CHECK-STATIC-LIB-THIN-linux-gnu: llvm-ar +// CHECK-STATIC-LIB-THIN-linux-gnu-DAG: [[BITCODEFILE]] +// CHECK-STATIC-LIB-THIN-linux-gnu-NOT: swift-autolink-extract + + + +// RUN: %swiftc_driver -driver-print-jobs %S/../Inputs/empty.swift -lto=llvm-full -static -emit-library -target x86_64-apple-macosx10.9 | %FileCheck %s --check-prefix=CHECK-STATIC-LIB-FULL --check-prefix=CHECK-STATIC-LIB-FULL-macosx +// RUN: %swiftc_driver -driver-print-jobs %S/../Inputs/empty.swift -lto=llvm-full -static -emit-library -target x86_64-unknown-linux-gnu | %FileCheck %s --check-prefix=CHECK-STATIC-LIB-FULL --check-prefix=CHECK-STATIC-LIB-FULL-linux-gnu + +// CHECK-STATIC-LIB-FULL: swift +// CHECK-STATIC-LIB-FULL-DAG: -emit-bc +// CHECK-STATIC-LIB-FULL-DAG: -lto=llvm-full +// CHECK-STATIC-LIB-FULL-DAG: -o [[BITCODEFILE:.*\.bc]] + +// CHECK-STATIC-LIB-FULL-macosx: libtool +// CHECK-STATIC-LIB-FULL-macosx-DAG: [[BITCODEFILE]] + +// CHECK-STATIC-LIB-FULL-linux-gnu: llvm-ar +// CHECK-STATIC-LIB-FULL-linux-gnu-DAG: [[BITCODEFILE]] +// CHECK-STATIC-LIB-FULL-linux-gnu-NOT: swift-autolink-extract + + + +// Ensure that -use-ld wins even if getting -lto option +// RUN: %swiftc_driver -driver-print-jobs %s -lto=llvm-thin -use-ld=gold -target x86_64-unknown-linux-gnu | %FileCheck -check-prefix PREFER_USE_LD %s +// RUN: %swiftc_driver -driver-print-jobs %s -lto=llvm-thin -use-ld=gold -target x86_64-unknown-windows-msvc | %FileCheck -check-prefix PREFER_USE_LD %s +// PREFER_USE_LD: -fuse-ld=gold diff --git a/test/Interpreter/Inputs/lto/module1.swift b/test/Interpreter/Inputs/lto/module1.swift new file mode 100644 index 0000000000000..ff0bf6bb83e2a --- /dev/null +++ b/test/Interpreter/Inputs/lto/module1.swift @@ -0,0 +1 @@ +public func unusedPublicFunction() {} diff --git a/test/Interpreter/llvm_link_time_opt.swift b/test/Interpreter/llvm_link_time_opt.swift new file mode 100644 index 0000000000000..f60b37e1af02b --- /dev/null +++ b/test/Interpreter/llvm_link_time_opt.swift @@ -0,0 +1,11 @@ +// UNSUPPORTED: OS=windows-msvc +// static library is not well supported yet on Windows + +// RUN: %empty-directory(%t) +// RUN: %target-swiftc_driver -emit-library -static -lto=llvm-full -emit-module %S/Inputs/lto/module1.swift -working-directory %t +// RUN: %target-swiftc_driver -lto=llvm-full %s -I%t -L%t -lmodule1 -module-name main -o %t/main +// RUN: %llvm-nm --defined-only %t/main | %FileCheck %s + +// CHECK-NOT: _$s7module120unusedPublicFunctionyyF + +import module1 diff --git a/test/lit.cfg b/test/lit.cfg index 08a38a66606f2..8b22275ef2ba0 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -351,6 +351,11 @@ differentiable_programming = lit_config.params.get('differentiable_programming', if differentiable_programming is not None: config.available_features.add('differentiable_programming') +# On Android, LLVM LTO is only supported when the driver uses lld. +# And skip lto tests when driver uses gold linker. +if not (run_os in ['linux-android', 'linux-androideabi']) or (config.android_linker_name == 'lld'): + config.available_features.add('lld_lto') + test_options = os.environ.get('SWIFT_TEST_OPTIONS') if test_options: config.swift_test_options += ' '