1 //===-------------------- Layer.cpp - Layer interfaces --------------------===//
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 #include "llvm/ExecutionEngine/Orc/Layer.h"
11 #include "llvm/Object/ObjectFile.h"
12 #include "llvm/Support/Debug.h"
13
14 #define DEBUG_TYPE "orc"
15
16 namespace llvm {
17 namespace orc {
18
IRLayer(ExecutionSession & ES)19 IRLayer::IRLayer(ExecutionSession &ES) : ES(ES) {}
~IRLayer()20 IRLayer::~IRLayer() {}
21
add(JITDylib & JD,ThreadSafeModule TSM,VModuleKey K)22 Error IRLayer::add(JITDylib &JD, ThreadSafeModule TSM, VModuleKey K) {
23 return JD.define(llvm::make_unique<BasicIRLayerMaterializationUnit>(
24 *this, std::move(K), std::move(TSM)));
25 }
26
IRMaterializationUnit(ExecutionSession & ES,ThreadSafeModule TSM,VModuleKey K)27 IRMaterializationUnit::IRMaterializationUnit(ExecutionSession &ES,
28 ThreadSafeModule TSM, VModuleKey K)
29 : MaterializationUnit(SymbolFlagsMap(), std::move(K)), TSM(std::move(TSM)) {
30
31 assert(this->TSM && "Module must not be null");
32
33 MangleAndInterner Mangle(ES, this->TSM.getModule()->getDataLayout());
34 for (auto &G : this->TSM.getModule()->global_values()) {
35 if (G.hasName() && !G.isDeclaration() && !G.hasLocalLinkage() &&
36 !G.hasAvailableExternallyLinkage() && !G.hasAppendingLinkage()) {
37 auto MangledName = Mangle(G.getName());
38 SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G);
39 SymbolToDefinition[MangledName] = &G;
40 }
41 }
42 }
43
IRMaterializationUnit(ThreadSafeModule TSM,VModuleKey K,SymbolFlagsMap SymbolFlags,SymbolNameToDefinitionMap SymbolToDefinition)44 IRMaterializationUnit::IRMaterializationUnit(
45 ThreadSafeModule TSM, VModuleKey K, SymbolFlagsMap SymbolFlags,
46 SymbolNameToDefinitionMap SymbolToDefinition)
47 : MaterializationUnit(std::move(SymbolFlags), std::move(K)),
48 TSM(std::move(TSM)), SymbolToDefinition(std::move(SymbolToDefinition)) {}
49
getName() const50 StringRef IRMaterializationUnit::getName() const {
51 if (TSM.getModule())
52 return TSM.getModule()->getModuleIdentifier();
53 return "<null module>";
54 }
55
discard(const JITDylib & JD,const SymbolStringPtr & Name)56 void IRMaterializationUnit::discard(const JITDylib &JD,
57 const SymbolStringPtr &Name) {
58 LLVM_DEBUG(JD.getExecutionSession().runSessionLocked([&]() {
59 dbgs() << "In " << JD.getName() << " discarding " << *Name << " from MU@"
60 << this << " (" << getName() << ")\n";
61 }););
62
63 auto I = SymbolToDefinition.find(Name);
64 assert(I != SymbolToDefinition.end() &&
65 "Symbol not provided by this MU, or previously discarded");
66 assert(!I->second->isDeclaration() &&
67 "Discard should only apply to definitions");
68 I->second->setLinkage(GlobalValue::AvailableExternallyLinkage);
69 SymbolToDefinition.erase(I);
70 }
71
BasicIRLayerMaterializationUnit(IRLayer & L,VModuleKey K,ThreadSafeModule TSM)72 BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit(
73 IRLayer &L, VModuleKey K, ThreadSafeModule TSM)
74 : IRMaterializationUnit(L.getExecutionSession(), std::move(TSM),
75 std::move(K)),
76 L(L), K(std::move(K)) {}
77
materialize(MaterializationResponsibility R)78 void BasicIRLayerMaterializationUnit::materialize(
79 MaterializationResponsibility R) {
80
81 // Throw away the SymbolToDefinition map: it's not usable after we hand
82 // off the module.
83 SymbolToDefinition.clear();
84
85 // If cloneToNewContextOnEmit is set, clone the module now.
86 if (L.getCloneToNewContextOnEmit())
87 TSM = cloneToNewContext(TSM);
88
89 #ifndef NDEBUG
90 auto &ES = R.getTargetJITDylib().getExecutionSession();
91 #endif // NDEBUG
92
93 auto Lock = TSM.getContextLock();
94 LLVM_DEBUG(ES.runSessionLocked([&]() {
95 dbgs() << "Emitting, for " << R.getTargetJITDylib().getName() << ", "
96 << *this << "\n";
97 }););
98 L.emit(std::move(R), std::move(TSM));
99 LLVM_DEBUG(ES.runSessionLocked([&]() {
100 dbgs() << "Finished emitting, for " << R.getTargetJITDylib().getName()
101 << ", " << *this << "\n";
102 }););
103 }
104
ObjectLayer(ExecutionSession & ES)105 ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {}
106
~ObjectLayer()107 ObjectLayer::~ObjectLayer() {}
108
add(JITDylib & JD,std::unique_ptr<MemoryBuffer> O,VModuleKey K)109 Error ObjectLayer::add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O,
110 VModuleKey K) {
111 auto ObjMU = BasicObjectLayerMaterializationUnit::Create(*this, std::move(K),
112 std::move(O));
113 if (!ObjMU)
114 return ObjMU.takeError();
115 return JD.define(std::move(*ObjMU));
116 }
117
118 Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
Create(ObjectLayer & L,VModuleKey K,std::unique_ptr<MemoryBuffer> O)119 BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L, VModuleKey K,
120 std::unique_ptr<MemoryBuffer> O) {
121 auto SymbolFlags =
122 getObjectSymbolFlags(L.getExecutionSession(), O->getMemBufferRef());
123
124 if (!SymbolFlags)
125 return SymbolFlags.takeError();
126
127 return std::unique_ptr<BasicObjectLayerMaterializationUnit>(
128 new BasicObjectLayerMaterializationUnit(L, K, std::move(O),
129 std::move(*SymbolFlags)));
130 }
131
BasicObjectLayerMaterializationUnit(ObjectLayer & L,VModuleKey K,std::unique_ptr<MemoryBuffer> O,SymbolFlagsMap SymbolFlags)132 BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit(
133 ObjectLayer &L, VModuleKey K, std::unique_ptr<MemoryBuffer> O,
134 SymbolFlagsMap SymbolFlags)
135 : MaterializationUnit(std::move(SymbolFlags), std::move(K)), L(L),
136 O(std::move(O)) {}
137
getName() const138 StringRef BasicObjectLayerMaterializationUnit::getName() const {
139 if (O)
140 return O->getBufferIdentifier();
141 return "<null object>";
142 }
143
materialize(MaterializationResponsibility R)144 void BasicObjectLayerMaterializationUnit::materialize(
145 MaterializationResponsibility R) {
146 L.emit(std::move(R), std::move(O));
147 }
148
discard(const JITDylib & JD,const SymbolStringPtr & Name)149 void BasicObjectLayerMaterializationUnit::discard(const JITDylib &JD,
150 const SymbolStringPtr &Name) {
151 // FIXME: Support object file level discard. This could be done by building a
152 // filter to pass to the object layer along with the object itself.
153 }
154
getObjectSymbolFlags(ExecutionSession & ES,MemoryBufferRef ObjBuffer)155 Expected<SymbolFlagsMap> getObjectSymbolFlags(ExecutionSession &ES,
156 MemoryBufferRef ObjBuffer) {
157 auto Obj = object::ObjectFile::createObjectFile(ObjBuffer);
158
159 if (!Obj)
160 return Obj.takeError();
161
162 SymbolFlagsMap SymbolFlags;
163 for (auto &Sym : (*Obj)->symbols()) {
164 // Skip symbols not defined in this object file.
165 if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined)
166 continue;
167
168 // Skip symbols that are not global.
169 if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global))
170 continue;
171
172 auto Name = Sym.getName();
173 if (!Name)
174 return Name.takeError();
175 auto InternedName = ES.intern(*Name);
176 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
177 if (!SymFlags)
178 return SymFlags.takeError();
179 SymbolFlags[InternedName] = std::move(*SymFlags);
180 }
181
182 return SymbolFlags;
183 }
184
185 } // End namespace orc.
186 } // End namespace llvm.
187