| //===- IRObjectFile.cpp - IR object file implementation ---------*- C++ -*-===// | 
 | // | 
 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
 | // See https://llvm.org/LICENSE.txt for license information. | 
 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | // Part of the IRObjectFile class implementation. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "llvm/Object/IRObjectFile.h" | 
 | #include "llvm/ADT/ArrayRef.h" | 
 | #include "llvm/BinaryFormat/Magic.h" | 
 | #include "llvm/Bitcode/BitcodeReader.h" | 
 | #include "llvm/IR/Module.h" | 
 | #include "llvm/Object/ObjectFile.h" | 
 | using namespace llvm; | 
 | using namespace object; | 
 |  | 
 | namespace llvm { | 
 | class LLVMContext; | 
 | class raw_ostream; | 
 | } // namespace llvm | 
 |  | 
 | IRObjectFile::IRObjectFile(MemoryBufferRef Object, | 
 |                            std::vector<std::unique_ptr<Module>> Mods) | 
 |     : SymbolicFile(Binary::ID_IR, Object), Mods(std::move(Mods)) { | 
 |   for (auto &M : this->Mods) | 
 |     SymTab.addModule(M.get()); | 
 | } | 
 |  | 
 | IRObjectFile::~IRObjectFile() = default; | 
 |  | 
 | static ModuleSymbolTable::Symbol getSym(DataRefImpl &Symb) { | 
 |   return *reinterpret_cast<ModuleSymbolTable::Symbol *>(Symb.p); | 
 | } | 
 |  | 
 | void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const { | 
 |   Symb.p += sizeof(ModuleSymbolTable::Symbol); | 
 | } | 
 |  | 
 | Error IRObjectFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const { | 
 |   SymTab.printSymbolName(OS, getSym(Symb)); | 
 |   return Error::success(); | 
 | } | 
 |  | 
 | Expected<uint32_t> IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { | 
 |   return SymTab.getSymbolFlags(getSym(Symb)); | 
 | } | 
 |  | 
 | basic_symbol_iterator IRObjectFile::symbol_begin() const { | 
 |   DataRefImpl Ret; | 
 |   Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data()); | 
 |   return basic_symbol_iterator(BasicSymbolRef(Ret, this)); | 
 | } | 
 |  | 
 | basic_symbol_iterator IRObjectFile::symbol_end() const { | 
 |   DataRefImpl Ret; | 
 |   Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data() + | 
 |                                       SymTab.symbols().size()); | 
 |   return basic_symbol_iterator(BasicSymbolRef(Ret, this)); | 
 | } | 
 |  | 
 | StringRef IRObjectFile::getTargetTriple() const { | 
 |   // Each module must have the same target triple, so we arbitrarily access the | 
 |   // first one. | 
 |   return Mods[0]->getTargetTriple().str(); | 
 | } | 
 |  | 
 | Expected<MemoryBufferRef> | 
 | IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) { | 
 |   for (const SectionRef &Sec : Obj.sections()) { | 
 |     if (Sec.isBitcode()) { | 
 |       Expected<StringRef> Contents = Sec.getContents(); | 
 |       if (!Contents) | 
 |         return Contents.takeError(); | 
 |       if (Contents->size() <= 1) | 
 |         return errorCodeToError(object_error::bitcode_section_not_found); | 
 |       return MemoryBufferRef(*Contents, Obj.getFileName()); | 
 |     } | 
 |   } | 
 |  | 
 |   return errorCodeToError(object_error::bitcode_section_not_found); | 
 | } | 
 |  | 
 | Expected<MemoryBufferRef> | 
 | IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) { | 
 |   file_magic Type = identify_magic(Object.getBuffer()); | 
 |   switch (Type) { | 
 |   case file_magic::bitcode: | 
 |     return Object; | 
 |   case file_magic::elf_relocatable: | 
 |   case file_magic::macho_object: | 
 |   case file_magic::wasm_object: | 
 |   case file_magic::coff_object: { | 
 |     Expected<std::unique_ptr<ObjectFile>> ObjFile = | 
 |         ObjectFile::createObjectFile(Object, Type); | 
 |     if (!ObjFile) | 
 |       return ObjFile.takeError(); | 
 |     return findBitcodeInObject(*ObjFile->get()); | 
 |   } | 
 |   default: | 
 |     return errorCodeToError(object_error::invalid_file_type); | 
 |   } | 
 | } | 
 |  | 
 | Expected<std::unique_ptr<IRObjectFile>> | 
 | IRObjectFile::create(MemoryBufferRef Object, LLVMContext &Context) { | 
 |   Expected<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object); | 
 |   if (!BCOrErr) | 
 |     return BCOrErr.takeError(); | 
 |  | 
 |   Expected<std::vector<BitcodeModule>> BMsOrErr = | 
 |       getBitcodeModuleList(*BCOrErr); | 
 |   if (!BMsOrErr) | 
 |     return BMsOrErr.takeError(); | 
 |  | 
 |   std::vector<std::unique_ptr<Module>> Mods; | 
 |   for (auto BM : *BMsOrErr) { | 
 |     Expected<std::unique_ptr<Module>> MOrErr = | 
 |         BM.getLazyModule(Context, /*ShouldLazyLoadMetadata*/ true, | 
 |                          /*IsImporting*/ false); | 
 |     if (!MOrErr) | 
 |       return MOrErr.takeError(); | 
 |  | 
 |     Mods.push_back(std::move(*MOrErr)); | 
 |   } | 
 |  | 
 |   return std::unique_ptr<IRObjectFile>( | 
 |       new IRObjectFile(*BCOrErr, std::move(Mods))); | 
 | } | 
 |  | 
 | Expected<IRSymtabFile> object::readIRSymtab(MemoryBufferRef MBRef) { | 
 |   IRSymtabFile F; | 
 |   Expected<MemoryBufferRef> BCOrErr = | 
 |       IRObjectFile::findBitcodeInMemBuffer(MBRef); | 
 |   if (!BCOrErr) | 
 |     return BCOrErr.takeError(); | 
 |  | 
 |   Expected<BitcodeFileContents> BFCOrErr = getBitcodeFileContents(*BCOrErr); | 
 |   if (!BFCOrErr) | 
 |     return BFCOrErr.takeError(); | 
 |  | 
 |   Expected<irsymtab::FileContents> FCOrErr = irsymtab::readBitcode(*BFCOrErr); | 
 |   if (!FCOrErr) | 
 |     return FCOrErr.takeError(); | 
 |  | 
 |   F.Mods = std::move(BFCOrErr->Mods); | 
 |   F.Symtab = std::move(FCOrErr->Symtab); | 
 |   F.Strtab = std::move(FCOrErr->Strtab); | 
 |   F.TheReader = std::move(FCOrErr->TheReader); | 
 |   return std::move(F); | 
 | } |