blob: f20ce6cf665ea7cc77e0726431a6e9149bf658ce [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
14#include "llvm/Bitcode/ReaderWriter.h"
15#include "llvm/IR/LLVMContext.h"
Rafael Espindolac3f9b5a2014-06-23 21:53:12 +000016#include "llvm/IR/GVMaterializer.h"
Rafael Espindolaa51f0f82014-02-28 02:17:23 +000017#include "llvm/IR/Mangler.h"
Rafael Espindolaf12b8282014-02-21 20:10:59 +000018#include "llvm/IR/Module.h"
19#include "llvm/Object/IRObjectFile.h"
Rafael Espindola2e60ca92014-06-24 13:56:32 +000020#include "llvm/Support/MemoryBuffer.h"
Rafael Espindola23f04062014-02-21 20:21:55 +000021#include "llvm/Support/raw_ostream.h"
Rafael Espindolaf12b8282014-02-21 20:10:59 +000022using namespace llvm;
23using namespace object;
24
Rafael Espindola2e60ca92014-06-24 13:56:32 +000025IRObjectFile::IRObjectFile(std::unique_ptr<MemoryBuffer> Object,
26 std::error_code &EC, LLVMContext &Context)
27 : SymbolicFile(Binary::ID_IR, std::move(Object)) {
28 ErrorOr<Module *> MOrErr = getLazyBitcodeModule(Data.get(), Context);
Rafael Espindolaf12b8282014-02-21 20:10:59 +000029 if ((EC = MOrErr.getError()))
30 return;
31
32 M.reset(MOrErr.get());
Rafael Espindolaa51f0f82014-02-28 02:17:23 +000033
34 // If we have a DataLayout, setup a mangler.
35 const DataLayout *DL = M->getDataLayout();
36 if (!DL)
37 return;
38
39 Mang.reset(new Mangler(DL));
Rafael Espindolaf12b8282014-02-21 20:10:59 +000040}
41
Rafael Espindolac3f9b5a2014-06-23 21:53:12 +000042IRObjectFile::~IRObjectFile() { M->getMaterializer()->releaseBuffer(); }
43
Rafael Espindolaf12b8282014-02-21 20:10:59 +000044static const GlobalValue &getGV(DataRefImpl &Symb) {
45 return *reinterpret_cast<GlobalValue*>(Symb.p & ~uintptr_t(3));
46}
47
48static uintptr_t skipEmpty(Module::const_alias_iterator I, const Module &M) {
49 if (I == M.alias_end())
50 return 3;
51 const GlobalValue *GV = &*I;
52 return reinterpret_cast<uintptr_t>(GV) | 2;
53}
54
55static uintptr_t skipEmpty(Module::const_global_iterator I, const Module &M) {
56 if (I == M.global_end())
57 return skipEmpty(M.alias_begin(), M);
58 const GlobalValue *GV = &*I;
59 return reinterpret_cast<uintptr_t>(GV) | 1;
60}
61
62static uintptr_t skipEmpty(Module::const_iterator I, const Module &M) {
63 if (I == M.end())
64 return skipEmpty(M.global_begin(), M);
65 const GlobalValue *GV = &*I;
66 return reinterpret_cast<uintptr_t>(GV) | 0;
67}
68
69void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
70 const GlobalValue *GV = &getGV(Symb);
71 const Module &M = *GV->getParent();
72 uintptr_t Res;
73 switch (Symb.p & 3) {
74 case 0: {
75 Module::const_iterator Iter(static_cast<const Function*>(GV));
76 ++Iter;
77 Res = skipEmpty(Iter, M);
78 break;
79 }
80 case 1: {
81 Module::const_global_iterator Iter(static_cast<const GlobalVariable*>(GV));
82 ++Iter;
83 Res = skipEmpty(Iter, M);
84 break;
85 }
86 case 2: {
87 Module::const_alias_iterator Iter(static_cast<const GlobalAlias*>(GV));
88 ++Iter;
89 Res = skipEmpty(Iter, M);
90 break;
91 }
92 case 3:
93 llvm_unreachable("Invalid symbol reference");
94 }
95
96 Symb.p = Res;
97}
98
Rafael Espindoladb4ed0b2014-06-13 02:24:39 +000099std::error_code IRObjectFile::printSymbolName(raw_ostream &OS,
100 DataRefImpl Symb) const {
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000101 const GlobalValue &GV = getGV(Symb);
Rafael Espindolaa51f0f82014-02-28 02:17:23 +0000102
103 if (Mang)
104 Mang->getNameWithPrefix(OS, &GV, false);
105 else
106 OS << GV.getName();
107
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000108 return object_error::success;
109}
110
Rafael Espindola8af5cb22014-06-18 19:05:24 +0000111static bool isDeclaration(const GlobalValue &V) {
112 if (V.hasAvailableExternallyLinkage())
113 return true;
114
115 if (V.isMaterializable())
116 return false;
117
118 return V.isDeclaration();
119}
120
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000121uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const {
122 const GlobalValue &GV = getGV(Symb);
123
124 uint32_t Res = BasicSymbolRef::SF_None;
Rafael Espindola8af5cb22014-06-18 19:05:24 +0000125 if (isDeclaration(GV))
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000126 Res |= BasicSymbolRef::SF_Undefined;
Rafael Espindola2fb5bc32014-03-13 23:18:37 +0000127 if (GV.hasPrivateLinkage())
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000128 Res |= BasicSymbolRef::SF_FormatSpecific;
129 if (!GV.hasLocalLinkage())
130 Res |= BasicSymbolRef::SF_Global;
131 if (GV.hasCommonLinkage())
132 Res |= BasicSymbolRef::SF_Common;
133 if (GV.hasLinkOnceLinkage() || GV.hasWeakLinkage())
134 Res |= BasicSymbolRef::SF_Weak;
135
136 return Res;
137}
138
139const GlobalValue &IRObjectFile::getSymbolGV(DataRefImpl Symb) const {
140 const GlobalValue &GV = getGV(Symb);
141 return GV;
142}
143
144basic_symbol_iterator IRObjectFile::symbol_begin_impl() const {
145 Module::const_iterator I = M->begin();
146 DataRefImpl Ret;
147 Ret.p = skipEmpty(I, *M);
148 return basic_symbol_iterator(BasicSymbolRef(Ret, this));
149}
150
151basic_symbol_iterator IRObjectFile::symbol_end_impl() const {
152 DataRefImpl Ret;
153 Ret.p = 3;
154 return basic_symbol_iterator(BasicSymbolRef(Ret, this));
155}
156
Rafael Espindola2e60ca92014-06-24 13:56:32 +0000157ErrorOr<SymbolicFile *> llvm::object::SymbolicFile::createIRObjectFile(
158 std::unique_ptr<MemoryBuffer> Object, LLVMContext &Context) {
Rafael Espindoladb4ed0b2014-06-13 02:24:39 +0000159 std::error_code EC;
Rafael Espindola2e60ca92014-06-24 13:56:32 +0000160 std::unique_ptr<IRObjectFile> Ret(
161 new IRObjectFile(std::move(Object), EC, Context));
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000162 if (EC)
163 return EC;
Ahmed Charles96c9d952014-03-05 10:19:29 +0000164 return Ret.release();
Rafael Espindolaf12b8282014-02-21 20:10:59 +0000165}