IRObjectFile.cpp revision cd81d94322a39503e4a3e87b6ee03d4fcb3465fb
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"
32using namespace llvm;
33using namespace object;
34
35IRObjectFile::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
116IRObjectFile::~IRObjectFile() {
117  GVMaterializer *GVM =  M->getMaterializer();
118  if (GVM)
119    GVM->releaseBuffer();
120 }
121
122static 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
129static 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
136static 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
143static 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
150static 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
157void 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
192std::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
210static 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
220uint32_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
251const GlobalValue *IRObjectFile::getSymbolGV(DataRefImpl Symb) const {
252  const GlobalValue *GV = getGV(Symb);
253  return GV;
254}
255
256basic_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
263basic_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
271ErrorOr<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