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" 2013b69d63SRafael Espindola #include "llvm/Object/RecordStreamer.h" 2113b69d63SRafael Espindola #include "llvm/MC/MCRegisterInfo.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/MCTargetAsmParser.h" 2713b69d63SRafael Espindola #include "llvm/MC/MCParser/MCAsmParser.h" 282e60ca96SRafael Espindola #include "llvm/Support/MemoryBuffer.h" 2913b69d63SRafael Espindola #include "llvm/Support/SourceMgr.h" 3013b69d63SRafael 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, 36dddd1fd9SRafael Espindola std::unique_ptr<Module> Mod) 37dddd1fd9SRafael Espindola : SymbolicFile(Binary::ID_IR, std::move(Object)), M(std::move(Mod)) { 38a51f0f83SRafael Espindola // If we have a DataLayout, setup a mangler. 39a51f0f83SRafael Espindola const DataLayout *DL = M->getDataLayout(); 40a51f0f83SRafael Espindola if (!DL) 41a51f0f83SRafael Espindola return; 42a51f0f83SRafael Espindola 43a51f0f83SRafael Espindola Mang.reset(new Mangler(DL)); 4413b69d63SRafael Espindola 4513b69d63SRafael Espindola const std::string &InlineAsm = M->getModuleInlineAsm(); 4613b69d63SRafael Espindola if (InlineAsm.empty()) 4713b69d63SRafael Espindola return; 4813b69d63SRafael Espindola 4913b69d63SRafael Espindola StringRef Triple = M->getTargetTriple(); 5013b69d63SRafael Espindola std::string Err; 5113b69d63SRafael Espindola const Target *T = TargetRegistry::lookupTarget(Triple, Err); 5213b69d63SRafael Espindola if (!T) 5313b69d63SRafael Espindola return; 5413b69d63SRafael Espindola 5513b69d63SRafael Espindola std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(Triple)); 5613b69d63SRafael Espindola if (!MRI) 5713b69d63SRafael Espindola return; 5813b69d63SRafael Espindola 5913b69d63SRafael Espindola std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, Triple)); 6013b69d63SRafael Espindola if (!MAI) 6113b69d63SRafael Espindola return; 6213b69d63SRafael Espindola 6313b69d63SRafael Espindola std::unique_ptr<MCSubtargetInfo> STI( 6413b69d63SRafael Espindola T->createMCSubtargetInfo(Triple, "", "")); 6513b69d63SRafael Espindola if (!STI) 6613b69d63SRafael Espindola return; 6713b69d63SRafael Espindola 6813b69d63SRafael Espindola std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo()); 6913b69d63SRafael Espindola if (!MCII) 7013b69d63SRafael Espindola return; 7113b69d63SRafael Espindola 7213b69d63SRafael Espindola MCObjectFileInfo MOFI; 7313b69d63SRafael Espindola MCContext MCCtx(MAI.get(), MRI.get(), &MOFI); 7413b69d63SRafael Espindola MOFI.InitMCObjectFileInfo(Triple, Reloc::Default, CodeModel::Default, MCCtx); 7513b69d63SRafael Espindola std::unique_ptr<RecordStreamer> Streamer(new RecordStreamer(MCCtx)); 7613b69d63SRafael Espindola 7713b69d63SRafael Espindola std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm)); 7813b69d63SRafael Espindola SourceMgr SrcMgr; 7913b69d63SRafael Espindola SrcMgr.AddNewSourceBuffer(Buffer.release(), SMLoc()); 8013b69d63SRafael Espindola std::unique_ptr<MCAsmParser> Parser( 8113b69d63SRafael Espindola createMCAsmParser(SrcMgr, MCCtx, *Streamer, *MAI)); 8213b69d63SRafael Espindola 8313b69d63SRafael Espindola MCTargetOptions MCOptions; 8413b69d63SRafael Espindola std::unique_ptr<MCTargetAsmParser> TAP( 8513b69d63SRafael Espindola T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions)); 8613b69d63SRafael Espindola if (!TAP) 8713b69d63SRafael Espindola return; 8813b69d63SRafael Espindola 8913b69d63SRafael Espindola Parser->setTargetParser(*TAP); 9013b69d63SRafael Espindola if (Parser->Run(false)) 9113b69d63SRafael Espindola return; 9213b69d63SRafael Espindola 9313b69d63SRafael Espindola for (auto &KV : *Streamer) { 9413b69d63SRafael Espindola StringRef Key = KV.first(); 9513b69d63SRafael Espindola RecordStreamer::State Value = KV.second; 9613b69d63SRafael Espindola uint32_t Res = BasicSymbolRef::SF_None; 9713b69d63SRafael Espindola switch (Value) { 9813b69d63SRafael Espindola case RecordStreamer::NeverSeen: 9913b69d63SRafael Espindola llvm_unreachable("foo"); 10013b69d63SRafael Espindola case RecordStreamer::DefinedGlobal: 10113b69d63SRafael Espindola Res |= BasicSymbolRef::SF_Global; 10213b69d63SRafael Espindola break; 10313b69d63SRafael Espindola case RecordStreamer::Defined: 10413b69d63SRafael Espindola break; 10513b69d63SRafael Espindola case RecordStreamer::Global: 10613b69d63SRafael Espindola case RecordStreamer::Used: 10713b69d63SRafael Espindola Res |= BasicSymbolRef::SF_Undefined; 10813b69d63SRafael Espindola Res |= BasicSymbolRef::SF_Global; 10913b69d63SRafael Espindola break; 11013b69d63SRafael Espindola } 11113b69d63SRafael Espindola AsmSymbols.push_back( 11213b69d63SRafael Espindola std::make_pair<std::string, uint32_t>(Key, std::move(Res))); 11313b69d63SRafael Espindola } 114f12b8282SRafael Espindola } 115f12b8282SRafael Espindola 116dddd1fd9SRafael Espindola IRObjectFile::~IRObjectFile() { 117dddd1fd9SRafael Espindola GVMaterializer *GVM = M->getMaterializer(); 118dddd1fd9SRafael Espindola if (GVM) 119dddd1fd9SRafael Espindola GVM->releaseBuffer(); 120dddd1fd9SRafael Espindola } 121c3f9b5a5SRafael Espindola 12213b69d63SRafael Espindola static const GlobalValue *getGV(DataRefImpl &Symb) { 12313b69d63SRafael Espindola if ((Symb.p & 3) == 3) 12413b69d63SRafael Espindola return nullptr; 12513b69d63SRafael Espindola 12613b69d63SRafael Espindola return reinterpret_cast<GlobalValue*>(Symb.p & ~uintptr_t(3)); 127f12b8282SRafael Espindola } 128f12b8282SRafael Espindola 129f12b8282SRafael Espindola static uintptr_t skipEmpty(Module::const_alias_iterator I, const Module &M) { 130f12b8282SRafael Espindola if (I == M.alias_end()) 131f12b8282SRafael Espindola return 3; 132f12b8282SRafael Espindola const GlobalValue *GV = &*I; 133f12b8282SRafael Espindola return reinterpret_cast<uintptr_t>(GV) | 2; 134f12b8282SRafael Espindola } 135f12b8282SRafael Espindola 136f12b8282SRafael Espindola static uintptr_t skipEmpty(Module::const_global_iterator I, const Module &M) { 137f12b8282SRafael Espindola if (I == M.global_end()) 138f12b8282SRafael Espindola return skipEmpty(M.alias_begin(), M); 139f12b8282SRafael Espindola const GlobalValue *GV = &*I; 140f12b8282SRafael Espindola return reinterpret_cast<uintptr_t>(GV) | 1; 141f12b8282SRafael Espindola } 142f12b8282SRafael Espindola 143f12b8282SRafael Espindola static uintptr_t skipEmpty(Module::const_iterator I, const Module &M) { 144f12b8282SRafael Espindola if (I == M.end()) 145f12b8282SRafael Espindola return skipEmpty(M.global_begin(), M); 146f12b8282SRafael Espindola const GlobalValue *GV = &*I; 147f12b8282SRafael Espindola return reinterpret_cast<uintptr_t>(GV) | 0; 148f12b8282SRafael Espindola } 149f12b8282SRafael Espindola 15013b69d63SRafael Espindola static unsigned getAsmSymIndex(DataRefImpl Symb) { 15113b69d63SRafael Espindola assert((Symb.p & uintptr_t(3)) == 3); 15213b69d63SRafael Espindola uintptr_t Index = Symb.p & ~uintptr_t(3); 15313b69d63SRafael Espindola Index >>= 2; 15413b69d63SRafael Espindola return Index; 15513b69d63SRafael Espindola } 15613b69d63SRafael Espindola 157f12b8282SRafael Espindola void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 15813b69d63SRafael Espindola const GlobalValue *GV = getGV(Symb); 159f12b8282SRafael Espindola uintptr_t Res; 16013b69d63SRafael Espindola 161f12b8282SRafael Espindola switch (Symb.p & 3) { 162f12b8282SRafael Espindola case 0: { 163f12b8282SRafael Espindola Module::const_iterator Iter(static_cast<const Function*>(GV)); 164f12b8282SRafael Espindola ++Iter; 16513b69d63SRafael Espindola Res = skipEmpty(Iter, *M); 166f12b8282SRafael Espindola break; 167f12b8282SRafael Espindola } 168f12b8282SRafael Espindola case 1: { 169f12b8282SRafael Espindola Module::const_global_iterator Iter(static_cast<const GlobalVariable*>(GV)); 170f12b8282SRafael Espindola ++Iter; 17113b69d63SRafael Espindola Res = skipEmpty(Iter, *M); 172f12b8282SRafael Espindola break; 173f12b8282SRafael Espindola } 174f12b8282SRafael Espindola case 2: { 175f12b8282SRafael Espindola Module::const_alias_iterator Iter(static_cast<const GlobalAlias*>(GV)); 176f12b8282SRafael Espindola ++Iter; 17713b69d63SRafael Espindola Res = skipEmpty(Iter, *M); 178f12b8282SRafael Espindola break; 179f12b8282SRafael Espindola } 18013b69d63SRafael Espindola case 3: { 18113b69d63SRafael Espindola unsigned Index = getAsmSymIndex(Symb); 18213b69d63SRafael Espindola assert(Index < AsmSymbols.size()); 18313b69d63SRafael Espindola ++Index; 18413b69d63SRafael Espindola Res = (Index << 2) | 3; 18513b69d63SRafael Espindola break; 18613b69d63SRafael Espindola } 187f12b8282SRafael Espindola } 188f12b8282SRafael Espindola 189f12b8282SRafael Espindola Symb.p = Res; 190f12b8282SRafael Espindola } 191f12b8282SRafael Espindola 192db4ed0bdSRafael Espindola std::error_code IRObjectFile::printSymbolName(raw_ostream &OS, 193f12b8282SRafael Espindola DataRefImpl Symb) const { 19413b69d63SRafael Espindola const GlobalValue *GV = getGV(Symb); 19513b69d63SRafael Espindola if (!GV) { 19613b69d63SRafael Espindola unsigned Index = getAsmSymIndex(Symb); 19713b69d63SRafael Espindola assert(Index <= AsmSymbols.size()); 19813b69d63SRafael Espindola OS << AsmSymbols[Index].first; 19913b69d63SRafael Espindola return object_error::success;; 20013b69d63SRafael Espindola } 201a51f0f83SRafael Espindola 202a51f0f83SRafael Espindola if (Mang) 20313b69d63SRafael Espindola Mang->getNameWithPrefix(OS, GV, false); 204a51f0f83SRafael Espindola else 20513b69d63SRafael Espindola OS << GV->getName(); 206a51f0f83SRafael Espindola 207f12b8282SRafael Espindola return object_error::success; 208f12b8282SRafael Espindola } 209f12b8282SRafael Espindola 2108af5cb2cSRafael Espindola static bool isDeclaration(const GlobalValue &V) { 2118af5cb2cSRafael Espindola if (V.hasAvailableExternallyLinkage()) 2128af5cb2cSRafael Espindola return true; 2138af5cb2cSRafael Espindola 2148af5cb2cSRafael Espindola if (V.isMaterializable()) 2158af5cb2cSRafael Espindola return false; 2168af5cb2cSRafael Espindola 2178af5cb2cSRafael Espindola return V.isDeclaration(); 2188af5cb2cSRafael Espindola } 2198af5cb2cSRafael Espindola 220f12b8282SRafael Espindola uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { 22113b69d63SRafael Espindola const GlobalValue *GV = getGV(Symb); 22213b69d63SRafael Espindola 22313b69d63SRafael Espindola if (!GV) { 22413b69d63SRafael Espindola unsigned Index = getAsmSymIndex(Symb); 22513b69d63SRafael Espindola assert(Index <= AsmSymbols.size()); 22613b69d63SRafael Espindola return AsmSymbols[Index].second; 22713b69d63SRafael Espindola } 228f12b8282SRafael Espindola 229f12b8282SRafael Espindola uint32_t Res = BasicSymbolRef::SF_None; 23013b69d63SRafael Espindola if (isDeclaration(*GV)) 231f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Undefined; 23213b69d63SRafael Espindola if (GV->hasPrivateLinkage()) 233f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_FormatSpecific; 23413b69d63SRafael Espindola if (!GV->hasLocalLinkage()) 235f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Global; 23613b69d63SRafael Espindola if (GV->hasCommonLinkage()) 237f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Common; 23813b69d63SRafael Espindola if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage()) 239f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Weak; 240f12b8282SRafael Espindola 241*2dc0d9bdSRafael Espindola if (GV->getName().startswith("llvm.")) 242b674c17dSRafael Espindola Res |= BasicSymbolRef::SF_FormatSpecific; 243*2dc0d9bdSRafael Espindola else if (auto *Var = dyn_cast<GlobalVariable>(GV)) { 244*2dc0d9bdSRafael Espindola if (Var->getSection() == StringRef("llvm.metadata")) 2453885090bSRafael Espindola Res |= BasicSymbolRef::SF_FormatSpecific; 2463885090bSRafael Espindola } 2473885090bSRafael Espindola 248f12b8282SRafael Espindola return Res; 249f12b8282SRafael Espindola } 250f12b8282SRafael Espindola 25113b69d63SRafael Espindola const GlobalValue *IRObjectFile::getSymbolGV(DataRefImpl Symb) const { 25213b69d63SRafael Espindola const GlobalValue *GV = getGV(Symb); 253f12b8282SRafael Espindola return GV; 254f12b8282SRafael Espindola } 255f12b8282SRafael Espindola 256f12b8282SRafael Espindola basic_symbol_iterator IRObjectFile::symbol_begin_impl() const { 257f12b8282SRafael Espindola Module::const_iterator I = M->begin(); 258f12b8282SRafael Espindola DataRefImpl Ret; 259f12b8282SRafael Espindola Ret.p = skipEmpty(I, *M); 260f12b8282SRafael Espindola return basic_symbol_iterator(BasicSymbolRef(Ret, this)); 261f12b8282SRafael Espindola } 262f12b8282SRafael Espindola 263f12b8282SRafael Espindola basic_symbol_iterator IRObjectFile::symbol_end_impl() const { 264f12b8282SRafael Espindola DataRefImpl Ret; 26513b69d63SRafael Espindola uint64_t NumAsm = AsmSymbols.size(); 26613b69d63SRafael Espindola NumAsm <<= 2; 26713b69d63SRafael Espindola Ret.p = 3 | NumAsm; 268f12b8282SRafael Espindola return basic_symbol_iterator(BasicSymbolRef(Ret, this)); 269f12b8282SRafael Espindola } 270f12b8282SRafael Espindola 27130f37f5fSRafael Espindola ErrorOr<IRObjectFile *> llvm::object::IRObjectFile::createIRObjectFile( 2722e60ca96SRafael Espindola std::unique_ptr<MemoryBuffer> Object, LLVMContext &Context) { 273dddd1fd9SRafael Espindola ErrorOr<Module *> MOrErr = getLazyBitcodeModule(Object.get(), Context); 274dddd1fd9SRafael Espindola if (std::error_code EC = MOrErr.getError()) 275f12b8282SRafael Espindola return EC; 276dddd1fd9SRafael Espindola 277dddd1fd9SRafael Espindola std::unique_ptr<Module> M(MOrErr.get()); 278dddd1fd9SRafael Espindola return new IRObjectFile(std::move(Object), std::move(M)); 279f12b8282SRafael Espindola } 280