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 
3848af1c2aSRafael Espindola IRObjectFile::IRObjectFile(MemoryBufferRef Object, std::unique_ptr<Module> Mod)
3948af1c2aSRafael Espindola     : SymbolicFile(Binary::ID_IR, Object), M(std::move(Mod)) {
40*863cbfbeSPeter Collingbourne   SymTab.addModule(M.get());
41f12b8282SRafael Espindola }
42f12b8282SRafael Espindola 
43e32baa0cSPeter Collingbourne IRObjectFile::~IRObjectFile() {}
4413b69d63SRafael Espindola 
45*863cbfbeSPeter Collingbourne static ModuleSymbolTable::Symbol getSym(DataRefImpl &Symb) {
46*863cbfbeSPeter Collingbourne   return *reinterpret_cast<ModuleSymbolTable::Symbol *>(Symb.p);
47*863cbfbeSPeter Collingbourne }
48*863cbfbeSPeter Collingbourne 
49f12b8282SRafael Espindola void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
50*863cbfbeSPeter Collingbourne   Symb.p += sizeof(ModuleSymbolTable::Symbol);
51f12b8282SRafael Espindola }
52f12b8282SRafael Espindola 
53db4ed0bdSRafael Espindola std::error_code IRObjectFile::printSymbolName(raw_ostream &OS,
54f12b8282SRafael Espindola                                               DataRefImpl Symb) const {
55*863cbfbeSPeter Collingbourne   SymTab.printSymbolName(OS, getSym(Symb));
567d099195SRui Ueyama   return std::error_code();
57f12b8282SRafael Espindola }
58f12b8282SRafael Espindola 
59f12b8282SRafael Espindola uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const {
60*863cbfbeSPeter Collingbourne   return SymTab.getSymbolFlags(getSym(Symb));
61f12b8282SRafael Espindola }
62f12b8282SRafael Espindola 
63e32baa0cSPeter Collingbourne GlobalValue *IRObjectFile::getSymbolGV(DataRefImpl Symb) {
64e32baa0cSPeter Collingbourne   return getSym(Symb).dyn_cast<GlobalValue *>();
65e32baa0cSPeter Collingbourne }
66f12b8282SRafael Espindola 
6725a7e0a8SRafael Espindola std::unique_ptr<Module> IRObjectFile::takeModule() { return std::move(M); }
6825a7e0a8SRafael Espindola 
69435890a4SPeter Collingbourne basic_symbol_iterator IRObjectFile::symbol_begin() const {
70f12b8282SRafael Espindola   DataRefImpl Ret;
71*863cbfbeSPeter Collingbourne   Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data());
72f12b8282SRafael Espindola   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
73f12b8282SRafael Espindola }
74f12b8282SRafael Espindola 
75435890a4SPeter Collingbourne basic_symbol_iterator IRObjectFile::symbol_end() const {
76f12b8282SRafael Espindola   DataRefImpl Ret;
77*863cbfbeSPeter Collingbourne   Ret.p = reinterpret_cast<uintptr_t>(SymTab.symbols().data() +
78*863cbfbeSPeter Collingbourne                                       SymTab.symbols().size());
79f12b8282SRafael Espindola   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
80f12b8282SRafael Espindola }
81f12b8282SRafael Espindola 
82debb6f6cSPeter Collingbourne StringRef IRObjectFile::getTargetTriple() const { return M->getTargetTriple(); }
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>>
1175dec7eaaSRafael Espindola llvm::object::IRObjectFile::create(MemoryBufferRef Object,
11848af1c2aSRafael Espindola                                    LLVMContext &Context) {
11910039c02SPeter Collingbourne   ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
12010039c02SPeter Collingbourne   if (!BCOrErr)
121d9445c49SPeter Collingbourne     return errorCodeToError(BCOrErr.getError());
12248af1c2aSRafael Espindola 
123d9445c49SPeter Collingbourne   Expected<std::unique_ptr<Module>> MOrErr =
124e2dcf7c3SPeter Collingbourne       getLazyBitcodeModule(*BCOrErr, Context,
125cba833a0SRafael Espindola                            /*ShouldLazyLoadMetadata*/ true);
126d9445c49SPeter Collingbourne   if (!MOrErr)
127d9445c49SPeter Collingbourne     return MOrErr.takeError();
128dddd1fd9SRafael Espindola 
129dcd1dca2SRafael Espindola   std::unique_ptr<Module> &M = MOrErr.get();
1309ba95f99STeresa Johnson   return llvm::make_unique<IRObjectFile>(BCOrErr.get(), std::move(M));
131f12b8282SRafael Espindola }
132