diff --git a/llvm/test/tools/llvm-ar/lto-kind-from-triple.test b/llvm/test/tools/llvm-ar/lto-kind-from-triple.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-ar/lto-kind-from-triple.test @@ -0,0 +1,26 @@ +## Ensure that we generate a GNU style archive if the first input is a bitcode +## file with a GNU target triple (absence of __.SYMDEF in the archive). + +# RUN: echo -e 'target triple = "x86_64-unknown-linux-gnu" \n define void @_Z3foov() { ret void }' > %t.gnu.ll +# RUN: llvm-as -o %t.gnu.o %t.gnu.ll + +# RUN: rm -f %t.ar +# RUN: llvm-ar crs %t.ar %t.gnu.o +# RUN: not grep -q __.SYMDEF %t.ar + +## Ensure that we generate a MachO style archive if the first input is a +## bitcode file with a MachO target triple (presence of __.SYMDEF in the +## archive). + +# RUN: echo -e 'target triple = "x86_64-apple-macosx10.9" \n define void @_Z3foov() { ret void }' > %t.macho.ll +# RUN: llvm-as -o %t.macho.o %t.macho.ll + +# RUN: rm -f %t.ar +# RUN: llvm-ar crs %t.ar %t.macho.o +# RUN: grep -q __.SYMDEF %t.ar + +## Verify that archive format is based on the first input's target triple. + +# RUN: rm -f %t.ar +# RUN: llvm-ar crs %t.ar %t.gnu.o %t.macho.o +# RUN: not grep -q __.SYMDEF %t.ar diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp --- a/llvm/tools/llvm-ar/llvm-ar.cpp +++ b/llvm/tools/llvm-ar/llvm-ar.cpp @@ -14,11 +14,14 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" +#include "llvm/BinaryFormat/Magic.h" #include "llvm/IR/LLVMContext.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ArchiveWriter.h" +#include "llvm/Object/IRObjectFile.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Object/SymbolicFile.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ConvertUTF.h" @@ -875,8 +878,9 @@ } static object::Archive::Kind getKindFromMember(const NewArchiveMember &Member) { + auto MemBufferRef = Member.Buf->getMemBufferRef(); Expected> OptionalObject = - object::ObjectFile::createObjectFile(Member.Buf->getMemBufferRef()); + object::ObjectFile::createObjectFile(MemBufferRef); if (OptionalObject) return isa(**OptionalObject) @@ -885,6 +889,23 @@ // squelch the error in case we had a non-object file consumeError(OptionalObject.takeError()); + + // If we're adding a bitcode file to the archive, detect the Archive kind + // based on the target triple. + LLVMContext Context; + if (identify_magic(MemBufferRef.getBuffer()) == file_magic::bitcode) { + if (auto ObjOrErr = object::SymbolicFile::createSymbolicFile( + MemBufferRef, file_magic::bitcode, &Context)) { + auto &IRObject = cast(**ObjOrErr); + return Triple(IRObject.getTargetTriple()).isOSDarwin() + ? object::Archive::K_DARWIN + : object::Archive::K_GNU; + } else { + // Squelch the error in case this was not a SymbolicFile. + consumeError(ObjOrErr.takeError()); + } + } + return getDefaultForHost(); }