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