llvm-project/llvm/lib/ExecutionEngine/JITLink/PerGraphTLSInfoEntryBuilder.h
luxufan ff6069b891 [JITLink] Add initial native TLS support to ELFNix platform
This patch use the same way as the https://reviews.llvm.org/rGfe1fa43f16beac1506a2e73a9f7b3c81179744eb to handle the thread local variable.

It allocates 2 * pointerSize space in GOT to represent the thread key and data address. Instead of using the _tls_get_addr function, I customed a function __orc_rt_elfnix_tls_get_addr to get the address of thread local varible. Currently, this is a wip patch, only one TLS relocation R_X86_64_TLSGD is supported and I need to add the corresponding test cases.

To allocate the TLS  descriptor in GOT, I need to get the edge kind information in PerGraphGOTAndPLTStubBuilder, So I add a `Edge::Kind K` argument in some functions in PerGraphGOTAndPLTStubBuilder.h. If it is not suitable, I can think further to solve this problem.

Differential Revision: https://reviews.llvm.org/D109293
2021-09-13 14:35:49 +08:00

79 lines
2.7 KiB
C++

//===---------------- PerGraphTLSInfoEntryBuilder.h -------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Construct Thread local storage info entry for each graph.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_JITLINK_PERGRAPHTLSINFOENTRYBUILDER_H
#define LLVM_EXECUTIONENGINE_JITLINK_PERGRAPHTLSINFOENTRYBUILDER_H
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/Support/Debug.h"
#define DEBUG_TYPE "jitlink"
namespace llvm {
namespace jitlink {
template <typename BuilderImplT> class PerGraphTLSInfoEntryBuilder {
public:
PerGraphTLSInfoEntryBuilder(LinkGraph &G) : G(G) {}
static Error asPass(LinkGraph &G) { return BuilderImplT(G).run(); }
Error run() {
LLVM_DEBUG(dbgs() << "Running Per-Graph TLS Info entry builder:\n ");
std::vector<Block *> Worklist(G.blocks().begin(), G.blocks().end());
for (auto *B : Worklist)
for (auto &E : B->edges()) {
if (impl().isTLSEdgeToFix(E)) {
LLVM_DEBUG({
dbgs() << " Fixing " << G.getEdgeKindName(E.getKind())
<< " edge at " << formatv("{0:x}", B->getFixupAddress(E))
<< " (" << formatv("{0:x}", B->getAddress()) << " + "
<< formatv("{0:x}", E.getOffset()) << ")\n";
});
impl().fixTLSEdge(E, getTLSInfoEntry(E.getTarget()));
}
}
return Error::success();
}
protected:
LinkGraph &G;
Symbol &getTLSInfoEntry(Symbol &Target) {
assert(Target.hasName() && "TLS edge cannot point to anonymous target");
auto TLSInfoEntryI = TLSInfoEntries.find(Target.getName());
if (TLSInfoEntryI == TLSInfoEntries.end()) {
auto &TLSInfoEntry = impl().createTLSInfoEntry(Target);
LLVM_DEBUG({
dbgs() << " Created TLS Info entry for " << Target.getName() << ": "
<< TLSInfoEntry << "\n";
});
TLSInfoEntryI =
TLSInfoEntries.insert(std::make_pair(Target.getName(), &TLSInfoEntry))
.first;
}
assert(TLSInfoEntryI != TLSInfoEntries.end() &&
"Could not get TLSInfo symbol");
LLVM_DEBUG({
dbgs() << " Using TLS Info entry" << *TLSInfoEntryI->second << "\n";
});
return *TLSInfoEntryI->second;
}
private:
DenseMap<StringRef, Symbol *> TLSInfoEntries;
BuilderImplT &impl() { return static_cast<BuilderImplT &>(*this); }
};
} // namespace jitlink
} // namespace llvm
#endif