diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a907b1c54daf..e173b3a18df27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -975,6 +975,8 @@ endif() # Which default linker to use. Prefer LLVM_USE_LINKER if it set, otherwise use # our own defaults. This should only be possible in a unified (not stand alone) # build environment. +include(GoldVersion) + if(LLVM_USE_LINKER) set(SWIFT_USE_LINKER_default "${LLVM_USE_LINKER}") elseif(SWIFT_HOST_VARIANT_SDK STREQUAL "ANDROID") @@ -984,7 +986,17 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND NOT CMAKE_HOST_SYSTEM_NAME STREQ elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") set(SWIFT_USE_LINKER_default "") else() - set(SWIFT_USE_LINKER_default "gold") + get_gold_version(gold_version) + if(NOT gold_version) + message(STATUS "GNU Gold not found; using lld instead") + set(SWIFT_USE_LINKER_default "lld") + elseif(gold_version VERSION_LESS "2.36") + message(STATUS "GNU Gold is too old (${gold_version}); using lld instead") + set(SWIFT_USE_LINKER_default "lld") + else() + message(STATUS "Using GNU Gold ${gold_version}") + set(SWIFT_USE_LINKER_default "gold") + endif() endif() set(SWIFT_USE_LINKER ${SWIFT_USE_LINKER_default} CACHE STRING "Build Swift with a non-default linker") diff --git a/cmake/modules/GoldVersion.cmake b/cmake/modules/GoldVersion.cmake new file mode 100644 index 0000000000000..b99f586c47424 --- /dev/null +++ b/cmake/modules/GoldVersion.cmake @@ -0,0 +1,18 @@ +# Find the version of ld.gold, if installed. +# +# Versions prior to 2.36 break Swift programs because they won't coalesce +# sections with different SHF_GNU_RETAIN flags. +function(get_gold_version result_var_name) + find_program(gold_executable "ld.gold") + if(gold_executable) + execute_process( + COMMAND "${gold_executable}" "--version" + COMMAND "head" "-n" "1" + COMMAND "sed" "-e" "s/^.* (\\([^)]*\\)).*$/\\1/g;s/.* \\([0-9][0-9]*\\(\\.[0-9][0-9]*\\)*\\).*/\\1/g" + OUTPUT_VARIABLE gold_version + OUTPUT_STRIP_TRAILING_WHITESPACE) + set("${result_var_name}" "${gold_version}" PARENT_SCOPE) + else() + set("${result_var_name}" "" PARENT_SCOPE) + endif() +endfunction() diff --git a/include/swift/RemoteInspection/ReflectionContext.h b/include/swift/RemoteInspection/ReflectionContext.h index 178152ef35b87..07c9982030e89 100644 --- a/include/swift/RemoteInspection/ReflectionContext.h +++ b/include/swift/RemoteInspection/ReflectionContext.h @@ -242,7 +242,7 @@ class ReflectionContext auto Buf = this->getReader().readBytes(ImageStart, sizeof(typename T::Header)); if (!Buf) - return false; + return {}; auto Header = reinterpret_cast(Buf.get()); assert(Header->magic == T::MagicNumber && "invalid MachO file"); @@ -262,7 +262,7 @@ class ReflectionContext RemoteAddress(CmdStartAddress.getAddressData() + Offset), SegmentCmdHdrSize); if (!CmdBuf) - return false; + return {}; auto CmdHdr = reinterpret_cast(CmdBuf.get()); if (strncmp(CmdHdr->segname, "__TEXT", sizeof(CmdHdr->segname)) == 0) { TextCommand = CmdHdr; @@ -274,7 +274,7 @@ class ReflectionContext // No __TEXT segment, bail out. if (!TextCommand) - return false; + return {}; // Find the load command offset. auto loadCmdOffset = ImageStart.getAddressData() + Offset + sizeof(typename T::Header); @@ -284,7 +284,7 @@ class ReflectionContext auto LoadCmdBuf = this->getReader().readBytes( RemoteAddress(LoadCmdAddress), sizeof(typename T::SegmentCmd)); if (!LoadCmdBuf) - return false; + return {}; auto LoadCmd = reinterpret_cast(LoadCmdBuf.get()); // The sections start immediately after the load command. @@ -294,7 +294,7 @@ class ReflectionContext auto Sections = this->getReader().readBytes( RemoteAddress(SectAddress), NumSect * sizeof(typename T::Section)); if (!Sections) - return false; + return {}; auto Slide = ImageStart.getAddressData() - TextCommand->vmaddr; auto SectionsBuf = reinterpret_cast(Sections.get()); @@ -346,7 +346,7 @@ class ReflectionContext ReflStrMdSec.first == nullptr && ConformMdSec.first == nullptr && MPEnumMdSec.first == nullptr) - return false; + return {}; ReflectionInfo info = {{FieldMdSec.first, FieldMdSec.second}, {AssocTySec.first, AssocTySec.second}, @@ -371,7 +371,7 @@ class ReflectionContext RemoteAddress(CmdStartAddress.getAddressData() + Offset), SegmentCmdHdrSize); if (!CmdBuf) - return false; + return {}; auto CmdHdr = reinterpret_cast(CmdBuf.get()); // Look for any segment name starting with __DATA or __AUTH. if (strncmp(CmdHdr->segname, "__DATA", 6) == 0 || @@ -398,7 +398,7 @@ class ReflectionContext auto DOSHdrBuf = this->getReader().readBytes( ImageStart, sizeof(llvm::object::dos_header)); if (!DOSHdrBuf) - return false; + return {}; auto DOSHdr = reinterpret_cast(DOSHdrBuf.get()); auto COFFFileHdrAddr = ImageStart.getAddressData() + @@ -408,7 +408,7 @@ class ReflectionContext auto COFFFileHdrBuf = this->getReader().readBytes( RemoteAddress(COFFFileHdrAddr), sizeof(llvm::object::coff_file_header)); if (!COFFFileHdrBuf) - return false; + return {}; auto COFFFileHdr = reinterpret_cast( COFFFileHdrBuf.get()); @@ -419,7 +419,7 @@ class ReflectionContext RemoteAddress(SectionTableAddr), sizeof(llvm::object::coff_section) * COFFFileHdr->NumberOfSections); if (!SectionTableBuf) - return false; + return {}; auto findCOFFSectionByName = [&](llvm::StringRef Name) -> std::pair, uint64_t> { @@ -481,7 +481,7 @@ class ReflectionContext ReflStrMdSec.first == nullptr && ConformMdSec.first == nullptr && MPEnumMdSec.first == nullptr) - return false; + return {}; ReflectionInfo Info = {{FieldMdSec.first, FieldMdSec.second}, {AssocTySec.first, AssocTySec.second}, @@ -502,7 +502,7 @@ class ReflectionContext auto Buf = this->getReader().readBytes(ImageStart, sizeof(llvm::object::dos_header)); if (!Buf) - return false; + return {}; auto DOSHdr = reinterpret_cast(Buf.get()); @@ -512,10 +512,10 @@ class ReflectionContext Buf = this->getReader().readBytes(RemoteAddress(PEHeaderAddress), sizeof(llvm::COFF::PEMagic)); if (!Buf) - return false; + return {}; if (memcmp(Buf.get(), llvm::COFF::PEMagic, sizeof(llvm::COFF::PEMagic))) - return false; + return {}; return readPECOFFSections(ImageStart, PotentialModuleNames); } @@ -550,7 +550,7 @@ class ReflectionContext const void *Buf = readData(0, sizeof(typename T::Header)); if (!Buf) - return false; + return {}; auto Hdr = reinterpret_cast(Buf); assert(Hdr->getFileClass() == T::ELFClass && "invalid ELF file class"); @@ -560,9 +560,9 @@ class ReflectionContext uint16_t SectionEntrySize = Hdr->e_shentsize; if (sizeof(typename T::Section) > SectionEntrySize) - return false; + return {}; if (SectionHdrNumEntries == 0) - return false; + return {}; // Collect all the section headers, we need them to look up the // reflection sections (by name) and the string table. @@ -573,7 +573,7 @@ class ReflectionContext uint64_t Offset = SectionHdrAddress + (I * SectionEntrySize); auto SecBuf = readData(Offset, sizeof(typename T::Section)); if (!SecBuf) - return false; + return {}; const typename T::Section *SecHdr = reinterpret_cast(SecBuf); @@ -597,11 +597,34 @@ class ReflectionContext auto StrTabBuf = readData(StrTabOffset, StrTabSize); if (!StrTabBuf) - return false; + return {}; auto StrTab = reinterpret_cast(StrTabBuf); bool Error = false; + + // GNU ld and lld both merge sections regardless of the + // `SHF_GNU_RETAIN` flag. gold, presently, does not. The Swift + // compiler has a couple of switches that control whether or not + // the reflection sections are stripped; when these are enabled, + // it will _not_ set `SHF_GNU_RETAIN` on the reflection metadata + // sections. However, `swiftrt.o` contains declarations of the + // sections _with_ the `SHF_GNU_RETAIN` flag set, which makes + // sense since at runtime we will only expect to be able to access + // reflection metadata that we said we wanted to exist at runtime. + // + // The upshot is that when linking with gold, we can end up with + // two sets of reflection metadata sections. In a normal build + // where the compiler flags are the same for every linked object, + // we'll have *either* all retained *or* all un-retained sections + // (the retained sections will still exist because of `swiftrt.o`, + // but will be empty). The only time we'd expect to have a mix is + // where some code was compiled with a different setting of the + // metadata stripping flags. If that happens, the code below will + // simply add both sets of reflection sections, with the retained + // ones added first. + // + // See also https://sourceware.org/bugzilla/show_bug.cgi?id=31415. auto findELFSectionByName = - [&](llvm::StringRef Name) -> std::pair, uint64_t> { + [&](llvm::StringRef Name, bool Retained) -> std::pair, uint64_t> { if (Error) return {nullptr, 0}; // Now for all the sections, find their name. @@ -616,6 +639,8 @@ class ReflectionContext std::string SecName(Start, StringSize); if (SecName != Name) continue; + if (Retained != bool(Hdr->sh_flags & llvm::ELF::SHF_GNU_RETAIN)) + continue; RemoteAddress SecStart = RemoteAddress(ImageStart.getAddressData() + Hdr->sh_addr); auto SecSize = Hdr->sh_size; @@ -649,48 +674,86 @@ class ReflectionContext SwiftObjectFileFormatELF ObjectFileFormat; auto FieldMdSec = findELFSectionByName( - ObjectFileFormat.getSectionName(ReflectionSectionKind::fieldmd)); + ObjectFileFormat.getSectionName(ReflectionSectionKind::fieldmd), true); auto AssocTySec = findELFSectionByName( - ObjectFileFormat.getSectionName(ReflectionSectionKind::assocty)); + ObjectFileFormat.getSectionName(ReflectionSectionKind::assocty), true); auto BuiltinTySec = findELFSectionByName( - ObjectFileFormat.getSectionName(ReflectionSectionKind::builtin)); + ObjectFileFormat.getSectionName(ReflectionSectionKind::builtin), true); auto CaptureSec = findELFSectionByName( - ObjectFileFormat.getSectionName(ReflectionSectionKind::capture)); + ObjectFileFormat.getSectionName(ReflectionSectionKind::capture), true); auto TypeRefMdSec = findELFSectionByName( - ObjectFileFormat.getSectionName(ReflectionSectionKind::typeref)); + ObjectFileFormat.getSectionName(ReflectionSectionKind::typeref), true); auto ReflStrMdSec = findELFSectionByName( - ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr)); + ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr), true); auto ConformMdSec = findELFSectionByName( - ObjectFileFormat.getSectionName(ReflectionSectionKind::conform)); + ObjectFileFormat.getSectionName(ReflectionSectionKind::conform), true); auto MPEnumMdSec = findELFSectionByName( - ObjectFileFormat.getSectionName(ReflectionSectionKind::mpenum)); + ObjectFileFormat.getSectionName(ReflectionSectionKind::mpenum), true); if (Error) - return false; + return {}; + + std::optional result = {}; // We succeed if at least one of the sections is present in the // ELF executable. - if (FieldMdSec.first == nullptr && - AssocTySec.first == nullptr && - BuiltinTySec.first == nullptr && - CaptureSec.first == nullptr && - TypeRefMdSec.first == nullptr && - ReflStrMdSec.first == nullptr && - ConformMdSec.first == nullptr && - MPEnumMdSec.first == nullptr) - return false; + if (FieldMdSec.first || AssocTySec.first || BuiltinTySec.first || + CaptureSec.first || TypeRefMdSec.first || ReflStrMdSec.first || + ConformMdSec.first || MPEnumMdSec.first) { + ReflectionInfo info = {{FieldMdSec.first, FieldMdSec.second}, + {AssocTySec.first, AssocTySec.second}, + {BuiltinTySec.first, BuiltinTySec.second}, + {CaptureSec.first, CaptureSec.second}, + {TypeRefMdSec.first, TypeRefMdSec.second}, + {ReflStrMdSec.first, ReflStrMdSec.second}, + {ConformMdSec.first, ConformMdSec.second}, + {MPEnumMdSec.first, MPEnumMdSec.second}, + PotentialModuleNames}; + result = this->addReflectionInfo(info); + } - ReflectionInfo info = {{FieldMdSec.first, FieldMdSec.second}, - {AssocTySec.first, AssocTySec.second}, - {BuiltinTySec.first, BuiltinTySec.second}, - {CaptureSec.first, CaptureSec.second}, - {TypeRefMdSec.first, TypeRefMdSec.second}, - {ReflStrMdSec.first, ReflStrMdSec.second}, - {ConformMdSec.first, ConformMdSec.second}, - {MPEnumMdSec.first, MPEnumMdSec.second}, - PotentialModuleNames}; + // Also check for the non-retained versions of the sections; we'll + // only return a single reflection info ID if both are found (and it'll + // be the one for the retained sections if we have them), but we'll + // still add all the reflection information. + FieldMdSec = findELFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::fieldmd), false); + AssocTySec = findELFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::assocty), false); + BuiltinTySec = findELFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::builtin), false); + CaptureSec = findELFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::capture), false); + TypeRefMdSec = findELFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::typeref), false); + ReflStrMdSec = findELFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr), false); + ConformMdSec = findELFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::conform), false); + MPEnumMdSec = findELFSectionByName( + ObjectFileFormat.getSectionName(ReflectionSectionKind::mpenum), false); + + if (Error) + return {}; - return this->addReflectionInfo(info); + if (FieldMdSec.first || AssocTySec.first || BuiltinTySec.first || + CaptureSec.first || TypeRefMdSec.first || ReflStrMdSec.first || + ConformMdSec.first || MPEnumMdSec.first) { + ReflectionInfo info = {{FieldMdSec.first, FieldMdSec.second}, + {AssocTySec.first, AssocTySec.second}, + {BuiltinTySec.first, BuiltinTySec.second}, + {CaptureSec.first, CaptureSec.second}, + {TypeRefMdSec.first, TypeRefMdSec.second}, + {ReflStrMdSec.first, ReflStrMdSec.second}, + {ConformMdSec.first, ConformMdSec.second}, + {MPEnumMdSec.first, MPEnumMdSec.second}, + PotentialModuleNames}; + auto rid = this->addReflectionInfo(info); + if (!result) + result = rid; + } + + return result; } /// Parses metadata information from an ELF image. Because the Section @@ -746,7 +809,7 @@ class ReflectionContext // Read the first few bytes to look for a magic header. auto Magic = this->getReader().readBytes(ImageStart, sizeof(uint32_t)); if (!Magic) - return false; + return {}; uint32_t MagicWord; memcpy(&MagicWord, Magic.get(), sizeof(MagicWord)); diff --git a/lib/Driver/UnixToolChains.cpp b/lib/Driver/UnixToolChains.cpp index f6856c17e1639..be0472b98e25a 100644 --- a/lib/Driver/UnixToolChains.cpp +++ b/lib/Driver/UnixToolChains.cpp @@ -214,17 +214,6 @@ toolchains::GenericUnix::constructInvocation(const DynamicLinkJobAction &job, #else Arguments.push_back(context.Args.MakeArgString("-fuse-ld=" + Linker)); #endif - // Starting with lld 13, Swift stopped working with the lld --gc-sections - // implementation for ELF, unless -z nostart-stop-gc is also passed to lld: - // - // https://reviews.llvm.org/D96914 - if (Linker == "lld" || (Linker.length() > 5 && - Linker.substr(Linker.length() - 6) == "ld.lld")) { - Arguments.push_back("-Xlinker"); - Arguments.push_back("-z"); - Arguments.push_back("-Xlinker"); - Arguments.push_back("nostart-stop-gc"); - } } // Configure the toolchain. diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 819e4f084a724..099284e13b5bf 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -1030,15 +1030,6 @@ bool LinkInfo::isUsed(IRLinkage IRL) { /// /// This value must have a definition by the time the module is finalized. void IRGenModule::addUsedGlobal(llvm::GlobalValue *global) { - - // As of reviews.llvm.org/D97448 "ELF: Create unique SHF_GNU_RETAIN sections - // for llvm.used global objects" LLVM creates separate sections for globals in - // llvm.used on ELF. Therefore we use llvm.compiler.used on ELF instead. - if (TargetInfo.OutputObjectFormat == llvm::Triple::ELF) { - addCompilerUsedGlobal(global); - return; - } - LLVMUsed.push_back(global); } diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp index 5b412bbbc8142..4d425524519a4 100644 --- a/lib/IRGen/IRGen.cpp +++ b/lib/IRGen/IRGen.cpp @@ -137,6 +137,9 @@ swift::getIRTargetOptions(const IRGenOptions &Opts, ASTContext &Ctx) { auto *Clang = static_cast(Ctx.getClangModuleLoader()); + // Set UseInitArray appropriately. + TargetOpts.UseInitArray = Clang->getCodeGenOpts().UseInitArray; + // WebAssembly doesn't support atomics yet, see // https://github.com/apple/swift/issues/54533 for more details. if (Clang->getTargetInfo().getTriple().isOSBinFormatWasm()) @@ -1655,8 +1658,10 @@ void swift::createSwiftModuleObjectFile(SILModule &SILMod, StringRef Buffer, break; } } + IGM.addUsedGlobal(ASTSym); ASTSym->setSection(Section); ASTSym->setAlignment(llvm::MaybeAlign(serialization::SWIFTMODULE_ALIGNMENT)); + IGM.finalize(); ::performLLVM(Opts, Ctx.Diags, nullptr, nullptr, IGM.getModule(), IGM.TargetMachine.get(), OutputPath, Ctx.getOutputBackend(), Ctx.Stats); diff --git a/stdlib/public/runtime/SwiftRT-ELF-WASM.cpp b/stdlib/public/runtime/SwiftRT-ELF-WASM.cpp index b83a570631c48..032a97cd442e4 100644 --- a/stdlib/public/runtime/SwiftRT-ELF-WASM.cpp +++ b/stdlib/public/runtime/SwiftRT-ELF-WASM.cpp @@ -28,7 +28,7 @@ static constexpr const void *__dso_handle = nullptr; #if SWIFT_ENABLE_BACKTRACING // Drag in a symbol from the backtracer, to force the static linker to include // the code. -static const void *__backtraceRef __attribute__((used)) +static const void *__backtraceRef __attribute__((used, retain)) = (const void *)swift::runtime::backtrace::_swift_backtrace_isThunkFunction; #endif @@ -36,32 +36,45 @@ static const void *__backtraceRef __attribute__((used)) // by the linker. Otherwise, we may end up with undefined symbol references as // the linker table section was never constructed. #if defined(__ELF__) -# define DECLARE_EMPTY_METADATA_SECTION(name) __asm__("\t.section " #name ",\"a\"\n"); +# define DECLARE_EMPTY_METADATA_SECTION(name, attrs) __asm__("\t.section " #name ",\"" attrs "\"\n"); #elif defined(__wasm__) -# define DECLARE_EMPTY_METADATA_SECTION(name) __asm__("\t.section " #name ",\"R\",@\n"); +# define DECLARE_EMPTY_METADATA_SECTION(name, attrs) __asm__("\t.section " #name ",\"R\",@\n"); #endif -#define DECLARE_SWIFT_SECTION(name) \ - DECLARE_EMPTY_METADATA_SECTION(name) \ - __attribute__((__visibility__("hidden"),__aligned__(1))) extern const char __start_##name; \ - __attribute__((__visibility__("hidden"),__aligned__(1))) extern const char __stop_##name; +#define BOUNDS_VISIBILITY __attribute__((__visibility__("hidden"), \ + __aligned__(1))) + +#define DECLARE_BOUNDS(name) \ + BOUNDS_VISIBILITY extern const char __start_##name; \ + BOUNDS_VISIBILITY extern const char __stop_##name; + +#define DECLARE_SWIFT_SECTION(name) \ + DECLARE_EMPTY_METADATA_SECTION(name, "aR") \ + DECLARE_BOUNDS(name) + +// These may or may not be present, depending on compiler switches; it's +// worth calling them out as a result. +#define DECLARE_SWIFT_REFLECTION_SECTION(name) \ + DECLARE_SWIFT_SECTION(name) extern "C" { DECLARE_SWIFT_SECTION(swift5_protocols) DECLARE_SWIFT_SECTION(swift5_protocol_conformances) DECLARE_SWIFT_SECTION(swift5_type_metadata) -DECLARE_SWIFT_SECTION(swift5_typeref) -DECLARE_SWIFT_SECTION(swift5_reflstr) -DECLARE_SWIFT_SECTION(swift5_fieldmd) -DECLARE_SWIFT_SECTION(swift5_assocty) +DECLARE_SWIFT_REFLECTION_SECTION(swift5_fieldmd) +DECLARE_SWIFT_REFLECTION_SECTION(swift5_builtin) +DECLARE_SWIFT_REFLECTION_SECTION(swift5_assocty) +DECLARE_SWIFT_REFLECTION_SECTION(swift5_capture) +DECLARE_SWIFT_REFLECTION_SECTION(swift5_reflstr) +DECLARE_SWIFT_REFLECTION_SECTION(swift5_typeref) +DECLARE_SWIFT_REFLECTION_SECTION(swift5_mpenum) + DECLARE_SWIFT_SECTION(swift5_replace) DECLARE_SWIFT_SECTION(swift5_replac2) -DECLARE_SWIFT_SECTION(swift5_builtin) -DECLARE_SWIFT_SECTION(swift5_capture) -DECLARE_SWIFT_SECTION(swift5_mpenum) DECLARE_SWIFT_SECTION(swift5_accessible_functions) DECLARE_SWIFT_SECTION(swift5_runtime_attributes) + DECLARE_SWIFT_SECTION(swift5_tests) } diff --git a/test/Distributed/distributed_actor_accessor_section_elf.swift b/test/Distributed/distributed_actor_accessor_section_elf.swift index cbd90e42faff5..5839638940bf7 100644 --- a/test/Distributed/distributed_actor_accessor_section_elf.swift +++ b/test/Distributed/distributed_actor_accessor_section_elf.swift @@ -137,7 +137,7 @@ public distributed actor MyOtherActor { // CHECK-SAME: (ptr @"$s27distributed_actor_accessors12MyOtherActorC5emptyyyYaKFTETFTu" to i{{32|64}}) // CHECK-SAME: , section "swift5_accessible_functions", {{.*}} -// CHECK: @llvm.compiler.used = appending global [{{.*}} x ptr] [ +// CHECK: @llvm.used = appending global [{{.*}} x ptr] [ // CHECK-SAME: @"$s27distributed_actor_accessors7MyActorC7simple1yySiYaKFTEHF" // CHECK-SAME: @"$s27distributed_actor_accessors7MyActorC7simple2ySSSiYaKFTEHF" // CHECK-SAME: @"$s27distributed_actor_accessors7MyActorC7simple3ySiSSYaKFTEHF" diff --git a/test/Driver/link-time-opt.swift b/test/Driver/link-time-opt.swift index 8cc918e8cd833..78fe69495e77c 100644 --- a/test/Driver/link-time-opt.swift +++ b/test/Driver/link-time-opt.swift @@ -1,3 +1,5 @@ +// UNSUPPORTED: linker_overridden + // 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 @@ -14,7 +16,6 @@ // 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: -Xlinker -z -Xlinker nostart-stop-gc // CHECK-SIMPLE-THIN-linux-gnu-DAG: [[BITCODEFILE]] // CHECK-SIMPLE-THIN-linux-gnu-NOT: swift-autolink-extract @@ -36,7 +37,6 @@ // 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: -Xlinker -z -Xlinker nostart-stop-gc // CHECK-SIMPLE-FULL-linux-gnu-DAG: [[BITCODEFILE]] // CHECK-SIMPLE-FULL-linux-gnu-NOT: swift-autolink-extract diff --git a/test/Driver/static-archive.swift b/test/Driver/static-archive.swift index f2b7dbfc3d1c8..88bc477fb5845 100644 --- a/test/Driver/static-archive.swift +++ b/test/Driver/static-archive.swift @@ -1,3 +1,5 @@ +// UNSUPPORTED: linker_overridden + // RUN: %swiftc_driver -driver-print-jobs -target x86_64-apple-macosx10.9 -emit-library %s -module-name ARCHIVER -static 2>&1 | %FileCheck -check-prefix CHECK-MACOS %s // CHECK-MACOS: swift diff --git a/test/IRGen/ELF-remove-autolink-section.swift b/test/IRGen/ELF-remove-autolink-section.swift index cd2ac6c74e4ec..154ef5143bed9 100644 --- a/test/IRGen/ELF-remove-autolink-section.swift +++ b/test/IRGen/ELF-remove-autolink-section.swift @@ -12,7 +12,7 @@ print("Hi from Swift!") -// ELF: @llvm.compiler.used = {{.*}}ptr @_swift1_autolink_entries +// ELF: @llvm.used = {{.*}}ptr @_swift1_autolink_entries // SECTION: .swift1_autolink_entries // NOSECTION-NOT: .swift1_autolink_entries diff --git a/test/IRGen/autolink_elf.swift b/test/IRGen/autolink_elf.swift index 54331527822a3..e276db7a8a15c 100644 --- a/test/IRGen/autolink_elf.swift +++ b/test/IRGen/autolink_elf.swift @@ -10,5 +10,4 @@ import Empty // as used. // CHECK-DAG: @_swift1_autolink_entries = private constant [26 x i8] c"-lswiftEmpty\00-lanotherLib\00", section ".swift1_autolink_entries",{{.*}} align 8 -// CHECK-DAG: @llvm.compiler.used = appending global [{{.*}} x ptr] [{{.*}}ptr @_swift1_autolink_entries{{.*}}], section "llvm.metadata" - +// CHECK-DAG: @llvm.used = appending global [{{.*}} x ptr] [{{.*}}ptr @_swift1_autolink_entries{{.*}}], section "llvm.metadata" diff --git a/test/IRGen/objc_protocol_vars.sil b/test/IRGen/objc_protocol_vars.sil index 3a455384e77a1..020bfd1194dab 100644 --- a/test/IRGen/objc_protocol_vars.sil +++ b/test/IRGen/objc_protocol_vars.sil @@ -27,6 +27,5 @@ import Foundation } // CHECK-macho: @llvm.used = appending global [{{.*}}] [{{.*}}, ptr @"\01l_OBJC_LABEL_PROTOCOL_$__TtP18objc_protocol_vars1T_", ptr @"\01l_OBJC_PROTOCOL_REFERENCE_$__TtP18objc_protocol_vars1T_", {{.*}}], {{.*}} -// CHECK-elf: @llvm.compiler.used = appending global [{{.*}}] [{{.*}}, ptr @"\01l_OBJC_LABEL_PROTOCOL_$__TtP18objc_protocol_vars1T_", ptr @"\01l_OBJC_PROTOCOL_REFERENCE_$__TtP18objc_protocol_vars1T_", {{.*}}], {{.*}} +// CHECK-elf: @llvm.used = appending global [{{.*}}] [{{.*}}, ptr @"\01l_OBJC_LABEL_PROTOCOL_$__TtP18objc_protocol_vars1T_", ptr @"\01l_OBJC_PROTOCOL_REFERENCE_$__TtP18objc_protocol_vars1T_", {{.*}}], {{.*}} // CHECK-coff: @llvm.used = appending global [{{.*}}] [{{.*}}, ptr @"\01l_OBJC_LABEL_PROTOCOL_$__TtP18objc_protocol_vars1T_", ptr @"\01l_OBJC_PROTOCOL_REFERENCE_$__TtP18objc_protocol_vars1T_", {{.*}}], {{.*}} - diff --git a/test/IRGen/section_asm.swift b/test/IRGen/section_asm.swift index 673c9ac71c09f..4f8706aa8416c 100644 --- a/test/IRGen/section_asm.swift +++ b/test/IRGen/section_asm.swift @@ -1,4 +1,5 @@ -// RUN: %target-swift-frontend -enable-experimental-feature SymbolLinkageMarkers -primary-file %S/section.swift -S -parse-as-library | %FileCheck %s +// RUN: %target-swift-frontend -enable-experimental-feature SymbolLinkageMarkers -primary-file %S/section.swift -S -parse-as-library | %FileCheck --check-prefix CHECK%target-os-binfmt-elf %s + // REQUIRES: swift_in_compiler // UNSUPPORTED: CPU=wasm32 @@ -25,3 +26,27 @@ // CHECK: $s7section2g5SpySiGSgvp: // CHECK-NOT: .section // CHECK: $s7section8MyStructV7static0SivpZ: + +// CHECKELF: .section{{.*}}"__TEXT,__mysection","ax" +// CHECKELF-NOT: .section +// CHECKELF: $s7section3fooyyF: + +// CHECKELF: .section{{.*}}"__TEXT,__mysection","ax" +// CHECKELF-NOT: .section +// CHECKELF: $s7section8MyStructV3fooyyF: + +// CHECKELF: .section{{.*}}"__DATA,__mysection","aw" +// CHECKELF-NOT: .section +// CHECKELF: $s7section2g0Sivp: +// CHECKELF-NOT: .section +// CHECKELF: $s7section2g1Si_Sitvp: +// CHECKELF-NOT: .section +// CHECKELF: $s7section2g2Sbvp: +// CHECKELF: .section{{.*}}"__DATA,__mysection","awR" +// CHECKELF: $s7section2g3Sbvp: +// CHECKELF: .section{{.*}}"__DATA,__mysection","aw" +// CHECKELF: $s7section2g4SpySiGSgvp: +// CHECKELF-NOT: .section +// CHECKELF: $s7section2g5SpySiGSgvp: +// CHECKELF-NOT: .section +// CHECKELF: $s7section8MyStructV7static0SivpZ: diff --git a/test/IRGen/unused.sil b/test/IRGen/unused.sil index a03a3dad630ef..6802916f301d0 100644 --- a/test/IRGen/unused.sil +++ b/test/IRGen/unused.sil @@ -56,7 +56,7 @@ bb0(%0 : $Int32, %1 : $UnsafeMutablePointer> // CHECK-elf: @"\01l_entry_point" = private constant { i32, i32 } { i32 trunc (i64 sub (i64 ptrtoint (ptr @main to i64), i64 ptrtoint (ptr @"\01l_entry_point" to i64)) to i32), i32 0 }, section "swift5_entry", align 4 // CHECK-macho: @llvm.used = appending global [4 x ptr] [ptr @frieda, ptr @main, ptr @"\01l_entry_point", ptr @__swift_reflection_version], section "llvm.metadata" -// CHECK-elf: @llvm.compiler.used = appending global [5 x ptr] [ptr @frieda, ptr @main, ptr @"\01l_entry_point", ptr @__swift_reflection_version, ptr @_swift1_autolink_entries], section "llvm.metadata" +// CHECK-elf: @llvm.used = appending global [5 x ptr] [ptr @frieda, ptr @main, ptr @"\01l_entry_point", ptr @__swift_reflection_version, ptr @_swift1_autolink_entries], section "llvm.metadata" // CHECK: define linkonce_odr hidden swiftcc void @qux() // CHECK: define hidden swiftcc void @fred() diff --git a/test/Interpreter/llvm_link_time_opt.swift b/test/Interpreter/llvm_link_time_opt.swift index 7f60f66770109..04a602236ee6e 100644 --- a/test/Interpreter/llvm_link_time_opt.swift +++ b/test/Interpreter/llvm_link_time_opt.swift @@ -10,6 +10,8 @@ // loaded too late"). // REQUIRES: no_asan +// UNSUPPORTED: linker_overridden + // RUN: %empty-directory(%t) // RUN: %use_just_built_liblto %target-swiftc_driver -emit-library -static -lto=llvm-full %lto_flags -emit-module %S/Inputs/lto/module1.swift -working-directory %t // RUN: %use_just_built_liblto %target-swiftc_driver -lto=llvm-full %lto_flags %s -I%t -L%t -lmodule1 -module-name main -o %t/main diff --git a/test/LinkerSections/function_sections.swift b/test/LinkerSections/function_sections.swift index a2cf2a39a5c34..f941adec11a39 100644 --- a/test/LinkerSections/function_sections.swift +++ b/test/LinkerSections/function_sections.swift @@ -1,10 +1,13 @@ // REQUIRES: OS=linux-gnu || OS=freebsd // RUN: %empty-directory(%t) // RUN: %target-build-swift -Xfrontend -function-sections -emit-module -emit-library -static -parse-stdlib %S/Inputs/FunctionSections.swift -// RUN: %target-build-swift -Xlinker --gc-sections -Xlinker -Map=%t/../../FunctionSections.map -I%t/../.. -L%t/../.. -lFunctionSections %S/Inputs/FunctionSectionsUse.swift -// RUN: %FileCheck %s < %t/../../FunctionSections.map +// RUN: %target-build-swift -Xlinker -v -Xlinker --gc-sections -Xlinker -Map=%t/../../FunctionSections.map -I%t/../.. -L%t/../.. -lFunctionSections %S/Inputs/FunctionSectionsUse.swift 2>&1 | sed 's/.*\(gold\|LLD\).*/\1/g' | tr "[:lower:]" "[:upper:]" > %t/../../Linker.txt +// RUN: %FileCheck --check-prefix $(cat %t/../../Linker.txt) %s < %t/../../FunctionSections.map -// CHECK: Discarded input sections -// CHECK: .text.$s16FunctionSections5func2yyF -// CHECK: Memory map -// CHECK: .text.$s16FunctionSections5func1yyF +// GOLD: Discarded input sections +// GOLD: .text.$s16FunctionSections5func2yyF +// GOLD: Memory map +// GOLD: .text.$s16FunctionSections5func1yyF + +// LLD: .text.$s16FunctionSections5func1yyF +// LLD-NOT: .text.$s16FunctionSections5func2yyF diff --git a/test/embedded/internalize-no-stdlib.swift b/test/embedded/internalize-no-stdlib.swift index 97d5d4662b77c..8473d2352d202 100644 --- a/test/embedded/internalize-no-stdlib.swift +++ b/test/embedded/internalize-no-stdlib.swift @@ -26,7 +26,7 @@ public func main() { } // CHECK-ELF: @_swift1_autolink_entries = -// CHECK-ELF: @llvm.compiler.used = appending global [1 x ptr] [ptr @_swift1_autolink_entries], section "llvm.metadata" +// CHECK-ELF: @llvm.used = appending global [1 x ptr] [ptr @_swift1_autolink_entries], section "llvm.metadata" // CHECK-ELF-NOT: @llvm.used // CHECK-MACHO-NOT: @llvm.compiler.used diff --git a/test/embedded/once.swift b/test/embedded/once.swift index 4291fa4cfd9ab..3a21f9a7ca112 100644 --- a/test/embedded/once.swift +++ b/test/embedded/once.swift @@ -6,6 +6,7 @@ // REQUIRES: executable_test // REQUIRES: optimized_stdlib // REQUIRES: OS=macosx || OS=linux-gnu +// UNSUPPORTED: linker_overridden // For LTO, the linker dlopen()'s the libLTO library, which is a scenario that // ASan cannot work in ("Interceptors are not working, AddressSanitizer is diff --git a/test/lit.cfg b/test/lit.cfg index f2f2f391f40be..e8e91c1582eba 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -542,6 +542,11 @@ config.swift_driver_test_options += os.environ.get('SWIFT_DRIVER_TEST_OPTIONS', config.swift_ide_test_test_options += os.environ.get('SWIFT_IDE_TEST_TEST_OPTIONS', '') config.sil_test_options = os.environ.get('SIL_TEST_OPTIONS', '') +# Check if we overrode the linker; if we do, set a feature to say that, which +# lets us disable tests that rely on the driver choosing the linker. +if re.search(r'(?:^|[ \t])-use-ld=[^ \t]*', config.swift_driver_test_options): + config.available_features.add('linker_overridden') + config.clang_module_cache_path = make_path(config.swift_test_results_dir, "clang-module-cache") shutil.rmtree(config.clang_module_cache_path, ignore_errors=True) mcp_opt = "-module-cache-path %s" % shell_quote(config.clang_module_cache_path) @@ -1022,6 +1027,46 @@ if run_os in ( ): target_mandates_stable_abi = "TRUE" config.available_features.add('swift_only_stable_abi') + +if run_os in ('macosx', 'ios', 'maccatalyst', 'tvos', 'watchos', 'xros'): + target_os_family = 'DARWIN' + target_os_binfmt = 'MACH-O' +elif run_os in ('windows-cygnus', 'windows-gnu', 'windows-msvc'): + target_os_family = 'WINDOWS' + target_os_binfmt = 'PE-COFF' +elif run_os in ('linux-gnu', 'linux-gnueabihf', 'linux-android', 'linux-androideabi'): + target_os_family = 'LINUX' + target_os_binfmt = 'ELF' +elif run_os in ('freebsd', 'openbsd'): + target_os_family = 'BSD' + target_os_binfmt = 'ELF' +else: + target_os_family = 'UNKNOWN' + target_os_binfmt = 'UNKNOWN' + +config.available_features.add('OS_FAMILY={}'.format(target_os_family.lower())) +config.available_features.add('OS_BINFMT={}'.format(target_os_binfmt.lower())) + +for family in ('DARWIN', 'WINDOWS', 'LINUX', 'BSD', 'UNKNOWN'): + if family == target_os_family: + subst = family + else: + subst = "" + config.substitutions.append( + ('%target-os-family-{}'.format(family.lower()), subst) + ) +config.substitutions.append(('%target-os-family', target_os_family)) + +for binfmt in ('MACH-O', 'PE-COFF', 'ELF', 'UNKNOWN'): + if binfmt == target_os_binfmt: + subst = binfmt + else: + subst = "" + config.substitutions.append( + ('%target-os-binfmt-{}'.format(binfmt.lower()), subst) + ) +config.substitutions.append(('%target-os-binfmt', target_os_binfmt)) + config.substitutions.append(('%target-os-abi', target_os_abi)) config.substitutions.append(('%target-os-is-maccatalyst', target_os_is_maccatalyst)) config.substitutions.append(('%target-mandates-stable-abi', diff --git a/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake b/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake index 3fabb4b510b27..00fc913fe8682 100644 --- a/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake +++ b/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake @@ -115,11 +115,14 @@ function(add_sourcekit_swift_runtime_link_flags target path HAS_SWIFT_MODULES) else() set(host_lib_dir "${SWIFTLIB_DIR}/${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}") endif() + set(host_lib_arch_dir "${host_lib_dir}/${SWIFT_HOST_VARIANT_ARCH}") + set(swiftrt "${host_lib_arch_dir}/swiftrt${CMAKE_C_OUTPUT_EXTENSION}") target_link_libraries(${target} PRIVATE ${swiftrt}) target_link_libraries(${target} PRIVATE "swiftCore") target_link_directories(${target} PRIVATE ${host_lib_dir}) + target_link_directories(${target} PRIVATE ${host_lib_arch_dir}) file(RELATIVE_PATH relative_rtlib_path "${path}" "${SWIFTLIB_DIR}/${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}") list(APPEND RPATH_LIST "$ORIGIN/${relative_rtlib_path}")