Skip to content

Commit dc925be

Browse files
authored
[BOLT][RISCV] Carry-over annotations when fixing calls (#66763)
`FixRISCVCallsPass` changes all different forms of calls to `PseudoCALL` instructions. However, the original call's annotations were lost in the process. This patch fixes this by moving all annotations from the old to the new call. `MCPlusBuilder::moveAnnotations` had to be made public for this.
1 parent 265d48a commit dc925be

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

bolt/include/bolt/Core/MCPlusBuilder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ class MCPlusBuilder {
170170
/// MCPlusBuilder classes must use convert/lower/create* interfaces instead.
171171
void setTailCall(MCInst &Inst);
172172

173+
public:
173174
/// Transfer annotations from \p SrcInst to \p DstInst.
174175
void moveAnnotations(MCInst &&SrcInst, MCInst &DstInst) const {
175176
assert(!getAnnotationInst(DstInst) &&
@@ -182,7 +183,6 @@ class MCPlusBuilder {
182183
removeAnnotationInst(SrcInst);
183184
}
184185

185-
public:
186186
/// Return iterator range covering def operands.
187187
iterator_range<MCInst::iterator> defOperands(MCInst &Inst) const {
188188
return make_range(Inst.begin(),

bolt/lib/Passes/FixRISCVCallsPass.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ void FixRISCVCallsPass::runOnFunction(BinaryFunction &BF) {
1919
auto *Target = MIB->getTargetSymbol(*II);
2020
assert(Target && "Cannot find call target");
2121

22+
MCInst OldCall = *II;
2223
auto L = BC.scopeLock();
2324

2425
if (MIB->isTailCall(*II))
2526
MIB->createTailCall(*II, Target, Ctx);
2627
else
2728
MIB->createCall(*II, Target, Ctx);
2829

30+
MIB->moveAnnotations(std::move(OldCall), *II);
2931
++II;
3032
continue;
3133
}
@@ -39,8 +41,19 @@ void FixRISCVCallsPass::runOnFunction(BinaryFunction &BF) {
3941
auto *Target = MIB->getTargetSymbol(*II);
4042
assert(Target && "Cannot find call target");
4143

44+
MCInst OldCall = *NextII;
4245
auto L = BC.scopeLock();
4346
MIB->createCall(*II, Target, Ctx);
47+
MIB->moveAnnotations(std::move(OldCall), *II);
48+
49+
// The original offset was set on the jalr of the auipc+jalr pair. Since
50+
// the whole pair is replaced by a call, adjust the offset by -4 (the
51+
// size of a auipc).
52+
if (std::optional<uint32_t> Offset = MIB->getOffset(*II)) {
53+
assert(*Offset >= 4 && "Illegal jalr offset");
54+
MIB->setOffset(*II, *Offset - 4);
55+
}
56+
4457
II = BB.eraseInstruction(NextII);
4558
continue;
4659
}

bolt/test/RISCV/call-annotations.s

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/// Test that annotations are properly carried over to fixed calls.
2+
/// Note that --enable-bat is used to force offsets to be kept.
3+
4+
// RUN: llvm-mc -triple riscv64 -filetype obj -o %t.o %s
5+
// RUN: ld.lld --emit-relocs -o %t %t.o
6+
// RUN: llvm-bolt --enable-bat --print-cfg --print-fix-riscv-calls \
7+
// RUN: --print-only=_start -o /dev/null %t | FileCheck %s
8+
9+
.text
10+
.global f
11+
.p2align 1
12+
f:
13+
ret
14+
.size f, .-f
15+
16+
// CHECK-LABEL: Binary Function "_start" after building cfg {
17+
// CHECK: auipc ra, f
18+
// CHECK-NEXT: jalr ra, -4(ra) # Offset: 4
19+
// CHECK-NEXT: jal ra, f # Offset: 8
20+
// CHECK-NEXT: jal zero, f # TAILCALL # Offset: 12
21+
22+
// CHECK-LABEL: Binary Function "_start" after fix-riscv-calls {
23+
// CHECK: call f # Offset: 0
24+
// CHECK-NEXT: call f # Offset: 8
25+
// CHECK-NEXT: tail f # TAILCALL # Offset: 12
26+
27+
.globl _start
28+
.p2align 1
29+
_start:
30+
call f
31+
jal f
32+
jal zero, f
33+
.size _start, .-_start

0 commit comments

Comments
 (0)