xref: /aosp_15_r20/external/llvm/lib/Object/IRObjectFile.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- IRObjectFile.cpp - IR object file implementation ---------*- C++ -*-===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // Part of the IRObjectFile class implementation.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker 
14*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/IRObjectFile.h"
15*9880d681SAndroid Build Coastguard Worker #include "RecordStreamer.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Bitcode/ReaderWriter.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/GVMaterializer.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/LLVMContext.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Mangler.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmInfo.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstrInfo.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCObjectFileInfo.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCAsmParser.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCTargetAsmParser.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCRegisterInfo.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSubtargetInfo.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/ObjectFile.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MemoryBuffer.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/SourceMgr.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetRegistry.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
35*9880d681SAndroid Build Coastguard Worker using namespace llvm;
36*9880d681SAndroid Build Coastguard Worker using namespace object;
37*9880d681SAndroid Build Coastguard Worker 
IRObjectFile(MemoryBufferRef Object,std::unique_ptr<Module> Mod)38*9880d681SAndroid Build Coastguard Worker IRObjectFile::IRObjectFile(MemoryBufferRef Object, std::unique_ptr<Module> Mod)
39*9880d681SAndroid Build Coastguard Worker     : SymbolicFile(Binary::ID_IR, Object), M(std::move(Mod)) {
40*9880d681SAndroid Build Coastguard Worker   Mang.reset(new Mangler());
41*9880d681SAndroid Build Coastguard Worker   CollectAsmUndefinedRefs(Triple(M->getTargetTriple()), M->getModuleInlineAsm(),
42*9880d681SAndroid Build Coastguard Worker                           [this](StringRef Name, BasicSymbolRef::Flags Flags) {
43*9880d681SAndroid Build Coastguard Worker                             AsmSymbols.emplace_back(Name, std::move(Flags));
44*9880d681SAndroid Build Coastguard Worker                           });
45*9880d681SAndroid Build Coastguard Worker }
46*9880d681SAndroid Build Coastguard Worker 
47*9880d681SAndroid Build Coastguard Worker // Parse inline ASM and collect the list of symbols that are not defined in
48*9880d681SAndroid Build Coastguard Worker // the current module. This is inspired from IRObjectFile.
CollectAsmUndefinedRefs(const Triple & TT,StringRef InlineAsm,function_ref<void (StringRef,BasicSymbolRef::Flags)> AsmUndefinedRefs)49*9880d681SAndroid Build Coastguard Worker void IRObjectFile::CollectAsmUndefinedRefs(
50*9880d681SAndroid Build Coastguard Worker     const Triple &TT, StringRef InlineAsm,
51*9880d681SAndroid Build Coastguard Worker     function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmUndefinedRefs) {
52*9880d681SAndroid Build Coastguard Worker   if (InlineAsm.empty())
53*9880d681SAndroid Build Coastguard Worker     return;
54*9880d681SAndroid Build Coastguard Worker 
55*9880d681SAndroid Build Coastguard Worker   std::string Err;
56*9880d681SAndroid Build Coastguard Worker   const Target *T = TargetRegistry::lookupTarget(TT.str(), Err);
57*9880d681SAndroid Build Coastguard Worker   if (!T)
58*9880d681SAndroid Build Coastguard Worker     return;
59*9880d681SAndroid Build Coastguard Worker 
60*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TT.str()));
61*9880d681SAndroid Build Coastguard Worker   if (!MRI)
62*9880d681SAndroid Build Coastguard Worker     return;
63*9880d681SAndroid Build Coastguard Worker 
64*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TT.str()));
65*9880d681SAndroid Build Coastguard Worker   if (!MAI)
66*9880d681SAndroid Build Coastguard Worker     return;
67*9880d681SAndroid Build Coastguard Worker 
68*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MCSubtargetInfo> STI(
69*9880d681SAndroid Build Coastguard Worker       T->createMCSubtargetInfo(TT.str(), "", ""));
70*9880d681SAndroid Build Coastguard Worker   if (!STI)
71*9880d681SAndroid Build Coastguard Worker     return;
72*9880d681SAndroid Build Coastguard Worker 
73*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo());
74*9880d681SAndroid Build Coastguard Worker   if (!MCII)
75*9880d681SAndroid Build Coastguard Worker     return;
76*9880d681SAndroid Build Coastguard Worker 
77*9880d681SAndroid Build Coastguard Worker   MCObjectFileInfo MOFI;
78*9880d681SAndroid Build Coastguard Worker   MCContext MCCtx(MAI.get(), MRI.get(), &MOFI);
79*9880d681SAndroid Build Coastguard Worker   MOFI.InitMCObjectFileInfo(TT, /*PIC*/ false, CodeModel::Default, MCCtx);
80*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<RecordStreamer> Streamer(new RecordStreamer(MCCtx));
81*9880d681SAndroid Build Coastguard Worker   T->createNullTargetStreamer(*Streamer);
82*9880d681SAndroid Build Coastguard Worker 
83*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm));
84*9880d681SAndroid Build Coastguard Worker   SourceMgr SrcMgr;
85*9880d681SAndroid Build Coastguard Worker   SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
86*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MCAsmParser> Parser(
87*9880d681SAndroid Build Coastguard Worker       createMCAsmParser(SrcMgr, MCCtx, *Streamer, *MAI));
88*9880d681SAndroid Build Coastguard Worker 
89*9880d681SAndroid Build Coastguard Worker   MCTargetOptions MCOptions;
90*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MCTargetAsmParser> TAP(
91*9880d681SAndroid Build Coastguard Worker       T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions));
92*9880d681SAndroid Build Coastguard Worker   if (!TAP)
93*9880d681SAndroid Build Coastguard Worker     return;
94*9880d681SAndroid Build Coastguard Worker 
95*9880d681SAndroid Build Coastguard Worker   Parser->setTargetParser(*TAP);
96*9880d681SAndroid Build Coastguard Worker   if (Parser->Run(false))
97*9880d681SAndroid Build Coastguard Worker     return;
98*9880d681SAndroid Build Coastguard Worker 
99*9880d681SAndroid Build Coastguard Worker   for (auto &KV : *Streamer) {
100*9880d681SAndroid Build Coastguard Worker     StringRef Key = KV.first();
101*9880d681SAndroid Build Coastguard Worker     RecordStreamer::State Value = KV.second;
102*9880d681SAndroid Build Coastguard Worker     uint32_t Res = BasicSymbolRef::SF_None;
103*9880d681SAndroid Build Coastguard Worker     switch (Value) {
104*9880d681SAndroid Build Coastguard Worker     case RecordStreamer::NeverSeen:
105*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("foo");
106*9880d681SAndroid Build Coastguard Worker     case RecordStreamer::DefinedGlobal:
107*9880d681SAndroid Build Coastguard Worker       Res |= BasicSymbolRef::SF_Global;
108*9880d681SAndroid Build Coastguard Worker       break;
109*9880d681SAndroid Build Coastguard Worker     case RecordStreamer::Defined:
110*9880d681SAndroid Build Coastguard Worker       break;
111*9880d681SAndroid Build Coastguard Worker     case RecordStreamer::Global:
112*9880d681SAndroid Build Coastguard Worker     case RecordStreamer::Used:
113*9880d681SAndroid Build Coastguard Worker       Res |= BasicSymbolRef::SF_Undefined;
114*9880d681SAndroid Build Coastguard Worker       Res |= BasicSymbolRef::SF_Global;
115*9880d681SAndroid Build Coastguard Worker       break;
116*9880d681SAndroid Build Coastguard Worker     case RecordStreamer::GlobalWeak:
117*9880d681SAndroid Build Coastguard Worker       Res |= BasicSymbolRef::SF_Weak;
118*9880d681SAndroid Build Coastguard Worker       Res |= BasicSymbolRef::SF_Global;
119*9880d681SAndroid Build Coastguard Worker       break;
120*9880d681SAndroid Build Coastguard Worker     }
121*9880d681SAndroid Build Coastguard Worker     AsmUndefinedRefs(Key, BasicSymbolRef::Flags(Res));
122*9880d681SAndroid Build Coastguard Worker   }
123*9880d681SAndroid Build Coastguard Worker }
124*9880d681SAndroid Build Coastguard Worker 
~IRObjectFile()125*9880d681SAndroid Build Coastguard Worker IRObjectFile::~IRObjectFile() {
126*9880d681SAndroid Build Coastguard Worker  }
127*9880d681SAndroid Build Coastguard Worker 
getGV(DataRefImpl & Symb)128*9880d681SAndroid Build Coastguard Worker static GlobalValue *getGV(DataRefImpl &Symb) {
129*9880d681SAndroid Build Coastguard Worker   if ((Symb.p & 3) == 3)
130*9880d681SAndroid Build Coastguard Worker     return nullptr;
131*9880d681SAndroid Build Coastguard Worker 
132*9880d681SAndroid Build Coastguard Worker   return reinterpret_cast<GlobalValue*>(Symb.p & ~uintptr_t(3));
133*9880d681SAndroid Build Coastguard Worker }
134*9880d681SAndroid Build Coastguard Worker 
skipEmpty(Module::const_alias_iterator I,const Module & M)135*9880d681SAndroid Build Coastguard Worker static uintptr_t skipEmpty(Module::const_alias_iterator I, const Module &M) {
136*9880d681SAndroid Build Coastguard Worker   if (I == M.alias_end())
137*9880d681SAndroid Build Coastguard Worker     return 3;
138*9880d681SAndroid Build Coastguard Worker   const GlobalValue *GV = &*I;
139*9880d681SAndroid Build Coastguard Worker   return reinterpret_cast<uintptr_t>(GV) | 2;
140*9880d681SAndroid Build Coastguard Worker }
141*9880d681SAndroid Build Coastguard Worker 
skipEmpty(Module::const_global_iterator I,const Module & M)142*9880d681SAndroid Build Coastguard Worker static uintptr_t skipEmpty(Module::const_global_iterator I, const Module &M) {
143*9880d681SAndroid Build Coastguard Worker   if (I == M.global_end())
144*9880d681SAndroid Build Coastguard Worker     return skipEmpty(M.alias_begin(), M);
145*9880d681SAndroid Build Coastguard Worker   const GlobalValue *GV = &*I;
146*9880d681SAndroid Build Coastguard Worker   return reinterpret_cast<uintptr_t>(GV) | 1;
147*9880d681SAndroid Build Coastguard Worker }
148*9880d681SAndroid Build Coastguard Worker 
skipEmpty(Module::const_iterator I,const Module & M)149*9880d681SAndroid Build Coastguard Worker static uintptr_t skipEmpty(Module::const_iterator I, const Module &M) {
150*9880d681SAndroid Build Coastguard Worker   if (I == M.end())
151*9880d681SAndroid Build Coastguard Worker     return skipEmpty(M.global_begin(), M);
152*9880d681SAndroid Build Coastguard Worker   const GlobalValue *GV = &*I;
153*9880d681SAndroid Build Coastguard Worker   return reinterpret_cast<uintptr_t>(GV) | 0;
154*9880d681SAndroid Build Coastguard Worker }
155*9880d681SAndroid Build Coastguard Worker 
getAsmSymIndex(DataRefImpl Symb)156*9880d681SAndroid Build Coastguard Worker static unsigned getAsmSymIndex(DataRefImpl Symb) {
157*9880d681SAndroid Build Coastguard Worker   assert((Symb.p & uintptr_t(3)) == 3);
158*9880d681SAndroid Build Coastguard Worker   uintptr_t Index = Symb.p & ~uintptr_t(3);
159*9880d681SAndroid Build Coastguard Worker   Index >>= 2;
160*9880d681SAndroid Build Coastguard Worker   return Index;
161*9880d681SAndroid Build Coastguard Worker }
162*9880d681SAndroid Build Coastguard Worker 
moveSymbolNext(DataRefImpl & Symb) const163*9880d681SAndroid Build Coastguard Worker void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
164*9880d681SAndroid Build Coastguard Worker   const GlobalValue *GV = getGV(Symb);
165*9880d681SAndroid Build Coastguard Worker   uintptr_t Res;
166*9880d681SAndroid Build Coastguard Worker 
167*9880d681SAndroid Build Coastguard Worker   switch (Symb.p & 3) {
168*9880d681SAndroid Build Coastguard Worker   case 0: {
169*9880d681SAndroid Build Coastguard Worker     Module::const_iterator Iter(static_cast<const Function*>(GV));
170*9880d681SAndroid Build Coastguard Worker     ++Iter;
171*9880d681SAndroid Build Coastguard Worker     Res = skipEmpty(Iter, *M);
172*9880d681SAndroid Build Coastguard Worker     break;
173*9880d681SAndroid Build Coastguard Worker   }
174*9880d681SAndroid Build Coastguard Worker   case 1: {
175*9880d681SAndroid Build Coastguard Worker     Module::const_global_iterator Iter(static_cast<const GlobalVariable*>(GV));
176*9880d681SAndroid Build Coastguard Worker     ++Iter;
177*9880d681SAndroid Build Coastguard Worker     Res = skipEmpty(Iter, *M);
178*9880d681SAndroid Build Coastguard Worker     break;
179*9880d681SAndroid Build Coastguard Worker   }
180*9880d681SAndroid Build Coastguard Worker   case 2: {
181*9880d681SAndroid Build Coastguard Worker     Module::const_alias_iterator Iter(static_cast<const GlobalAlias*>(GV));
182*9880d681SAndroid Build Coastguard Worker     ++Iter;
183*9880d681SAndroid Build Coastguard Worker     Res = skipEmpty(Iter, *M);
184*9880d681SAndroid Build Coastguard Worker     break;
185*9880d681SAndroid Build Coastguard Worker   }
186*9880d681SAndroid Build Coastguard Worker   case 3: {
187*9880d681SAndroid Build Coastguard Worker     unsigned Index = getAsmSymIndex(Symb);
188*9880d681SAndroid Build Coastguard Worker     assert(Index < AsmSymbols.size());
189*9880d681SAndroid Build Coastguard Worker     ++Index;
190*9880d681SAndroid Build Coastguard Worker     Res = (Index << 2) | 3;
191*9880d681SAndroid Build Coastguard Worker     break;
192*9880d681SAndroid Build Coastguard Worker   }
193*9880d681SAndroid Build Coastguard Worker   default:
194*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("unreachable case");
195*9880d681SAndroid Build Coastguard Worker   }
196*9880d681SAndroid Build Coastguard Worker 
197*9880d681SAndroid Build Coastguard Worker   Symb.p = Res;
198*9880d681SAndroid Build Coastguard Worker }
199*9880d681SAndroid Build Coastguard Worker 
printSymbolName(raw_ostream & OS,DataRefImpl Symb) const200*9880d681SAndroid Build Coastguard Worker std::error_code IRObjectFile::printSymbolName(raw_ostream &OS,
201*9880d681SAndroid Build Coastguard Worker                                               DataRefImpl Symb) const {
202*9880d681SAndroid Build Coastguard Worker   const GlobalValue *GV = getGV(Symb);
203*9880d681SAndroid Build Coastguard Worker   if (!GV) {
204*9880d681SAndroid Build Coastguard Worker     unsigned Index = getAsmSymIndex(Symb);
205*9880d681SAndroid Build Coastguard Worker     assert(Index <= AsmSymbols.size());
206*9880d681SAndroid Build Coastguard Worker     OS << AsmSymbols[Index].first;
207*9880d681SAndroid Build Coastguard Worker     return std::error_code();
208*9880d681SAndroid Build Coastguard Worker   }
209*9880d681SAndroid Build Coastguard Worker 
210*9880d681SAndroid Build Coastguard Worker   if (GV->hasDLLImportStorageClass())
211*9880d681SAndroid Build Coastguard Worker     OS << "__imp_";
212*9880d681SAndroid Build Coastguard Worker 
213*9880d681SAndroid Build Coastguard Worker   if (Mang)
214*9880d681SAndroid Build Coastguard Worker     Mang->getNameWithPrefix(OS, GV, false);
215*9880d681SAndroid Build Coastguard Worker   else
216*9880d681SAndroid Build Coastguard Worker     OS << GV->getName();
217*9880d681SAndroid Build Coastguard Worker 
218*9880d681SAndroid Build Coastguard Worker   return std::error_code();
219*9880d681SAndroid Build Coastguard Worker }
220*9880d681SAndroid Build Coastguard Worker 
getSymbolFlags(DataRefImpl Symb) const221*9880d681SAndroid Build Coastguard Worker uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const {
222*9880d681SAndroid Build Coastguard Worker   const GlobalValue *GV = getGV(Symb);
223*9880d681SAndroid Build Coastguard Worker 
224*9880d681SAndroid Build Coastguard Worker   if (!GV) {
225*9880d681SAndroid Build Coastguard Worker     unsigned Index = getAsmSymIndex(Symb);
226*9880d681SAndroid Build Coastguard Worker     assert(Index <= AsmSymbols.size());
227*9880d681SAndroid Build Coastguard Worker     return AsmSymbols[Index].second;
228*9880d681SAndroid Build Coastguard Worker   }
229*9880d681SAndroid Build Coastguard Worker 
230*9880d681SAndroid Build Coastguard Worker   uint32_t Res = BasicSymbolRef::SF_None;
231*9880d681SAndroid Build Coastguard Worker   if (GV->isDeclarationForLinker())
232*9880d681SAndroid Build Coastguard Worker     Res |= BasicSymbolRef::SF_Undefined;
233*9880d681SAndroid Build Coastguard Worker   else if (GV->hasHiddenVisibility() && !GV->hasLocalLinkage())
234*9880d681SAndroid Build Coastguard Worker     Res |= BasicSymbolRef::SF_Hidden;
235*9880d681SAndroid Build Coastguard Worker   if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) {
236*9880d681SAndroid Build Coastguard Worker     if (GVar->isConstant())
237*9880d681SAndroid Build Coastguard Worker       Res |= BasicSymbolRef::SF_Const;
238*9880d681SAndroid Build Coastguard Worker   }
239*9880d681SAndroid Build Coastguard Worker   if (GV->hasPrivateLinkage())
240*9880d681SAndroid Build Coastguard Worker     Res |= BasicSymbolRef::SF_FormatSpecific;
241*9880d681SAndroid Build Coastguard Worker   if (!GV->hasLocalLinkage())
242*9880d681SAndroid Build Coastguard Worker     Res |= BasicSymbolRef::SF_Global;
243*9880d681SAndroid Build Coastguard Worker   if (GV->hasCommonLinkage())
244*9880d681SAndroid Build Coastguard Worker     Res |= BasicSymbolRef::SF_Common;
245*9880d681SAndroid Build Coastguard Worker   if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
246*9880d681SAndroid Build Coastguard Worker       GV->hasExternalWeakLinkage())
247*9880d681SAndroid Build Coastguard Worker     Res |= BasicSymbolRef::SF_Weak;
248*9880d681SAndroid Build Coastguard Worker 
249*9880d681SAndroid Build Coastguard Worker   if (GV->getName().startswith("llvm."))
250*9880d681SAndroid Build Coastguard Worker     Res |= BasicSymbolRef::SF_FormatSpecific;
251*9880d681SAndroid Build Coastguard Worker   else if (auto *Var = dyn_cast<GlobalVariable>(GV)) {
252*9880d681SAndroid Build Coastguard Worker     if (Var->getSection() == "llvm.metadata")
253*9880d681SAndroid Build Coastguard Worker       Res |= BasicSymbolRef::SF_FormatSpecific;
254*9880d681SAndroid Build Coastguard Worker   }
255*9880d681SAndroid Build Coastguard Worker 
256*9880d681SAndroid Build Coastguard Worker   return Res;
257*9880d681SAndroid Build Coastguard Worker }
258*9880d681SAndroid Build Coastguard Worker 
getSymbolGV(DataRefImpl Symb)259*9880d681SAndroid Build Coastguard Worker GlobalValue *IRObjectFile::getSymbolGV(DataRefImpl Symb) { return getGV(Symb); }
260*9880d681SAndroid Build Coastguard Worker 
takeModule()261*9880d681SAndroid Build Coastguard Worker std::unique_ptr<Module> IRObjectFile::takeModule() { return std::move(M); }
262*9880d681SAndroid Build Coastguard Worker 
symbol_begin_impl() const263*9880d681SAndroid Build Coastguard Worker basic_symbol_iterator IRObjectFile::symbol_begin_impl() const {
264*9880d681SAndroid Build Coastguard Worker   Module::const_iterator I = M->begin();
265*9880d681SAndroid Build Coastguard Worker   DataRefImpl Ret;
266*9880d681SAndroid Build Coastguard Worker   Ret.p = skipEmpty(I, *M);
267*9880d681SAndroid Build Coastguard Worker   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
268*9880d681SAndroid Build Coastguard Worker }
269*9880d681SAndroid Build Coastguard Worker 
symbol_end_impl() const270*9880d681SAndroid Build Coastguard Worker basic_symbol_iterator IRObjectFile::symbol_end_impl() const {
271*9880d681SAndroid Build Coastguard Worker   DataRefImpl Ret;
272*9880d681SAndroid Build Coastguard Worker   uint64_t NumAsm = AsmSymbols.size();
273*9880d681SAndroid Build Coastguard Worker   NumAsm <<= 2;
274*9880d681SAndroid Build Coastguard Worker   Ret.p = 3 | NumAsm;
275*9880d681SAndroid Build Coastguard Worker   return basic_symbol_iterator(BasicSymbolRef(Ret, this));
276*9880d681SAndroid Build Coastguard Worker }
277*9880d681SAndroid Build Coastguard Worker 
findBitcodeInObject(const ObjectFile & Obj)278*9880d681SAndroid Build Coastguard Worker ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) {
279*9880d681SAndroid Build Coastguard Worker   for (const SectionRef &Sec : Obj.sections()) {
280*9880d681SAndroid Build Coastguard Worker     if (Sec.isBitcode()) {
281*9880d681SAndroid Build Coastguard Worker       StringRef SecContents;
282*9880d681SAndroid Build Coastguard Worker       if (std::error_code EC = Sec.getContents(SecContents))
283*9880d681SAndroid Build Coastguard Worker         return EC;
284*9880d681SAndroid Build Coastguard Worker       return MemoryBufferRef(SecContents, Obj.getFileName());
285*9880d681SAndroid Build Coastguard Worker     }
286*9880d681SAndroid Build Coastguard Worker   }
287*9880d681SAndroid Build Coastguard Worker 
288*9880d681SAndroid Build Coastguard Worker   return object_error::bitcode_section_not_found;
289*9880d681SAndroid Build Coastguard Worker }
290*9880d681SAndroid Build Coastguard Worker 
findBitcodeInMemBuffer(MemoryBufferRef Object)291*9880d681SAndroid Build Coastguard Worker ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) {
292*9880d681SAndroid Build Coastguard Worker   sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer());
293*9880d681SAndroid Build Coastguard Worker   switch (Type) {
294*9880d681SAndroid Build Coastguard Worker   case sys::fs::file_magic::bitcode:
295*9880d681SAndroid Build Coastguard Worker     return Object;
296*9880d681SAndroid Build Coastguard Worker   case sys::fs::file_magic::elf_relocatable:
297*9880d681SAndroid Build Coastguard Worker   case sys::fs::file_magic::macho_object:
298*9880d681SAndroid Build Coastguard Worker   case sys::fs::file_magic::coff_object: {
299*9880d681SAndroid Build Coastguard Worker     Expected<std::unique_ptr<ObjectFile>> ObjFile =
300*9880d681SAndroid Build Coastguard Worker         ObjectFile::createObjectFile(Object, Type);
301*9880d681SAndroid Build Coastguard Worker     if (!ObjFile)
302*9880d681SAndroid Build Coastguard Worker       return errorToErrorCode(ObjFile.takeError());
303*9880d681SAndroid Build Coastguard Worker     return findBitcodeInObject(*ObjFile->get());
304*9880d681SAndroid Build Coastguard Worker   }
305*9880d681SAndroid Build Coastguard Worker   default:
306*9880d681SAndroid Build Coastguard Worker     return object_error::invalid_file_type;
307*9880d681SAndroid Build Coastguard Worker   }
308*9880d681SAndroid Build Coastguard Worker }
309*9880d681SAndroid Build Coastguard Worker 
310*9880d681SAndroid Build Coastguard Worker ErrorOr<std::unique_ptr<IRObjectFile>>
create(MemoryBufferRef Object,LLVMContext & Context)311*9880d681SAndroid Build Coastguard Worker llvm::object::IRObjectFile::create(MemoryBufferRef Object,
312*9880d681SAndroid Build Coastguard Worker                                    LLVMContext &Context) {
313*9880d681SAndroid Build Coastguard Worker   ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
314*9880d681SAndroid Build Coastguard Worker   if (!BCOrErr)
315*9880d681SAndroid Build Coastguard Worker     return BCOrErr.getError();
316*9880d681SAndroid Build Coastguard Worker 
317*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<MemoryBuffer> Buff =
318*9880d681SAndroid Build Coastguard Worker       MemoryBuffer::getMemBuffer(BCOrErr.get(), false);
319*9880d681SAndroid Build Coastguard Worker 
320*9880d681SAndroid Build Coastguard Worker   ErrorOr<std::unique_ptr<Module>> MOrErr =
321*9880d681SAndroid Build Coastguard Worker       getLazyBitcodeModule(std::move(Buff), Context,
322*9880d681SAndroid Build Coastguard Worker                            /*ShouldLazyLoadMetadata*/ true);
323*9880d681SAndroid Build Coastguard Worker   if (std::error_code EC = MOrErr.getError())
324*9880d681SAndroid Build Coastguard Worker     return EC;
325*9880d681SAndroid Build Coastguard Worker 
326*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<Module> &M = MOrErr.get();
327*9880d681SAndroid Build Coastguard Worker   return llvm::make_unique<IRObjectFile>(Object, std::move(M));
328*9880d681SAndroid Build Coastguard Worker }
329