1 //===- IRObjectFile.cpp - IR object file implementation ---------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Part of the IRObjectFile class implementation. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/Bitcode/ReaderWriter.h" 15 #include "llvm/IR/LLVMContext.h" 16 #include "llvm/IR/Module.h" 17 #include "llvm/Object/IRObjectFile.h" 18 #include "llvm/Support/raw_ostream.h" 19 using namespace llvm; 20 using namespace object; 21 22 IRObjectFile::IRObjectFile(MemoryBuffer *Object, error_code &EC, 23 LLVMContext &Context, bool BufferOwned) 24 : SymbolicFile(Binary::ID_IR, Object, BufferOwned) { 25 ErrorOr<Module*> MOrErr = parseBitcodeFile(Object, Context); 26 if ((EC = MOrErr.getError())) 27 return; 28 29 M.reset(MOrErr.get()); 30 } 31 32 static const GlobalValue &getGV(DataRefImpl &Symb) { 33 return *reinterpret_cast<GlobalValue*>(Symb.p & ~uintptr_t(3)); 34 } 35 36 static uintptr_t skipEmpty(Module::const_alias_iterator I, const Module &M) { 37 if (I == M.alias_end()) 38 return 3; 39 const GlobalValue *GV = &*I; 40 return reinterpret_cast<uintptr_t>(GV) | 2; 41 } 42 43 static uintptr_t skipEmpty(Module::const_global_iterator I, const Module &M) { 44 if (I == M.global_end()) 45 return skipEmpty(M.alias_begin(), M); 46 const GlobalValue *GV = &*I; 47 return reinterpret_cast<uintptr_t>(GV) | 1; 48 } 49 50 static uintptr_t skipEmpty(Module::const_iterator I, const Module &M) { 51 if (I == M.end()) 52 return skipEmpty(M.global_begin(), M); 53 const GlobalValue *GV = &*I; 54 return reinterpret_cast<uintptr_t>(GV) | 0; 55 } 56 57 void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 58 const GlobalValue *GV = &getGV(Symb); 59 const Module &M = *GV->getParent(); 60 uintptr_t Res; 61 switch (Symb.p & 3) { 62 case 0: { 63 Module::const_iterator Iter(static_cast<const Function*>(GV)); 64 ++Iter; 65 Res = skipEmpty(Iter, M); 66 break; 67 } 68 case 1: { 69 Module::const_global_iterator Iter(static_cast<const GlobalVariable*>(GV)); 70 ++Iter; 71 Res = skipEmpty(Iter, M); 72 break; 73 } 74 case 2: { 75 Module::const_alias_iterator Iter(static_cast<const GlobalAlias*>(GV)); 76 ++Iter; 77 Res = skipEmpty(Iter, M); 78 break; 79 } 80 case 3: 81 llvm_unreachable("Invalid symbol reference"); 82 } 83 84 Symb.p = Res; 85 } 86 87 error_code IRObjectFile::printSymbolName(raw_ostream &OS, 88 DataRefImpl Symb) const { 89 // FIXME: This should use the Mangler. 90 const GlobalValue &GV = getGV(Symb); 91 OS << GV.getName(); 92 return object_error::success; 93 } 94 95 uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { 96 const GlobalValue &GV = getGV(Symb); 97 98 uint32_t Res = BasicSymbolRef::SF_None; 99 if (GV.isDeclaration() || GV.hasAvailableExternallyLinkage()) 100 Res |= BasicSymbolRef::SF_Undefined; 101 if (GV.hasPrivateLinkage() || GV.hasLinkerPrivateLinkage() || 102 GV.hasLinkerPrivateWeakLinkage()) 103 Res |= BasicSymbolRef::SF_FormatSpecific; 104 if (!GV.hasLocalLinkage()) 105 Res |= BasicSymbolRef::SF_Global; 106 if (GV.hasCommonLinkage()) 107 Res |= BasicSymbolRef::SF_Common; 108 if (GV.hasLinkOnceLinkage() || GV.hasWeakLinkage()) 109 Res |= BasicSymbolRef::SF_Weak; 110 111 return Res; 112 } 113 114 const GlobalValue &IRObjectFile::getSymbolGV(DataRefImpl Symb) const { 115 const GlobalValue &GV = getGV(Symb); 116 return GV; 117 } 118 119 basic_symbol_iterator IRObjectFile::symbol_begin_impl() const { 120 Module::const_iterator I = M->begin(); 121 DataRefImpl Ret; 122 Ret.p = skipEmpty(I, *M); 123 return basic_symbol_iterator(BasicSymbolRef(Ret, this)); 124 } 125 126 basic_symbol_iterator IRObjectFile::symbol_end_impl() const { 127 DataRefImpl Ret; 128 Ret.p = 3; 129 return basic_symbol_iterator(BasicSymbolRef(Ret, this)); 130 } 131 132 ErrorOr<SymbolicFile *> llvm::object::SymbolicFile::createIRObjectFile( 133 MemoryBuffer *Object, LLVMContext &Context, bool BufferOwned) { 134 error_code EC; 135 OwningPtr<IRObjectFile> Ret( 136 new IRObjectFile(Object, EC, Context, BufferOwned)); 137 if (EC) 138 return EC; 139 return Ret.take(); 140 } 141