xref: /freebsd/contrib/llvm-project/llvm/lib/Object/IRObjectFile.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
10b57cec5SDimitry Andric //===- IRObjectFile.cpp - IR object file implementation ---------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Part of the IRObjectFile class implementation.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/Object/IRObjectFile.h"
14*81ad6265SDimitry Andric #include "llvm/ADT/ArrayRef.h"
15*81ad6265SDimitry Andric #include "llvm/ADT/PointerUnion.h"
160b57cec5SDimitry Andric #include "llvm/BinaryFormat/Magic.h"
170b57cec5SDimitry Andric #include "llvm/Bitcode/BitcodeReader.h"
180b57cec5SDimitry Andric #include "llvm/IR/Module.h"
190b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h"
200b57cec5SDimitry Andric using namespace llvm;
210b57cec5SDimitry Andric using namespace object;
220b57cec5SDimitry Andric 
23*81ad6265SDimitry Andric namespace llvm {
24*81ad6265SDimitry Andric class LLVMContext;
25*81ad6265SDimitry Andric class raw_ostream;
26*81ad6265SDimitry Andric } // namespace llvm
27*81ad6265SDimitry Andric 
280b57cec5SDimitry Andric IRObjectFile::IRObjectFile(MemoryBufferRef Object,
290b57cec5SDimitry Andric                            std::vector<std::unique_ptr<Module>> Mods)
300b57cec5SDimitry Andric     : SymbolicFile(Binary::ID_IR, Object), Mods(std::move(Mods)) {
310b57cec5SDimitry Andric   for (auto &M : this->Mods)
320b57cec5SDimitry Andric     SymTab.addModule(M.get());
330b57cec5SDimitry Andric }
340b57cec5SDimitry Andric 
35*81ad6265SDimitry Andric IRObjectFile::~IRObjectFile() = default;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric static ModuleSymbolTable::Symbol getSym(DataRefImpl &Symb) {
380b57cec5SDimitry Andric   return *reinterpret_cast<ModuleSymbolTable::Symbol *>(Symb.p);
390b57cec5SDimitry Andric }
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
420b57cec5SDimitry Andric   Symb.p += sizeof(ModuleSymbolTable::Symbol);
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric Error IRObjectFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const {
460b57cec5SDimitry Andric   SymTab.printSymbolName(OS, getSym(Symb));
470b57cec5SDimitry Andric   return Error::success();
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
505ffd83dbSDimitry Andric Expected<uint32_t> IRObjectFile::getSymbolFlags(DataRefImpl Symb) const {
510b57cec5SDimitry Andric   return SymTab.getSymbolFlags(getSym(Symb));
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric basic_symbol_iterator IRObjectFile::symbol_begin() const {
550b57cec5SDimitry Andric   DataRefImpl Ret;
560b57cec5SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data());
570b57cec5SDimitry Andric   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric basic_symbol_iterator IRObjectFile::symbol_end() const {
610b57cec5SDimitry Andric   DataRefImpl Ret;
620b57cec5SDimitry Andric   Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data() +
630b57cec5SDimitry Andric                                       SymTab.symbols().size());
640b57cec5SDimitry Andric   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric StringRef IRObjectFile::getTargetTriple() const {
680b57cec5SDimitry Andric   // Each module must have the same target triple, so we arbitrarily access the
690b57cec5SDimitry Andric   // first one.
700b57cec5SDimitry Andric   return Mods[0]->getTargetTriple();
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric Expected<MemoryBufferRef>
740b57cec5SDimitry Andric IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) {
750b57cec5SDimitry Andric   for (const SectionRef &Sec : Obj.sections()) {
760b57cec5SDimitry Andric     if (Sec.isBitcode()) {
770b57cec5SDimitry Andric       Expected<StringRef> Contents = Sec.getContents();
780b57cec5SDimitry Andric       if (!Contents)
790b57cec5SDimitry Andric         return Contents.takeError();
800b57cec5SDimitry Andric       if (Contents->size() <= 1)
810b57cec5SDimitry Andric         return errorCodeToError(object_error::bitcode_section_not_found);
820b57cec5SDimitry Andric       return MemoryBufferRef(*Contents, Obj.getFileName());
830b57cec5SDimitry Andric     }
840b57cec5SDimitry Andric   }
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   return errorCodeToError(object_error::bitcode_section_not_found);
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric Expected<MemoryBufferRef>
900b57cec5SDimitry Andric IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) {
910b57cec5SDimitry Andric   file_magic Type = identify_magic(Object.getBuffer());
920b57cec5SDimitry Andric   switch (Type) {
930b57cec5SDimitry Andric   case file_magic::bitcode:
940b57cec5SDimitry Andric     return Object;
950b57cec5SDimitry Andric   case file_magic::elf_relocatable:
960b57cec5SDimitry Andric   case file_magic::macho_object:
975ffd83dbSDimitry Andric   case file_magic::wasm_object:
980b57cec5SDimitry Andric   case file_magic::coff_object: {
990b57cec5SDimitry Andric     Expected<std::unique_ptr<ObjectFile>> ObjFile =
1000b57cec5SDimitry Andric         ObjectFile::createObjectFile(Object, Type);
1010b57cec5SDimitry Andric     if (!ObjFile)
1020b57cec5SDimitry Andric       return ObjFile.takeError();
1030b57cec5SDimitry Andric     return findBitcodeInObject(*ObjFile->get());
1040b57cec5SDimitry Andric   }
1050b57cec5SDimitry Andric   default:
1060b57cec5SDimitry Andric     return errorCodeToError(object_error::invalid_file_type);
1070b57cec5SDimitry Andric   }
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric Expected<std::unique_ptr<IRObjectFile>>
1110b57cec5SDimitry Andric IRObjectFile::create(MemoryBufferRef Object, LLVMContext &Context) {
1120b57cec5SDimitry Andric   Expected<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
1130b57cec5SDimitry Andric   if (!BCOrErr)
1140b57cec5SDimitry Andric     return BCOrErr.takeError();
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   Expected<std::vector<BitcodeModule>> BMsOrErr =
1170b57cec5SDimitry Andric       getBitcodeModuleList(*BCOrErr);
1180b57cec5SDimitry Andric   if (!BMsOrErr)
1190b57cec5SDimitry Andric     return BMsOrErr.takeError();
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   std::vector<std::unique_ptr<Module>> Mods;
1220b57cec5SDimitry Andric   for (auto BM : *BMsOrErr) {
1230b57cec5SDimitry Andric     Expected<std::unique_ptr<Module>> MOrErr =
1240b57cec5SDimitry Andric         BM.getLazyModule(Context, /*ShouldLazyLoadMetadata*/ true,
1250b57cec5SDimitry Andric                          /*IsImporting*/ false);
1260b57cec5SDimitry Andric     if (!MOrErr)
1270b57cec5SDimitry Andric       return MOrErr.takeError();
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric     Mods.push_back(std::move(*MOrErr));
1300b57cec5SDimitry Andric   }
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   return std::unique_ptr<IRObjectFile>(
1330b57cec5SDimitry Andric       new IRObjectFile(*BCOrErr, std::move(Mods)));
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric Expected<IRSymtabFile> object::readIRSymtab(MemoryBufferRef MBRef) {
1370b57cec5SDimitry Andric   IRSymtabFile F;
1380b57cec5SDimitry Andric   Expected<MemoryBufferRef> BCOrErr =
1390b57cec5SDimitry Andric       IRObjectFile::findBitcodeInMemBuffer(MBRef);
1400b57cec5SDimitry Andric   if (!BCOrErr)
1410b57cec5SDimitry Andric     return BCOrErr.takeError();
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   Expected<BitcodeFileContents> BFCOrErr = getBitcodeFileContents(*BCOrErr);
1440b57cec5SDimitry Andric   if (!BFCOrErr)
1450b57cec5SDimitry Andric     return BFCOrErr.takeError();
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   Expected<irsymtab::FileContents> FCOrErr = irsymtab::readBitcode(*BFCOrErr);
1480b57cec5SDimitry Andric   if (!FCOrErr)
1490b57cec5SDimitry Andric     return FCOrErr.takeError();
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   F.Mods = std::move(BFCOrErr->Mods);
1520b57cec5SDimitry Andric   F.Symtab = std::move(FCOrErr->Symtab);
1530b57cec5SDimitry Andric   F.Strtab = std::move(FCOrErr->Strtab);
1540b57cec5SDimitry Andric   F.TheReader = std::move(FCOrErr->TheReader);
1550b57cec5SDimitry Andric   return std::move(F);
1560b57cec5SDimitry Andric }
157