15ca98fd9SDimitry Andric //===- IRObjectFile.cpp - IR object file implementation ---------*- C++ -*-===//
25ca98fd9SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ca98fd9SDimitry Andric //
75ca98fd9SDimitry Andric //===----------------------------------------------------------------------===//
85ca98fd9SDimitry Andric //
95ca98fd9SDimitry Andric // Part of the IRObjectFile class implementation.
105ca98fd9SDimitry Andric //
115ca98fd9SDimitry Andric //===----------------------------------------------------------------------===//
125ca98fd9SDimitry Andric
135ca98fd9SDimitry Andric #include "llvm/Object/IRObjectFile.h"
14145449b1SDimitry Andric #include "llvm/ADT/ArrayRef.h"
157ab83427SDimitry Andric #include "llvm/BinaryFormat/Magic.h"
16b915e9e0SDimitry Andric #include "llvm/Bitcode/BitcodeReader.h"
175ca98fd9SDimitry Andric #include "llvm/IR/Module.h"
1867c32a98SDimitry Andric #include "llvm/Object/ObjectFile.h"
195ca98fd9SDimitry Andric using namespace llvm;
205ca98fd9SDimitry Andric using namespace object;
215ca98fd9SDimitry Andric
22145449b1SDimitry Andric namespace llvm {
23145449b1SDimitry Andric class LLVMContext;
24145449b1SDimitry Andric class raw_ostream;
25145449b1SDimitry Andric } // namespace llvm
26145449b1SDimitry Andric
IRObjectFile(MemoryBufferRef Object,std::vector<std::unique_ptr<Module>> Mods)27b915e9e0SDimitry Andric IRObjectFile::IRObjectFile(MemoryBufferRef Object,
28b915e9e0SDimitry Andric std::vector<std::unique_ptr<Module>> Mods)
29b915e9e0SDimitry Andric : SymbolicFile(Binary::ID_IR, Object), Mods(std::move(Mods)) {
30b915e9e0SDimitry Andric for (auto &M : this->Mods)
31b915e9e0SDimitry Andric SymTab.addModule(M.get());
3201095a5dSDimitry Andric }
335ca98fd9SDimitry Andric
34145449b1SDimitry Andric IRObjectFile::~IRObjectFile() = default;
355ca98fd9SDimitry Andric
getSym(DataRefImpl & Symb)36b915e9e0SDimitry Andric static ModuleSymbolTable::Symbol getSym(DataRefImpl &Symb) {
37b915e9e0SDimitry Andric return *reinterpret_cast<ModuleSymbolTable::Symbol *>(Symb.p);
385ca98fd9SDimitry Andric }
395ca98fd9SDimitry Andric
moveSymbolNext(DataRefImpl & Symb) const405ca98fd9SDimitry Andric void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
41b915e9e0SDimitry Andric Symb.p += sizeof(ModuleSymbolTable::Symbol);
425ca98fd9SDimitry Andric }
435ca98fd9SDimitry Andric
printSymbolName(raw_ostream & OS,DataRefImpl Symb) const44e6d15924SDimitry Andric Error IRObjectFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const {
45b915e9e0SDimitry Andric SymTab.printSymbolName(OS, getSym(Symb));
46e6d15924SDimitry Andric return Error::success();
475ca98fd9SDimitry Andric }
485ca98fd9SDimitry Andric
getSymbolFlags(DataRefImpl Symb) const49cfca06d7SDimitry Andric Expected<uint32_t> IRObjectFile::getSymbolFlags(DataRefImpl Symb) const {
50b915e9e0SDimitry Andric return SymTab.getSymbolFlags(getSym(Symb));
515ca98fd9SDimitry Andric }
525ca98fd9SDimitry Andric
symbol_begin() const53b915e9e0SDimitry Andric basic_symbol_iterator IRObjectFile::symbol_begin() const {
545ca98fd9SDimitry Andric DataRefImpl Ret;
55b915e9e0SDimitry Andric Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data());
565ca98fd9SDimitry Andric return basic_symbol_iterator(BasicSymbolRef(Ret, this));
575ca98fd9SDimitry Andric }
585ca98fd9SDimitry Andric
symbol_end() const59b915e9e0SDimitry Andric basic_symbol_iterator IRObjectFile::symbol_end() const {
605ca98fd9SDimitry Andric DataRefImpl Ret;
61b915e9e0SDimitry Andric Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data() +
62b915e9e0SDimitry Andric SymTab.symbols().size());
635ca98fd9SDimitry Andric return basic_symbol_iterator(BasicSymbolRef(Ret, this));
645ca98fd9SDimitry Andric }
655ca98fd9SDimitry Andric
getTargetTriple() const66b915e9e0SDimitry Andric StringRef IRObjectFile::getTargetTriple() const {
67b915e9e0SDimitry Andric // Each module must have the same target triple, so we arbitrarily access the
68b915e9e0SDimitry Andric // first one.
69b915e9e0SDimitry Andric return Mods[0]->getTargetTriple();
70b915e9e0SDimitry Andric }
71b915e9e0SDimitry Andric
72044eb2f6SDimitry Andric Expected<MemoryBufferRef>
findBitcodeInObject(const ObjectFile & Obj)73044eb2f6SDimitry Andric IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) {
7467c32a98SDimitry Andric for (const SectionRef &Sec : Obj.sections()) {
7501095a5dSDimitry Andric if (Sec.isBitcode()) {
76e6d15924SDimitry Andric Expected<StringRef> Contents = Sec.getContents();
77e6d15924SDimitry Andric if (!Contents)
78e6d15924SDimitry Andric return Contents.takeError();
79e6d15924SDimitry Andric if (Contents->size() <= 1)
80e6d15924SDimitry Andric return errorCodeToError(object_error::bitcode_section_not_found);
81e6d15924SDimitry Andric return MemoryBufferRef(*Contents, Obj.getFileName());
8267c32a98SDimitry Andric }
8367c32a98SDimitry Andric }
8467c32a98SDimitry Andric
85044eb2f6SDimitry Andric return errorCodeToError(object_error::bitcode_section_not_found);
8667c32a98SDimitry Andric }
8767c32a98SDimitry Andric
88044eb2f6SDimitry Andric Expected<MemoryBufferRef>
findBitcodeInMemBuffer(MemoryBufferRef Object)89044eb2f6SDimitry Andric IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) {
907ab83427SDimitry Andric file_magic Type = identify_magic(Object.getBuffer());
9167c32a98SDimitry Andric switch (Type) {
927ab83427SDimitry Andric case file_magic::bitcode:
9367c32a98SDimitry Andric return Object;
947ab83427SDimitry Andric case file_magic::elf_relocatable:
957ab83427SDimitry Andric case file_magic::macho_object:
96cfca06d7SDimitry Andric case file_magic::wasm_object:
977ab83427SDimitry Andric case file_magic::coff_object: {
9801095a5dSDimitry Andric Expected<std::unique_ptr<ObjectFile>> ObjFile =
9967c32a98SDimitry Andric ObjectFile::createObjectFile(Object, Type);
10067c32a98SDimitry Andric if (!ObjFile)
101044eb2f6SDimitry Andric return ObjFile.takeError();
10267c32a98SDimitry Andric return findBitcodeInObject(*ObjFile->get());
10367c32a98SDimitry Andric }
10467c32a98SDimitry Andric default:
105044eb2f6SDimitry Andric return errorCodeToError(object_error::invalid_file_type);
10667c32a98SDimitry Andric }
10767c32a98SDimitry Andric }
10867c32a98SDimitry Andric
109b915e9e0SDimitry Andric Expected<std::unique_ptr<IRObjectFile>>
create(MemoryBufferRef Object,LLVMContext & Context)110b915e9e0SDimitry Andric IRObjectFile::create(MemoryBufferRef Object, LLVMContext &Context) {
111044eb2f6SDimitry Andric Expected<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
11267c32a98SDimitry Andric if (!BCOrErr)
113044eb2f6SDimitry Andric return BCOrErr.takeError();
11467c32a98SDimitry Andric
115b915e9e0SDimitry Andric Expected<std::vector<BitcodeModule>> BMsOrErr =
116b915e9e0SDimitry Andric getBitcodeModuleList(*BCOrErr);
117b915e9e0SDimitry Andric if (!BMsOrErr)
118b915e9e0SDimitry Andric return BMsOrErr.takeError();
11967c32a98SDimitry Andric
120b915e9e0SDimitry Andric std::vector<std::unique_ptr<Module>> Mods;
121b915e9e0SDimitry Andric for (auto BM : *BMsOrErr) {
122b915e9e0SDimitry Andric Expected<std::unique_ptr<Module>> MOrErr =
123b915e9e0SDimitry Andric BM.getLazyModule(Context, /*ShouldLazyLoadMetadata*/ true,
124b915e9e0SDimitry Andric /*IsImporting*/ false);
125b915e9e0SDimitry Andric if (!MOrErr)
126b915e9e0SDimitry Andric return MOrErr.takeError();
1275ca98fd9SDimitry Andric
128b915e9e0SDimitry Andric Mods.push_back(std::move(*MOrErr));
129b915e9e0SDimitry Andric }
130b915e9e0SDimitry Andric
131b915e9e0SDimitry Andric return std::unique_ptr<IRObjectFile>(
132b915e9e0SDimitry Andric new IRObjectFile(*BCOrErr, std::move(Mods)));
1335ca98fd9SDimitry Andric }
1347ab83427SDimitry Andric
readIRSymtab(MemoryBufferRef MBRef)1357ab83427SDimitry Andric Expected<IRSymtabFile> object::readIRSymtab(MemoryBufferRef MBRef) {
1367ab83427SDimitry Andric IRSymtabFile F;
137044eb2f6SDimitry Andric Expected<MemoryBufferRef> BCOrErr =
1387ab83427SDimitry Andric IRObjectFile::findBitcodeInMemBuffer(MBRef);
1397ab83427SDimitry Andric if (!BCOrErr)
140044eb2f6SDimitry Andric return BCOrErr.takeError();
1417ab83427SDimitry Andric
1427ab83427SDimitry Andric Expected<BitcodeFileContents> BFCOrErr = getBitcodeFileContents(*BCOrErr);
1437ab83427SDimitry Andric if (!BFCOrErr)
1447ab83427SDimitry Andric return BFCOrErr.takeError();
1457ab83427SDimitry Andric
1467ab83427SDimitry Andric Expected<irsymtab::FileContents> FCOrErr = irsymtab::readBitcode(*BFCOrErr);
1477ab83427SDimitry Andric if (!FCOrErr)
1487ab83427SDimitry Andric return FCOrErr.takeError();
1497ab83427SDimitry Andric
1507ab83427SDimitry Andric F.Mods = std::move(BFCOrErr->Mods);
1517ab83427SDimitry Andric F.Symtab = std::move(FCOrErr->Symtab);
1527ab83427SDimitry Andric F.Strtab = std::move(FCOrErr->Strtab);
1537ab83427SDimitry Andric F.TheReader = std::move(FCOrErr->TheReader);
1547ab83427SDimitry Andric return std::move(F);
1557ab83427SDimitry Andric }
156