1f12b8282SRafael Espindola //===- IRObjectFile.cpp - IR object file implementation ---------*- C++ -*-===//
2f12b8282SRafael Espindola //
3f12b8282SRafael Espindola //                     The LLVM Compiler Infrastructure
4f12b8282SRafael Espindola //
5f12b8282SRafael Espindola // This file is distributed under the University of Illinois Open Source
6f12b8282SRafael Espindola // License. See LICENSE.TXT for details.
7f12b8282SRafael Espindola //
8f12b8282SRafael Espindola //===----------------------------------------------------------------------===//
9f12b8282SRafael Espindola //
10f12b8282SRafael Espindola // Part of the IRObjectFile class implementation.
11f12b8282SRafael Espindola //
12f12b8282SRafael Espindola //===----------------------------------------------------------------------===//
13f12b8282SRafael Espindola 
14ba79dba8SRafael Espindola #include "llvm/Object/IRObjectFile.h"
15ba79dba8SRafael Espindola #include "RecordStreamer.h"
160a446fd5SBenjamin Kramer #include "llvm/ADT/STLExtras.h"
17264b5d9eSZachary Turner #include "llvm/BinaryFormat/Magic.h"
18ad17679aSTeresa Johnson #include "llvm/Bitcode/BitcodeReader.h"
19c3f9b5a5SRafael Espindola #include "llvm/IR/GVMaterializer.h"
20d9903888SChandler Carruth #include "llvm/IR/LLVMContext.h"
21a51f0f83SRafael Espindola #include "llvm/IR/Mangler.h"
22f12b8282SRafael Espindola #include "llvm/IR/Module.h"
2313b69d63SRafael Espindola #include "llvm/MC/MCAsmInfo.h"
2413b69d63SRafael Espindola #include "llvm/MC/MCContext.h"
2513b69d63SRafael Espindola #include "llvm/MC/MCInstrInfo.h"
2613b69d63SRafael Espindola #include "llvm/MC/MCObjectFileInfo.h"
2713b69d63SRafael Espindola #include "llvm/MC/MCParser/MCAsmParser.h"
28b3e8a6d2SBenjamin Kramer #include "llvm/MC/MCParser/MCTargetAsmParser.h"
29d9903888SChandler Carruth #include "llvm/MC/MCRegisterInfo.h"
3081902a3aSPete Cooper #include "llvm/MC/MCSubtargetInfo.h"
3110039c02SPeter Collingbourne #include "llvm/Object/ObjectFile.h"
322e60ca96SRafael Espindola #include "llvm/Support/MemoryBuffer.h"
3313b69d63SRafael Espindola #include "llvm/Support/SourceMgr.h"
3413b69d63SRafael Espindola #include "llvm/Support/TargetRegistry.h"
3523f04061SRafael Espindola #include "llvm/Support/raw_ostream.h"
36f12b8282SRafael Espindola using namespace llvm;
37f12b8282SRafael Espindola using namespace object;
38f12b8282SRafael Espindola 
3945102a24SPeter Collingbourne IRObjectFile::IRObjectFile(MemoryBufferRef Object,
4045102a24SPeter Collingbourne                            std::vector<std::unique_ptr<Module>> Mods)
4145102a24SPeter Collingbourne     : SymbolicFile(Binary::ID_IR, Object), Mods(std::move(Mods)) {
4245102a24SPeter Collingbourne   for (auto &M : this->Mods)
43863cbfbeSPeter Collingbourne     SymTab.addModule(M.get());
44f12b8282SRafael Espindola }
45f12b8282SRafael Espindola 
46e32baa0cSPeter Collingbourne IRObjectFile::~IRObjectFile() {}
4713b69d63SRafael Espindola 
48863cbfbeSPeter Collingbourne static ModuleSymbolTable::Symbol getSym(DataRefImpl &Symb) {
49863cbfbeSPeter Collingbourne   return *reinterpret_cast<ModuleSymbolTable::Symbol *>(Symb.p);
50863cbfbeSPeter Collingbourne }
51863cbfbeSPeter Collingbourne 
52f12b8282SRafael Espindola void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
53863cbfbeSPeter Collingbourne   Symb.p += sizeof(ModuleSymbolTable::Symbol);
54f12b8282SRafael Espindola }
55f12b8282SRafael Espindola 
56db4ed0bdSRafael Espindola std::error_code IRObjectFile::printSymbolName(raw_ostream &OS,
57f12b8282SRafael Espindola                                               DataRefImpl Symb) const {
58863cbfbeSPeter Collingbourne   SymTab.printSymbolName(OS, getSym(Symb));
597d099195SRui Ueyama   return std::error_code();
60f12b8282SRafael Espindola }
61f12b8282SRafael Espindola 
62f12b8282SRafael Espindola uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const {
63863cbfbeSPeter Collingbourne   return SymTab.getSymbolFlags(getSym(Symb));
64f12b8282SRafael Espindola }
65f12b8282SRafael Espindola 
66435890a4SPeter Collingbourne basic_symbol_iterator IRObjectFile::symbol_begin() const {
67f12b8282SRafael Espindola   DataRefImpl Ret;
68863cbfbeSPeter Collingbourne   Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data());
69f12b8282SRafael Espindola   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
70f12b8282SRafael Espindola }
71f12b8282SRafael Espindola 
72435890a4SPeter Collingbourne basic_symbol_iterator IRObjectFile::symbol_end() const {
73f12b8282SRafael Espindola   DataRefImpl Ret;
74863cbfbeSPeter Collingbourne   Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data() +
75863cbfbeSPeter Collingbourne                                       SymTab.symbols().size());
76f12b8282SRafael Espindola   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
77f12b8282SRafael Espindola }
78f12b8282SRafael Espindola 
7945102a24SPeter Collingbourne StringRef IRObjectFile::getTargetTriple() const {
8045102a24SPeter Collingbourne   // Each module must have the same target triple, so we arbitrarily access the
8145102a24SPeter Collingbourne   // first one.
8245102a24SPeter Collingbourne   return Mods[0]->getTargetTriple();
8345102a24SPeter Collingbourne }
84debb6f6cSPeter Collingbourne 
8510039c02SPeter Collingbourne ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) {
8610039c02SPeter Collingbourne   for (const SectionRef &Sec : Obj.sections()) {
87f2fe0141SSteven Wu     if (Sec.isBitcode()) {
8810039c02SPeter Collingbourne       StringRef SecContents;
8910039c02SPeter Collingbourne       if (std::error_code EC = Sec.getContents(SecContents))
9010039c02SPeter Collingbourne         return EC;
9110039c02SPeter Collingbourne       return MemoryBufferRef(SecContents, Obj.getFileName());
9210039c02SPeter Collingbourne     }
9310039c02SPeter Collingbourne   }
9410039c02SPeter Collingbourne 
9510039c02SPeter Collingbourne   return object_error::bitcode_section_not_found;
9610039c02SPeter Collingbourne }
9710039c02SPeter Collingbourne 
9810039c02SPeter Collingbourne ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) {
99264b5d9eSZachary Turner   file_magic Type = identify_magic(Object.getBuffer());
10010039c02SPeter Collingbourne   switch (Type) {
101264b5d9eSZachary Turner   case file_magic::bitcode:
10210039c02SPeter Collingbourne     return Object;
103264b5d9eSZachary Turner   case file_magic::elf_relocatable:
104264b5d9eSZachary Turner   case file_magic::macho_object:
105264b5d9eSZachary Turner   case file_magic::coff_object: {
1063fcdf6aeSKevin Enderby     Expected<std::unique_ptr<ObjectFile>> ObjFile =
10710039c02SPeter Collingbourne         ObjectFile::createObjectFile(Object, Type);
10810039c02SPeter Collingbourne     if (!ObjFile)
1093fcdf6aeSKevin Enderby       return errorToErrorCode(ObjFile.takeError());
11010039c02SPeter Collingbourne     return findBitcodeInObject(*ObjFile->get());
11110039c02SPeter Collingbourne   }
11210039c02SPeter Collingbourne   default:
11310039c02SPeter Collingbourne     return object_error::invalid_file_type;
11410039c02SPeter Collingbourne   }
11510039c02SPeter Collingbourne }
11610039c02SPeter Collingbourne 
117d9445c49SPeter Collingbourne Expected<std::unique_ptr<IRObjectFile>>
11845102a24SPeter Collingbourne IRObjectFile::create(MemoryBufferRef Object, LLVMContext &Context) {
11910039c02SPeter Collingbourne   ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
12010039c02SPeter Collingbourne   if (!BCOrErr)
121d9445c49SPeter Collingbourne     return errorCodeToError(BCOrErr.getError());
12248af1c2aSRafael Espindola 
12345102a24SPeter Collingbourne   Expected<std::vector<BitcodeModule>> BMsOrErr =
12445102a24SPeter Collingbourne       getBitcodeModuleList(*BCOrErr);
12545102a24SPeter Collingbourne   if (!BMsOrErr)
12645102a24SPeter Collingbourne     return BMsOrErr.takeError();
12745102a24SPeter Collingbourne 
12845102a24SPeter Collingbourne   std::vector<std::unique_ptr<Module>> Mods;
12945102a24SPeter Collingbourne   for (auto BM : *BMsOrErr) {
130d9445c49SPeter Collingbourne     Expected<std::unique_ptr<Module>> MOrErr =
131a61f5e37STeresa Johnson         BM.getLazyModule(Context, /*ShouldLazyLoadMetadata*/ true,
132a61f5e37STeresa Johnson                          /*IsImporting*/ false);
133d9445c49SPeter Collingbourne     if (!MOrErr)
134d9445c49SPeter Collingbourne       return MOrErr.takeError();
135dddd1fd9SRafael Espindola 
13645102a24SPeter Collingbourne     Mods.push_back(std::move(*MOrErr));
13745102a24SPeter Collingbourne   }
13845102a24SPeter Collingbourne 
139c5fecb4fSPeter Collingbourne   return std::unique_ptr<IRObjectFile>(
14045102a24SPeter Collingbourne       new IRObjectFile(*BCOrErr, std::move(Mods)));
141f12b8282SRafael Espindola }
142c00c2b24SPeter Collingbourne 
143c00c2b24SPeter Collingbourne Expected<IRSymtabFile> object::readIRSymtab(MemoryBufferRef MBRef) {
144c00c2b24SPeter Collingbourne   IRSymtabFile F;
145c00c2b24SPeter Collingbourne   ErrorOr<MemoryBufferRef> BCOrErr =
146c00c2b24SPeter Collingbourne       IRObjectFile::findBitcodeInMemBuffer(MBRef);
147c00c2b24SPeter Collingbourne   if (!BCOrErr)
148c00c2b24SPeter Collingbourne     return errorCodeToError(BCOrErr.getError());
149c00c2b24SPeter Collingbourne 
150*8dde4cbaSPeter Collingbourne   Expected<BitcodeFileContents> BFCOrErr = getBitcodeFileContents(*BCOrErr);
151*8dde4cbaSPeter Collingbourne   if (!BFCOrErr)
152*8dde4cbaSPeter Collingbourne     return BFCOrErr.takeError();
153c00c2b24SPeter Collingbourne 
154*8dde4cbaSPeter Collingbourne   Expected<irsymtab::FileContents> FCOrErr = irsymtab::readBitcode(*BFCOrErr);
155c00c2b24SPeter Collingbourne   if (!FCOrErr)
156c00c2b24SPeter Collingbourne     return FCOrErr.takeError();
157c00c2b24SPeter Collingbourne 
158*8dde4cbaSPeter Collingbourne   F.Mods = std::move(BFCOrErr->Mods);
159c00c2b24SPeter Collingbourne   F.Symtab = std::move(FCOrErr->Symtab);
160c00c2b24SPeter Collingbourne   F.Strtab = std::move(FCOrErr->Strtab);
161c00c2b24SPeter Collingbourne   F.TheReader = std::move(FCOrErr->TheReader);
162c00c2b24SPeter Collingbourne   return std::move(F);
163c00c2b24SPeter Collingbourne }
164