[llvm] 66b4095 - llvm-link: Add support for archive files as inputs

Richard Smith via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 14 17:08:15 PDT 2020


Fixed in f49edafd9abf75aaa7d9254c345026620e69b5ce. Please double-check
that's what you intended.

On Tue, 14 Jul 2020 at 15:29, Richard Smith <richard at metafoo.co.uk> wrote:

> On Tue, 14 Jul 2020 at 12:32, Jan Sjodin via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
>>
>> Author: Jan Sjodin
>> Date: 2020-07-14T15:30:59-04:00
>> New Revision: 66b409582a1d349a3ce5480237aeab92dd5ebde1
>>
>> URL:
>> https://github.com/llvm/llvm-project/commit/66b409582a1d349a3ce5480237aeab92dd5ebde1
>> DIFF:
>> https://github.com/llvm/llvm-project/commit/66b409582a1d349a3ce5480237aeab92dd5ebde1.diff
>>
>> LOG: 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
>>
>> Added:
>>     llvm/test/tools/llvm-link/Inputs/f.ll
>>     llvm/test/tools/llvm-link/Inputs/g.ll
>>     llvm/test/tools/llvm-link/Inputs/h.ll
>>     llvm/test/tools/llvm-link/archive-bad.ll
>>     llvm/test/tools/llvm-link/archive.ll
>>     llvm/test/tools/llvm-link/archivell.ll
>>
>> Modified:
>>     llvm/tools/llvm-link/llvm-link.cpp
>>
>> Removed:
>>
>>
>>
>>
>> ################################################################################
>> diff  --git a/llvm/test/tools/llvm-link/Inputs/f.ll
>> b/llvm/test/tools/llvm-link/Inputs/f.ll
>> new file mode 100644
>> index 000000000000..a7cdacea82fb
>> --- /dev/null
>> +++ b/llvm/test/tools/llvm-link/Inputs/f.ll
>> @@ -0,0 +1,6 @@
>> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> +
>> +define void @f() {
>> +entry:
>> +  ret void
>> +}
>>
>> diff  --git a/llvm/test/tools/llvm-link/Inputs/g.ll
>> b/llvm/test/tools/llvm-link/Inputs/g.ll
>> new file mode 100644
>> index 000000000000..b81de922b4da
>> --- /dev/null
>> +++ b/llvm/test/tools/llvm-link/Inputs/g.ll
>> @@ -0,0 +1,6 @@
>> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> +
>> +define void @g() {
>> +entry:
>> +  ret void
>> +}
>>
>> diff  --git a/llvm/test/tools/llvm-link/Inputs/h.ll
>> b/llvm/test/tools/llvm-link/Inputs/h.ll
>> new file mode 100644
>> index 000000000000..c2bda1712a40
>> --- /dev/null
>> +++ b/llvm/test/tools/llvm-link/Inputs/h.ll
>> @@ -0,0 +1,6 @@
>> +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
>> +
>> +define void @h() {
>> +entry:
>> +  ret void
>> +}
>>
>> diff  --git a/llvm/test/tools/llvm-link/archive-bad.ll
>> b/llvm/test/tools/llvm-link/archive-bad.ll
>> new file mode 100644
>> index 000000000000..80ce6fc1fe0d
>> --- /dev/null
>> +++ b/llvm/test/tools/llvm-link/archive-bad.ll
>> @@ -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
>>
>> diff  --git a/llvm/test/tools/llvm-link/archive.ll
>> b/llvm/test/tools/llvm-link/archive.ll
>> new file mode 100644
>> index 000000000000..10ab83a3d5be
>> --- /dev/null
>> +++ b/llvm/test/tools/llvm-link/archive.ll
>> @@ -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
>>
>> diff  --git a/llvm/test/tools/llvm-link/archivell.ll
>> b/llvm/test/tools/llvm-link/archivell.ll
>> new file mode 100644
>> index 000000000000..7474df14e907
>> --- /dev/null
>> +++ b/llvm/test/tools/llvm-link/archivell.ll
>> @@ -0,0 +1,7 @@
>> +# RUN: llvm-ar cr %t.fg.a %S/Inputs/f.ll llvm-as %S/Inputs/g.ll
>>
>
> Did you really mean to include the 'llvm-as' binary in the archive here?
> This is causing this test to break in our test environment.
>
>
>> +# 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
>>
>> diff  --git a/llvm/tools/llvm-link/llvm-link.cpp
>> b/llvm/tools/llvm-link/llvm-link.cpp
>> index a7cda24bbe0a..7141bd1ca7a1 100644
>> --- a/llvm/tools/llvm-link/llvm-link.cpp
>> +++ b/llvm/tools/llvm-link/llvm-link.cpp
>> @@ -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";
>>
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200714/a3e77626/attachment.html>


More information about the llvm-commits mailing list