[llvm] 11a02de - [JITLink][PowerPC] Change method to check if a symbol is external to current object
Kai Luo via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 25 20:21:03 PDT 2023
Author: Kai Luo
Date: 2023-07-26T03:20:56Z
New Revision: 11a02de7829aa252e84d96c7353ff39c34c3bd38
URL: https://github.com/llvm/llvm-project/commit/11a02de7829aa252e84d96c7353ff39c34c3bd38
DIFF: https://github.com/llvm/llvm-project/commit/11a02de7829aa252e84d96c7353ff39c34c3bd38.diff
LOG: [JITLink][PowerPC] Change method to check if a symbol is external to current object
After PrePrunePass `claimOrExternalizeWeakAndCommonSymbols`, a defined symbol might become external. So determine a function call is external or not when building the linkgraph is not accurate. This largely affects updating TOC pointer on PowerPC. TOC pointer is supposed to be the same in one object file(if no mulitple TOC appears) and is updated when control flow transferred to another object file.
This patch defers checking a function call is external or not, in `buildTables_ELF_ppc64` which is a PostPrunePass.
This patch fixes failures when `jitlink -orc-runtime=/path/to/libort_rt.a` is used.
Reviewed By: lhames
Differential Revision: https://reviews.llvm.org/D155925
Added:
Modified:
llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h
llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp
llvm/lib/ExecutionEngine/JITLink/ppc64.cpp
llvm/test/ExecutionEngine/JITLink/ppc64/external_weak.s
Removed:
################################################################################
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h b/llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h
index 0b2d562b71c487..a94acce5674b70 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/ppc64.h
@@ -36,17 +36,18 @@ enum EdgeKind_ppc64 : Edge::Kind {
CallBranchDelta,
// Need to restore r2 after the bl, suggesting the bl is followed by a nop.
CallBranchDeltaRestoreTOC,
- // Need PLT call stub using TOC, TOC pointer is not saved before branching.
- RequestPLTCallStub,
- // Need PLT call stub using TOC, TOC pointer is saved before branching.
- RequestPLTCallStubSaveTOC,
- // Need PLT call stub without using TOC.
- RequestPLTCallStubNoTOC,
+ // Request calling function with TOC.
+ RequestCall,
+ // Request calling function without TOC.
+ RequestCallNoTOC,
};
enum PLTCallStubKind {
+ // Setup function entry(r12) and long branch to target using TOC.
LongBranch,
+ // Save TOC pointer, setup function entry and long branch to target using TOC.
LongBranchSaveR2,
+ // Setup function entry(r12) and long branch to target without using TOC.
LongBranchNoTOC,
};
@@ -141,8 +142,7 @@ class TOCTableManager : public TableManager<TOCTableManager<Endianness>> {
case TOCDelta16DS:
case TOCDelta16LODS:
case CallBranchDeltaRestoreTOC:
- case RequestPLTCallStub:
- case RequestPLTCallStubSaveTOC:
+ case RequestCall:
// Create TOC section if TOC relocation, PLT or GOT is used.
getOrCreateTOCSection(G);
return false;
@@ -174,14 +174,25 @@ class PLTTableManager : public TableManager<PLTTableManager<Endianness>> {
static StringRef getSectionName() { return "$__STUBS"; }
bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
+ bool isExternal = E.getTarget().isExternal();
Edge::Kind K = E.getKind();
- if (K == ppc64::RequestPLTCallStubSaveTOC && E.getTarget().isExternal()) {
- E.setKind(ppc64::CallBranchDeltaRestoreTOC);
- this->StubKind = LongBranchSaveR2;
- E.setTarget(this->getEntryForTarget(G, E.getTarget()));
+ if (K == ppc64::RequestCall) {
+ if (isExternal) {
+ E.setKind(ppc64::CallBranchDeltaRestoreTOC);
+ this->StubKind = LongBranchSaveR2;
+ E.setTarget(this->getEntryForTarget(G, E.getTarget()));
+ // We previously set branching to local entry. Now reverse that
+ // operation.
+ E.setAddend(0);
+ } else
+ // TODO: There are cases a local function call need a call stub.
+ // 1. Caller uses TOC, the callee doesn't, need a r2 save stub.
+ // 2. Caller doesn't use TOC, the callee does, need a r12 setup stub.
+ // 3. Branching target is out of range.
+ E.setKind(ppc64::CallBranchDelta);
return true;
}
- if (K == ppc64::RequestPLTCallStubNoTOC && E.getTarget().isExternal()) {
+ if (K == ppc64::RequestCallNoTOC) {
E.setKind(ppc64::CallBranchDelta);
this->StubKind = LongBranchNoTOC;
E.setTarget(this->getEntryForTarget(G, E.getTarget()));
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp
index a30b9ce51c8482..a42d86ea609378 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_ppc64.cpp
@@ -217,23 +217,14 @@ class ELFLinkGraphBuilder_ppc64
Kind = ppc64::Delta32;
break;
case ELF::R_PPC64_REL24_NOTOC:
- case ELF::R_PPC64_REL24: {
- bool isLocal = !GraphSymbol->isExternal();
- if (isLocal) {
- // TODO: There are cases a local function call need a call stub.
- // 1. Caller uses TOC, the callee doesn't, need a r2 save stub.
- // 2. Caller doesn't use TOC, the callee does, need a r12 setup stub.
- // FIXME: For a local call, we might need a thunk if branch target is
- // out of range.
- Kind = ppc64::CallBranchDelta;
- // Branch to local entry.
- Addend += ELF::decodePPC64LocalEntryOffset((*ObjSymbol)->st_other);
- } else {
- Kind = ELFReloc == ELF::R_PPC64_REL24 ? ppc64::RequestPLTCallStubSaveTOC
- : ppc64::RequestPLTCallStubNoTOC;
- }
+ Kind = ppc64::RequestCallNoTOC;
+ break;
+ case ELF::R_PPC64_REL24:
+ Kind = ppc64::RequestCall;
+ assert(Addend == 0 && "Addend is expected to be 0 for a function call");
+ // We assume branching to local entry, will reverse the addend if not.
+ Addend = ELF::decodePPC64LocalEntryOffset((*ObjSymbol)->st_other);
break;
- }
case ELF::R_PPC64_REL64:
Kind = ppc64::Delta64;
break;
diff --git a/llvm/lib/ExecutionEngine/JITLink/ppc64.cpp b/llvm/lib/ExecutionEngine/JITLink/ppc64.cpp
index 4e21eace21d086..8ec460fa545688 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ppc64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ppc64.cpp
@@ -88,12 +88,10 @@ const char *getEdgeKindName(Edge::Kind K) {
return "CallBranchDelta";
case CallBranchDeltaRestoreTOC:
return "CallBranchDeltaRestoreTOC";
- case RequestPLTCallStub:
- return "RequestPLTCallStub";
- case RequestPLTCallStubSaveTOC:
- return "RequestPLTCallStubSaveTOC";
- case RequestPLTCallStubNoTOC:
- return "RequestPLTCallStubNoTOC";
+ case RequestCall:
+ return "RequestCall";
+ case RequestCallNoTOC:
+ return "RequestCallNoTOC";
default:
return getGenericEdgeKindName(static_cast<Edge::Kind>(K));
}
diff --git a/llvm/test/ExecutionEngine/JITLink/ppc64/external_weak.s b/llvm/test/ExecutionEngine/JITLink/ppc64/external_weak.s
index 3fda4cec4394c0..0bc90903caf974 100644
--- a/llvm/test/ExecutionEngine/JITLink/ppc64/external_weak.s
+++ b/llvm/test/ExecutionEngine/JITLink/ppc64/external_weak.s
@@ -11,7 +11,7 @@
# CHECK: External symbols:
# CHECK: {{.*}} linkage: weak, scope: default, dead - foo
# CHECK: section .text:
-# CHECK: {{.*}} kind = CallBranchDelta, target = foo
+# CHECK: {{.*}} kind = CallBranchDeltaRestoreTOC, target = addressable@{{.*}}
# `foo` is weak in both relocatable files. `foo` is resolved to the one
# defined in `%t/external_weak.o`. So calling `foo` in `%t/external_weak_main.o`
# is expected to be an external function call.
More information about the llvm-commits
mailing list