11cf9987fSLang Hames //===-------------------- Layer.cpp - Layer interfaces --------------------===//
21cf9987fSLang Hames //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61cf9987fSLang Hames //
71cf9987fSLang Hames //===----------------------------------------------------------------------===//
81cf9987fSLang Hames
91cf9987fSLang Hames #include "llvm/ExecutionEngine/Orc/Layer.h"
1085fb9976SLang Hames
1138a8760bSLang Hames #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
1285fb9976SLang Hames #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
134299d8d0SLang Hames #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
14ce2207abSLang Hames #include "llvm/IR/Constants.h"
1546f40a71SLang Hames #include "llvm/Support/Debug.h"
1646f40a71SLang Hames
1746f40a71SLang Hames #define DEBUG_TYPE "orc"
181cf9987fSLang Hames
191cf9987fSLang Hames namespace llvm {
201cf9987fSLang Hames namespace orc {
211cf9987fSLang Hames
22*3a3cb929SKazu Hirata IRLayer::~IRLayer() = default;
231cf9987fSLang Hames
add(ResourceTrackerSP RT,ThreadSafeModule TSM)240aec49c8SLang Hames Error IRLayer::add(ResourceTrackerSP RT, ThreadSafeModule TSM) {
250aec49c8SLang Hames assert(RT && "RT can not be null");
260aec49c8SLang Hames auto &JD = RT->getJITDylib();
270eaee545SJonas Devlieghere return JD.define(std::make_unique<BasicIRLayerMaterializationUnit>(
280aec49c8SLang Hames *this, *getManglingOptions(), std::move(TSM)),
290aec49c8SLang Hames std::move(RT));
301cf9987fSLang Hames }
311cf9987fSLang Hames
IRMaterializationUnit(ExecutionSession & ES,const IRSymbolMapper::ManglingOptions & MO,ThreadSafeModule TSM)3285fb9976SLang Hames IRMaterializationUnit::IRMaterializationUnit(
3385fb9976SLang Hames ExecutionSession &ES, const IRSymbolMapper::ManglingOptions &MO,
340aec49c8SLang Hames ThreadSafeModule TSM)
35ae73f3fdSLang Hames : MaterializationUnit(Interface()), TSM(std::move(TSM)) {
361cf9987fSLang Hames
378d76c711SLang Hames assert(this->TSM && "Module must not be null");
388d76c711SLang Hames
39809e9d1eSLang Hames MangleAndInterner Mangle(ES, this->TSM.getModuleUnlocked()->getDataLayout());
40809e9d1eSLang Hames this->TSM.withModuleDo([&](Module &M) {
41809e9d1eSLang Hames for (auto &G : M.global_values()) {
42ce2207abSLang Hames // Skip globals that don't generate symbols.
4385fb9976SLang Hames
44ce2207abSLang Hames if (!G.hasName() || G.isDeclaration() || G.hasLocalLinkage() ||
45ce2207abSLang Hames G.hasAvailableExternallyLinkage() || G.hasAppendingLinkage())
46ce2207abSLang Hames continue;
47ce2207abSLang Hames
48ce2207abSLang Hames // thread locals generate different symbols depending on whether or not
49ce2207abSLang Hames // emulated TLS is enabled.
50ce2207abSLang Hames if (G.isThreadLocal() && MO.EmulatedTLS) {
51ce2207abSLang Hames auto &GV = cast<GlobalVariable>(G);
52ce2207abSLang Hames
53ce2207abSLang Hames auto Flags = JITSymbolFlags::fromGlobalValue(GV);
54ce2207abSLang Hames
55ce2207abSLang Hames auto EmuTLSV = Mangle(("__emutls_v." + GV.getName()).str());
56ce2207abSLang Hames SymbolFlags[EmuTLSV] = Flags;
57ce2207abSLang Hames SymbolToDefinition[EmuTLSV] = &GV;
58ce2207abSLang Hames
59ce2207abSLang Hames // If this GV has a non-zero initializer we'll need to emit an
60ce2207abSLang Hames // __emutls.t symbol too.
61ce2207abSLang Hames if (GV.hasInitializer()) {
62ce2207abSLang Hames const auto *InitVal = GV.getInitializer();
63ce2207abSLang Hames
64ce2207abSLang Hames // Skip zero-initializers.
65ce2207abSLang Hames if (isa<ConstantAggregateZero>(InitVal))
66ce2207abSLang Hames continue;
67ce2207abSLang Hames const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal);
68ce2207abSLang Hames if (InitIntValue && InitIntValue->isZero())
69ce2207abSLang Hames continue;
70ce2207abSLang Hames
71ce2207abSLang Hames auto EmuTLST = Mangle(("__emutls_t." + GV.getName()).str());
72ce2207abSLang Hames SymbolFlags[EmuTLST] = Flags;
73ce2207abSLang Hames }
74ce2207abSLang Hames continue;
75ce2207abSLang Hames }
76ce2207abSLang Hames
77ce2207abSLang Hames // Otherwise we just need a normal linker mangling.
781cf9987fSLang Hames auto MangledName = Mangle(G.getName());
791cf9987fSLang Hames SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G);
80d3a76f5bSLang Hames SymbolToDefinition[MangledName] = &G;
811cf9987fSLang Hames }
8285fb9976SLang Hames
8385fb9976SLang Hames // If we need an init symbol for this module then create one.
8485fb9976SLang Hames if (!llvm::empty(getStaticInitGVs(M))) {
85cb84e482SLang Hames size_t Counter = 0;
86cb84e482SLang Hames
879a47bcaeSStefan Gränitz do {
8885fb9976SLang Hames std::string InitSymbolName;
8985fb9976SLang Hames raw_string_ostream(InitSymbolName)
90cb84e482SLang Hames << "$." << M.getModuleIdentifier() << ".__inits." << Counter++;
9185fb9976SLang Hames InitSymbol = ES.intern(InitSymbolName);
929a47bcaeSStefan Gränitz } while (SymbolFlags.count(InitSymbol));
939a47bcaeSStefan Gränitz
949a47bcaeSStefan Gränitz SymbolFlags[InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
9585fb9976SLang Hames }
96809e9d1eSLang Hames });
971cf9987fSLang Hames }
981cf9987fSLang Hames
IRMaterializationUnit(ThreadSafeModule TSM,Interface I,SymbolNameToDefinitionMap SymbolToDefinition)99d6155ff0SLang Hames IRMaterializationUnit::IRMaterializationUnit(
100ae73f3fdSLang Hames ThreadSafeModule TSM, Interface I,
101ae73f3fdSLang Hames SymbolNameToDefinitionMap SymbolToDefinition)
102ae73f3fdSLang Hames : MaterializationUnit(std::move(I)), TSM(std::move(TSM)),
103ae73f3fdSLang Hames SymbolToDefinition(std::move(SymbolToDefinition)) {}
104d6155ff0SLang Hames
getName() const10546f40a71SLang Hames StringRef IRMaterializationUnit::getName() const {
106809e9d1eSLang Hames if (TSM)
107809e9d1eSLang Hames return TSM.withModuleDo(
1085b3275e5SMatthias Gehre [](const Module &M) -> StringRef { return M.getModuleIdentifier(); });
10946f40a71SLang Hames return "<null module>";
11046f40a71SLang Hames }
11146f40a71SLang Hames
discard(const JITDylib & JD,const SymbolStringPtr & Name)112cb5702c3SLang Hames void IRMaterializationUnit::discard(const JITDylib &JD,
113cb5702c3SLang Hames const SymbolStringPtr &Name) {
11446f40a71SLang Hames LLVM_DEBUG(JD.getExecutionSession().runSessionLocked([&]() {
11546f40a71SLang Hames dbgs() << "In " << JD.getName() << " discarding " << *Name << " from MU@"
11646f40a71SLang Hames << this << " (" << getName() << ")\n";
11746f40a71SLang Hames }););
11846f40a71SLang Hames
119d3a76f5bSLang Hames auto I = SymbolToDefinition.find(Name);
120d3a76f5bSLang Hames assert(I != SymbolToDefinition.end() &&
1211cf9987fSLang Hames "Symbol not provided by this MU, or previously discarded");
122d3a76f5bSLang Hames assert(!I->second->isDeclaration() &&
123d3a76f5bSLang Hames "Discard should only apply to definitions");
1241cf9987fSLang Hames I->second->setLinkage(GlobalValue::AvailableExternallyLinkage);
125d3a76f5bSLang Hames SymbolToDefinition.erase(I);
1261cf9987fSLang Hames }
1271cf9987fSLang Hames
BasicIRLayerMaterializationUnit(IRLayer & L,const IRSymbolMapper::ManglingOptions & MO,ThreadSafeModule TSM)1285261aa9fSLang Hames BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit(
1290aec49c8SLang Hames IRLayer &L, const IRSymbolMapper::ManglingOptions &MO, ThreadSafeModule TSM)
1300aec49c8SLang Hames : IRMaterializationUnit(L.getExecutionSession(), MO, std::move(TSM)), L(L) {
1310aec49c8SLang Hames }
1325261aa9fSLang Hames
materialize(std::unique_ptr<MaterializationResponsibility> R)1335261aa9fSLang Hames void BasicIRLayerMaterializationUnit::materialize(
1347dcd0042SLang Hames std::unique_ptr<MaterializationResponsibility> R) {
1358d76c711SLang Hames
136c3053e41SLang Hames // Throw away the SymbolToDefinition map: it's not usable after we hand
137c3053e41SLang Hames // off the module.
138c3053e41SLang Hames SymbolToDefinition.clear();
139c3053e41SLang Hames
140c3053e41SLang Hames // If cloneToNewContextOnEmit is set, clone the module now.
1418d76c711SLang Hames if (L.getCloneToNewContextOnEmit())
1428d76c711SLang Hames TSM = cloneToNewContext(TSM);
1438d76c711SLang Hames
14446f40a71SLang Hames #ifndef NDEBUG
1457dcd0042SLang Hames auto &ES = R->getTargetJITDylib().getExecutionSession();
1467dcd0042SLang Hames auto &N = R->getTargetJITDylib().getName();
14746f40a71SLang Hames #endif // NDEBUG
14846f40a71SLang Hames
14928e351afSNick Desaulniers LLVM_DEBUG(ES.runSessionLocked(
15028e351afSNick Desaulniers [&]() { dbgs() << "Emitting, for " << N << ", " << *this << "\n"; }););
1518b94274fSLang Hames L.emit(std::move(R), std::move(TSM));
15246f40a71SLang Hames LLVM_DEBUG(ES.runSessionLocked([&]() {
15328e351afSNick Desaulniers dbgs() << "Finished emitting, for " << N << ", " << *this << "\n";
15446f40a71SLang Hames }););
1555261aa9fSLang Hames }
1565261aa9fSLang Hames
157406ef36bSStefan Gränitz char ObjectLayer::ID;
158406ef36bSStefan Gränitz
ObjectLayer(ExecutionSession & ES)1591cf9987fSLang Hames ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {}
1601cf9987fSLang Hames
161*3a3cb929SKazu Hirata ObjectLayer::~ObjectLayer() = default;
1621cf9987fSLang Hames
add(ResourceTrackerSP RT,std::unique_ptr<MemoryBuffer> O,MaterializationUnit::Interface I)1634299d8d0SLang Hames Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O,
1644299d8d0SLang Hames MaterializationUnit::Interface I) {
1650aec49c8SLang Hames assert(RT && "RT can not be null");
1660aec49c8SLang Hames auto &JD = RT->getJITDylib();
1674299d8d0SLang Hames return JD.define(std::make_unique<BasicObjectLayerMaterializationUnit>(
1684299d8d0SLang Hames *this, std::move(O), std::move(I)),
1694299d8d0SLang Hames std::move(RT));
1704299d8d0SLang Hames }
1714299d8d0SLang Hames
add(ResourceTrackerSP RT,std::unique_ptr<MemoryBuffer> O)1724299d8d0SLang Hames Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O) {
1734299d8d0SLang Hames auto I = getObjectFileInterface(getExecutionSession(), O->getMemBufferRef());
1744299d8d0SLang Hames if (!I)
1754299d8d0SLang Hames return I.takeError();
1764299d8d0SLang Hames return add(std::move(RT), std::move(O), std::move(*I));
1774299d8d0SLang Hames }
1784299d8d0SLang Hames
add(JITDylib & JD,std::unique_ptr<MemoryBuffer> O)1794299d8d0SLang Hames Error ObjectLayer::add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O) {
1804299d8d0SLang Hames auto I = getObjectFileInterface(getExecutionSession(), O->getMemBufferRef());
1814299d8d0SLang Hames if (!I)
1824299d8d0SLang Hames return I.takeError();
1834299d8d0SLang Hames return add(JD, std::move(O), std::move(*I));
1841cf9987fSLang Hames }
1851cf9987fSLang Hames
186bfea8cdcSLang Hames Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
Create(ObjectLayer & L,std::unique_ptr<MemoryBuffer> O)1870aec49c8SLang Hames BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L,
188bfea8cdcSLang Hames std::unique_ptr<MemoryBuffer> O) {
1894299d8d0SLang Hames
190ae73f3fdSLang Hames auto ObjInterface =
1914299d8d0SLang Hames getObjectFileInterface(L.getExecutionSession(), O->getMemBufferRef());
192c0514f00SLang Hames
193ae73f3fdSLang Hames if (!ObjInterface)
194ae73f3fdSLang Hames return ObjInterface.takeError();
195c0514f00SLang Hames
196c0514f00SLang Hames return std::unique_ptr<BasicObjectLayerMaterializationUnit>(
197ae73f3fdSLang Hames new BasicObjectLayerMaterializationUnit(L, std::move(O),
198ae73f3fdSLang Hames std::move(*ObjInterface)));
199c0514f00SLang Hames }
200c0514f00SLang Hames
BasicObjectLayerMaterializationUnit(ObjectLayer & L,std::unique_ptr<MemoryBuffer> O,Interface I)201c0514f00SLang Hames BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit(
202ae73f3fdSLang Hames ObjectLayer &L, std::unique_ptr<MemoryBuffer> O, Interface I)
203ae73f3fdSLang Hames : MaterializationUnit(std::move(I)), L(L), O(std::move(O)) {}
204c0514f00SLang Hames
getName() const20546f40a71SLang Hames StringRef BasicObjectLayerMaterializationUnit::getName() const {
20646f40a71SLang Hames if (O)
20746f40a71SLang Hames return O->getBufferIdentifier();
20846f40a71SLang Hames return "<null object>";
20946f40a71SLang Hames }
21046f40a71SLang Hames
materialize(std::unique_ptr<MaterializationResponsibility> R)211c0514f00SLang Hames void BasicObjectLayerMaterializationUnit::materialize(
2127dcd0042SLang Hames std::unique_ptr<MaterializationResponsibility> R) {
2138b94274fSLang Hames L.emit(std::move(R), std::move(O));
214c0514f00SLang Hames }
215c0514f00SLang Hames
discard(const JITDylib & JD,const SymbolStringPtr & Name)216d5f56c59SLang Hames void BasicObjectLayerMaterializationUnit::discard(const JITDylib &JD,
217cb5702c3SLang Hames const SymbolStringPtr &Name) {
21822ed8c49SLang Hames // This is a no-op for object files: Having removed 'Name' from SymbolFlags
21922ed8c49SLang Hames // the symbol will be dead-stripped by the JIT linker.
220c0514f00SLang Hames }
221c0514f00SLang Hames
2221cf9987fSLang Hames } // End namespace orc.
2231cf9987fSLang Hames } // End namespace llvm.
224