Skip to content

Commit 9c38a17

Browse files
author
Kai Luo
committed
[JITLink][PowerPC] Add basic TLS support for ppc64
Add basic TLS support for ppc64. Only global-dynamic model is supported. Reviewed By: lhames Differential Revision: https://reviews.llvm.org/D155926
1 parent a011943 commit 9c38a17

File tree

6 files changed

+120
-3
lines changed

6 files changed

+120
-3
lines changed

compiler-rt/lib/orc/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ set(ALL_ORC_ASM_SOURCES
2424
macho_tlv.arm64.S
2525
elfnix_tls.x86-64.S
2626
elfnix_tls.aarch64.S
27+
elfnix_tls.ppc64.S
2728
)
2829

2930
# Common implementation headers will go here.
@@ -149,6 +150,7 @@ else() # not Apple
149150
set(ORC_ASM_SOURCES
150151
elfnix_tls.x86-64.S
151152
elfnix_tls.aarch64.S
153+
elfnix_tls.ppc64.S
152154
)
153155
endif()
154156

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===-- orc_rt_elfnix_tls.ppc64.s -------------------------------*- ASM -*-===//
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+
// This file is a part of the ORC runtime support library.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
// The content of this file is PowerPC64 only.
14+
#if defined(__powerpc64__)
15+
16+
.text
17+
// TODO: add fast-path for repeat access.
18+
// See https://github.com/llvm/llvm-project/issues/51162.
19+
.global ___orc_rt_elfnix_tls_get_addr
20+
___orc_rt_elfnix_tls_get_addr:
21+
addis 2, 12, .TOC.-___orc_rt_elfnix_tls_get_addr@ha
22+
addi 2, 2, .TOC.-___orc_rt_elfnix_tls_get_addr@l
23+
mflr 0
24+
std 0, 16(1)
25+
stdu 1, -32(1)
26+
bl __orc_rt_elfnix_tls_get_addr_impl
27+
nop
28+
addi 1, 1, 32
29+
ld 0, 16(1)
30+
mtlr 0
31+
blr
32+
33+
#endif

compiler-rt/test/orc/TestCases/Linux/ppc64/trivial-tls.S

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// XFAIL: target={{powerpc64.*}}
21
// RUN: %clang -c -o %t %s
32
// RUN: %llvm_jitlink %t
43
//

llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ enum EdgeKind_ppc64 : Edge::Kind {
4141
RequestCall,
4242
// Request calling function without TOC.
4343
RequestCallNoTOC,
44+
RequestTLSDescInGOTAndTransformToTOCDelta16HA,
45+
RequestTLSDescInGOTAndTransformToTOCDelta16LO,
4446
};
4547

4648
enum PLTCallStubKind {

llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,70 @@ using namespace llvm::jitlink;
3131
constexpr StringRef ELFTOCSymbolName = ".TOC.";
3232
constexpr StringRef TOCSymbolAliasIdent = "__TOC__";
3333
constexpr uint64_t ELFTOCBaseOffset = 0x8000;
34+
constexpr StringRef ELFTLSInfoSectionName = "$__TLSINFO";
35+
36+
template <support::endianness Endianness>
37+
class TLSInfoTableManager_ELF_ppc64
38+
: public TableManager<TLSInfoTableManager_ELF_ppc64<Endianness>> {
39+
public:
40+
static const uint8_t TLSInfoEntryContent[16];
41+
42+
static StringRef getSectionName() { return ELFTLSInfoSectionName; }
43+
44+
bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
45+
Edge::Kind K = E.getKind();
46+
if (K == ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16HA) {
47+
E.setKind(ppc64::TOCDelta16HA);
48+
E.setTarget(this->getEntryForTarget(G, E.getTarget()));
49+
return true;
50+
}
51+
if (K == ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16LO) {
52+
E.setKind(ppc64::TOCDelta16LO);
53+
E.setTarget(this->getEntryForTarget(G, E.getTarget()));
54+
return true;
55+
}
56+
return false;
57+
}
58+
59+
Symbol &createEntry(LinkGraph &G, Symbol &Target) {
60+
// The TLS Info entry's key value will be written by
61+
// `fixTLVSectionsAndEdges`, so create mutable content.
62+
auto &TLSInfoEntry = G.createMutableContentBlock(
63+
getTLSInfoSection(G), G.allocateContent(getTLSInfoEntryContent()),
64+
orc::ExecutorAddr(), 8, 0);
65+
TLSInfoEntry.addEdge(ppc64::Pointer64, 8, Target, 0);
66+
return G.addAnonymousSymbol(TLSInfoEntry, 0, 16, false, false);
67+
}
68+
69+
private:
70+
Section &getTLSInfoSection(LinkGraph &G) {
71+
if (!TLSInfoTable)
72+
TLSInfoTable =
73+
&G.createSection(ELFTLSInfoSectionName, orc::MemProt::Read);
74+
return *TLSInfoTable;
75+
}
76+
77+
ArrayRef<char> getTLSInfoEntryContent() const {
78+
return {reinterpret_cast<const char *>(TLSInfoEntryContent),
79+
sizeof(TLSInfoEntryContent)};
80+
}
81+
82+
Section *TLSInfoTable = nullptr;
83+
};
84+
85+
template <>
86+
const uint8_t TLSInfoTableManager_ELF_ppc64<
87+
support::endianness::little>::TLSInfoEntryContent[16] = {
88+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */
89+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/
90+
};
91+
92+
template <>
93+
const uint8_t TLSInfoTableManager_ELF_ppc64<
94+
support::endianness::big>::TLSInfoEntryContent[16] = {
95+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */
96+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/
97+
};
3498

3599
template <support::endianness Endianness>
36100
Symbol &createELFGOTHeader(LinkGraph &G,
@@ -91,8 +155,8 @@ Error buildTables_ELF_ppc64(LinkGraph &G) {
91155
registerExistingGOTEntries(G, TOC);
92156

93157
ppc64::PLTTableManager<Endianness> PLT(TOC);
94-
visitExistingEdges(G, TOC, PLT);
95-
// TODO: Add TLS support.
158+
TLSInfoTableManager_ELF_ppc64<Endianness> TLSInfo;
159+
visitExistingEdges(G, TOC, PLT, TLSInfo);
96160

97161
// After visiting edges in LinkGraph, we have GOT entries built in the
98162
// synthesized section.
@@ -164,6 +228,13 @@ class ELFLinkGraphBuilder_ppc64
164228
if (LLVM_UNLIKELY(ELFReloc == ELF::R_PPC64_NONE))
165229
return Error::success();
166230

231+
// TLS model markers. We only support global-dynamic model now.
232+
if (ELFReloc == ELF::R_PPC64_TLSGD)
233+
return Error::success();
234+
if (ELFReloc == ELF::R_PPC64_TLSLD)
235+
return make_error<StringError>("Local-dynamic TLS model is not supported",
236+
inconvertibleErrorCode());
237+
167238
auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
168239
if (!ObjSymbol)
169240
return ObjSymbol.takeError();
@@ -234,6 +305,12 @@ class ELFLinkGraphBuilder_ppc64
234305
case ELF::R_PPC64_PCREL34:
235306
Kind = ppc64::Delta34;
236307
break;
308+
case ELF::R_PPC64_GOT_TLSGD16_HA:
309+
Kind = ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16HA;
310+
break;
311+
case ELF::R_PPC64_GOT_TLSGD16_LO:
312+
Kind = ppc64::RequestTLSDescInGOTAndTransformToTOCDelta16LO;
313+
break;
237314
}
238315

239316
Edge GE(Kind, Offset, *GraphSymbol, Addend);

llvm/lib/ExecutionEngine/JITLink/ppc64.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ const char *getEdgeKindName(Edge::Kind K) {
9494
return "RequestCall";
9595
case RequestCallNoTOC:
9696
return "RequestCallNoTOC";
97+
case RequestTLSDescInGOTAndTransformToTOCDelta16HA:
98+
return "RequestTLSDescInGOTAndTransformToTOCDelta16HA";
99+
case RequestTLSDescInGOTAndTransformToTOCDelta16LO:
100+
return "RequestTLSDescInGOTAndTransformToTOCDelta16LO";
97101
default:
98102
return getGenericEdgeKindName(static_cast<Edge::Kind>(K));
99103
}

0 commit comments

Comments
 (0)