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:
parent
6794d96976
commit
1e6d1b7612
6
test/tools/llvm-link/Inputs/f.ll
Normal file
6
test/tools/llvm-link/Inputs/f.ll
Normal 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
|
||||
}
|
6
test/tools/llvm-link/Inputs/g.ll
Normal file
6
test/tools/llvm-link/Inputs/g.ll
Normal 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
|
||||
}
|
6
test/tools/llvm-link/Inputs/h.ll
Normal file
6
test/tools/llvm-link/Inputs/h.ll
Normal 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
|
||||
}
|
7
test/tools/llvm-link/archive-bad.ll
Normal file
7
test/tools/llvm-link/archive-bad.ll
Normal 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
|
17
test/tools/llvm-link/archive.ll
Normal file
17
test/tools/llvm-link/archive.ll
Normal 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
|
7
test/tools/llvm-link/archivell.ll
Normal file
7
test/tools/llvm-link/archivell.ll
Normal 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
|
@ -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";
|
||||
|
Loading…
x
Reference in New Issue
Block a user