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