diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h index ef745ec6b3772..703452b4f05dc 100644 --- a/include/swift/AST/IRGenOptions.h +++ b/include/swift/AST/IRGenOptions.h @@ -65,6 +65,12 @@ enum class IRGenDebugInfoFormat : unsigned { CodeView }; +enum class IRGenLLVMLTOKind : unsigned { + None, + Thin, + Full, +}; + enum class IRGenEmbedMode : unsigned { None, EmbedMarker, @@ -220,6 +226,8 @@ class IRGenOptions { /// Whether we should embed the bitcode file. IRGenEmbedMode EmbedMode : 2; + IRGenLLVMLTOKind LLVMLTOKind : 2; + /// Add names to LLVM values. unsigned HasValueNamesSetting : 1; unsigned ValueNames : 1; @@ -320,21 +328,21 @@ class IRGenOptions { DebugInfoLevel(IRGenDebugInfoLevel::None), DebugInfoFormat(IRGenDebugInfoFormat::None), DisableClangModuleSkeletonCUs(false), UseJIT(false), - DisableLLVMOptzns(false), - DisableSwiftSpecificLLVMOptzns(false), DisableLLVMSLPVectorizer(false), - Playground(false), EmitStackPromotionChecks(false), - FunctionSections(false), PrintInlineTree(false), EmbedMode(IRGenEmbedMode::None), - HasValueNamesSetting(false), ValueNames(false), - EnableReflectionMetadata(true), EnableReflectionNames(true), - EnableAnonymousContextMangledNames(false), ForcePublicLinkage(false), - LazyInitializeClassMetadata(false), + DisableLLVMOptzns(false), DisableSwiftSpecificLLVMOptzns(false), + DisableLLVMSLPVectorizer(false), Playground(false), + EmitStackPromotionChecks(false), FunctionSections(false), + PrintInlineTree(false), EmbedMode(IRGenEmbedMode::None), + LLVMLTOKind(IRGenLLVMLTOKind::None), HasValueNamesSetting(false), + ValueNames(false), EnableReflectionMetadata(true), + EnableReflectionNames(true), EnableAnonymousContextMangledNames(false), + ForcePublicLinkage(false), LazyInitializeClassMetadata(false), LazyInitializeProtocolConformances(false), DisableLegacyTypeInfo(false), PrespecializeGenericMetadata(false), UseIncrementalLLVMCodeGen(true), - UseSwiftCall(false), UseTypeLayoutValueHandling(true), GenerateProfile(false), - EnableDynamicReplacementChaining(false), + UseSwiftCall(false), UseTypeLayoutValueHandling(true), + GenerateProfile(false), EnableDynamicReplacementChaining(false), DisableRoundTripDebugTypes(false), DisableDebuggerShadowCopies(false), - DisableConcreteTypeMetadataMangledNameAccessors(false), - CmdArgs(), SanitizeCoverage(llvm::SanitizerCoverageOptions()), + DisableConcreteTypeMetadataMangledNameAccessors(false), CmdArgs(), + SanitizeCoverage(llvm::SanitizerCoverageOptions()), TypeInfoFilter(TypeInfoDumpFilter::All) {} /// Appends to \p os an arbitrary string representing all options which diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 226a26d64a367..bf07e0615b055 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -523,6 +523,10 @@ def disable_bridging_pch : Flag<["-"], "disable-bridging-pch">, Flags<[HelpHidden]>, HelpText<"Disable automatic generation of bridging PCH files">; +def lto : Joined<["-"], "lto=">, + Flags<[FrontendOption, NoInteractiveOption]>, + HelpText<"Specify the LTO type to either 'llvm-thin' or 'llvm-full'">; + // Experimental feature options // Note: this flag will be removed when JVP/differential generation in the diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index fa1ee67f03b91..2f8aed6a173ae 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1474,6 +1474,18 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args, } } + if (const Arg *A = Args.getLastArg(options::OPT_lto)) { + auto LLVMLTOKind = + llvm::StringSwitch>(A->getValue()) + .Case("llvm-thin", IRGenLLVMLTOKind::Thin) + .Case("llvm-full", IRGenLLVMLTOKind::Full) + .Default(llvm::None); + if (LLVMLTOKind) + Opts.LLVMLTOKind = LLVMLTOKind.getValue(); + else + Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value, + A->getAsString(Args), A->getValue()); + } if (const Arg *A = Args.getLastArg(options::OPT_sanitize_coverage_EQ)) { Opts.SanitizeCoverage = diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp index 2f9d160152144..4806950d2a42f 100644 --- a/lib/IRGen/IRGen.cpp +++ b/lib/IRGen/IRGen.cpp @@ -548,9 +548,14 @@ bool swift::performLLVM(const IRGenOptions &Opts, case IRGenOutputKind::LLVMAssembly: EmitPasses.add(createPrintModulePass(*RawOS)); break; - case IRGenOutputKind::LLVMBitcode: - EmitPasses.add(createBitcodeWriterPass(*RawOS)); + case IRGenOutputKind::LLVMBitcode: { + if (Opts.LLVMLTOKind == IRGenLLVMLTOKind::Thin) { + EmitPasses.add(createWriteThinLTOBitcodePass(*RawOS)); + } else { + EmitPasses.add(createBitcodeWriterPass(*RawOS)); + } break; + } case IRGenOutputKind::NativeAssembly: case IRGenOutputKind::ObjectFile: { CodeGenFileType FileType; diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp index c7d01eb932b15..f9545f7c9a366 100644 --- a/lib/IRGen/IRGenModule.cpp +++ b/lib/IRGen/IRGenModule.cpp @@ -1108,8 +1108,6 @@ llvm::SmallString<32> getTargetDependentLibraryOption(const llvm::Triple &T, } void IRGenModule::addLinkLibrary(const LinkLibrary &linkLib) { - llvm::LLVMContext &ctx = Module.getContext(); - // The debugger gets the autolink information directly from // the LinkLibraries of the module, so there's no reason to // emit it into the IR of debugger expressions. @@ -1118,10 +1116,7 @@ void IRGenModule::addLinkLibrary(const LinkLibrary &linkLib) { switch (linkLib.getKind()) { case LibraryKind::Library: { - llvm::SmallString<32> opt = - getTargetDependentLibraryOption(Triple, linkLib.getName()); - AutolinkEntries.push_back( - llvm::MDNode::get(ctx, llvm::MDString::get(ctx, opt))); + AutolinkEntries.emplace_back(linkLib); break; } case LibraryKind::Framework: { @@ -1130,12 +1125,7 @@ void IRGenModule::addLinkLibrary(const LinkLibrary &linkLib) { if (std::find(frameworks.begin(), frameworks.end(), linkLib.getName()) != frameworks.end()) return; - - llvm::Metadata *args[] = { - llvm::MDString::get(ctx, "-framework"), - llvm::MDString::get(ctx, linkLib.getName()) - }; - AutolinkEntries.push_back(llvm::MDNode::get(ctx, args)); + AutolinkEntries.emplace_back(linkLib); break; } } @@ -1205,38 +1195,132 @@ static bool isFirstObjectFileInModule(IRGenModule &IGM) { return containingModule->getFiles().front() == file; } -void IRGenModule::emitAutolinkInfo() { - // Collect the linker options already in the module (from ClangCodeGen). +static bool +doesTargetAutolinkUsingAutolinkExtract(const SwiftTargetInfo &TargetInfo, + const llvm::Triple &Triple) { + if (TargetInfo.OutputObjectFormat == llvm::Triple::ELF && !Triple.isPS4()) + return true; + + if (TargetInfo.OutputObjectFormat == llvm::Triple::Wasm) + return true; + + if (Triple.isOSCygMing()) + return true; + + return false; +} + +namespace { + +struct AutolinkKind { + enum ValueTy { + LLVMLinkerOptions, + LLVMDependentLibraries, + SwiftAutoLinkExtract, + }; + + ValueTy Value; + + AutolinkKind(ValueTy value) : Value(value) {} + AutolinkKind(const AutolinkKind &kind) : Value(kind.Value) {} + + StringRef getSectionNameMetadata(); + + template + void collectEntriesFromLibraries(llvm::SetVector &Entries, + ArrayRef AutolinkEntries, + IRGenModule &IGM); + + template + void writeEntries(llvm::SetVector Entries, + llvm::NamedMDNode *Metadata, IRGenModule &IGM); + + static AutolinkKind create(const SwiftTargetInfo &TargetInfo, + llvm::Triple Triple, IRGenLLVMLTOKind LLVMLTOKind); +}; + +} // anonymous namespace + +StringRef AutolinkKind::getSectionNameMetadata() { // FIXME: This constant should be vended by LLVM somewhere. - auto *Metadata = Module.getOrInsertNamedMetadata("llvm.linker.options"); - for (llvm::MDNode *LinkOption : Metadata->operands()) - AutolinkEntries.push_back(LinkOption); - - // Remove duplicates. - llvm::SmallPtrSet knownAutolinkEntries; - AutolinkEntries.erase(std::remove_if(AutolinkEntries.begin(), - AutolinkEntries.end(), - [&](llvm::MDNode *entry) -> bool { - return !knownAutolinkEntries.insert( - entry).second; - }), - AutolinkEntries.end()); - - const bool AutolinkExtractRequired = - (TargetInfo.OutputObjectFormat == llvm::Triple::ELF && !Triple.isPS4()) || - TargetInfo.OutputObjectFormat == llvm::Triple::Wasm || - Triple.isOSCygMing(); - - if (!AutolinkExtractRequired) { + switch (Value) { + case AutolinkKind::LLVMDependentLibraries: + return "llvm.dependent-libraries"; + case AutolinkKind::LLVMLinkerOptions: + case AutolinkKind::SwiftAutoLinkExtract: + return "llvm.linker.options"; + } + + llvm_unreachable("Unhandled AutolinkKind in switch."); +} + +template +void AutolinkKind::collectEntriesFromLibraries( + llvm::SetVector &Entries, + ArrayRef AutolinkEntries, IRGenModule &IGM) { + llvm::LLVMContext &ctx = IGM.getLLVMContext(); + + switch (Value) { + case AutolinkKind::LLVMLinkerOptions: + case AutolinkKind::SwiftAutoLinkExtract: { + // On platforms that support autolinking, continue to use the metadata. + for (LinkLibrary linkLib : AutolinkEntries) { + switch (linkLib.getKind()) { + case LibraryKind::Library: { + llvm::SmallString<32> opt = + getTargetDependentLibraryOption(IGM.Triple, linkLib.getName()); + Entries.insert(llvm::MDNode::get(ctx, llvm::MDString::get(ctx, opt))); + continue; + } + case LibraryKind::Framework: { + llvm::Metadata *args[] = {llvm::MDString::get(ctx, "-framework"), + llvm::MDString::get(ctx, linkLib.getName())}; + Entries.insert(llvm::MDNode::get(ctx, args)); + continue; + } + } + llvm_unreachable("Unhandled LibraryKind in switch."); + } + return; + } + case AutolinkKind::LLVMDependentLibraries: { + for (LinkLibrary linkLib : AutolinkEntries) { + switch (linkLib.getKind()) { + case LibraryKind::Library: { + Entries.insert(llvm::MDNode::get( + ctx, llvm::MDString::get(ctx, linkLib.getName()))); + continue; + } + case LibraryKind::Framework: { + llvm_unreachable( + "llvm.dependent-libraries doesn't support framework dependency"); + } + } + llvm_unreachable("Unhandled LibraryKind in switch."); + } + return; + } + } + llvm_unreachable("Unhandled AutolinkKind in switch."); +} + +template +void AutolinkKind::writeEntries(llvm::SetVector Entries, + llvm::NamedMDNode *Metadata, IRGenModule &IGM) { + switch (Value) { + case AutolinkKind::LLVMLinkerOptions: + case AutolinkKind::LLVMDependentLibraries: { // On platforms that support autolinking, continue to use the metadata. Metadata->clearOperands(); - for (auto *Entry : AutolinkEntries) + for (auto *Entry : Entries) Metadata->addOperand(Entry); - } else { + return; + } + case AutolinkKind::SwiftAutoLinkExtract: { // Merge the entries into null-separated string. llvm::SmallString<64> EntriesString; - for (auto &EntryNode : AutolinkEntries) { - const llvm::MDNode *MD = cast(EntryNode); + for (auto EntryNode : Entries) { + const auto *MD = cast(EntryNode); for (auto &Entry : MD->operands()) { const llvm::MDString *MS = cast(Entry); EntriesString += MS->getString(); @@ -1244,24 +1328,64 @@ void IRGenModule::emitAutolinkInfo() { } } auto EntriesConstant = llvm::ConstantDataArray::getString( - getLLVMContext(), EntriesString, /*AddNull=*/false); + IGM.getLLVMContext(), EntriesString, /*AddNull=*/false); // Mark the swift1_autolink_entries section with the SHF_EXCLUDE attribute // to get the linker to drop it in the final linked binary. - // LLVM doesn't provide an interface to specify section attributs in the IR - // so we pass the attribute with inline assembly. - if (TargetInfo.OutputObjectFormat == llvm::Triple::ELF) - Module.appendModuleInlineAsm(".section .swift1_autolink_entries," - "\"0x80000000\""); + // LLVM doesn't provide an interface to specify section attributs in the + // IR so we pass the attribute with inline assembly. + if (IGM.TargetInfo.OutputObjectFormat == llvm::Triple::ELF) + IGM.Module.appendModuleInlineAsm(".section .swift1_autolink_entries," + "\"0x80000000\""); auto var = - new llvm::GlobalVariable(*getModule(), EntriesConstant->getType(), true, - llvm::GlobalValue::PrivateLinkage, + new llvm::GlobalVariable(*IGM.getModule(), EntriesConstant->getType(), + true, llvm::GlobalValue::PrivateLinkage, EntriesConstant, "_swift1_autolink_entries"); var->setSection(".swift1_autolink_entries"); - var->setAlignment(llvm::MaybeAlign(getPointerAlignment().getValue())); + var->setAlignment(llvm::MaybeAlign(IGM.getPointerAlignment().getValue())); - disableAddressSanitizer(*this, var); - addUsedGlobal(var); + disableAddressSanitizer(IGM, var); + IGM.addUsedGlobal(var); + return; } + } + llvm_unreachable("Unhandled AutolinkKind in switch."); +} + +AutolinkKind AutolinkKind::create(const SwiftTargetInfo &TargetInfo, + llvm::Triple Triple, + IRGenLLVMLTOKind LLVMLTOKind) { + // When performing LTO, we always use lld that supports auto linking + // mechanism with ELF. So embed dependent libraries names in + // "llvm.dependent-libraries" instead of "llvm.linker.options". + if (TargetInfo.OutputObjectFormat == llvm::Triple::ELF && + LLVMLTOKind != IRGenLLVMLTOKind::None) { + return AutolinkKind::LLVMDependentLibraries; + } + + if (doesTargetAutolinkUsingAutolinkExtract(TargetInfo, Triple)) { + return AutolinkKind::SwiftAutoLinkExtract; + } + + return AutolinkKind::LLVMLinkerOptions; +} + +void IRGenModule::emitAutolinkInfo() { + auto Autolink = + AutolinkKind::create(TargetInfo, Triple, IRGen.Opts.LLVMLTOKind); + + StringRef AutolinkSectionName = Autolink.getSectionNameMetadata(); + + auto *Metadata = Module.getOrInsertNamedMetadata(AutolinkSectionName); + llvm::SmallSetVector Entries; + + // Collect the linker options already in the module (from ClangCodeGen). + for (auto Entry : Metadata->operands()) { + Entries.insert(Entry); + } + + Autolink.collectEntriesFromLibraries(Entries, AutolinkEntries, *this); + + Autolink.writeEntries(Entries, Metadata, *this); if (!IRGen.Opts.ForceLoadSymbolName.empty() && (Triple.supportsCOMDAT() || isFirstObjectFileInModule(*this))) { diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h index 19485b72bceae..d8634e056470d 100644 --- a/lib/IRGen/IRGenModule.h +++ b/lib/IRGen/IRGenModule.h @@ -22,6 +22,7 @@ #include "SwiftTargetInfo.h" #include "TypeLayout.h" #include "swift/AST/Decl.h" +#include "swift/AST/LinkLibrary.h" #include "swift/AST/Module.h" #include "swift/AST/ReferenceCounting.h" #include "swift/AST/SourceFile.h" @@ -1076,7 +1077,7 @@ class IRGenModule { SmallVector LLVMCompilerUsed; /// Metadata nodes for autolinking info. - SmallVector AutolinkEntries; + SmallVector AutolinkEntries; /// List of Objective-C classes, bitcast to i8*. SmallVector ObjCClasses; diff --git a/test/IRGen/Inputs/Frameworks/LinkFramework.framework/Headers/LinkFramework.h b/test/IRGen/Inputs/Frameworks/LinkFramework.framework/Headers/LinkFramework.h new file mode 100644 index 0000000000000..237c9be32ff83 --- /dev/null +++ b/test/IRGen/Inputs/Frameworks/LinkFramework.framework/Headers/LinkFramework.h @@ -0,0 +1,2 @@ + +extern int IComeFromLinkFramework; diff --git a/test/IRGen/Inputs/Frameworks/LinkFramework.framework/LinkFramework b/test/IRGen/Inputs/Frameworks/LinkFramework.framework/LinkFramework new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/test/IRGen/Inputs/Frameworks/LinkFramework.framework/module.map b/test/IRGen/Inputs/Frameworks/LinkFramework.framework/module.map new file mode 100644 index 0000000000000..abdf6780a2f11 --- /dev/null +++ b/test/IRGen/Inputs/Frameworks/LinkFramework.framework/module.map @@ -0,0 +1,4 @@ +framework module LinkFramework { + header "LinkFramework.h" + export * +} diff --git a/test/IRGen/Inputs/autolink-elf-c-pragma-transitive.h b/test/IRGen/Inputs/autolink-elf-c-pragma-transitive.h new file mode 100644 index 0000000000000..d3644cee43cb4 --- /dev/null +++ b/test/IRGen/Inputs/autolink-elf-c-pragma-transitive.h @@ -0,0 +1 @@ +#pragma comment(lib, "transitive-module") diff --git a/test/IRGen/Inputs/autolink-elf-c-pragma.h b/test/IRGen/Inputs/autolink-elf-c-pragma.h new file mode 100644 index 0000000000000..08318e9e3358b --- /dev/null +++ b/test/IRGen/Inputs/autolink-elf-c-pragma.h @@ -0,0 +1,3 @@ +#include "autolink-elf-c-pragma-transitive.h" + +#pragma comment(lib, "module") diff --git a/test/IRGen/Inputs/module.modulemap b/test/IRGen/Inputs/module.modulemap index d396471ea63e0..c680830f71802 100644 --- a/test/IRGen/Inputs/module.modulemap +++ b/test/IRGen/Inputs/module.modulemap @@ -7,3 +7,17 @@ module AutolinkCoffCPragmaTransitive { header "autolink-coff-c-pragma-transitive.h" export * } + +module AutolinkElfCPragma { + header "autolink-elf-c-pragma.h" + export * +} + +module AutolinkElfCPragmaTransitive { + header "autolink-elf-c-pragma-transitive.h" + export * +} + +module AutolinkModuleMapLink { + link "autolink-module-map-link" +} diff --git a/test/IRGen/autolink_merge_from_clangimporter.swift b/test/IRGen/autolink_merge_from_clangimporter.swift new file mode 100644 index 0000000000000..f682f5107be34 --- /dev/null +++ b/test/IRGen/autolink_merge_from_clangimporter.swift @@ -0,0 +1,19 @@ +// This checks that link entries derived from clang importer are merged properly + +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -emit-module -o %t -module-name empty -module-link-name empty %S/../Inputs/empty.swift +// RUN: %target-swift-emit-ir -I %t -Fsystem %S/Inputs/Frameworks %s | %FileCheck %s --check-prefix CHECK +// Linux uses a different autolinking mechanism, based on +// swift-autolink-extract. This file tests the Darwin mechanism. +// UNSUPPORTED: autolink-extract + +import empty +import LinkFramework + +func useLibrarySym() { + let _ = LinkFramework.IComeFromLinkFramework +} + +// CHECK-DAG: !llvm.linker.options = !{ +// CHECK-DAG: !{{[0-9]+}} = !{!"-lempty"} +// CHECK-DAG: !{{[0-9]+}} = !{!"-framework", !"LinkFramework"} diff --git a/test/IRGen/lto_autolink.swift b/test/IRGen/lto_autolink.swift new file mode 100644 index 0000000000000..af82d6f6df05f --- /dev/null +++ b/test/IRGen/lto_autolink.swift @@ -0,0 +1,64 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -target x86_64-apple-macosx10.15 -emit-module -parse-stdlib -o %t -module-name empty -module-link-name empty %S/../Inputs/empty.swift +// RUN: %target-swift-emit-ir -target x86_64-apple-macosx10.15 -lto=llvm-full -parse-stdlib -I %t %s | %FileCheck %s --check-prefix CHECK-MACHO +// RUN: %target-swift-emit-ir -target x86_64-apple-macosx10.15 -lto=llvm-thin -parse-stdlib -I %t %s | %FileCheck %s --check-prefix CHECK-MACHO + +// CHECK-MACHO-DAG: !llvm.linker.options = !{ +// CHECK-MACHO-DAG: !{{[0-9]+}} = !{!"-lempty"} + +// RUN: %target-swift-frontend -target x86_64-unknown-linux-gnu -emit-module -parse-stdlib -o %t -module-name empty -module-link-name empty %S/../Inputs/empty.swift +// RUN: %target-swift-emit-ir -target x86_64-unknown-linux-gnu -lto=llvm-full -parse-stdlib -I %t %s | %FileCheck %s --check-prefix CHECK-ELF +// RUN: %target-swift-emit-ir -target x86_64-unknown-linux-gnu -lto=llvm-thin -parse-stdlib -I %t %s | %FileCheck %s --check-prefix CHECK-ELF + +// CHECK-ELF-DAG: !llvm.dependent-libraries = !{ +// CHECK-ELF-DAG: !{{[0-9]+}} = !{!"empty"} + +// RUN: %target-swift-frontend -target x86_64-unknown-windows-msvc -emit-module -parse-stdlib -o %t -module-name empty -module-link-name empty %S/../Inputs/empty.swift +// RUN: %target-swift-emit-ir -target x86_64-unknown-windows-msvc -lto=llvm-full -parse-stdlib -I %t %s | %FileCheck %s --check-prefix CHECK-COFF +// RUN: %target-swift-emit-ir -target x86_64-unknown-windows-msvc -lto=llvm-thin -parse-stdlib -I %t %s | %FileCheck %s --check-prefix CHECK-COFF + +// CHECK-COFF-DAG: !llvm.linker.options = !{ +// CHECK-COFF-DAG: !{{[0-9]+}} = !{!"/DEFAULTLIB:empty.lib"} + + +import empty + +// Ensure the dependent libraries embeded by clang are merged. + + +// RUN: %target-swift-frontend -target x86_64-apple-macosx10.15 -emit-module -parse-stdlib -o %t -module-name empty -module-link-name empty %S/../Inputs/empty.swift +// RUN: %target-swift-emit-ir -target x86_64-apple-macosx10.15 -lto=llvm-full -parse-stdlib -I %t -I %S/Inputs -DTEST_CLANG_OPTIONS_MERGE %s | %FileCheck %s --check-prefix CHECK-MACHO-MERGE +// RUN: %target-swift-emit-ir -target x86_64-apple-macosx10.15 -lto=llvm-thin -parse-stdlib -I %t -I %S/Inputs -DTEST_CLANG_OPTIONS_MERGE %s | %FileCheck %s --check-prefix CHECK-MACHO-MERGE + +// CHECK-MACHO-MERGE-DAG: !llvm.linker.options = !{ +// CHECK-MACHO-MERGE-DAG: !{{[0-9]+}} = !{!"-lempty"} +// CHECK-MACHO-MERGE-DAG: !{{[0-9]+}} = !{!"-lautolink-module-map-link"} + + +// RUN: %target-swift-frontend -target x86_64-unknown-linux-gnu -emit-module -parse-stdlib -o %t -module-name empty -module-link-name empty %S/../Inputs/empty.swift +// RUN: %target-swift-emit-ir -target x86_64-unknown-linux-gnu -lto=llvm-full -parse-stdlib -I %t -I %S/Inputs -DTEST_CLANG_OPTIONS_MERGE %s | %FileCheck %s --check-prefix CHECK-ELF-MERGE +// RUN: %target-swift-emit-ir -target x86_64-unknown-linux-gnu -lto=llvm-thin -parse-stdlib -I %t -I %S/Inputs -DTEST_CLANG_OPTIONS_MERGE %s | %FileCheck %s --check-prefix CHECK-ELF-MERGE + +// CHECK-ELF-MERGE-DAG: !llvm.dependent-libraries = !{ +// CHECK-ELF-MERGE-DAG: !{{[0-9]+}} = !{!"empty"} +// CHECK-ELF-MERGE-DAG: !{{[0-9]+}} = !{!"module"} +// CHECK-ELF-MERGE-DAG: !{{[0-9]+}} = !{!"transitive-module"} +// CHECK-ELF-MERGE-DAG: !{{[0-9]+}} = !{!"autolink-module-map-link"} + + +// RUN: %target-swift-frontend -target x86_64-unknown-windows-msvc -emit-module -parse-stdlib -o %t -module-name empty -module-link-name empty %S/../Inputs/empty.swift +// RUN: %target-swift-emit-ir -target x86_64-unknown-windows-msvc -lto=llvm-full -parse-stdlib -I %t -I %S/Inputs -DTEST_CLANG_OPTIONS_MERGE %s | %FileCheck %s --check-prefix CHECK-COFF +// RUN: %target-swift-emit-ir -target x86_64-unknown-windows-msvc -lto=llvm-thin -parse-stdlib -I %t -I %S/Inputs -DTEST_CLANG_OPTIONS_MERGE %s | %FileCheck %s --check-prefix CHECK-COFF + +// CHECK-COFF-MERGE-DAG: !llvm.linker.options = !{ +// CHECK-COFF-MERGE-DAG: !{{[0-9]+}} = !{!"/DEFAULTLIB:empty.lib"} +// CHECK-COFF-MERGE-DAG: !{{[0-9]+}} = !{!"/DEFAULTLIB:module.lib"} +// CHECK-COFF-MERGE-DAG: !{{[0-9]+}} = !{!"/DEFAULTLIB:transitive-module.lib"} +// CHECK-COFF-MERGE-DAG: !{{[0-9]+}} = !{!"/DEFAULTLIB:autolink-module-map-link.lib"} + + +#if TEST_CLANG_OPTIONS_MERGE +import AutolinkElfCPragma +import AutolinkModuleMapLink +#endif +