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 14f12b8282SRafael Espindola #include "llvm/Bitcode/ReaderWriter.h" 15f12b8282SRafael Espindola #include "llvm/IR/LLVMContext.h" 16c3f9b5a5SRafael Espindola #include "llvm/IR/GVMaterializer.h" 17a51f0f83SRafael Espindola #include "llvm/IR/Mangler.h" 18f12b8282SRafael Espindola #include "llvm/IR/Module.h" 19f12b8282SRafael Espindola #include "llvm/Object/IRObjectFile.h" 20*13b69d63SRafael Espindola #include "llvm/Object/RecordStreamer.h" 21*13b69d63SRafael Espindola #include "llvm/MC/MCRegisterInfo.h" 22*13b69d63SRafael Espindola #include "llvm/MC/MCAsmInfo.h" 23*13b69d63SRafael Espindola #include "llvm/MC/MCContext.h" 24*13b69d63SRafael Espindola #include "llvm/MC/MCInstrInfo.h" 25*13b69d63SRafael Espindola #include "llvm/MC/MCObjectFileInfo.h" 26*13b69d63SRafael Espindola #include "llvm/MC/MCTargetAsmParser.h" 27*13b69d63SRafael Espindola #include "llvm/MC/MCParser/MCAsmParser.h" 282e60ca96SRafael Espindola #include "llvm/Support/MemoryBuffer.h" 29*13b69d63SRafael Espindola #include "llvm/Support/SourceMgr.h" 30*13b69d63SRafael Espindola #include "llvm/Support/TargetRegistry.h" 3123f04061SRafael Espindola #include "llvm/Support/raw_ostream.h" 32f12b8282SRafael Espindola using namespace llvm; 33f12b8282SRafael Espindola using namespace object; 34f12b8282SRafael Espindola 352e60ca96SRafael Espindola IRObjectFile::IRObjectFile(std::unique_ptr<MemoryBuffer> Object, 362e60ca96SRafael Espindola std::error_code &EC, LLVMContext &Context) 372e60ca96SRafael Espindola : SymbolicFile(Binary::ID_IR, std::move(Object)) { 382e60ca96SRafael Espindola ErrorOr<Module *> MOrErr = getLazyBitcodeModule(Data.get(), Context); 39f12b8282SRafael Espindola if ((EC = MOrErr.getError())) 40f12b8282SRafael Espindola return; 41f12b8282SRafael Espindola 42f12b8282SRafael Espindola M.reset(MOrErr.get()); 43a51f0f83SRafael Espindola 44a51f0f83SRafael Espindola // If we have a DataLayout, setup a mangler. 45a51f0f83SRafael Espindola const DataLayout *DL = M->getDataLayout(); 46a51f0f83SRafael Espindola if (!DL) 47a51f0f83SRafael Espindola return; 48a51f0f83SRafael Espindola 49a51f0f83SRafael Espindola Mang.reset(new Mangler(DL)); 50*13b69d63SRafael Espindola 51*13b69d63SRafael Espindola const std::string &InlineAsm = M->getModuleInlineAsm(); 52*13b69d63SRafael Espindola if (InlineAsm.empty()) 53*13b69d63SRafael Espindola return; 54*13b69d63SRafael Espindola 55*13b69d63SRafael Espindola StringRef Triple = M->getTargetTriple(); 56*13b69d63SRafael Espindola std::string Err; 57*13b69d63SRafael Espindola const Target *T = TargetRegistry::lookupTarget(Triple, Err); 58*13b69d63SRafael Espindola if (!T) 59*13b69d63SRafael Espindola return; 60*13b69d63SRafael Espindola 61*13b69d63SRafael Espindola std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(Triple)); 62*13b69d63SRafael Espindola if (!MRI) 63*13b69d63SRafael Espindola return; 64*13b69d63SRafael Espindola 65*13b69d63SRafael Espindola std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, Triple)); 66*13b69d63SRafael Espindola if (!MAI) 67*13b69d63SRafael Espindola return; 68*13b69d63SRafael Espindola 69*13b69d63SRafael Espindola std::unique_ptr<MCSubtargetInfo> STI( 70*13b69d63SRafael Espindola T->createMCSubtargetInfo(Triple, "", "")); 71*13b69d63SRafael Espindola if (!STI) 72*13b69d63SRafael Espindola return; 73*13b69d63SRafael Espindola 74*13b69d63SRafael Espindola std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo()); 75*13b69d63SRafael Espindola if (!MCII) 76*13b69d63SRafael Espindola return; 77*13b69d63SRafael Espindola 78*13b69d63SRafael Espindola MCObjectFileInfo MOFI; 79*13b69d63SRafael Espindola MCContext MCCtx(MAI.get(), MRI.get(), &MOFI); 80*13b69d63SRafael Espindola MOFI.InitMCObjectFileInfo(Triple, Reloc::Default, CodeModel::Default, MCCtx); 81*13b69d63SRafael Espindola std::unique_ptr<RecordStreamer> Streamer(new RecordStreamer(MCCtx)); 82*13b69d63SRafael Espindola 83*13b69d63SRafael Espindola std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm)); 84*13b69d63SRafael Espindola SourceMgr SrcMgr; 85*13b69d63SRafael Espindola SrcMgr.AddNewSourceBuffer(Buffer.release(), SMLoc()); 86*13b69d63SRafael Espindola std::unique_ptr<MCAsmParser> Parser( 87*13b69d63SRafael Espindola createMCAsmParser(SrcMgr, MCCtx, *Streamer, *MAI)); 88*13b69d63SRafael Espindola 89*13b69d63SRafael Espindola MCTargetOptions MCOptions; 90*13b69d63SRafael Espindola std::unique_ptr<MCTargetAsmParser> TAP( 91*13b69d63SRafael Espindola T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions)); 92*13b69d63SRafael Espindola if (!TAP) 93*13b69d63SRafael Espindola return; 94*13b69d63SRafael Espindola 95*13b69d63SRafael Espindola Parser->setTargetParser(*TAP); 96*13b69d63SRafael Espindola if (Parser->Run(false)) 97*13b69d63SRafael Espindola return; 98*13b69d63SRafael Espindola 99*13b69d63SRafael Espindola for (auto &KV : *Streamer) { 100*13b69d63SRafael Espindola StringRef Key = KV.first(); 101*13b69d63SRafael Espindola RecordStreamer::State Value = KV.second; 102*13b69d63SRafael Espindola uint32_t Res = BasicSymbolRef::SF_None; 103*13b69d63SRafael Espindola switch (Value) { 104*13b69d63SRafael Espindola case RecordStreamer::NeverSeen: 105*13b69d63SRafael Espindola llvm_unreachable("foo"); 106*13b69d63SRafael Espindola case RecordStreamer::DefinedGlobal: 107*13b69d63SRafael Espindola Res |= BasicSymbolRef::SF_Global; 108*13b69d63SRafael Espindola break; 109*13b69d63SRafael Espindola case RecordStreamer::Defined: 110*13b69d63SRafael Espindola break; 111*13b69d63SRafael Espindola case RecordStreamer::Global: 112*13b69d63SRafael Espindola case RecordStreamer::Used: 113*13b69d63SRafael Espindola Res |= BasicSymbolRef::SF_Undefined; 114*13b69d63SRafael Espindola Res |= BasicSymbolRef::SF_Global; 115*13b69d63SRafael Espindola break; 116*13b69d63SRafael Espindola } 117*13b69d63SRafael Espindola AsmSymbols.push_back( 118*13b69d63SRafael Espindola std::make_pair<std::string, uint32_t>(Key, std::move(Res))); 119*13b69d63SRafael Espindola } 120f12b8282SRafael Espindola } 121f12b8282SRafael Espindola 122c3f9b5a5SRafael Espindola IRObjectFile::~IRObjectFile() { M->getMaterializer()->releaseBuffer(); } 123c3f9b5a5SRafael Espindola 124*13b69d63SRafael Espindola static const GlobalValue *getGV(DataRefImpl &Symb) { 125*13b69d63SRafael Espindola if ((Symb.p & 3) == 3) 126*13b69d63SRafael Espindola return nullptr; 127*13b69d63SRafael Espindola 128*13b69d63SRafael Espindola return reinterpret_cast<GlobalValue*>(Symb.p & ~uintptr_t(3)); 129f12b8282SRafael Espindola } 130f12b8282SRafael Espindola 131f12b8282SRafael Espindola static uintptr_t skipEmpty(Module::const_alias_iterator I, const Module &M) { 132f12b8282SRafael Espindola if (I == M.alias_end()) 133f12b8282SRafael Espindola return 3; 134f12b8282SRafael Espindola const GlobalValue *GV = &*I; 135f12b8282SRafael Espindola return reinterpret_cast<uintptr_t>(GV) | 2; 136f12b8282SRafael Espindola } 137f12b8282SRafael Espindola 138f12b8282SRafael Espindola static uintptr_t skipEmpty(Module::const_global_iterator I, const Module &M) { 139f12b8282SRafael Espindola if (I == M.global_end()) 140f12b8282SRafael Espindola return skipEmpty(M.alias_begin(), M); 141f12b8282SRafael Espindola const GlobalValue *GV = &*I; 142f12b8282SRafael Espindola return reinterpret_cast<uintptr_t>(GV) | 1; 143f12b8282SRafael Espindola } 144f12b8282SRafael Espindola 145f12b8282SRafael Espindola static uintptr_t skipEmpty(Module::const_iterator I, const Module &M) { 146f12b8282SRafael Espindola if (I == M.end()) 147f12b8282SRafael Espindola return skipEmpty(M.global_begin(), M); 148f12b8282SRafael Espindola const GlobalValue *GV = &*I; 149f12b8282SRafael Espindola return reinterpret_cast<uintptr_t>(GV) | 0; 150f12b8282SRafael Espindola } 151f12b8282SRafael Espindola 152*13b69d63SRafael Espindola static unsigned getAsmSymIndex(DataRefImpl Symb) { 153*13b69d63SRafael Espindola assert((Symb.p & uintptr_t(3)) == 3); 154*13b69d63SRafael Espindola uintptr_t Index = Symb.p & ~uintptr_t(3); 155*13b69d63SRafael Espindola Index >>= 2; 156*13b69d63SRafael Espindola return Index; 157*13b69d63SRafael Espindola } 158*13b69d63SRafael Espindola 159f12b8282SRafael Espindola void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 160*13b69d63SRafael Espindola const GlobalValue *GV = getGV(Symb); 161f12b8282SRafael Espindola uintptr_t Res; 162*13b69d63SRafael Espindola 163f12b8282SRafael Espindola switch (Symb.p & 3) { 164f12b8282SRafael Espindola case 0: { 165f12b8282SRafael Espindola Module::const_iterator Iter(static_cast<const Function*>(GV)); 166f12b8282SRafael Espindola ++Iter; 167*13b69d63SRafael Espindola Res = skipEmpty(Iter, *M); 168f12b8282SRafael Espindola break; 169f12b8282SRafael Espindola } 170f12b8282SRafael Espindola case 1: { 171f12b8282SRafael Espindola Module::const_global_iterator Iter(static_cast<const GlobalVariable*>(GV)); 172f12b8282SRafael Espindola ++Iter; 173*13b69d63SRafael Espindola Res = skipEmpty(Iter, *M); 174f12b8282SRafael Espindola break; 175f12b8282SRafael Espindola } 176f12b8282SRafael Espindola case 2: { 177f12b8282SRafael Espindola Module::const_alias_iterator Iter(static_cast<const GlobalAlias*>(GV)); 178f12b8282SRafael Espindola ++Iter; 179*13b69d63SRafael Espindola Res = skipEmpty(Iter, *M); 180f12b8282SRafael Espindola break; 181f12b8282SRafael Espindola } 182*13b69d63SRafael Espindola case 3: { 183*13b69d63SRafael Espindola unsigned Index = getAsmSymIndex(Symb); 184*13b69d63SRafael Espindola assert(Index < AsmSymbols.size()); 185*13b69d63SRafael Espindola ++Index; 186*13b69d63SRafael Espindola Res = (Index << 2) | 3; 187*13b69d63SRafael Espindola break; 188*13b69d63SRafael Espindola } 189f12b8282SRafael Espindola } 190f12b8282SRafael Espindola 191f12b8282SRafael Espindola Symb.p = Res; 192f12b8282SRafael Espindola } 193f12b8282SRafael Espindola 194db4ed0bdSRafael Espindola std::error_code IRObjectFile::printSymbolName(raw_ostream &OS, 195f12b8282SRafael Espindola DataRefImpl Symb) const { 196*13b69d63SRafael Espindola const GlobalValue *GV = getGV(Symb); 197*13b69d63SRafael Espindola if (!GV) { 198*13b69d63SRafael Espindola unsigned Index = getAsmSymIndex(Symb); 199*13b69d63SRafael Espindola assert(Index <= AsmSymbols.size()); 200*13b69d63SRafael Espindola OS << AsmSymbols[Index].first; 201*13b69d63SRafael Espindola return object_error::success;; 202*13b69d63SRafael Espindola } 203a51f0f83SRafael Espindola 204a51f0f83SRafael Espindola if (Mang) 205*13b69d63SRafael Espindola Mang->getNameWithPrefix(OS, GV, false); 206a51f0f83SRafael Espindola else 207*13b69d63SRafael Espindola OS << GV->getName(); 208a51f0f83SRafael Espindola 209f12b8282SRafael Espindola return object_error::success; 210f12b8282SRafael Espindola } 211f12b8282SRafael Espindola 2128af5cb2cSRafael Espindola static bool isDeclaration(const GlobalValue &V) { 2138af5cb2cSRafael Espindola if (V.hasAvailableExternallyLinkage()) 2148af5cb2cSRafael Espindola return true; 2158af5cb2cSRafael Espindola 2168af5cb2cSRafael Espindola if (V.isMaterializable()) 2178af5cb2cSRafael Espindola return false; 2188af5cb2cSRafael Espindola 2198af5cb2cSRafael Espindola return V.isDeclaration(); 2208af5cb2cSRafael Espindola } 2218af5cb2cSRafael Espindola 222f12b8282SRafael Espindola uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { 223*13b69d63SRafael Espindola const GlobalValue *GV = getGV(Symb); 224*13b69d63SRafael Espindola 225*13b69d63SRafael Espindola if (!GV) { 226*13b69d63SRafael Espindola unsigned Index = getAsmSymIndex(Symb); 227*13b69d63SRafael Espindola assert(Index <= AsmSymbols.size()); 228*13b69d63SRafael Espindola return AsmSymbols[Index].second; 229*13b69d63SRafael Espindola } 230f12b8282SRafael Espindola 231f12b8282SRafael Espindola uint32_t Res = BasicSymbolRef::SF_None; 232*13b69d63SRafael Espindola if (isDeclaration(*GV)) 233f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Undefined; 234*13b69d63SRafael Espindola if (GV->hasPrivateLinkage()) 235f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_FormatSpecific; 236*13b69d63SRafael Espindola if (!GV->hasLocalLinkage()) 237f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Global; 238*13b69d63SRafael Espindola if (GV->hasCommonLinkage()) 239f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Common; 240*13b69d63SRafael Espindola if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage()) 241f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Weak; 242f12b8282SRafael Espindola 243f12b8282SRafael Espindola return Res; 244f12b8282SRafael Espindola } 245f12b8282SRafael Espindola 246*13b69d63SRafael Espindola const GlobalValue *IRObjectFile::getSymbolGV(DataRefImpl Symb) const { 247*13b69d63SRafael Espindola const GlobalValue *GV = getGV(Symb); 248f12b8282SRafael Espindola return GV; 249f12b8282SRafael Espindola } 250f12b8282SRafael Espindola 251f12b8282SRafael Espindola basic_symbol_iterator IRObjectFile::symbol_begin_impl() const { 252f12b8282SRafael Espindola Module::const_iterator I = M->begin(); 253f12b8282SRafael Espindola DataRefImpl Ret; 254f12b8282SRafael Espindola Ret.p = skipEmpty(I, *M); 255f12b8282SRafael Espindola return basic_symbol_iterator(BasicSymbolRef(Ret, this)); 256f12b8282SRafael Espindola } 257f12b8282SRafael Espindola 258f12b8282SRafael Espindola basic_symbol_iterator IRObjectFile::symbol_end_impl() const { 259f12b8282SRafael Espindola DataRefImpl Ret; 260*13b69d63SRafael Espindola uint64_t NumAsm = AsmSymbols.size(); 261*13b69d63SRafael Espindola NumAsm <<= 2; 262*13b69d63SRafael Espindola Ret.p = 3 | NumAsm; 263f12b8282SRafael Espindola return basic_symbol_iterator(BasicSymbolRef(Ret, this)); 264f12b8282SRafael Espindola } 265f12b8282SRafael Espindola 2662e60ca96SRafael Espindola ErrorOr<SymbolicFile *> llvm::object::SymbolicFile::createIRObjectFile( 2672e60ca96SRafael Espindola std::unique_ptr<MemoryBuffer> Object, LLVMContext &Context) { 268db4ed0bdSRafael Espindola std::error_code EC; 2692e60ca96SRafael Espindola std::unique_ptr<IRObjectFile> Ret( 2702e60ca96SRafael Espindola new IRObjectFile(std::move(Object), EC, Context)); 271f12b8282SRafael Espindola if (EC) 272f12b8282SRafael Espindola return EC; 27396c9d95fSAhmed Charles return Ret.release(); 274f12b8282SRafael Espindola } 275