109467b48Spatrick //===-------------------- Layer.cpp - Layer interfaces --------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick
909467b48Spatrick #include "llvm/ExecutionEngine/Orc/Layer.h"
10097a140dSpatrick
11097a140dSpatrick #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
12097a140dSpatrick #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
13*d415bd75Srobert #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
1409467b48Spatrick #include "llvm/IR/Constants.h"
1509467b48Spatrick #include "llvm/Support/Debug.h"
1609467b48Spatrick
1709467b48Spatrick #define DEBUG_TYPE "orc"
1809467b48Spatrick
1909467b48Spatrick namespace llvm {
2009467b48Spatrick namespace orc {
2109467b48Spatrick
22*d415bd75Srobert IRLayer::~IRLayer() = default;
2309467b48Spatrick
add(ResourceTrackerSP RT,ThreadSafeModule TSM)2473471bf0Spatrick Error IRLayer::add(ResourceTrackerSP RT, ThreadSafeModule TSM) {
2573471bf0Spatrick assert(RT && "RT can not be null");
2673471bf0Spatrick auto &JD = RT->getJITDylib();
2709467b48Spatrick return JD.define(std::make_unique<BasicIRLayerMaterializationUnit>(
2873471bf0Spatrick *this, *getManglingOptions(), std::move(TSM)),
2973471bf0Spatrick std::move(RT));
3009467b48Spatrick }
3109467b48Spatrick
IRMaterializationUnit(ExecutionSession & ES,const IRSymbolMapper::ManglingOptions & MO,ThreadSafeModule TSM)32097a140dSpatrick IRMaterializationUnit::IRMaterializationUnit(
33097a140dSpatrick ExecutionSession &ES, const IRSymbolMapper::ManglingOptions &MO,
3473471bf0Spatrick ThreadSafeModule TSM)
35*d415bd75Srobert : MaterializationUnit(Interface()), TSM(std::move(TSM)) {
3609467b48Spatrick
3709467b48Spatrick assert(this->TSM && "Module must not be null");
3809467b48Spatrick
3909467b48Spatrick MangleAndInterner Mangle(ES, this->TSM.getModuleUnlocked()->getDataLayout());
4009467b48Spatrick this->TSM.withModuleDo([&](Module &M) {
4109467b48Spatrick for (auto &G : M.global_values()) {
4209467b48Spatrick // Skip globals that don't generate symbols.
43097a140dSpatrick
4409467b48Spatrick if (!G.hasName() || G.isDeclaration() || G.hasLocalLinkage() ||
4509467b48Spatrick G.hasAvailableExternallyLinkage() || G.hasAppendingLinkage())
4609467b48Spatrick continue;
4709467b48Spatrick
4809467b48Spatrick // thread locals generate different symbols depending on whether or not
4909467b48Spatrick // emulated TLS is enabled.
5009467b48Spatrick if (G.isThreadLocal() && MO.EmulatedTLS) {
5109467b48Spatrick auto &GV = cast<GlobalVariable>(G);
5209467b48Spatrick
5309467b48Spatrick auto Flags = JITSymbolFlags::fromGlobalValue(GV);
5409467b48Spatrick
5509467b48Spatrick auto EmuTLSV = Mangle(("__emutls_v." + GV.getName()).str());
5609467b48Spatrick SymbolFlags[EmuTLSV] = Flags;
5709467b48Spatrick SymbolToDefinition[EmuTLSV] = &GV;
5809467b48Spatrick
5909467b48Spatrick // If this GV has a non-zero initializer we'll need to emit an
6009467b48Spatrick // __emutls.t symbol too.
6109467b48Spatrick if (GV.hasInitializer()) {
6209467b48Spatrick const auto *InitVal = GV.getInitializer();
6309467b48Spatrick
6409467b48Spatrick // Skip zero-initializers.
6509467b48Spatrick if (isa<ConstantAggregateZero>(InitVal))
6609467b48Spatrick continue;
6709467b48Spatrick const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal);
6809467b48Spatrick if (InitIntValue && InitIntValue->isZero())
6909467b48Spatrick continue;
7009467b48Spatrick
7109467b48Spatrick auto EmuTLST = Mangle(("__emutls_t." + GV.getName()).str());
7209467b48Spatrick SymbolFlags[EmuTLST] = Flags;
7309467b48Spatrick }
7409467b48Spatrick continue;
7509467b48Spatrick }
7609467b48Spatrick
7709467b48Spatrick // Otherwise we just need a normal linker mangling.
7809467b48Spatrick auto MangledName = Mangle(G.getName());
7909467b48Spatrick SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G);
80*d415bd75Srobert if (G.getComdat() &&
81*d415bd75Srobert G.getComdat()->getSelectionKind() != Comdat::NoDeduplicate)
82*d415bd75Srobert SymbolFlags[MangledName] |= JITSymbolFlags::Weak;
8309467b48Spatrick SymbolToDefinition[MangledName] = &G;
8409467b48Spatrick }
85097a140dSpatrick
86097a140dSpatrick // If we need an init symbol for this module then create one.
87*d415bd75Srobert if (!getStaticInitGVs(M).empty()) {
88097a140dSpatrick size_t Counter = 0;
89097a140dSpatrick
9073471bf0Spatrick do {
91097a140dSpatrick std::string InitSymbolName;
92097a140dSpatrick raw_string_ostream(InitSymbolName)
93097a140dSpatrick << "$." << M.getModuleIdentifier() << ".__inits." << Counter++;
94097a140dSpatrick InitSymbol = ES.intern(InitSymbolName);
9573471bf0Spatrick } while (SymbolFlags.count(InitSymbol));
9673471bf0Spatrick
9773471bf0Spatrick SymbolFlags[InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
98097a140dSpatrick }
9909467b48Spatrick });
10009467b48Spatrick }
10109467b48Spatrick
IRMaterializationUnit(ThreadSafeModule TSM,Interface I,SymbolNameToDefinitionMap SymbolToDefinition)10209467b48Spatrick IRMaterializationUnit::IRMaterializationUnit(
103*d415bd75Srobert ThreadSafeModule TSM, Interface I,
104*d415bd75Srobert SymbolNameToDefinitionMap SymbolToDefinition)
105*d415bd75Srobert : MaterializationUnit(std::move(I)), TSM(std::move(TSM)),
106*d415bd75Srobert SymbolToDefinition(std::move(SymbolToDefinition)) {}
10709467b48Spatrick
getName() const10809467b48Spatrick StringRef IRMaterializationUnit::getName() const {
10909467b48Spatrick if (TSM)
11009467b48Spatrick return TSM.withModuleDo(
11109467b48Spatrick [](const Module &M) -> StringRef { return M.getModuleIdentifier(); });
11209467b48Spatrick return "<null module>";
11309467b48Spatrick }
11409467b48Spatrick
discard(const JITDylib & JD,const SymbolStringPtr & Name)11509467b48Spatrick void IRMaterializationUnit::discard(const JITDylib &JD,
11609467b48Spatrick const SymbolStringPtr &Name) {
11709467b48Spatrick LLVM_DEBUG(JD.getExecutionSession().runSessionLocked([&]() {
11809467b48Spatrick dbgs() << "In " << JD.getName() << " discarding " << *Name << " from MU@"
11909467b48Spatrick << this << " (" << getName() << ")\n";
12009467b48Spatrick }););
12109467b48Spatrick
12209467b48Spatrick auto I = SymbolToDefinition.find(Name);
12309467b48Spatrick assert(I != SymbolToDefinition.end() &&
12409467b48Spatrick "Symbol not provided by this MU, or previously discarded");
12509467b48Spatrick assert(!I->second->isDeclaration() &&
12609467b48Spatrick "Discard should only apply to definitions");
12709467b48Spatrick I->second->setLinkage(GlobalValue::AvailableExternallyLinkage);
128*d415bd75Srobert // According to the IR verifier, "Declaration[s] may not be in a Comdat!"
129*d415bd75Srobert // Remove it, if this is a GlobalObject.
130*d415bd75Srobert if (auto *GO = dyn_cast<GlobalObject>(I->second))
131*d415bd75Srobert GO->setComdat(nullptr);
13209467b48Spatrick SymbolToDefinition.erase(I);
13309467b48Spatrick }
13409467b48Spatrick
BasicIRLayerMaterializationUnit(IRLayer & L,const IRSymbolMapper::ManglingOptions & MO,ThreadSafeModule TSM)13509467b48Spatrick BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit(
13673471bf0Spatrick IRLayer &L, const IRSymbolMapper::ManglingOptions &MO, ThreadSafeModule TSM)
13773471bf0Spatrick : IRMaterializationUnit(L.getExecutionSession(), MO, std::move(TSM)), L(L) {
13873471bf0Spatrick }
13909467b48Spatrick
materialize(std::unique_ptr<MaterializationResponsibility> R)14009467b48Spatrick void BasicIRLayerMaterializationUnit::materialize(
14173471bf0Spatrick std::unique_ptr<MaterializationResponsibility> R) {
14209467b48Spatrick
14309467b48Spatrick // Throw away the SymbolToDefinition map: it's not usable after we hand
14409467b48Spatrick // off the module.
14509467b48Spatrick SymbolToDefinition.clear();
14609467b48Spatrick
14709467b48Spatrick // If cloneToNewContextOnEmit is set, clone the module now.
14809467b48Spatrick if (L.getCloneToNewContextOnEmit())
14909467b48Spatrick TSM = cloneToNewContext(TSM);
15009467b48Spatrick
15109467b48Spatrick #ifndef NDEBUG
15273471bf0Spatrick auto &ES = R->getTargetJITDylib().getExecutionSession();
15373471bf0Spatrick auto &N = R->getTargetJITDylib().getName();
15409467b48Spatrick #endif // NDEBUG
15509467b48Spatrick
15609467b48Spatrick LLVM_DEBUG(ES.runSessionLocked(
15709467b48Spatrick [&]() { dbgs() << "Emitting, for " << N << ", " << *this << "\n"; }););
15809467b48Spatrick L.emit(std::move(R), std::move(TSM));
15909467b48Spatrick LLVM_DEBUG(ES.runSessionLocked([&]() {
16009467b48Spatrick dbgs() << "Finished emitting, for " << N << ", " << *this << "\n";
16109467b48Spatrick }););
16209467b48Spatrick }
16309467b48Spatrick
16473471bf0Spatrick char ObjectLayer::ID;
16573471bf0Spatrick
ObjectLayer(ExecutionSession & ES)16609467b48Spatrick ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {}
16709467b48Spatrick
168*d415bd75Srobert ObjectLayer::~ObjectLayer() = default;
169*d415bd75Srobert
add(ResourceTrackerSP RT,std::unique_ptr<MemoryBuffer> O,MaterializationUnit::Interface I)170*d415bd75Srobert Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O,
171*d415bd75Srobert MaterializationUnit::Interface I) {
172*d415bd75Srobert assert(RT && "RT can not be null");
173*d415bd75Srobert auto &JD = RT->getJITDylib();
174*d415bd75Srobert return JD.define(std::make_unique<BasicObjectLayerMaterializationUnit>(
175*d415bd75Srobert *this, std::move(O), std::move(I)),
176*d415bd75Srobert std::move(RT));
177*d415bd75Srobert }
17809467b48Spatrick
add(ResourceTrackerSP RT,std::unique_ptr<MemoryBuffer> O)17973471bf0Spatrick Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O) {
180*d415bd75Srobert auto I = getObjectFileInterface(getExecutionSession(), O->getMemBufferRef());
181*d415bd75Srobert if (!I)
182*d415bd75Srobert return I.takeError();
183*d415bd75Srobert return add(std::move(RT), std::move(O), std::move(*I));
184*d415bd75Srobert }
185*d415bd75Srobert
add(JITDylib & JD,std::unique_ptr<MemoryBuffer> O)186*d415bd75Srobert Error ObjectLayer::add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O) {
187*d415bd75Srobert auto I = getObjectFileInterface(getExecutionSession(), O->getMemBufferRef());
188*d415bd75Srobert if (!I)
189*d415bd75Srobert return I.takeError();
190*d415bd75Srobert return add(JD, std::move(O), std::move(*I));
19109467b48Spatrick }
19209467b48Spatrick
19309467b48Spatrick Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
Create(ObjectLayer & L,std::unique_ptr<MemoryBuffer> O)19473471bf0Spatrick BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L,
19509467b48Spatrick std::unique_ptr<MemoryBuffer> O) {
19609467b48Spatrick
197*d415bd75Srobert auto ObjInterface =
198*d415bd75Srobert getObjectFileInterface(L.getExecutionSession(), O->getMemBufferRef());
199097a140dSpatrick
200*d415bd75Srobert if (!ObjInterface)
201*d415bd75Srobert return ObjInterface.takeError();
20209467b48Spatrick
20309467b48Spatrick return std::unique_ptr<BasicObjectLayerMaterializationUnit>(
204*d415bd75Srobert new BasicObjectLayerMaterializationUnit(L, std::move(O),
205*d415bd75Srobert std::move(*ObjInterface)));
20609467b48Spatrick }
20709467b48Spatrick
BasicObjectLayerMaterializationUnit(ObjectLayer & L,std::unique_ptr<MemoryBuffer> O,Interface I)20809467b48Spatrick BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit(
209*d415bd75Srobert ObjectLayer &L, std::unique_ptr<MemoryBuffer> O, Interface I)
210*d415bd75Srobert : MaterializationUnit(std::move(I)), L(L), O(std::move(O)) {}
21109467b48Spatrick
getName() const21209467b48Spatrick StringRef BasicObjectLayerMaterializationUnit::getName() const {
21309467b48Spatrick if (O)
21409467b48Spatrick return O->getBufferIdentifier();
21509467b48Spatrick return "<null object>";
21609467b48Spatrick }
21709467b48Spatrick
materialize(std::unique_ptr<MaterializationResponsibility> R)21809467b48Spatrick void BasicObjectLayerMaterializationUnit::materialize(
21973471bf0Spatrick std::unique_ptr<MaterializationResponsibility> R) {
22009467b48Spatrick L.emit(std::move(R), std::move(O));
22109467b48Spatrick }
22209467b48Spatrick
discard(const JITDylib & JD,const SymbolStringPtr & Name)22309467b48Spatrick void BasicObjectLayerMaterializationUnit::discard(const JITDylib &JD,
22409467b48Spatrick const SymbolStringPtr &Name) {
225097a140dSpatrick // This is a no-op for object files: Having removed 'Name' from SymbolFlags
226097a140dSpatrick // the symbol will be dead-stripped by the JIT linker.
22709467b48Spatrick }
22809467b48Spatrick
22909467b48Spatrick } // End namespace orc.
23009467b48Spatrick } // End namespace llvm.
231