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" 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)) { 40c233f74eSRafael Espindola Mang.reset(new Mangler()); 41b0b52fc4SBenjamin Kramer CollectAsmUndefinedRefs(Triple(M->getTargetTriple()), M->getModuleInlineAsm(), 42a0cb890fSMehdi Amini [this](StringRef Name, BasicSymbolRef::Flags Flags) { 43b0b52fc4SBenjamin Kramer AsmSymbols.emplace_back(Name, std::move(Flags)); 44e9cffafdSMehdi Amini }); 45e9cffafdSMehdi Amini } 4613b69d63SRafael Espindola 47e9cffafdSMehdi Amini // Parse inline ASM and collect the list of symbols that are not defined in 48e9cffafdSMehdi Amini // the current module. This is inspired from IRObjectFile. 49e9cffafdSMehdi Amini void IRObjectFile::CollectAsmUndefinedRefs( 50a0cb890fSMehdi Amini const Triple &TT, StringRef InlineAsm, 51b0b52fc4SBenjamin Kramer function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmUndefinedRefs) { 5213b69d63SRafael Espindola if (InlineAsm.empty()) 5313b69d63SRafael Espindola return; 5413b69d63SRafael Espindola 5513b69d63SRafael Espindola std::string Err; 568d8b13dcSDaniel Sanders const Target *T = TargetRegistry::lookupTarget(TT.str(), Err); 5713b69d63SRafael Espindola if (!T) 5813b69d63SRafael Espindola return; 5913b69d63SRafael Espindola 608d8b13dcSDaniel Sanders std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TT.str())); 6113b69d63SRafael Espindola if (!MRI) 6213b69d63SRafael Espindola return; 6313b69d63SRafael Espindola 648d8b13dcSDaniel Sanders std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TT.str())); 6513b69d63SRafael Espindola if (!MAI) 6613b69d63SRafael Espindola return; 6713b69d63SRafael Espindola 6813b69d63SRafael Espindola std::unique_ptr<MCSubtargetInfo> STI( 698d8b13dcSDaniel Sanders T->createMCSubtargetInfo(TT.str(), "", "")); 7013b69d63SRafael Espindola if (!STI) 7113b69d63SRafael Espindola return; 7213b69d63SRafael Espindola 7313b69d63SRafael Espindola std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo()); 7413b69d63SRafael Espindola if (!MCII) 7513b69d63SRafael Espindola return; 7613b69d63SRafael Espindola 7713b69d63SRafael Espindola MCObjectFileInfo MOFI; 7813b69d63SRafael Espindola MCContext MCCtx(MAI.get(), MRI.get(), &MOFI); 79699281ccSRafael Espindola MOFI.InitMCObjectFileInfo(TT, /*PIC*/ false, CodeModel::Default, MCCtx); 8013b69d63SRafael Espindola std::unique_ptr<RecordStreamer> Streamer(new RecordStreamer(MCCtx)); 8120c7259cSPeter Collingbourne T->createNullTargetStreamer(*Streamer); 8213b69d63SRafael Espindola 8313b69d63SRafael Espindola std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm)); 8413b69d63SRafael Espindola SourceMgr SrcMgr; 851961f14cSDavid Blaikie SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); 8613b69d63SRafael Espindola std::unique_ptr<MCAsmParser> Parser( 8713b69d63SRafael Espindola createMCAsmParser(SrcMgr, MCCtx, *Streamer, *MAI)); 8813b69d63SRafael Espindola 8913b69d63SRafael Espindola MCTargetOptions MCOptions; 9013b69d63SRafael Espindola std::unique_ptr<MCTargetAsmParser> TAP( 9113b69d63SRafael Espindola T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions)); 9213b69d63SRafael Espindola if (!TAP) 9313b69d63SRafael Espindola return; 9413b69d63SRafael Espindola 9513b69d63SRafael Espindola Parser->setTargetParser(*TAP); 9613b69d63SRafael Espindola if (Parser->Run(false)) 9713b69d63SRafael Espindola return; 9813b69d63SRafael Espindola 9913b69d63SRafael Espindola for (auto &KV : *Streamer) { 10013b69d63SRafael Espindola StringRef Key = KV.first(); 10113b69d63SRafael Espindola RecordStreamer::State Value = KV.second; 10213b69d63SRafael Espindola uint32_t Res = BasicSymbolRef::SF_None; 10313b69d63SRafael Espindola switch (Value) { 10413b69d63SRafael Espindola case RecordStreamer::NeverSeen: 105cc1aa053SDavide Italiano llvm_unreachable("NeverSeen should have been replaced earlier"); 10613b69d63SRafael Espindola case RecordStreamer::DefinedGlobal: 10713b69d63SRafael Espindola Res |= BasicSymbolRef::SF_Global; 10813b69d63SRafael Espindola break; 10913b69d63SRafael Espindola case RecordStreamer::Defined: 11013b69d63SRafael Espindola break; 11113b69d63SRafael Espindola case RecordStreamer::Global: 11213b69d63SRafael Espindola case RecordStreamer::Used: 11313b69d63SRafael Espindola Res |= BasicSymbolRef::SF_Undefined; 11413b69d63SRafael Espindola Res |= BasicSymbolRef::SF_Global; 11513b69d63SRafael Espindola break; 116f7518498SDavide Italiano case RecordStreamer::DefinedWeak: 117ec7e29e9SDavide Italiano Res |= BasicSymbolRef::SF_Weak; 118ec7e29e9SDavide Italiano Res |= BasicSymbolRef::SF_Global; 11936c54fb7SDavide Italiano break; 120f7518498SDavide Italiano case RecordStreamer::UndefinedWeak: 121f7518498SDavide Italiano Res |= BasicSymbolRef::SF_Weak; 122f7518498SDavide Italiano Res |= BasicSymbolRef::SF_Undefined; 12313b69d63SRafael Espindola } 124e9cffafdSMehdi Amini AsmUndefinedRefs(Key, BasicSymbolRef::Flags(Res)); 12513b69d63SRafael Espindola } 126f12b8282SRafael Espindola } 127f12b8282SRafael Espindola 128dddd1fd9SRafael Espindola IRObjectFile::~IRObjectFile() { 129dddd1fd9SRafael Espindola } 130c3f9b5a5SRafael Espindola 131527e846eSRafael Espindola static GlobalValue *getGV(DataRefImpl &Symb) { 13213b69d63SRafael Espindola if ((Symb.p & 3) == 3) 13313b69d63SRafael Espindola return nullptr; 13413b69d63SRafael Espindola 13513b69d63SRafael Espindola return reinterpret_cast<GlobalValue*>(Symb.p & ~uintptr_t(3)); 136f12b8282SRafael Espindola } 137f12b8282SRafael Espindola 138f12b8282SRafael Espindola static uintptr_t skipEmpty(Module::const_alias_iterator I, const Module &M) { 139f12b8282SRafael Espindola if (I == M.alias_end()) 140f12b8282SRafael Espindola return 3; 141f12b8282SRafael Espindola const GlobalValue *GV = &*I; 142f12b8282SRafael Espindola return reinterpret_cast<uintptr_t>(GV) | 2; 143f12b8282SRafael Espindola } 144f12b8282SRafael Espindola 145f12b8282SRafael Espindola static uintptr_t skipEmpty(Module::const_global_iterator I, const Module &M) { 146f12b8282SRafael Espindola if (I == M.global_end()) 147f12b8282SRafael Espindola return skipEmpty(M.alias_begin(), M); 148f12b8282SRafael Espindola const GlobalValue *GV = &*I; 149f12b8282SRafael Espindola return reinterpret_cast<uintptr_t>(GV) | 1; 150f12b8282SRafael Espindola } 151f12b8282SRafael Espindola 152f12b8282SRafael Espindola static uintptr_t skipEmpty(Module::const_iterator I, const Module &M) { 153f12b8282SRafael Espindola if (I == M.end()) 154f12b8282SRafael Espindola return skipEmpty(M.global_begin(), M); 155f12b8282SRafael Espindola const GlobalValue *GV = &*I; 156f12b8282SRafael Espindola return reinterpret_cast<uintptr_t>(GV) | 0; 157f12b8282SRafael Espindola } 158f12b8282SRafael Espindola 15913b69d63SRafael Espindola static unsigned getAsmSymIndex(DataRefImpl Symb) { 16013b69d63SRafael Espindola assert((Symb.p & uintptr_t(3)) == 3); 16113b69d63SRafael Espindola uintptr_t Index = Symb.p & ~uintptr_t(3); 16213b69d63SRafael Espindola Index >>= 2; 16313b69d63SRafael Espindola return Index; 16413b69d63SRafael Espindola } 16513b69d63SRafael Espindola 166f12b8282SRafael Espindola void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 16713b69d63SRafael Espindola const GlobalValue *GV = getGV(Symb); 168f12b8282SRafael Espindola uintptr_t Res; 16913b69d63SRafael Espindola 170f12b8282SRafael Espindola switch (Symb.p & 3) { 171f12b8282SRafael Espindola case 0: { 172f12b8282SRafael Espindola Module::const_iterator Iter(static_cast<const Function*>(GV)); 173f12b8282SRafael Espindola ++Iter; 17413b69d63SRafael Espindola Res = skipEmpty(Iter, *M); 175f12b8282SRafael Espindola break; 176f12b8282SRafael Espindola } 177f12b8282SRafael Espindola case 1: { 178f12b8282SRafael Espindola Module::const_global_iterator Iter(static_cast<const GlobalVariable*>(GV)); 179f12b8282SRafael Espindola ++Iter; 18013b69d63SRafael Espindola Res = skipEmpty(Iter, *M); 181f12b8282SRafael Espindola break; 182f12b8282SRafael Espindola } 183f12b8282SRafael Espindola case 2: { 184f12b8282SRafael Espindola Module::const_alias_iterator Iter(static_cast<const GlobalAlias*>(GV)); 185f12b8282SRafael Espindola ++Iter; 18613b69d63SRafael Espindola Res = skipEmpty(Iter, *M); 187f12b8282SRafael Espindola break; 188f12b8282SRafael Espindola } 18913b69d63SRafael Espindola case 3: { 19013b69d63SRafael Espindola unsigned Index = getAsmSymIndex(Symb); 19113b69d63SRafael Espindola assert(Index < AsmSymbols.size()); 19213b69d63SRafael Espindola ++Index; 19313b69d63SRafael Espindola Res = (Index << 2) | 3; 19413b69d63SRafael Espindola break; 19513b69d63SRafael Espindola } 196addddc44SMichael Ilseman default: 197addddc44SMichael Ilseman llvm_unreachable("unreachable case"); 198f12b8282SRafael Espindola } 199f12b8282SRafael Espindola 200f12b8282SRafael Espindola Symb.p = Res; 201f12b8282SRafael Espindola } 202f12b8282SRafael Espindola 203db4ed0bdSRafael Espindola std::error_code IRObjectFile::printSymbolName(raw_ostream &OS, 204f12b8282SRafael Espindola DataRefImpl Symb) const { 20513b69d63SRafael Espindola const GlobalValue *GV = getGV(Symb); 20613b69d63SRafael Espindola if (!GV) { 20713b69d63SRafael Espindola unsigned Index = getAsmSymIndex(Symb); 20813b69d63SRafael Espindola assert(Index <= AsmSymbols.size()); 20913b69d63SRafael Espindola OS << AsmSymbols[Index].first; 2107d099195SRui Ueyama return std::error_code(); 21113b69d63SRafael Espindola } 212a51f0f83SRafael Espindola 21382e657b5SPeter Collingbourne if (GV->hasDLLImportStorageClass()) 21482e657b5SPeter Collingbourne OS << "__imp_"; 21582e657b5SPeter Collingbourne 216a51f0f83SRafael Espindola if (Mang) 21713b69d63SRafael Espindola Mang->getNameWithPrefix(OS, GV, false); 218a51f0f83SRafael Espindola else 21913b69d63SRafael Espindola OS << GV->getName(); 220a51f0f83SRafael Espindola 2217d099195SRui Ueyama return std::error_code(); 222f12b8282SRafael Espindola } 223f12b8282SRafael Espindola 224f12b8282SRafael Espindola uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { 22513b69d63SRafael Espindola const GlobalValue *GV = getGV(Symb); 22613b69d63SRafael Espindola 22713b69d63SRafael Espindola if (!GV) { 22813b69d63SRafael Espindola unsigned Index = getAsmSymIndex(Symb); 22913b69d63SRafael Espindola assert(Index <= AsmSymbols.size()); 23013b69d63SRafael Espindola return AsmSymbols[Index].second; 23113b69d63SRafael Espindola } 232f12b8282SRafael Espindola 233f12b8282SRafael Espindola uint32_t Res = BasicSymbolRef::SF_None; 234d4bcefc7SRafael Espindola if (GV->isDeclarationForLinker()) 235f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Undefined; 236dc0dbe1fSKevin Enderby else if (GV->hasHiddenVisibility() && !GV->hasLocalLinkage()) 237dc0dbe1fSKevin Enderby Res |= BasicSymbolRef::SF_Hidden; 238dc0dbe1fSKevin Enderby if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) { 239dc0dbe1fSKevin Enderby if (GVar->isConstant()) 240dc0dbe1fSKevin Enderby Res |= BasicSymbolRef::SF_Const; 241dc0dbe1fSKevin Enderby } 24213b69d63SRafael Espindola if (GV->hasPrivateLinkage()) 243f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_FormatSpecific; 24413b69d63SRafael Espindola if (!GV->hasLocalLinkage()) 245f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Global; 24613b69d63SRafael Espindola if (GV->hasCommonLinkage()) 247f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Common; 2488d6fbc3aSRafael Espindola if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() || 2498d6fbc3aSRafael Espindola GV->hasExternalWeakLinkage()) 250f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Weak; 251f12b8282SRafael Espindola 2522dc0d9bdSRafael Espindola if (GV->getName().startswith("llvm.")) 253b674c17dSRafael Espindola Res |= BasicSymbolRef::SF_FormatSpecific; 2542dc0d9bdSRafael Espindola else if (auto *Var = dyn_cast<GlobalVariable>(GV)) { 25583658d6eSRafael Espindola if (Var->getSection() == "llvm.metadata") 2563885090bSRafael Espindola Res |= BasicSymbolRef::SF_FormatSpecific; 2573885090bSRafael Espindola } 2583885090bSRafael Espindola 259f12b8282SRafael Espindola return Res; 260f12b8282SRafael Espindola } 261f12b8282SRafael Espindola 262527e846eSRafael Espindola GlobalValue *IRObjectFile::getSymbolGV(DataRefImpl Symb) { return getGV(Symb); } 263f12b8282SRafael Espindola 26425a7e0a8SRafael Espindola std::unique_ptr<Module> IRObjectFile::takeModule() { return std::move(M); } 26525a7e0a8SRafael Espindola 266f12b8282SRafael Espindola basic_symbol_iterator IRObjectFile::symbol_begin_impl() const { 267f12b8282SRafael Espindola Module::const_iterator I = M->begin(); 268f12b8282SRafael Espindola DataRefImpl Ret; 269f12b8282SRafael Espindola Ret.p = skipEmpty(I, *M); 270f12b8282SRafael Espindola return basic_symbol_iterator(BasicSymbolRef(Ret, this)); 271f12b8282SRafael Espindola } 272f12b8282SRafael Espindola 273f12b8282SRafael Espindola basic_symbol_iterator IRObjectFile::symbol_end_impl() const { 274f12b8282SRafael Espindola DataRefImpl Ret; 27513b69d63SRafael Espindola uint64_t NumAsm = AsmSymbols.size(); 27613b69d63SRafael Espindola NumAsm <<= 2; 27713b69d63SRafael Espindola Ret.p = 3 | NumAsm; 278f12b8282SRafael Espindola return basic_symbol_iterator(BasicSymbolRef(Ret, this)); 279f12b8282SRafael Espindola } 280f12b8282SRafael Espindola 28110039c02SPeter Collingbourne ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) { 28210039c02SPeter Collingbourne for (const SectionRef &Sec : Obj.sections()) { 283f2fe0141SSteven Wu if (Sec.isBitcode()) { 28410039c02SPeter Collingbourne StringRef SecContents; 28510039c02SPeter Collingbourne if (std::error_code EC = Sec.getContents(SecContents)) 28610039c02SPeter Collingbourne return EC; 28710039c02SPeter Collingbourne return MemoryBufferRef(SecContents, Obj.getFileName()); 28810039c02SPeter Collingbourne } 28910039c02SPeter Collingbourne } 29010039c02SPeter Collingbourne 29110039c02SPeter Collingbourne return object_error::bitcode_section_not_found; 29210039c02SPeter Collingbourne } 29310039c02SPeter Collingbourne 29410039c02SPeter Collingbourne ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) { 29510039c02SPeter Collingbourne sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer()); 29610039c02SPeter Collingbourne switch (Type) { 29710039c02SPeter Collingbourne case sys::fs::file_magic::bitcode: 29810039c02SPeter Collingbourne return Object; 29910039c02SPeter Collingbourne case sys::fs::file_magic::elf_relocatable: 30010039c02SPeter Collingbourne case sys::fs::file_magic::macho_object: 30110039c02SPeter Collingbourne case sys::fs::file_magic::coff_object: { 3023fcdf6aeSKevin Enderby Expected<std::unique_ptr<ObjectFile>> ObjFile = 30310039c02SPeter Collingbourne ObjectFile::createObjectFile(Object, Type); 30410039c02SPeter Collingbourne if (!ObjFile) 3053fcdf6aeSKevin Enderby return errorToErrorCode(ObjFile.takeError()); 30610039c02SPeter Collingbourne return findBitcodeInObject(*ObjFile->get()); 30710039c02SPeter Collingbourne } 30810039c02SPeter Collingbourne default: 30910039c02SPeter Collingbourne return object_error::invalid_file_type; 31010039c02SPeter Collingbourne } 31110039c02SPeter Collingbourne } 31210039c02SPeter Collingbourne 31310a27df8SDavid Blaikie ErrorOr<std::unique_ptr<IRObjectFile>> 3145dec7eaaSRafael Espindola llvm::object::IRObjectFile::create(MemoryBufferRef Object, 31548af1c2aSRafael Espindola LLVMContext &Context) { 31610039c02SPeter Collingbourne ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object); 31710039c02SPeter Collingbourne if (!BCOrErr) 31810039c02SPeter Collingbourne return BCOrErr.getError(); 31948af1c2aSRafael Espindola 320dcd1dca2SRafael Espindola ErrorOr<std::unique_ptr<Module>> MOrErr = 321*e2dcf7c3SPeter Collingbourne getLazyBitcodeModule(*BCOrErr, Context, 322cba833a0SRafael Espindola /*ShouldLazyLoadMetadata*/ true); 323dddd1fd9SRafael Espindola if (std::error_code EC = MOrErr.getError()) 324f12b8282SRafael Espindola return EC; 325dddd1fd9SRafael Espindola 326dcd1dca2SRafael Espindola std::unique_ptr<Module> &M = MOrErr.get(); 3279ba95f99STeresa Johnson return llvm::make_unique<IRObjectFile>(BCOrErr.get(), std::move(M)); 328f12b8282SRafael Espindola } 329