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" 17f12b8282SRafael Espindola #include "llvm/Bitcode/ReaderWriter.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" 27d9903888SChandler Carruth #include "llvm/MC/MCRegisterInfo.h" 28d9903888SChandler Carruth #include "llvm/MC/MCTargetAsmParser.h" 2910039c02SPeter Collingbourne #include "llvm/Object/ObjectFile.h" 302e60ca96SRafael Espindola #include "llvm/Support/MemoryBuffer.h" 3113b69d63SRafael Espindola #include "llvm/Support/SourceMgr.h" 3213b69d63SRafael Espindola #include "llvm/Support/TargetRegistry.h" 3323f04061SRafael Espindola #include "llvm/Support/raw_ostream.h" 34f12b8282SRafael Espindola using namespace llvm; 35f12b8282SRafael Espindola using namespace object; 36f12b8282SRafael Espindola 3748af1c2aSRafael Espindola IRObjectFile::IRObjectFile(MemoryBufferRef Object, std::unique_ptr<Module> Mod) 3848af1c2aSRafael Espindola : SymbolicFile(Binary::ID_IR, Object), M(std::move(Mod)) { 3946a43556SMehdi Amini // Setup a mangler with the DataLayout. 4046a43556SMehdi Amini const DataLayout &DL = M->getDataLayout(); 4146a43556SMehdi Amini Mang.reset(new Mangler(&DL)); 4213b69d63SRafael Espindola 4313b69d63SRafael Espindola const std::string &InlineAsm = M->getModuleInlineAsm(); 4413b69d63SRafael Espindola if (InlineAsm.empty()) 4513b69d63SRafael Espindola return; 4613b69d63SRafael Espindola 4713b69d63SRafael Espindola StringRef Triple = M->getTargetTriple(); 4813b69d63SRafael Espindola std::string Err; 4913b69d63SRafael Espindola const Target *T = TargetRegistry::lookupTarget(Triple, Err); 5013b69d63SRafael Espindola if (!T) 5113b69d63SRafael Espindola return; 5213b69d63SRafael Espindola 5313b69d63SRafael Espindola std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(Triple)); 5413b69d63SRafael Espindola if (!MRI) 5513b69d63SRafael Espindola return; 5613b69d63SRafael Espindola 5713b69d63SRafael Espindola std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, Triple)); 5813b69d63SRafael Espindola if (!MAI) 5913b69d63SRafael Espindola return; 6013b69d63SRafael Espindola 6113b69d63SRafael Espindola std::unique_ptr<MCSubtargetInfo> STI( 6213b69d63SRafael Espindola T->createMCSubtargetInfo(Triple, "", "")); 6313b69d63SRafael Espindola if (!STI) 6413b69d63SRafael Espindola return; 6513b69d63SRafael Espindola 6613b69d63SRafael Espindola std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo()); 6713b69d63SRafael Espindola if (!MCII) 6813b69d63SRafael Espindola return; 6913b69d63SRafael Espindola 7013b69d63SRafael Espindola MCObjectFileInfo MOFI; 7113b69d63SRafael Espindola MCContext MCCtx(MAI.get(), MRI.get(), &MOFI); 7213b69d63SRafael Espindola MOFI.InitMCObjectFileInfo(Triple, Reloc::Default, CodeModel::Default, MCCtx); 7313b69d63SRafael Espindola std::unique_ptr<RecordStreamer> Streamer(new RecordStreamer(MCCtx)); 7420c7259cSPeter Collingbourne T->createNullTargetStreamer(*Streamer); 7513b69d63SRafael Espindola 7613b69d63SRafael Espindola std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm)); 7713b69d63SRafael Espindola SourceMgr SrcMgr; 781961f14cSDavid Blaikie SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); 7913b69d63SRafael Espindola std::unique_ptr<MCAsmParser> Parser( 8013b69d63SRafael Espindola createMCAsmParser(SrcMgr, MCCtx, *Streamer, *MAI)); 8113b69d63SRafael Espindola 8213b69d63SRafael Espindola MCTargetOptions MCOptions; 8313b69d63SRafael Espindola std::unique_ptr<MCTargetAsmParser> TAP( 8413b69d63SRafael Espindola T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions)); 8513b69d63SRafael Espindola if (!TAP) 8613b69d63SRafael Espindola return; 8713b69d63SRafael Espindola 8813b69d63SRafael Espindola Parser->setTargetParser(*TAP); 8913b69d63SRafael Espindola if (Parser->Run(false)) 9013b69d63SRafael Espindola return; 9113b69d63SRafael Espindola 9213b69d63SRafael Espindola for (auto &KV : *Streamer) { 9313b69d63SRafael Espindola StringRef Key = KV.first(); 9413b69d63SRafael Espindola RecordStreamer::State Value = KV.second; 9513b69d63SRafael Espindola uint32_t Res = BasicSymbolRef::SF_None; 9613b69d63SRafael Espindola switch (Value) { 9713b69d63SRafael Espindola case RecordStreamer::NeverSeen: 9813b69d63SRafael Espindola llvm_unreachable("foo"); 9913b69d63SRafael Espindola case RecordStreamer::DefinedGlobal: 10013b69d63SRafael Espindola Res |= BasicSymbolRef::SF_Global; 10113b69d63SRafael Espindola break; 10213b69d63SRafael Espindola case RecordStreamer::Defined: 10313b69d63SRafael Espindola break; 10413b69d63SRafael Espindola case RecordStreamer::Global: 10513b69d63SRafael Espindola case RecordStreamer::Used: 10613b69d63SRafael Espindola Res |= BasicSymbolRef::SF_Undefined; 10713b69d63SRafael Espindola Res |= BasicSymbolRef::SF_Global; 10813b69d63SRafael Espindola break; 10913b69d63SRafael Espindola } 11013b69d63SRafael Espindola AsmSymbols.push_back( 11113b69d63SRafael Espindola std::make_pair<std::string, uint32_t>(Key, std::move(Res))); 11213b69d63SRafael Espindola } 113f12b8282SRafael Espindola } 114f12b8282SRafael Espindola 115dddd1fd9SRafael Espindola IRObjectFile::~IRObjectFile() { 116dddd1fd9SRafael Espindola } 117c3f9b5a5SRafael Espindola 118527e846eSRafael Espindola static GlobalValue *getGV(DataRefImpl &Symb) { 11913b69d63SRafael Espindola if ((Symb.p & 3) == 3) 12013b69d63SRafael Espindola return nullptr; 12113b69d63SRafael Espindola 12213b69d63SRafael Espindola return reinterpret_cast<GlobalValue*>(Symb.p & ~uintptr_t(3)); 123f12b8282SRafael Espindola } 124f12b8282SRafael Espindola 125f12b8282SRafael Espindola static uintptr_t skipEmpty(Module::const_alias_iterator I, const Module &M) { 126f12b8282SRafael Espindola if (I == M.alias_end()) 127f12b8282SRafael Espindola return 3; 128f12b8282SRafael Espindola const GlobalValue *GV = &*I; 129f12b8282SRafael Espindola return reinterpret_cast<uintptr_t>(GV) | 2; 130f12b8282SRafael Espindola } 131f12b8282SRafael Espindola 132f12b8282SRafael Espindola static uintptr_t skipEmpty(Module::const_global_iterator I, const Module &M) { 133f12b8282SRafael Espindola if (I == M.global_end()) 134f12b8282SRafael Espindola return skipEmpty(M.alias_begin(), M); 135f12b8282SRafael Espindola const GlobalValue *GV = &*I; 136f12b8282SRafael Espindola return reinterpret_cast<uintptr_t>(GV) | 1; 137f12b8282SRafael Espindola } 138f12b8282SRafael Espindola 139f12b8282SRafael Espindola static uintptr_t skipEmpty(Module::const_iterator I, const Module &M) { 140f12b8282SRafael Espindola if (I == M.end()) 141f12b8282SRafael Espindola return skipEmpty(M.global_begin(), M); 142f12b8282SRafael Espindola const GlobalValue *GV = &*I; 143f12b8282SRafael Espindola return reinterpret_cast<uintptr_t>(GV) | 0; 144f12b8282SRafael Espindola } 145f12b8282SRafael Espindola 14613b69d63SRafael Espindola static unsigned getAsmSymIndex(DataRefImpl Symb) { 14713b69d63SRafael Espindola assert((Symb.p & uintptr_t(3)) == 3); 14813b69d63SRafael Espindola uintptr_t Index = Symb.p & ~uintptr_t(3); 14913b69d63SRafael Espindola Index >>= 2; 15013b69d63SRafael Espindola return Index; 15113b69d63SRafael Espindola } 15213b69d63SRafael Espindola 153f12b8282SRafael Espindola void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 15413b69d63SRafael Espindola const GlobalValue *GV = getGV(Symb); 155f12b8282SRafael Espindola uintptr_t Res; 15613b69d63SRafael Espindola 157f12b8282SRafael Espindola switch (Symb.p & 3) { 158f12b8282SRafael Espindola case 0: { 159f12b8282SRafael Espindola Module::const_iterator Iter(static_cast<const Function*>(GV)); 160f12b8282SRafael Espindola ++Iter; 16113b69d63SRafael Espindola Res = skipEmpty(Iter, *M); 162f12b8282SRafael Espindola break; 163f12b8282SRafael Espindola } 164f12b8282SRafael Espindola case 1: { 165f12b8282SRafael Espindola Module::const_global_iterator Iter(static_cast<const GlobalVariable*>(GV)); 166f12b8282SRafael Espindola ++Iter; 16713b69d63SRafael Espindola Res = skipEmpty(Iter, *M); 168f12b8282SRafael Espindola break; 169f12b8282SRafael Espindola } 170f12b8282SRafael Espindola case 2: { 171f12b8282SRafael Espindola Module::const_alias_iterator Iter(static_cast<const GlobalAlias*>(GV)); 172f12b8282SRafael Espindola ++Iter; 17313b69d63SRafael Espindola Res = skipEmpty(Iter, *M); 174f12b8282SRafael Espindola break; 175f12b8282SRafael Espindola } 17613b69d63SRafael Espindola case 3: { 17713b69d63SRafael Espindola unsigned Index = getAsmSymIndex(Symb); 17813b69d63SRafael Espindola assert(Index < AsmSymbols.size()); 17913b69d63SRafael Espindola ++Index; 18013b69d63SRafael Espindola Res = (Index << 2) | 3; 18113b69d63SRafael Espindola break; 18213b69d63SRafael Espindola } 183addddc44SMichael Ilseman default: 184addddc44SMichael Ilseman llvm_unreachable("unreachable case"); 185f12b8282SRafael Espindola } 186f12b8282SRafael Espindola 187f12b8282SRafael Espindola Symb.p = Res; 188f12b8282SRafael Espindola } 189f12b8282SRafael Espindola 190db4ed0bdSRafael Espindola std::error_code IRObjectFile::printSymbolName(raw_ostream &OS, 191f12b8282SRafael Espindola DataRefImpl Symb) const { 19213b69d63SRafael Espindola const GlobalValue *GV = getGV(Symb); 19313b69d63SRafael Espindola if (!GV) { 19413b69d63SRafael Espindola unsigned Index = getAsmSymIndex(Symb); 19513b69d63SRafael Espindola assert(Index <= AsmSymbols.size()); 19613b69d63SRafael Espindola OS << AsmSymbols[Index].first; 19713b69d63SRafael Espindola return object_error::success;; 19813b69d63SRafael Espindola } 199a51f0f83SRafael Espindola 200a51f0f83SRafael Espindola if (Mang) 20113b69d63SRafael Espindola Mang->getNameWithPrefix(OS, GV, false); 202a51f0f83SRafael Espindola else 20313b69d63SRafael Espindola OS << GV->getName(); 204a51f0f83SRafael Espindola 205f12b8282SRafael Espindola return object_error::success; 206f12b8282SRafael Espindola } 207f12b8282SRafael Espindola 208f12b8282SRafael Espindola uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { 20913b69d63SRafael Espindola const GlobalValue *GV = getGV(Symb); 21013b69d63SRafael Espindola 21113b69d63SRafael Espindola if (!GV) { 21213b69d63SRafael Espindola unsigned Index = getAsmSymIndex(Symb); 21313b69d63SRafael Espindola assert(Index <= AsmSymbols.size()); 21413b69d63SRafael Espindola return AsmSymbols[Index].second; 21513b69d63SRafael Espindola } 216f12b8282SRafael Espindola 217f12b8282SRafael Espindola uint32_t Res = BasicSymbolRef::SF_None; 218d4bcefc7SRafael Espindola if (GV->isDeclarationForLinker()) 219f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Undefined; 22013b69d63SRafael Espindola if (GV->hasPrivateLinkage()) 221f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_FormatSpecific; 22213b69d63SRafael Espindola if (!GV->hasLocalLinkage()) 223f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Global; 22413b69d63SRafael Espindola if (GV->hasCommonLinkage()) 225f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Common; 22613b69d63SRafael Espindola if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage()) 227f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Weak; 228f12b8282SRafael Espindola 2292dc0d9bdSRafael Espindola if (GV->getName().startswith("llvm.")) 230b674c17dSRafael Espindola Res |= BasicSymbolRef::SF_FormatSpecific; 2312dc0d9bdSRafael Espindola else if (auto *Var = dyn_cast<GlobalVariable>(GV)) { 2322dc0d9bdSRafael Espindola if (Var->getSection() == StringRef("llvm.metadata")) 2333885090bSRafael Espindola Res |= BasicSymbolRef::SF_FormatSpecific; 2343885090bSRafael Espindola } 2353885090bSRafael Espindola 236f12b8282SRafael Espindola return Res; 237f12b8282SRafael Espindola } 238f12b8282SRafael Espindola 239527e846eSRafael Espindola GlobalValue *IRObjectFile::getSymbolGV(DataRefImpl Symb) { return getGV(Symb); } 240f12b8282SRafael Espindola 24125a7e0a8SRafael Espindola std::unique_ptr<Module> IRObjectFile::takeModule() { return std::move(M); } 24225a7e0a8SRafael Espindola 243f12b8282SRafael Espindola basic_symbol_iterator IRObjectFile::symbol_begin_impl() const { 244f12b8282SRafael Espindola Module::const_iterator I = M->begin(); 245f12b8282SRafael Espindola DataRefImpl Ret; 246f12b8282SRafael Espindola Ret.p = skipEmpty(I, *M); 247f12b8282SRafael Espindola return basic_symbol_iterator(BasicSymbolRef(Ret, this)); 248f12b8282SRafael Espindola } 249f12b8282SRafael Espindola 250f12b8282SRafael Espindola basic_symbol_iterator IRObjectFile::symbol_end_impl() const { 251f12b8282SRafael Espindola DataRefImpl Ret; 25213b69d63SRafael Espindola uint64_t NumAsm = AsmSymbols.size(); 25313b69d63SRafael Espindola NumAsm <<= 2; 25413b69d63SRafael Espindola Ret.p = 3 | NumAsm; 255f12b8282SRafael Espindola return basic_symbol_iterator(BasicSymbolRef(Ret, this)); 256f12b8282SRafael Espindola } 257f12b8282SRafael Espindola 25810039c02SPeter Collingbourne ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) { 25910039c02SPeter Collingbourne for (const SectionRef &Sec : Obj.sections()) { 26010039c02SPeter Collingbourne StringRef SecName; 26110039c02SPeter Collingbourne if (std::error_code EC = Sec.getName(SecName)) 26210039c02SPeter Collingbourne return EC; 26310039c02SPeter Collingbourne if (SecName == ".llvmbc") { 26410039c02SPeter Collingbourne StringRef SecContents; 26510039c02SPeter Collingbourne if (std::error_code EC = Sec.getContents(SecContents)) 26610039c02SPeter Collingbourne return EC; 26710039c02SPeter Collingbourne return MemoryBufferRef(SecContents, Obj.getFileName()); 26810039c02SPeter Collingbourne } 26910039c02SPeter Collingbourne } 27010039c02SPeter Collingbourne 27110039c02SPeter Collingbourne return object_error::bitcode_section_not_found; 27210039c02SPeter Collingbourne } 27310039c02SPeter Collingbourne 27410039c02SPeter Collingbourne ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) { 27510039c02SPeter Collingbourne sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer()); 27610039c02SPeter Collingbourne switch (Type) { 27710039c02SPeter Collingbourne case sys::fs::file_magic::bitcode: 27810039c02SPeter Collingbourne return Object; 27910039c02SPeter Collingbourne case sys::fs::file_magic::elf_relocatable: 28010039c02SPeter Collingbourne case sys::fs::file_magic::macho_object: 28110039c02SPeter Collingbourne case sys::fs::file_magic::coff_object: { 28210039c02SPeter Collingbourne ErrorOr<std::unique_ptr<ObjectFile>> ObjFile = 28310039c02SPeter Collingbourne ObjectFile::createObjectFile(Object, Type); 28410039c02SPeter Collingbourne if (!ObjFile) 28510039c02SPeter Collingbourne return ObjFile.getError(); 28610039c02SPeter Collingbourne return findBitcodeInObject(*ObjFile->get()); 28710039c02SPeter Collingbourne } 28810039c02SPeter Collingbourne default: 28910039c02SPeter Collingbourne return object_error::invalid_file_type; 29010039c02SPeter Collingbourne } 29110039c02SPeter Collingbourne } 29210039c02SPeter Collingbourne 29310a27df8SDavid Blaikie ErrorOr<std::unique_ptr<IRObjectFile>> 2945dec7eaaSRafael Espindola llvm::object::IRObjectFile::create(MemoryBufferRef Object, 29548af1c2aSRafael Espindola LLVMContext &Context) { 29610039c02SPeter Collingbourne ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object); 29710039c02SPeter Collingbourne if (!BCOrErr) 29810039c02SPeter Collingbourne return BCOrErr.getError(); 29948af1c2aSRafael Espindola 30010039c02SPeter Collingbourne std::unique_ptr<MemoryBuffer> Buff( 30110039c02SPeter Collingbourne MemoryBuffer::getMemBuffer(BCOrErr.get(), false)); 30248af1c2aSRafael Espindola 303*cba833a0SRafael Espindola ErrorOr<Module *> MOrErr = 304*cba833a0SRafael Espindola getLazyBitcodeModule(std::move(Buff), Context, nullptr, 305*cba833a0SRafael Espindola /*ShouldLazyLoadMetadata*/ true); 306dddd1fd9SRafael Espindola if (std::error_code EC = MOrErr.getError()) 307f12b8282SRafael Espindola return EC; 308dddd1fd9SRafael Espindola 309dddd1fd9SRafael Espindola std::unique_ptr<Module> M(MOrErr.get()); 31010a27df8SDavid Blaikie return llvm::make_unique<IRObjectFile>(Object, std::move(M)); 311f12b8282SRafael Espindola } 312