Skip to content

Commit

Permalink
[Autolink Extract] Filter out common Swift libraries from being linke…
Browse files Browse the repository at this point in the history
…d more than once

A partial solution to swiftlang#58380
  • Loading branch information
artemcm committed May 26, 2022
1 parent b4e3d05 commit 5636d0b
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 9 deletions.
46 changes: 37 additions & 9 deletions lib/DriverTool/autolink_extract_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ class AutolinkExtractInvocation {
static bool
extractLinkerFlagsFromObjectFile(const llvm::object::ObjectFile *ObjectFile,
std::vector<std::string> &LinkerFlags,
std::unordered_map<std::string, bool> &SwiftRuntimeLibraries,
CompilerInstance &Instance) {
// Search for the section we hold autolink entries in
for (auto &Section : ObjectFile->sections()) {
Expand Down Expand Up @@ -140,8 +141,13 @@ extractLinkerFlagsFromObjectFile(const llvm::object::ObjectFile *ObjectFile,
llvm::SmallVector<llvm::StringRef, 4> SplitFlags;
SectionData->split(SplitFlags, llvm::StringRef("\0", 1), -1,
/*KeepEmpty=*/false);
for (const auto &Flag : SplitFlags)
LinkerFlags.push_back(Flag.str());
for (const auto &Flag : SplitFlags) {
auto RuntimeLibEntry = SwiftRuntimeLibraries.find(Flag.str());
if (RuntimeLibEntry == SwiftRuntimeLibraries.end())
LinkerFlags.emplace_back(Flag.str());
else
RuntimeLibEntry->second = true;
}
}
}
return false;
Expand All @@ -153,6 +159,7 @@ extractLinkerFlagsFromObjectFile(const llvm::object::ObjectFile *ObjectFile,
static bool
extractLinkerFlagsFromObjectFile(const llvm::object::WasmObjectFile *ObjectFile,
std::vector<std::string> &LinkerFlags,
std::unordered_map<std::string, bool> &SwiftRuntimeLibraries,
CompilerInstance &Instance) {
// Search for the data segment we hold autolink entries in
for (const llvm::object::WasmSegment &Segment : ObjectFile->dataSegments()) {
Expand All @@ -164,8 +171,13 @@ extractLinkerFlagsFromObjectFile(const llvm::object::WasmObjectFile *ObjectFile,
llvm::SmallVector<llvm::StringRef, 4> SplitFlags;
SegmentData.split(SplitFlags, llvm::StringRef("\0", 1), -1,
/*KeepEmpty=*/false);
for (const auto &Flag : SplitFlags)
LinkerFlags.push_back(Flag.str());
for (const auto &Flag : SplitFlags) {
auto RuntimeLibEntry = SwiftRuntimeLibraries.find(Flag.str());
if (RuntimeLibEntry == SwiftRuntimeLibraries.end())
LinkerFlags.emplace_back(Flag.str());
else
RuntimeLibEntry->second = true;
}
}
}
return false;
Expand All @@ -178,12 +190,13 @@ extractLinkerFlagsFromObjectFile(const llvm::object::WasmObjectFile *ObjectFile,
static bool extractLinkerFlags(const llvm::object::Binary *Bin,
CompilerInstance &Instance,
StringRef BinaryFileName,
std::vector<std::string> &LinkerFlags) {
std::vector<std::string> &LinkerFlags,
std::unordered_map<std::string, bool> &SwiftRuntimeLibraries) {
if (auto *ObjectFile = llvm::dyn_cast<llvm::object::ELFObjectFileBase>(Bin)) {
return extractLinkerFlagsFromObjectFile(ObjectFile, LinkerFlags, Instance);
return extractLinkerFlagsFromObjectFile(ObjectFile, LinkerFlags, SwiftRuntimeLibraries, Instance);
} else if (auto *ObjectFile =
llvm::dyn_cast<llvm::object::WasmObjectFile>(Bin)) {
return extractLinkerFlagsFromObjectFile(ObjectFile, LinkerFlags, Instance);
return extractLinkerFlagsFromObjectFile(ObjectFile, LinkerFlags, SwiftRuntimeLibraries, Instance);
} else if (auto *Archive = llvm::dyn_cast<llvm::object::Archive>(Bin)) {
llvm::Error Error = llvm::Error::success();
for (const auto &Child : Archive->children(Error)) {
Expand All @@ -197,7 +210,7 @@ static bool extractLinkerFlags(const llvm::object::Binary *Bin,
return true;
}
if (extractLinkerFlags(ChildBinary->get(), Instance, BinaryFileName,
LinkerFlags)) {
LinkerFlags, SwiftRuntimeLibraries)) {
return true;
}
}
Expand Down Expand Up @@ -229,6 +242,15 @@ int autolink_extract_main(ArrayRef<const char *> Args, const char *Argv0,

std::vector<std::string> LinkerFlags;

// Keep track of whether we've already added the common
// Swift libraries that ususally have autolink directives
// in most object fiels
std::unordered_map<std::string, bool> SwiftRuntimeLibraries = {
{"-lswiftSwiftOnoneSupport", false},
{"-lswiftCore", false},
{"-lswift_Concurrency", false},
};

// Extract the linker flags from the objects.
for (const auto &BinaryFileName : Invocation.getInputFilenames()) {
auto BinaryOwner = llvm::object::createBinary(BinaryFileName);
Expand All @@ -245,7 +267,7 @@ int autolink_extract_main(ArrayRef<const char *> Args, const char *Argv0,
}

if (extractLinkerFlags(BinaryOwner->getBinary(), Instance, BinaryFileName,
LinkerFlags)) {
LinkerFlags, SwiftRuntimeLibraries)) {
return 1;
}
}
Expand All @@ -264,5 +286,11 @@ int autolink_extract_main(ArrayRef<const char *> Args, const char *Argv0,
OutOS << Flag << '\n';
}

for (const auto &RuntimeLib : SwiftRuntimeLibraries) {
if (RuntimeLib.second)
OutOS << RuntimeLib.first << '\n';
}


return 0;
}
5 changes: 5 additions & 0 deletions test/AutolinkExtract/import.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@
// RUN: %target-swiftc_driver -emit-module -emit-module-path %t/empty.swiftmodule -module-name empty -module-link-name empty %S/empty.swift
// RUN: %target-swiftc_driver -c %s -I %t -o %t/import_experimental.o
// RUN: %target-swift-autolink-extract %t/import_experimental.o -o - | %FileCheck --check-prefix CHECK-%target-object-format %s
// RUN: %target-swiftc_driver -c %s -I %t -o %t/import_experimental_again.o
// RUN: %target-swift-autolink-extract %t/import_experimental.o %t/import_experimental_again.o -o - | %FileCheck --check-prefix CHECK-%target-object-format %s
// RUN: %target-swift-autolink-extract %t/import_experimental.o %t/import_experimental_again.o -o - | %FileCheck --check-prefix UNIQUE %s

// REQUIRES: autolink-extract

// UNIQUE-COUNT-1: -lswiftCore

// CHECK-elf-DAG: -lswiftCore
// CHECK-elf-DAG: -lempty

Expand Down

0 comments on commit 5636d0b

Please sign in to comment.