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)) { 40c233f74eSRafael Espindola Mang.reset(new Mangler()); 41*e32baa0cSPeter Collingbourne 42*e32baa0cSPeter Collingbourne for (Function &F : *M) 43*e32baa0cSPeter Collingbourne SymTab.push_back(&F); 44*e32baa0cSPeter Collingbourne for (GlobalVariable &GV : M->globals()) 45*e32baa0cSPeter Collingbourne SymTab.push_back(&GV); 46*e32baa0cSPeter Collingbourne for (GlobalAlias &GA : M->aliases()) 47*e32baa0cSPeter Collingbourne SymTab.push_back(&GA); 48*e32baa0cSPeter Collingbourne 49b0b52fc4SBenjamin Kramer CollectAsmUndefinedRefs(Triple(M->getTargetTriple()), M->getModuleInlineAsm(), 50a0cb890fSMehdi Amini [this](StringRef Name, BasicSymbolRef::Flags Flags) { 51*e32baa0cSPeter Collingbourne SymTab.push_back(new (AsmSymbols.Allocate()) 52*e32baa0cSPeter Collingbourne AsmSymbol(Name, Flags)); 53e9cffafdSMehdi Amini }); 54e9cffafdSMehdi Amini } 5513b69d63SRafael Espindola 56e9cffafdSMehdi Amini // Parse inline ASM and collect the list of symbols that are not defined in 57e9cffafdSMehdi Amini // the current module. This is inspired from IRObjectFile. 58e9cffafdSMehdi Amini void IRObjectFile::CollectAsmUndefinedRefs( 59a0cb890fSMehdi Amini const Triple &TT, StringRef InlineAsm, 60b0b52fc4SBenjamin Kramer function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmUndefinedRefs) { 6113b69d63SRafael Espindola if (InlineAsm.empty()) 6213b69d63SRafael Espindola return; 6313b69d63SRafael Espindola 6413b69d63SRafael Espindola std::string Err; 658d8b13dcSDaniel Sanders const Target *T = TargetRegistry::lookupTarget(TT.str(), Err); 663624bdf6STeresa Johnson assert(T && T->hasMCAsmParser()); 6713b69d63SRafael Espindola 688d8b13dcSDaniel Sanders std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TT.str())); 6913b69d63SRafael Espindola if (!MRI) 7013b69d63SRafael Espindola return; 7113b69d63SRafael Espindola 728d8b13dcSDaniel Sanders std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TT.str())); 7313b69d63SRafael Espindola if (!MAI) 7413b69d63SRafael Espindola return; 7513b69d63SRafael Espindola 7613b69d63SRafael Espindola std::unique_ptr<MCSubtargetInfo> STI( 778d8b13dcSDaniel Sanders T->createMCSubtargetInfo(TT.str(), "", "")); 7813b69d63SRafael Espindola if (!STI) 7913b69d63SRafael Espindola return; 8013b69d63SRafael Espindola 8113b69d63SRafael Espindola std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo()); 8213b69d63SRafael Espindola if (!MCII) 8313b69d63SRafael Espindola return; 8413b69d63SRafael Espindola 8513b69d63SRafael Espindola MCObjectFileInfo MOFI; 8613b69d63SRafael Espindola MCContext MCCtx(MAI.get(), MRI.get(), &MOFI); 87699281ccSRafael Espindola MOFI.InitMCObjectFileInfo(TT, /*PIC*/ false, CodeModel::Default, MCCtx); 8863e10c9cSPeter Collingbourne RecordStreamer Streamer(MCCtx); 8963e10c9cSPeter Collingbourne T->createNullTargetStreamer(Streamer); 9013b69d63SRafael Espindola 9113b69d63SRafael Espindola std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm)); 9213b69d63SRafael Espindola SourceMgr SrcMgr; 931961f14cSDavid Blaikie SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); 9413b69d63SRafael Espindola std::unique_ptr<MCAsmParser> Parser( 9563e10c9cSPeter Collingbourne createMCAsmParser(SrcMgr, MCCtx, Streamer, *MAI)); 9613b69d63SRafael Espindola 9713b69d63SRafael Espindola MCTargetOptions MCOptions; 9813b69d63SRafael Espindola std::unique_ptr<MCTargetAsmParser> TAP( 9913b69d63SRafael Espindola T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions)); 10013b69d63SRafael Espindola if (!TAP) 10113b69d63SRafael Espindola return; 10213b69d63SRafael Espindola 10313b69d63SRafael Espindola Parser->setTargetParser(*TAP); 10413b69d63SRafael Espindola if (Parser->Run(false)) 10513b69d63SRafael Espindola return; 10613b69d63SRafael Espindola 10763e10c9cSPeter Collingbourne for (auto &KV : Streamer) { 10813b69d63SRafael Espindola StringRef Key = KV.first(); 10913b69d63SRafael Espindola RecordStreamer::State Value = KV.second; 11013b69d63SRafael Espindola uint32_t Res = BasicSymbolRef::SF_None; 11113b69d63SRafael Espindola switch (Value) { 11213b69d63SRafael Espindola case RecordStreamer::NeverSeen: 113cc1aa053SDavide Italiano llvm_unreachable("NeverSeen should have been replaced earlier"); 11413b69d63SRafael Espindola case RecordStreamer::DefinedGlobal: 11513b69d63SRafael Espindola Res |= BasicSymbolRef::SF_Global; 11613b69d63SRafael Espindola break; 11713b69d63SRafael Espindola case RecordStreamer::Defined: 11813b69d63SRafael Espindola break; 11913b69d63SRafael Espindola case RecordStreamer::Global: 12013b69d63SRafael Espindola case RecordStreamer::Used: 12113b69d63SRafael Espindola Res |= BasicSymbolRef::SF_Undefined; 12213b69d63SRafael Espindola Res |= BasicSymbolRef::SF_Global; 12313b69d63SRafael Espindola break; 124f7518498SDavide Italiano case RecordStreamer::DefinedWeak: 125ec7e29e9SDavide Italiano Res |= BasicSymbolRef::SF_Weak; 126ec7e29e9SDavide Italiano Res |= BasicSymbolRef::SF_Global; 12736c54fb7SDavide Italiano break; 128f7518498SDavide Italiano case RecordStreamer::UndefinedWeak: 129f7518498SDavide Italiano Res |= BasicSymbolRef::SF_Weak; 130f7518498SDavide Italiano Res |= BasicSymbolRef::SF_Undefined; 13113b69d63SRafael Espindola } 132e9cffafdSMehdi Amini AsmUndefinedRefs(Key, BasicSymbolRef::Flags(Res)); 13313b69d63SRafael Espindola } 134f12b8282SRafael Espindola } 135f12b8282SRafael Espindola 136*e32baa0cSPeter Collingbourne IRObjectFile::~IRObjectFile() {} 13713b69d63SRafael Espindola 138f12b8282SRafael Espindola void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 139*e32baa0cSPeter Collingbourne Symb.p += sizeof(Sym); 140f12b8282SRafael Espindola } 141f12b8282SRafael Espindola 142db4ed0bdSRafael Espindola std::error_code IRObjectFile::printSymbolName(raw_ostream &OS, 143f12b8282SRafael Espindola DataRefImpl Symb) const { 144*e32baa0cSPeter Collingbourne Sym S = getSym(Symb); 145*e32baa0cSPeter Collingbourne if (S.is<AsmSymbol *>()) { 146*e32baa0cSPeter Collingbourne OS << S.get<AsmSymbol *>()->first; 1477d099195SRui Ueyama return std::error_code(); 14813b69d63SRafael Espindola } 149a51f0f83SRafael Espindola 150*e32baa0cSPeter Collingbourne auto *GV = S.get<GlobalValue *>(); 15182e657b5SPeter Collingbourne if (GV->hasDLLImportStorageClass()) 15282e657b5SPeter Collingbourne OS << "__imp_"; 15382e657b5SPeter Collingbourne 154a51f0f83SRafael Espindola if (Mang) 15513b69d63SRafael Espindola Mang->getNameWithPrefix(OS, GV, false); 156a51f0f83SRafael Espindola else 15713b69d63SRafael Espindola OS << GV->getName(); 158a51f0f83SRafael Espindola 1597d099195SRui Ueyama return std::error_code(); 160f12b8282SRafael Espindola } 161f12b8282SRafael Espindola 162f12b8282SRafael Espindola uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { 163*e32baa0cSPeter Collingbourne Sym S = getSym(Symb); 164*e32baa0cSPeter Collingbourne if (S.is<AsmSymbol *>()) 165*e32baa0cSPeter Collingbourne return S.get<AsmSymbol *>()->second; 16613b69d63SRafael Espindola 167*e32baa0cSPeter Collingbourne auto *GV = S.get<GlobalValue *>(); 168f12b8282SRafael Espindola 169f12b8282SRafael Espindola uint32_t Res = BasicSymbolRef::SF_None; 170d4bcefc7SRafael Espindola if (GV->isDeclarationForLinker()) 171f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Undefined; 172dc0dbe1fSKevin Enderby else if (GV->hasHiddenVisibility() && !GV->hasLocalLinkage()) 173dc0dbe1fSKevin Enderby Res |= BasicSymbolRef::SF_Hidden; 174dc0dbe1fSKevin Enderby if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) { 175dc0dbe1fSKevin Enderby if (GVar->isConstant()) 176dc0dbe1fSKevin Enderby Res |= BasicSymbolRef::SF_Const; 177dc0dbe1fSKevin Enderby } 17813b69d63SRafael Espindola if (GV->hasPrivateLinkage()) 179f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_FormatSpecific; 18013b69d63SRafael Espindola if (!GV->hasLocalLinkage()) 181f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Global; 18213b69d63SRafael Espindola if (GV->hasCommonLinkage()) 183f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Common; 1848d6fbc3aSRafael Espindola if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() || 1858d6fbc3aSRafael Espindola GV->hasExternalWeakLinkage()) 186f12b8282SRafael Espindola Res |= BasicSymbolRef::SF_Weak; 187f12b8282SRafael Espindola 1882dc0d9bdSRafael Espindola if (GV->getName().startswith("llvm.")) 189b674c17dSRafael Espindola Res |= BasicSymbolRef::SF_FormatSpecific; 1902dc0d9bdSRafael Espindola else if (auto *Var = dyn_cast<GlobalVariable>(GV)) { 19183658d6eSRafael Espindola if (Var->getSection() == "llvm.metadata") 1923885090bSRafael Espindola Res |= BasicSymbolRef::SF_FormatSpecific; 1933885090bSRafael Espindola } 1943885090bSRafael Espindola 195f12b8282SRafael Espindola return Res; 196f12b8282SRafael Espindola } 197f12b8282SRafael Espindola 198*e32baa0cSPeter Collingbourne GlobalValue *IRObjectFile::getSymbolGV(DataRefImpl Symb) { 199*e32baa0cSPeter Collingbourne return getSym(Symb).dyn_cast<GlobalValue *>(); 200*e32baa0cSPeter Collingbourne } 201f12b8282SRafael Espindola 20225a7e0a8SRafael Espindola std::unique_ptr<Module> IRObjectFile::takeModule() { return std::move(M); } 20325a7e0a8SRafael Espindola 204435890a4SPeter Collingbourne basic_symbol_iterator IRObjectFile::symbol_begin() const { 205f12b8282SRafael Espindola DataRefImpl Ret; 206*e32baa0cSPeter Collingbourne Ret.p = reinterpret_cast<uintptr_t>(SymTab.data()); 207f12b8282SRafael Espindola return basic_symbol_iterator(BasicSymbolRef(Ret, this)); 208f12b8282SRafael Espindola } 209f12b8282SRafael Espindola 210435890a4SPeter Collingbourne basic_symbol_iterator IRObjectFile::symbol_end() const { 211f12b8282SRafael Espindola DataRefImpl Ret; 212*e32baa0cSPeter Collingbourne Ret.p = reinterpret_cast<uintptr_t>(SymTab.data() + SymTab.size()); 213f12b8282SRafael Espindola return basic_symbol_iterator(BasicSymbolRef(Ret, this)); 214f12b8282SRafael Espindola } 215f12b8282SRafael Espindola 21610039c02SPeter Collingbourne ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) { 21710039c02SPeter Collingbourne for (const SectionRef &Sec : Obj.sections()) { 218f2fe0141SSteven Wu if (Sec.isBitcode()) { 21910039c02SPeter Collingbourne StringRef SecContents; 22010039c02SPeter Collingbourne if (std::error_code EC = Sec.getContents(SecContents)) 22110039c02SPeter Collingbourne return EC; 22210039c02SPeter Collingbourne return MemoryBufferRef(SecContents, Obj.getFileName()); 22310039c02SPeter Collingbourne } 22410039c02SPeter Collingbourne } 22510039c02SPeter Collingbourne 22610039c02SPeter Collingbourne return object_error::bitcode_section_not_found; 22710039c02SPeter Collingbourne } 22810039c02SPeter Collingbourne 22910039c02SPeter Collingbourne ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) { 23010039c02SPeter Collingbourne sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer()); 23110039c02SPeter Collingbourne switch (Type) { 23210039c02SPeter Collingbourne case sys::fs::file_magic::bitcode: 23310039c02SPeter Collingbourne return Object; 23410039c02SPeter Collingbourne case sys::fs::file_magic::elf_relocatable: 23510039c02SPeter Collingbourne case sys::fs::file_magic::macho_object: 23610039c02SPeter Collingbourne case sys::fs::file_magic::coff_object: { 2373fcdf6aeSKevin Enderby Expected<std::unique_ptr<ObjectFile>> ObjFile = 23810039c02SPeter Collingbourne ObjectFile::createObjectFile(Object, Type); 23910039c02SPeter Collingbourne if (!ObjFile) 2403fcdf6aeSKevin Enderby return errorToErrorCode(ObjFile.takeError()); 24110039c02SPeter Collingbourne return findBitcodeInObject(*ObjFile->get()); 24210039c02SPeter Collingbourne } 24310039c02SPeter Collingbourne default: 24410039c02SPeter Collingbourne return object_error::invalid_file_type; 24510039c02SPeter Collingbourne } 24610039c02SPeter Collingbourne } 24710039c02SPeter Collingbourne 248d9445c49SPeter Collingbourne Expected<std::unique_ptr<IRObjectFile>> 2495dec7eaaSRafael Espindola llvm::object::IRObjectFile::create(MemoryBufferRef Object, 25048af1c2aSRafael Espindola LLVMContext &Context) { 25110039c02SPeter Collingbourne ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object); 25210039c02SPeter Collingbourne if (!BCOrErr) 253d9445c49SPeter Collingbourne return errorCodeToError(BCOrErr.getError()); 25448af1c2aSRafael Espindola 255d9445c49SPeter Collingbourne Expected<std::unique_ptr<Module>> MOrErr = 256e2dcf7c3SPeter Collingbourne getLazyBitcodeModule(*BCOrErr, Context, 257cba833a0SRafael Espindola /*ShouldLazyLoadMetadata*/ true); 258d9445c49SPeter Collingbourne if (!MOrErr) 259d9445c49SPeter Collingbourne return MOrErr.takeError(); 260dddd1fd9SRafael Espindola 261dcd1dca2SRafael Espindola std::unique_ptr<Module> &M = MOrErr.get(); 2629ba95f99STeresa Johnson return llvm::make_unique<IRObjectFile>(BCOrErr.get(), std::move(M)); 263f12b8282SRafael Espindola } 264