Home | History | Annotate | Download | only in Object
      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/Object/IRObjectFile.h"
     15 #include "RecordStreamer.h"
     16 #include "llvm/Bitcode/ReaderWriter.h"
     17 #include "llvm/IR/LLVMContext.h"
     18 #include "llvm/IR/GVMaterializer.h"
     19 #include "llvm/IR/Mangler.h"
     20 #include "llvm/IR/Module.h"
     21 #include "llvm/MC/MCRegisterInfo.h"
     22 #include "llvm/MC/MCAsmInfo.h"
     23 #include "llvm/MC/MCContext.h"
     24 #include "llvm/MC/MCInstrInfo.h"
     25 #include "llvm/MC/MCObjectFileInfo.h"
     26 #include "llvm/MC/MCTargetAsmParser.h"
     27 #include "llvm/MC/MCParser/MCAsmParser.h"
     28 #include "llvm/Support/MemoryBuffer.h"
     29 #include "llvm/Support/SourceMgr.h"
     30 #include "llvm/Support/TargetRegistry.h"
     31 #include "llvm/Support/raw_ostream.h"
     32 using namespace llvm;
     33 using namespace object;
     34 
     35 IRObjectFile::IRObjectFile(std::unique_ptr<MemoryBuffer> Object,
     36                            std::unique_ptr<Module> Mod)
     37     : SymbolicFile(Binary::ID_IR, std::move(Object)), M(std::move(Mod)) {
     38   // If we have a DataLayout, setup a mangler.
     39   const DataLayout *DL = M->getDataLayout();
     40   if (!DL)
     41     return;
     42 
     43   Mang.reset(new Mangler(DL));
     44 
     45   const std::string &InlineAsm = M->getModuleInlineAsm();
     46   if (InlineAsm.empty())
     47     return;
     48 
     49   StringRef Triple = M->getTargetTriple();
     50   std::string Err;
     51   const Target *T = TargetRegistry::lookupTarget(Triple, Err);
     52   if (!T)
     53     return;
     54 
     55   std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(Triple));
     56   if (!MRI)
     57     return;
     58 
     59   std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, Triple));
     60   if (!MAI)
     61     return;
     62 
     63   std::unique_ptr<MCSubtargetInfo> STI(
     64       T->createMCSubtargetInfo(Triple, "", ""));
     65   if (!STI)
     66     return;
     67 
     68   std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo());
     69   if (!MCII)
     70     return;
     71 
     72   MCObjectFileInfo MOFI;
     73   MCContext MCCtx(MAI.get(), MRI.get(), &MOFI);
     74   MOFI.InitMCObjectFileInfo(Triple, Reloc::Default, CodeModel::Default, MCCtx);
     75   std::unique_ptr<RecordStreamer> Streamer(new RecordStreamer(MCCtx));
     76 
     77   std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm));
     78   SourceMgr SrcMgr;
     79   SrcMgr.AddNewSourceBuffer(Buffer.release(), SMLoc());
     80   std::unique_ptr<MCAsmParser> Parser(
     81       createMCAsmParser(SrcMgr, MCCtx, *Streamer, *MAI));
     82 
     83   MCTargetOptions MCOptions;
     84   std::unique_ptr<MCTargetAsmParser> TAP(
     85       T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions));
     86   if (!TAP)
     87     return;
     88 
     89   Parser->setTargetParser(*TAP);
     90   if (Parser->Run(false))
     91     return;
     92 
     93   for (auto &KV : *Streamer) {
     94     StringRef Key = KV.first();
     95     RecordStreamer::State Value = KV.second;
     96     uint32_t Res = BasicSymbolRef::SF_None;
     97     switch (Value) {
     98     case RecordStreamer::NeverSeen:
     99       llvm_unreachable("foo");
    100     case RecordStreamer::DefinedGlobal:
    101       Res |= BasicSymbolRef::SF_Global;
    102       break;
    103     case RecordStreamer::Defined:
    104       break;
    105     case RecordStreamer::Global:
    106     case RecordStreamer::Used:
    107       Res |= BasicSymbolRef::SF_Undefined;
    108       Res |= BasicSymbolRef::SF_Global;
    109       break;
    110     }
    111     AsmSymbols.push_back(
    112         std::make_pair<std::string, uint32_t>(Key, std::move(Res)));
    113   }
    114 }
    115 
    116 IRObjectFile::~IRObjectFile() {
    117   GVMaterializer *GVM =  M->getMaterializer();
    118   if (GVM)
    119     GVM->releaseBuffer();
    120  }
    121 
    122 static const GlobalValue *getGV(DataRefImpl &Symb) {
    123   if ((Symb.p & 3) == 3)
    124     return nullptr;
    125 
    126   return reinterpret_cast<GlobalValue*>(Symb.p & ~uintptr_t(3));
    127 }
    128 
    129 static uintptr_t skipEmpty(Module::const_alias_iterator I, const Module &M) {
    130   if (I == M.alias_end())
    131     return 3;
    132   const GlobalValue *GV = &*I;
    133   return reinterpret_cast<uintptr_t>(GV) | 2;
    134 }
    135 
    136 static uintptr_t skipEmpty(Module::const_global_iterator I, const Module &M) {
    137   if (I == M.global_end())
    138     return skipEmpty(M.alias_begin(), M);
    139   const GlobalValue *GV = &*I;
    140   return reinterpret_cast<uintptr_t>(GV) | 1;
    141 }
    142 
    143 static uintptr_t skipEmpty(Module::const_iterator I, const Module &M) {
    144   if (I == M.end())
    145     return skipEmpty(M.global_begin(), M);
    146   const GlobalValue *GV = &*I;
    147   return reinterpret_cast<uintptr_t>(GV) | 0;
    148 }
    149 
    150 static unsigned getAsmSymIndex(DataRefImpl Symb) {
    151   assert((Symb.p & uintptr_t(3)) == 3);
    152   uintptr_t Index = Symb.p & ~uintptr_t(3);
    153   Index >>= 2;
    154   return Index;
    155 }
    156 
    157 void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
    158   const GlobalValue *GV = getGV(Symb);
    159   uintptr_t Res;
    160 
    161   switch (Symb.p & 3) {
    162   case 0: {
    163     Module::const_iterator Iter(static_cast<const Function*>(GV));
    164     ++Iter;
    165     Res = skipEmpty(Iter, *M);
    166     break;
    167   }
    168   case 1: {
    169     Module::const_global_iterator Iter(static_cast<const GlobalVariable*>(GV));
    170     ++Iter;
    171     Res = skipEmpty(Iter, *M);
    172     break;
    173   }
    174   case 2: {
    175     Module::const_alias_iterator Iter(static_cast<const GlobalAlias*>(GV));
    176     ++Iter;
    177     Res = skipEmpty(Iter, *M);
    178     break;
    179   }
    180   case 3: {
    181     unsigned Index = getAsmSymIndex(Symb);
    182     assert(Index < AsmSymbols.size());
    183     ++Index;
    184     Res = (Index << 2) | 3;
    185     break;
    186   }
    187   }
    188 
    189   Symb.p = Res;
    190 }
    191 
    192 std::error_code IRObjectFile::printSymbolName(raw_ostream &OS,
    193                                               DataRefImpl Symb) const {
    194   const GlobalValue *GV = getGV(Symb);
    195   if (!GV) {
    196     unsigned Index = getAsmSymIndex(Symb);
    197     assert(Index <= AsmSymbols.size());
    198     OS << AsmSymbols[Index].first;
    199     return object_error::success;;
    200   }
    201 
    202   if (Mang)
    203     Mang->getNameWithPrefix(OS, GV, false);
    204   else
    205     OS << GV->getName();
    206 
    207   return object_error::success;
    208 }
    209 
    210 static bool isDeclaration(const GlobalValue &V) {
    211   if (V.hasAvailableExternallyLinkage())
    212     return true;
    213 
    214   if (V.isMaterializable())
    215     return false;
    216 
    217   return V.isDeclaration();
    218 }
    219 
    220 uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const {
    221   const GlobalValue *GV = getGV(Symb);
    222 
    223   if (!GV) {
    224     unsigned Index = getAsmSymIndex(Symb);
    225     assert(Index <= AsmSymbols.size());
    226     return AsmSymbols[Index].second;
    227   }
    228 
    229   uint32_t Res = BasicSymbolRef::SF_None;
    230   if (isDeclaration(*GV))
    231     Res |= BasicSymbolRef::SF_Undefined;
    232   if (GV->hasPrivateLinkage())
    233     Res |= BasicSymbolRef::SF_FormatSpecific;
    234   if (!GV->hasLocalLinkage())
    235     Res |= BasicSymbolRef::SF_Global;
    236   if (GV->hasCommonLinkage())
    237     Res |= BasicSymbolRef::SF_Common;
    238   if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage())
    239     Res |= BasicSymbolRef::SF_Weak;
    240 
    241   if (GV->getName().startswith("llvm."))
    242     Res |= BasicSymbolRef::SF_FormatSpecific;
    243   else if (auto *Var = dyn_cast<GlobalVariable>(GV)) {
    244     if (Var->getSection() == StringRef("llvm.metadata"))
    245       Res |= BasicSymbolRef::SF_FormatSpecific;
    246   }
    247 
    248   return Res;
    249 }
    250 
    251 const GlobalValue *IRObjectFile::getSymbolGV(DataRefImpl Symb) const {
    252   const GlobalValue *GV = getGV(Symb);
    253   return GV;
    254 }
    255 
    256 basic_symbol_iterator IRObjectFile::symbol_begin_impl() const {
    257   Module::const_iterator I = M->begin();
    258   DataRefImpl Ret;
    259   Ret.p = skipEmpty(I, *M);
    260   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
    261 }
    262 
    263 basic_symbol_iterator IRObjectFile::symbol_end_impl() const {
    264   DataRefImpl Ret;
    265   uint64_t NumAsm = AsmSymbols.size();
    266   NumAsm <<= 2;
    267   Ret.p = 3 | NumAsm;
    268   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
    269 }
    270 
    271 ErrorOr<IRObjectFile *> llvm::object::IRObjectFile::createIRObjectFile(
    272     std::unique_ptr<MemoryBuffer> Object, LLVMContext &Context) {
    273   ErrorOr<Module *> MOrErr = getLazyBitcodeModule(Object.get(), Context);
    274   if (std::error_code EC = MOrErr.getError())
    275     return EC;
    276 
    277   std::unique_ptr<Module> M(MOrErr.get());
    278   return new IRObjectFile(std::move(Object), std::move(M));
    279 }
    280