llvm-project/llvm/lib/ExecutionEngine/Orc/LinkGraphLayer.cpp
Lang Hames b3d2548d5b
[ORC] Introduce LinkGraphLayer interface and LinkGraphLinkingLayer. (#120182)
Introduces a new layer interface, LinkGraphLayer, that can be used to
add LinkGraphs to an ExecutionSession.

This patch moves most of ObjectLinkingLayer's functionality into a new
LinkGraphLinkingLayer which should (in the future) be able to be used
without linking libObject. ObjectLinkingLayer now inherits from
LinkGraphLinkingLayer and just handles conversion of object files to
LinkGraphs, which are then handed down to LinkGraphLinkingLayer to be
linked.
2024-12-17 17:18:58 +11:00

106 lines
2.8 KiB
C++

//===----- LinkGraphLayer.cpp - Add LinkGraphs to an ExecutionSession -----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/LinkGraphLayer.h"
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h"
#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
#define DEBUG_TYPE "orc"
using namespace llvm;
using namespace llvm::jitlink;
using namespace llvm::orc;
namespace {
bool hasInitializerSection(LinkGraph &G) {
bool IsMachO = G.getTargetTriple().isOSBinFormatMachO();
bool IsElf = G.getTargetTriple().isOSBinFormatELF();
if (!IsMachO && !IsElf)
return false;
for (auto &Sec : G.sections()) {
if (IsMachO && isMachOInitializerSection(Sec.getName()))
return true;
if (IsElf && isELFInitializerSection(Sec.getName()))
return true;
}
return false;
}
} // end anonymous namespace
namespace llvm::orc {
LinkGraphLayer::~LinkGraphLayer() = default;
MaterializationUnit::Interface LinkGraphLayer::getInterface(LinkGraph &G) {
MaterializationUnit::Interface LGI;
auto AddSymbol = [&](Symbol *Sym) {
// Skip local symbols.
if (Sym->getScope() == Scope::Local)
return;
assert(Sym->hasName() && "Anonymous non-local symbol?");
LGI.SymbolFlags[Sym->getName()] = getJITSymbolFlagsForSymbol(*Sym);
};
for (auto *Sym : G.defined_symbols())
AddSymbol(Sym);
for (auto *Sym : G.absolute_symbols())
AddSymbol(Sym);
if (hasInitializerSection(G)) {
std::string InitSymString;
{
raw_string_ostream(InitSymString)
<< "$." << G.getName() << ".__inits" << Counter++;
}
LGI.InitSymbol = ES.intern(InitSymString);
}
return LGI;
}
JITSymbolFlags LinkGraphLayer::getJITSymbolFlagsForSymbol(Symbol &Sym) {
JITSymbolFlags Flags;
if (Sym.getLinkage() == Linkage::Weak)
Flags |= JITSymbolFlags::Weak;
if (Sym.getScope() == Scope::Default)
Flags |= JITSymbolFlags::Exported;
else if (Sym.getScope() == Scope::SideEffectsOnly)
Flags |= JITSymbolFlags::MaterializationSideEffectsOnly;
if (Sym.isCallable())
Flags |= JITSymbolFlags::Callable;
return Flags;
}
StringRef LinkGraphMaterializationUnit::getName() const { return G->getName(); }
void LinkGraphMaterializationUnit::discard(const JITDylib &JD,
const SymbolStringPtr &Name) {
for (auto *Sym : G->defined_symbols())
if (Sym->getName() == Name) {
assert(Sym->getLinkage() == Linkage::Weak &&
"Discarding non-weak definition");
G->makeExternal(*Sym);
break;
}
}
} // namespace llvm::orc