1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

llvm-link: Add support for archive files as inputs

This patch adds support for archive files as inputs to llvm-link. One
of the use-cases is for OpenMP, where device specific libraries need
to be extracted from libraries containing bundled object files. The
clang-offload-bundler will support extracting these archives, which
will be passed into llvm-link, see https://reviews.llvm.org/D80816.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D81109
This commit is contained in:
Jan Sjodin 2020-06-22 13:04:12 -04:00
parent 6794d96976
commit 1e6d1b7612
7 changed files with 121 additions and 1 deletions

View File

@ -0,0 +1,6 @@
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
define void @f() {
entry:
ret void
}

View File

@ -0,0 +1,6 @@
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
define void @g() {
entry:
ret void
}

View File

@ -0,0 +1,6 @@
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
define void @h() {
entry:
ret void
}

View File

@ -0,0 +1,7 @@
# RUN: cp %S/Inputs/f.ll %t.fg.a
# RUN: not llvm-link %S/Inputs/h.ll %t.fg.a -o %t.linked.bc 2>&1 | FileCheck %s
# RUN: rm -f %t.fg.a
# RUN: rm -f %t.linked.bc
# CHECK: file too small to be an archive

View File

@ -0,0 +1,17 @@
# RUN: llvm-as %S/Inputs/f.ll -o %t.f.bc
# RUN: llvm-as %S/Inputs/g.ll -o %t.g.bc
# RUN: llvm-ar cr %t.fg.a %t.f.bc %t.g.bc
# RUN: llvm-ar cr %t.empty.a
# RUN: llvm-link %S/Inputs/h.ll %t.fg.a %t.empty.a -o %t.linked.bc
# RUN: llvm-nm %t.linked.bc | FileCheck %s
# RUN: rm -f %t.f.bc
# RUN: rm -f %t.g.bc
# RUN: rm -f %t.fg.a
# RUN: rm -f %t.empty.a
# RUN: rm -f %t.linked.bc
# CHECK: -------- T f
# CHECK: -------- T g
# CHECK: -------- T h

View File

@ -0,0 +1,7 @@
# RUN: llvm-ar cr %t.fg.a %S/Inputs/f.ll llvm-as %S/Inputs/g.ll
# RUN: not llvm-link %S/Inputs/h.ll %t.fg.a -o %t.linked.bc 2>&1 | FileCheck %s
# RUN: rm -f %t.fg.a
# RUN: rm -f %t.linked.bc
# CHECK: error: member of archive is not a bitcode file

View File

@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/Object/Archive.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Bitcode/BitcodeWriter.h"
@ -139,6 +140,73 @@ static std::unique_ptr<Module> loadFile(const char *argv0,
return Result;
}
static std::unique_ptr<Module> loadArFile(const char *Argv0,
const std::string &ArchiveName,
LLVMContext &Context, Linker &L,
unsigned OrigFlags,
unsigned ApplicableFlags) {
std::unique_ptr<Module> Result(new Module("ArchiveModule", Context));
if (Verbose)
errs() << "Reading library archive file '" << ArchiveName
<< "' to memory\n";
ErrorOr<std::unique_ptr<MemoryBuffer>> Buf =
MemoryBuffer::getFile(ArchiveName, -1, false);
ExitOnErr(errorCodeToError(Buf.getError()));
Error Err = Error::success();
object::Archive Archive(Buf.get()->getMemBufferRef(), Err);
ExitOnErr(std::move(Err));
for (const object::Archive::Child &C : Archive.children(Err)) {
Expected<StringRef> Ename = C.getName();
if (Error E = Ename.takeError()) {
errs() << Argv0 << ": ";
WithColor::error()
<< " failed to read name of archive member"
<< ArchiveName << "'\n";
return nullptr;
};
std::string ChildName = Ename.get().str();
if (Verbose)
errs() << "Parsing member '" << ChildName
<< "' of archive library to module.\n";
SMDiagnostic ParseErr;
Expected<MemoryBufferRef> MemBuf = C.getMemoryBufferRef();
if (Error E = MemBuf.takeError()) {
errs() << Argv0 << ": ";
WithColor::error() << " loading memory for member '" << ChildName
<< "' of archive library failed'" << ArchiveName
<< "'\n";
return nullptr;
};
if (!isBitcode(reinterpret_cast<const unsigned char *>
(MemBuf.get().getBufferStart()),
reinterpret_cast<const unsigned char *>
(MemBuf.get().getBufferEnd()))) {
errs() << Argv0 << ": ";
WithColor::error() << " member of archive is not a bitcode file: '"
<< ChildName << "'\n";
return nullptr;
}
std::unique_ptr<Module> M = parseIR(MemBuf.get(), ParseErr, Context);
if (!M.get()) {
errs() << Argv0 << ": ";
WithColor::error() << " parsing member '" << ChildName
<< "' of archive library failed'" << ArchiveName
<< "'\n";
return nullptr;
}
if (Verbose)
errs() << "Linking member '" << ChildName << "' of archive library.\n";
if (L.linkModules(*Result, std::move(M), ApplicableFlags))
return nullptr;
ApplicableFlags = OrigFlags;
} // end for each child
ExitOnErr(std::move(Err));
return Result;
}
namespace {
/// Helper to load on demand a Module from file and cache it for subsequent
@ -281,7 +349,10 @@ static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L,
// Similar to some flags, internalization doesn't apply to the first file.
bool InternalizeLinkedSymbols = false;
for (const auto &File : Files) {
std::unique_ptr<Module> M = loadFile(argv0, File, Context);
std::unique_ptr<Module> M =
(llvm::sys::path::extension(File) == ".a")
? loadArFile(argv0, File, Context, L, Flags, ApplicableFlags)
: loadFile(argv0, File, Context);
if (!M.get()) {
errs() << argv0 << ": ";
WithColor::error() << " loading file '" << File << "'\n";