blob: 51b2446535b7fd59b638c219ab938587a646227f [file] [log] [blame]
Rafael Espindolaf12b8282014-02-21 20:10:59 +00001//===- 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
Rafael Espindolaba79dba2014-07-04 22:44:18 +000014#include "llvm/Object/IRObjectFile.h"
15#include "RecordStreamer.h"
Benjamin Kramer0a446fd2015-03-01 21:28:53 +000016#include "llvm/ADT/STLExtras.h"
Teresa Johnsonad176792016-11-11 05:34:58 +000017#include "llvm/Bitcode/BitcodeReader.h"
Rafael Espindolac3f9b5a2014-06-23 21:53:12 +000018#include "llvm/IR/GVMaterializer.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000019#include "llvm/IR/LLVMContext.h"
Rafael Espindolaa51f0f82014-02-28 02:17:23 +000020#include "llvm/IR/Mangler.h"
Rafael Espindolaf12b8282014-02-21 20:10:59 +000021#include "llvm/IR/Module.h"
Rafael Espindola13b69d62014-07-03 18:59:23 +000022#include "llvm/MC/MCAsmInfo.h"
23#include "llvm/MC/MCContext.h"
24#include "llvm/MC/MCInstrInfo.h"
25#include "llvm/MC/MCObjectFileInfo.h"
Rafael Espindola13b69d62014-07-03 18:59:23 +000026#include "llvm/MC/MCParser/MCAsmParser.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000027#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000028#include "llvm/MC/MCRegisterInfo.h"
Pete Cooper81902a32015-05-15 22:19:42 +000029#include "llvm/MC/MCSubtargetInfo.h"
Peter Collingbourne10039c02014-09-18 21:28:49 +000030#include "llvm/Object/ObjectFile.h"
Rafael Espindola2e60ca92014-06-24 13:56:32 +000031#include "llvm/Support/MemoryBuffer.h"
Rafael Espindola13b69d62014-07-03 18:59:23 +000032#include "llvm/Support/SourceMgr.h"
33#include "llvm/Support/TargetRegistry.h"
Rafael Espindola23f04062014-02-21 20:21:55 +000034#include "llvm/Support/raw_ostream.h"
Rafael Espindolaf12b8282014-02-21 20:10:59 +000035using namespace llvm;
36using namespace object;
37
Rafael Espindola48af1c22014-08-19 18:44:46 +000038IRObjectFile::IRObjectFile(MemoryBufferRef Object, std::unique_ptr<Module> Mod)
39 : SymbolicFile(Binary::ID_IR, Object), M(std::move(Mod)) {
Rafael Espindolac233f742015-06-23 13:59:29 +000040 Mang.reset(new Mangler());
Peter Collingbournee32baa02016-11-24 00:41:05 +000041
42 for (Function &F : *M)
43 SymTab.push_back(&F);
44 for (GlobalVariable &GV : M->globals())
45 SymTab.push_back(&GV);
46 for (GlobalAlias &GA : M->aliases())
47 SymTab.push_back(&GA);
48
Benjamin Kramerb0b52fc2016-07-01 11:05:15 +000049 CollectAsmUndefinedRefs(Triple(M->getTargetTriple()), M->getModuleInlineAsm(),
50 [this](StringRef Name, BasicSymbolRef::Flags Flags) {
Peter Collingbournee32baa02016-11-24 00:41:05 +000051 SymTab.push_back(new (AsmSymbols.Allocate())
52 AsmSymbol(Name, Flags));
Benjamin Kramerb0b52fc2016-07-01 11:05:15 +000053 });
Mehdi Aminie9cffaf2016-04-22 04:28:05 +000054}
Rafael Espindola13b69d62014-07-03 18:59:23 +000055
Mehdi Aminie9cffaf2016-04-22 04:28:05 +000056// Parse inline ASM and collect the list of symbols that are not defined in
57// the current module. This is inspired from IRObjectFile.
58void IRObjectFile::CollectAsmUndefinedRefs(
Mehdi Aminia0cb8902016-04-22 04:58:12 +000059 const Triple &TT, StringRef InlineAsm,
Benjamin Kramerb0b52fc2016-07-01 11:05:15 +000060 function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmUndefinedRefs) {
Rafael Espindola13b69d62014-07-03 18:59:23 +000061 if (InlineAsm.empty())
62 return;
63
Rafael Espindola13b69d62014-07-03 18:59:23 +000064 std::string Err;
Daniel Sanders8d8b13d2015-06-16 12:18:07 +000065 const Target *T = TargetRegistry::lookupTarget(TT.str(), Err);
Teresa Johnson3624bdf2016-11-14 17:12:32 +000066 assert(T && T->hasMCAsmParser());
Rafael Espindola13b69d62014-07-03 18:59:23 +000067
Daniel Sanders8d8b13d2015-06-16 12:18:07 +000068 std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TT.str()));
Rafael Espindola13b69d62014-07-03 18:59:23 +000069 if (!MRI)
70 return;
71
Daniel Sanders8d8b13d2015-06-16 12:18:07 +000072 std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TT.str()));
Rafael Espindola13b69d62014-07-03 18:59:23 +000073 if (!MAI)
74 return;
75
76 std::unique_ptr<MCSubtargetInfo> STI(
Daniel Sanders8d8b13d2015-06-16 12:18:07 +000077 T->createMCSubtargetInfo(TT.str(), "", ""));
Rafael Espindola13b69d62014-07-03 18:59:23 +000078 if (!STI)
79 return;
80
81 std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo());
82 if (!MCII)
83 return;
84
85 MCObjectFileInfo MOFI;
86 MCContext MCCtx(MAI.get(), MRI.get(), &MOFI);
Rafael Espindola699281c2016-05-18 11:58:50 +000087 MOFI.InitMCObjectFileInfo(TT, /*PIC*/ false, CodeModel::Default, MCCtx);
Peter Collingbourne63e10c92016-11-18 03:20:36 +000088 RecordStreamer Streamer(MCCtx);
89 T->createNullTargetStreamer(Streamer);
Rafael Espindola13b69d62014-07-03 18:59:23 +000090
91 std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm));
92 SourceMgr SrcMgr;
David Blaikie1961f142014-08-21 20:44:56 +000093 SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
Rafael Espindola13b69d62014-07-03 18:59:23 +000094 std::unique_ptr<MCAsmParser> Parser(
Peter Collingbourne63e10c92016-11-18 03:20:36 +000095 createMCAsmParser(SrcMgr, MCCtx, Streamer, *MAI));
Rafael Espindola13b69d62014-07-03 18:59:23 +000096
97 MCTargetOptions MCOptions;
98 std::unique_ptr<MCTargetAsmParser> TAP(
99 T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions));
100 if (!TAP)
101 return;
102
103 Parser->setTargetParser(*TAP);
104 if (Parser->Run(false))
105 return;
106
Peter Collingbourne63e10c92016-11-18 03:20:36 +0000107 for (auto &KV : Streamer) {
Rafael Espindola13b69d62014-07-03 18:59:23 +0000108 StringRef Key = KV.first();
109 RecordStreamer::State Value = KV.second;
110 uint32_t Res = BasicSymbolRef::SF_None;
111 switch (Value) {
112 case RecordStreamer::NeverSeen:
Davide Italianocc1aa052016-09-16 16:07:19 +0000113 llvm_unreachable("NeverSeen should have been replaced earlier");
Rafael Espindola13b69d62014-07-03 18:59:23 +0000114 case RecordStreamer::DefinedGlobal:
115 Res |= BasicSymbolRef::SF_Global;
116 break;
117 case RecordStreamer::Defined:
118 break;
119 case RecordStreamer::Global:
120 case RecordStreamer::Used:
121 Res |= BasicSymbolRef::SF_Undefined;
122 Res |= BasicSymbolRef::SF_Global;
123 break;
Davide Italianof7518492016-09-15 17:54:22 +0000124 case RecordStreamer::DefinedWeak:
Davide Italianoec7e29e2016-06-22 20:48:15 +0000125 Res |= BasicSymbolRef::SF_Weak;
126 Res |= BasicSymbolRef::SF_Global;
Davide Italiano36c54fb2016-06-23 00:07:31 +0000127 break;
Davide Italianof7518492016-09-15 17:54:22 +0000128 case RecordStreamer::UndefinedWeak:
129 Res |= BasicSymbolRef::SF_Weak;
130 Res |= BasicSymbolRef::SF_Undefined;
Rafael Espindola13b69d62014-07-03 18:59:23 +0000131 }
Mehdi Aminie9cffaf2016-04-22 04:28:05 +0000132 AsmUndefinedRefs(Key, BasicSymbolRef::Flags(Res));
Rafael Espindola13b69d62014-07-03 18:59:23 +0000133 }
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000134}
135
Peter Collingbournee32baa02016-11-24 00:41:05 +0000136IRObjectFile::~IRObjectFile() {}
Rafael Espindola13b69d62014-07-03 18:59:23 +0000137
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000138void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
Peter Collingbournee32baa02016-11-24 00:41:05 +0000139 Symb.p += sizeof(Sym);
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000140}
141
Rafael Espindoladb4ed0b2014-06-13 02:24:39 +0000142std::error_code IRObjectFile::printSymbolName(raw_ostream &OS,
143 DataRefImpl Symb) const {
Peter Collingbournee32baa02016-11-24 00:41:05 +0000144 Sym S = getSym(Symb);
145 if (S.is<AsmSymbol *>()) {
146 OS << S.get<AsmSymbol *>()->first;
Rui Ueyama7d099192015-06-09 15:20:42 +0000147 return std::error_code();
Rafael Espindola13b69d62014-07-03 18:59:23 +0000148 }
Rafael Espindolaa51f0f82014-02-28 02:17:23 +0000149
Peter Collingbournee32baa02016-11-24 00:41:05 +0000150 auto *GV = S.get<GlobalValue *>();
Peter Collingbourne82e657b2015-06-11 21:42:18 +0000151 if (GV->hasDLLImportStorageClass())
152 OS << "__imp_";
153
Rafael Espindolaa51f0f82014-02-28 02:17:23 +0000154 if (Mang)
Rafael Espindola13b69d62014-07-03 18:59:23 +0000155 Mang->getNameWithPrefix(OS, GV, false);
Rafael Espindolaa51f0f82014-02-28 02:17:23 +0000156 else
Rafael Espindola13b69d62014-07-03 18:59:23 +0000157 OS << GV->getName();
Rafael Espindolaa51f0f82014-02-28 02:17:23 +0000158
Rui Ueyama7d099192015-06-09 15:20:42 +0000159 return std::error_code();
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000160}
161
162uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const {
Peter Collingbournee32baa02016-11-24 00:41:05 +0000163 Sym S = getSym(Symb);
164 if (S.is<AsmSymbol *>())
165 return S.get<AsmSymbol *>()->second;
Rafael Espindola13b69d62014-07-03 18:59:23 +0000166
Peter Collingbournee32baa02016-11-24 00:41:05 +0000167 auto *GV = S.get<GlobalValue *>();
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000168
169 uint32_t Res = BasicSymbolRef::SF_None;
Rafael Espindolad4bcefc2014-10-24 18:13:04 +0000170 if (GV->isDeclarationForLinker())
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000171 Res |= BasicSymbolRef::SF_Undefined;
Kevin Enderbydc0dbe12015-11-10 00:31:08 +0000172 else if (GV->hasHiddenVisibility() && !GV->hasLocalLinkage())
173 Res |= BasicSymbolRef::SF_Hidden;
174 if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) {
175 if (GVar->isConstant())
176 Res |= BasicSymbolRef::SF_Const;
177 }
Rafael Espindola13b69d62014-07-03 18:59:23 +0000178 if (GV->hasPrivateLinkage())
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000179 Res |= BasicSymbolRef::SF_FormatSpecific;
Rafael Espindola13b69d62014-07-03 18:59:23 +0000180 if (!GV->hasLocalLinkage())
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000181 Res |= BasicSymbolRef::SF_Global;
Rafael Espindola13b69d62014-07-03 18:59:23 +0000182 if (GV->hasCommonLinkage())
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000183 Res |= BasicSymbolRef::SF_Common;
Rafael Espindola8d6fbc32016-02-29 14:26:06 +0000184 if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() ||
185 GV->hasExternalWeakLinkage())
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000186 Res |= BasicSymbolRef::SF_Weak;
187
Rafael Espindola2dc0d9b2014-07-04 19:08:22 +0000188 if (GV->getName().startswith("llvm."))
189 Res |= BasicSymbolRef::SF_FormatSpecific;
190 else if (auto *Var = dyn_cast<GlobalVariable>(GV)) {
Rafael Espindola83658d62016-05-11 18:21:59 +0000191 if (Var->getSection() == "llvm.metadata")
Rafael Espindolab674c172014-07-04 15:03:17 +0000192 Res |= BasicSymbolRef::SF_FormatSpecific;
193 }
194
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000195 return Res;
196}
197
Peter Collingbournee32baa02016-11-24 00:41:05 +0000198GlobalValue *IRObjectFile::getSymbolGV(DataRefImpl Symb) {
199 return getSym(Symb).dyn_cast<GlobalValue *>();
200}
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000201
Rafael Espindola25a7e0a2014-12-09 16:18:11 +0000202std::unique_ptr<Module> IRObjectFile::takeModule() { return std::move(M); }
203
Peter Collingbourne435890a2016-11-22 03:38:40 +0000204basic_symbol_iterator IRObjectFile::symbol_begin() const {
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000205 DataRefImpl Ret;
Peter Collingbournee32baa02016-11-24 00:41:05 +0000206 Ret.p = reinterpret_cast<uintptr_t>(SymTab.data());
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000207 return basic_symbol_iterator(BasicSymbolRef(Ret, this));
208}
209
Peter Collingbourne435890a2016-11-22 03:38:40 +0000210basic_symbol_iterator IRObjectFile::symbol_end() const {
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000211 DataRefImpl Ret;
Peter Collingbournee32baa02016-11-24 00:41:05 +0000212 Ret.p = reinterpret_cast<uintptr_t>(SymTab.data() + SymTab.size());
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000213 return basic_symbol_iterator(BasicSymbolRef(Ret, this));
214}
215
Peter Collingbournedebb6f62016-11-24 01:13:09 +0000216StringRef IRObjectFile::getTargetTriple() const { return M->getTargetTriple(); }
217
Peter Collingbourne10039c02014-09-18 21:28:49 +0000218ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) {
219 for (const SectionRef &Sec : Obj.sections()) {
Steven Wuf2fe0142016-02-29 19:40:10 +0000220 if (Sec.isBitcode()) {
Peter Collingbourne10039c02014-09-18 21:28:49 +0000221 StringRef SecContents;
222 if (std::error_code EC = Sec.getContents(SecContents))
223 return EC;
224 return MemoryBufferRef(SecContents, Obj.getFileName());
225 }
226 }
227
228 return object_error::bitcode_section_not_found;
229}
230
231ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) {
232 sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer());
233 switch (Type) {
234 case sys::fs::file_magic::bitcode:
235 return Object;
236 case sys::fs::file_magic::elf_relocatable:
237 case sys::fs::file_magic::macho_object:
238 case sys::fs::file_magic::coff_object: {
Kevin Enderby3fcdf6a2016-04-06 22:14:09 +0000239 Expected<std::unique_ptr<ObjectFile>> ObjFile =
Peter Collingbourne10039c02014-09-18 21:28:49 +0000240 ObjectFile::createObjectFile(Object, Type);
241 if (!ObjFile)
Kevin Enderby3fcdf6a2016-04-06 22:14:09 +0000242 return errorToErrorCode(ObjFile.takeError());
Peter Collingbourne10039c02014-09-18 21:28:49 +0000243 return findBitcodeInObject(*ObjFile->get());
244 }
245 default:
246 return object_error::invalid_file_type;
247 }
248}
249
Peter Collingbourned9445c42016-11-13 07:00:17 +0000250Expected<std::unique_ptr<IRObjectFile>>
Rafael Espindola5dec7ea2014-12-09 20:36:13 +0000251llvm::object::IRObjectFile::create(MemoryBufferRef Object,
252 LLVMContext &Context) {
Peter Collingbourne10039c02014-09-18 21:28:49 +0000253 ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
254 if (!BCOrErr)
Peter Collingbourned9445c42016-11-13 07:00:17 +0000255 return errorCodeToError(BCOrErr.getError());
Rafael Espindola48af1c22014-08-19 18:44:46 +0000256
Peter Collingbourned9445c42016-11-13 07:00:17 +0000257 Expected<std::unique_ptr<Module>> MOrErr =
Peter Collingbournee2dcf7c2016-11-08 06:03:43 +0000258 getLazyBitcodeModule(*BCOrErr, Context,
Rafael Espindolacba833a2015-03-13 21:54:20 +0000259 /*ShouldLazyLoadMetadata*/ true);
Peter Collingbourned9445c42016-11-13 07:00:17 +0000260 if (!MOrErr)
261 return MOrErr.takeError();
Rafael Espindoladddd1fd2014-07-04 18:40:36 +0000262
Rafael Espindoladcd1dca2015-06-16 22:27:55 +0000263 std::unique_ptr<Module> &M = MOrErr.get();
Teresa Johnson9ba95f92016-08-11 14:58:12 +0000264 return llvm::make_unique<IRObjectFile>(BCOrErr.get(), std::move(M));
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000265}