Index: include/llvm/Object/IRObjectFile.h =================================================================== --- include/llvm/Object/IRObjectFile.h +++ include/llvm/Object/IRObjectFile.h @@ -22,6 +22,8 @@ class GlobalValue; namespace object { +class ObjectFile; + class IRObjectFile : public SymbolicFile { std::unique_ptr M; std::unique_ptr Mang; @@ -49,6 +51,10 @@ return v->isIR(); } + static ErrorOr getBitcodeFromObject(ObjectFile *Obj); + static ErrorOr + getBitcodeFromMemBuffer(MemoryBufferRef Object); + static ErrorOr> createIRObjectFile(MemoryBufferRef Object, LLVMContext &Context); }; Index: lib/LTO/LTOModule.cpp =================================================================== --- lib/LTO/LTOModule.cpp +++ lib/LTO/LTOModule.cpp @@ -29,6 +29,8 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/MC/SubtargetFeature.h" +#include "llvm/Object/IRObjectFile.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -44,6 +46,7 @@ #include "llvm/Transforms/Utils/GlobalStatus.h" #include using namespace llvm; +using namespace llvm::object; LTOModule::LTOModule(std::unique_ptr Obj, llvm::TargetMachine *TM) @@ -51,23 +54,48 @@ /// isBitcodeFile - Returns 'true' if the file (or memory contents) is LLVM /// bitcode. -bool LTOModule::isBitcodeFile(const void *mem, size_t length) { - return sys::fs::identify_magic(StringRef((const char *)mem, length)) == - sys::fs::file_magic::bitcode; +bool LTOModule::isBitcodeFile(const void *Mem, size_t Length) { + auto BCData = IRObjectFile::getBitcodeFromMemBuffer( + MemoryBufferRef(StringRef((const char *)Mem, Length), "")); + return BCData && !BCData->getBuffer().empty(); } -bool LTOModule::isBitcodeFile(const char *path) { - sys::fs::file_magic type; - if (sys::fs::identify_magic(path, type)) +bool LTOModule::isBitcodeFile(const char *Path) { + sys::fs::file_magic Type; + if (sys::fs::identify_magic(Path, Type)) return false; - return type == sys::fs::file_magic::bitcode; + switch (Type) { + case sys::fs::file_magic::bitcode: + return true; + case sys::fs::file_magic::elf_relocatable: + case sys::fs::file_magic::macho_object: + case sys::fs::file_magic::coff_object: { + ErrorOr> BufferOrErr = + MemoryBuffer::getFile(Path); + if (!BufferOrErr) + return false; + + auto Obj = ObjectFile::createObjectFile( + BufferOrErr.get()->getMemBufferRef(), Type); + if (!Obj) + return false; + + auto BCData = IRObjectFile::getBitcodeFromObject(Obj->get()); + return BCData && !BCData->getBuffer().empty(); + } + default: + return false; + } } -bool LTOModule::isBitcodeForTarget(MemoryBuffer *buffer, - StringRef triplePrefix) { - std::string Triple = - getBitcodeTargetTriple(buffer->getMemBufferRef(), getGlobalContext()); - return StringRef(Triple).startswith(triplePrefix); +bool LTOModule::isBitcodeForTarget(MemoryBuffer *Buffer, + StringRef TriplePrefix) { + ErrorOr BCOrErr = + IRObjectFile::getBitcodeFromMemBuffer(Buffer->getMemBufferRef()); + if (!BCOrErr) + return false; + std::string Triple = getBitcodeTargetTriple(*BCOrErr, getGlobalContext()); + return StringRef(Triple).startswith(TriplePrefix); } LTOModule *LTOModule::createFromFile(const char *path, TargetOptions options, @@ -113,7 +141,13 @@ LTOModule *LTOModule::makeLTOModule(MemoryBufferRef Buffer, TargetOptions options, std::string &errMsg) { - ErrorOr MOrErr = parseBitcodeFile(Buffer, getGlobalContext()); + ErrorOr MBOrErr = + IRObjectFile::getBitcodeFromMemBuffer(Buffer); + if (std::error_code EC = MBOrErr.getError()) { + errMsg = EC.message(); + return nullptr; + } + ErrorOr MOrErr = parseBitcodeFile(*MBOrErr, getGlobalContext()); if (std::error_code EC = MOrErr.getError()) { errMsg = EC.message(); return nullptr; Index: lib/Object/IRObjectFile.cpp =================================================================== --- lib/Object/IRObjectFile.cpp +++ lib/Object/IRObjectFile.cpp @@ -25,6 +25,7 @@ #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" @@ -264,11 +265,52 @@ return basic_symbol_iterator(BasicSymbolRef(Ret, this)); } +ErrorOr IRObjectFile::getBitcodeFromObject(ObjectFile *Obj) { + for (auto Sec : Obj->sections()) { + StringRef SecName; + if (std::error_code EC = Sec.getName(SecName)) { + return EC; + } + if (SecName == ".llvmbc") { + StringRef SecContents; + if (std::error_code EC = Sec.getContents(SecContents)) { + return EC; + } + return MemoryBufferRef(SecContents, Obj->getFileName()); + } + } + + return MemoryBufferRef(); +} + +ErrorOr IRObjectFile::getBitcodeFromMemBuffer(MemoryBufferRef Object) { + sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer()); + switch (Type) { + case sys::fs::file_magic::bitcode: + return Object; + case sys::fs::file_magic::elf_relocatable: + case sys::fs::file_magic::macho_object: + case sys::fs::file_magic::coff_object: { + auto ObjFile = ObjectFile::createObjectFile(Object, Type); + if (!ObjFile) { + return ObjFile.getError(); + } + return getBitcodeFromObject(ObjFile->get()); + } + default: + return MemoryBufferRef(); + } +} + ErrorOr> llvm::object::IRObjectFile::createIRObjectFile(MemoryBufferRef Object, LLVMContext &Context) { + ErrorOr BCOrErr = getBitcodeFromMemBuffer(Object); + if (!BCOrErr) + return BCOrErr.getError(); - std::unique_ptr Buff(MemoryBuffer::getMemBuffer(Object, false)); + std::unique_ptr Buff( + MemoryBuffer::getMemBuffer(BCOrErr.get(), false)); ErrorOr MOrErr = getLazyBitcodeModule(std::move(Buff), Context); if (std::error_code EC = MOrErr.getError()) Index: lib/Object/SymbolicFile.cpp =================================================================== --- lib/Object/SymbolicFile.cpp +++ lib/Object/SymbolicFile.cpp @@ -40,11 +40,9 @@ case sys::fs::file_magic::macho_universal_binary: case sys::fs::file_magic::windows_resource: return object_error::invalid_file_type; - case sys::fs::file_magic::elf_relocatable: case sys::fs::file_magic::elf_executable: case sys::fs::file_magic::elf_shared_object: case sys::fs::file_magic::elf_core: - case sys::fs::file_magic::macho_object: case sys::fs::file_magic::macho_executable: case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: case sys::fs::file_magic::macho_core: @@ -54,10 +52,24 @@ case sys::fs::file_magic::macho_bundle: case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: case sys::fs::file_magic::macho_dsym_companion: - case sys::fs::file_magic::coff_object: case sys::fs::file_magic::coff_import_library: case sys::fs::file_magic::pecoff_executable: return ObjectFile::createObjectFile(Object, Type); + case sys::fs::file_magic::elf_relocatable: + case sys::fs::file_magic::macho_object: + case sys::fs::file_magic::coff_object: { + auto Obj = ObjectFile::createObjectFile(Object, Type); + if (!Obj || !Context) + return std::move(Obj); + + auto BCData = IRObjectFile::getBitcodeFromObject(Obj->get()); + if (!BCData || BCData->getBuffer().empty()) + return std::move(Obj); + + return IRObjectFile::createIRObjectFile( + MemoryBufferRef(BCData->getBuffer(), Object.getBufferIdentifier()), + *Context); + } } llvm_unreachable("Unexpected Binary File Type"); } Index: test/LTO/Inputs/bcsection.macho.s =================================================================== --- /dev/null +++ test/LTO/Inputs/bcsection.macho.s @@ -0,0 +1,2 @@ +.section .llvmbc,.llvmbc +.incbin "bcsection.bc" Index: test/LTO/Inputs/bcsection.s =================================================================== --- /dev/null +++ test/LTO/Inputs/bcsection.s @@ -0,0 +1,2 @@ +.section .llvmbc +.incbin "bcsection.bc" Index: test/LTO/bcsection.ll =================================================================== --- /dev/null +++ test/LTO/bcsection.ll @@ -0,0 +1,21 @@ +; RUN: llvm-as -o %T/bcsection.bc %s + +; RUN: llvm-mc -I=%T -filetype=obj -triple=x86_64-pc-win32 -o %T/bcsection.coff.bco %p/Inputs/bcsection.s +; RUN: llvm-nm %T/bcsection.coff.bco | FileCheck %s +; RUN: llvm-lto -exported-symbol=main -o %T/bcsection.coff.o %T/bcsection.coff.bco +; RUN: llvm-nm %T/bcsection.coff.o | FileCheck %s + +; RUN: llvm-mc -I=%T -filetype=obj -triple=x86_64-unknown-linux-gnu -o %T/bcsection.elf.bco %p/Inputs/bcsection.s +; RUN: llvm-nm %T/bcsection.elf.bco | FileCheck %s +; RUN: llvm-lto -exported-symbol=main -o %T/bcsection.elf.o %T/bcsection.elf.bco +; RUN: llvm-nm %T/bcsection.elf.o | FileCheck %s + +; RUN: llvm-mc -I=%T -filetype=obj -triple=x86_64-apple-darwin11 -o %T/bcsection.macho.bco %p/Inputs/bcsection.macho.s +; RUN: llvm-nm %T/bcsection.macho.bco | FileCheck %s +; RUN: llvm-lto -exported-symbol=main -o %T/bcsection.macho.o %T/bcsection.macho.bco +; RUN: llvm-nm %T/bcsection.macho.o | FileCheck %s + +; CHECK: main +define i32 @main() { + ret i32 0 +} Index: test/tools/gold/Inputs/bcsection.s =================================================================== --- /dev/null +++ test/tools/gold/Inputs/bcsection.s @@ -0,0 +1,2 @@ +.section .llvmbc +.incbin "bcsection.bc" Index: test/tools/gold/bcsection.ll =================================================================== --- /dev/null +++ test/tools/gold/bcsection.ll @@ -0,0 +1,10 @@ +; RUN: llvm-as -o %T/bcsection.bc %s + +; RUN: llvm-mc -I=%T -filetype=obj -o %T/bcsection.bco %p/Inputs/bcsection.s +; RUN: ld -r -o %T/bcsection.o -plugin %llvmshlibdir/LLVMgold.so %T/bcsection.bco +; RUN: llvm-nm %T/bcsection.o | FileCheck %s + +; CHECK: main +define i32 @main() { + ret i32 0 +} Index: tools/gold/gold-plugin.cpp =================================================================== --- tools/gold/gold-plugin.cpp +++ tools/gold/gold-plugin.cpp @@ -548,8 +548,15 @@ if (get_view(F.handle, &View) != LDPS_OK) message(LDPL_FATAL, "Failed to get a view of file"); - std::unique_ptr Buffer = MemoryBuffer::getMemBuffer( - StringRef((char *)View, File.filesize), "", false); + llvm::ErrorOr MBOrErr = + object::IRObjectFile::getBitcodeFromMemBuffer( + MemoryBufferRef(StringRef((const char *)View, File.filesize), "")); + if (std::error_code EC = MBOrErr.getError()) + message(LDPL_FATAL, "Could not read bitcode from file : %s", + EC.message().c_str()); + + std::unique_ptr Buffer = + MemoryBuffer::getMemBuffer(MBOrErr->getBuffer(), "", false); if (release_input_file(F.handle) != LDPS_OK) message(LDPL_FATAL, "Failed to release file information");