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"
17ad17679aSTeresa Johnson #include "llvm/Bitcode/BitcodeReader.h"
18c3f9b5a5SRafael Espindola #include "llvm/IR/GVMaterializer.h"
19d9903888SChandler Carruth #include "llvm/IR/LLVMContext.h"
20a51f0f83SRafael Espindola #include "llvm/IR/Mangler.h"
21f12b8282SRafael Espindola #include "llvm/IR/Module.h"
2213b69d63SRafael Espindola #include "llvm/MC/MCAsmInfo.h"
2313b69d63SRafael Espindola #include "llvm/MC/MCContext.h"
2413b69d63SRafael Espindola #include "llvm/MC/MCInstrInfo.h"
2513b69d63SRafael Espindola #include "llvm/MC/MCObjectFileInfo.h"
2613b69d63SRafael Espindola #include "llvm/MC/MCParser/MCAsmParser.h"
27b3e8a6d2SBenjamin Kramer #include "llvm/MC/MCParser/MCTargetAsmParser.h"
28d9903888SChandler Carruth #include "llvm/MC/MCRegisterInfo.h"
2981902a3aSPete Cooper #include "llvm/MC/MCSubtargetInfo.h"
3010039c02SPeter Collingbourne #include "llvm/Object/ObjectFile.h"
312e60ca96SRafael Espindola #include "llvm/Support/MemoryBuffer.h"
3213b69d63SRafael Espindola #include "llvm/Support/SourceMgr.h"
3313b69d63SRafael Espindola #include "llvm/Support/TargetRegistry.h"
3423f04061SRafael Espindola #include "llvm/Support/raw_ostream.h"
35f12b8282SRafael Espindola using namespace llvm;
36f12b8282SRafael Espindola using namespace object;
37f12b8282SRafael Espindola 
38*45102a24SPeter Collingbourne IRObjectFile::IRObjectFile(MemoryBufferRef Object,
39*45102a24SPeter Collingbourne                            std::vector<std::unique_ptr<Module>> Mods)
40*45102a24SPeter Collingbourne     : SymbolicFile(Binary::ID_IR, Object), Mods(std::move(Mods)) {
41*45102a24SPeter Collingbourne   for (auto &M : this->Mods)
42863cbfbeSPeter Collingbourne     SymTab.addModule(M.get());
43f12b8282SRafael Espindola }
44f12b8282SRafael Espindola 
45e32baa0cSPeter Collingbourne IRObjectFile::~IRObjectFile() {}
4613b69d63SRafael Espindola 
47863cbfbeSPeter Collingbourne static ModuleSymbolTable::Symbol getSym(DataRefImpl &Symb) {
48863cbfbeSPeter Collingbourne   return *reinterpret_cast<ModuleSymbolTable::Symbol *>(Symb.p);
49863cbfbeSPeter Collingbourne }
50863cbfbeSPeter Collingbourne 
51f12b8282SRafael Espindola void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
52863cbfbeSPeter Collingbourne   Symb.p += sizeof(ModuleSymbolTable::Symbol);
53f12b8282SRafael Espindola }
54f12b8282SRafael Espindola 
55db4ed0bdSRafael Espindola std::error_code IRObjectFile::printSymbolName(raw_ostream &OS,
56f12b8282SRafael Espindola                                               DataRefImpl Symb) const {
57863cbfbeSPeter Collingbourne   SymTab.printSymbolName(OS, getSym(Symb));
587d099195SRui Ueyama   return std::error_code();
59f12b8282SRafael Espindola }
60f12b8282SRafael Espindola 
61f12b8282SRafael Espindola uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const {
62863cbfbeSPeter Collingbourne   return SymTab.getSymbolFlags(getSym(Symb));
63f12b8282SRafael Espindola }
64f12b8282SRafael Espindola 
65435890a4SPeter Collingbourne basic_symbol_iterator IRObjectFile::symbol_begin() const {
66f12b8282SRafael Espindola   DataRefImpl Ret;
67863cbfbeSPeter Collingbourne   Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data());
68f12b8282SRafael Espindola   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
69f12b8282SRafael Espindola }
70f12b8282SRafael Espindola 
71435890a4SPeter Collingbourne basic_symbol_iterator IRObjectFile::symbol_end() const {
72f12b8282SRafael Espindola   DataRefImpl Ret;
73863cbfbeSPeter Collingbourne   Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data() +
74863cbfbeSPeter Collingbourne                                       SymTab.symbols().size());
75f12b8282SRafael Espindola   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
76f12b8282SRafael Espindola }
77f12b8282SRafael Espindola 
78*45102a24SPeter Collingbourne StringRef IRObjectFile::getTargetTriple() const {
79*45102a24SPeter Collingbourne   // Each module must have the same target triple, so we arbitrarily access the
80*45102a24SPeter Collingbourne   // first one.
81*45102a24SPeter Collingbourne   return Mods[0]->getTargetTriple();
82*45102a24SPeter Collingbourne }
83debb6f6cSPeter Collingbourne 
8410039c02SPeter Collingbourne ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) {
8510039c02SPeter Collingbourne   for (const SectionRef &Sec : Obj.sections()) {
86f2fe0141SSteven Wu     if (Sec.isBitcode()) {
8710039c02SPeter Collingbourne       StringRef SecContents;
8810039c02SPeter Collingbourne       if (std::error_code EC = Sec.getContents(SecContents))
8910039c02SPeter Collingbourne         return EC;
9010039c02SPeter Collingbourne       return MemoryBufferRef(SecContents, Obj.getFileName());
9110039c02SPeter Collingbourne     }
9210039c02SPeter Collingbourne   }
9310039c02SPeter Collingbourne 
9410039c02SPeter Collingbourne   return object_error::bitcode_section_not_found;
9510039c02SPeter Collingbourne }
9610039c02SPeter Collingbourne 
9710039c02SPeter Collingbourne ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) {
9810039c02SPeter Collingbourne   sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer());
9910039c02SPeter Collingbourne   switch (Type) {
10010039c02SPeter Collingbourne   case sys::fs::file_magic::bitcode:
10110039c02SPeter Collingbourne     return Object;
10210039c02SPeter Collingbourne   case sys::fs::file_magic::elf_relocatable:
10310039c02SPeter Collingbourne   case sys::fs::file_magic::macho_object:
10410039c02SPeter Collingbourne   case sys::fs::file_magic::coff_object: {
1053fcdf6aeSKevin Enderby     Expected<std::unique_ptr<ObjectFile>> ObjFile =
10610039c02SPeter Collingbourne         ObjectFile::createObjectFile(Object, Type);
10710039c02SPeter Collingbourne     if (!ObjFile)
1083fcdf6aeSKevin Enderby       return errorToErrorCode(ObjFile.takeError());
10910039c02SPeter Collingbourne     return findBitcodeInObject(*ObjFile->get());
11010039c02SPeter Collingbourne   }
11110039c02SPeter Collingbourne   default:
11210039c02SPeter Collingbourne     return object_error::invalid_file_type;
11310039c02SPeter Collingbourne   }
11410039c02SPeter Collingbourne }
11510039c02SPeter Collingbourne 
116d9445c49SPeter Collingbourne Expected<std::unique_ptr<IRObjectFile>>
117*45102a24SPeter Collingbourne IRObjectFile::create(MemoryBufferRef Object, LLVMContext &Context) {
11810039c02SPeter Collingbourne   ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
11910039c02SPeter Collingbourne   if (!BCOrErr)
120d9445c49SPeter Collingbourne     return errorCodeToError(BCOrErr.getError());
12148af1c2aSRafael Espindola 
122*45102a24SPeter Collingbourne   Expected<std::vector<BitcodeModule>> BMsOrErr =
123*45102a24SPeter Collingbourne       getBitcodeModuleList(*BCOrErr);
124*45102a24SPeter Collingbourne   if (!BMsOrErr)
125*45102a24SPeter Collingbourne     return BMsOrErr.takeError();
126*45102a24SPeter Collingbourne 
127*45102a24SPeter Collingbourne   std::vector<std::unique_ptr<Module>> Mods;
128*45102a24SPeter Collingbourne   for (auto BM : *BMsOrErr) {
129d9445c49SPeter Collingbourne     Expected<std::unique_ptr<Module>> MOrErr =
130*45102a24SPeter Collingbourne         BM.getLazyModule(Context, /*ShouldLazyLoadMetadata*/ true);
131d9445c49SPeter Collingbourne     if (!MOrErr)
132d9445c49SPeter Collingbourne       return MOrErr.takeError();
133dddd1fd9SRafael Espindola 
134*45102a24SPeter Collingbourne     Mods.push_back(std::move(*MOrErr));
135*45102a24SPeter Collingbourne   }
136*45102a24SPeter Collingbourne 
137c5fecb4fSPeter Collingbourne   return std::unique_ptr<IRObjectFile>(
138*45102a24SPeter Collingbourne       new IRObjectFile(*BCOrErr, std::move(Mods)));
139f12b8282SRafael Espindola }
140