diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index b815904f9672b..f48cf21852dcb 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -170,6 +170,7 @@ class MCPlusBuilder { /// MCPlusBuilder classes must use convert/lower/create* interfaces instead. void setTailCall(MCInst &Inst); +public: /// Transfer annotations from \p SrcInst to \p DstInst. void moveAnnotations(MCInst &&SrcInst, MCInst &DstInst) const { assert(!getAnnotationInst(DstInst) && @@ -182,7 +183,6 @@ class MCPlusBuilder { removeAnnotationInst(SrcInst); } -public: /// Return iterator range covering def operands. iterator_range defOperands(MCInst &Inst) const { return make_range(Inst.begin(), diff --git a/bolt/lib/Passes/FixRISCVCallsPass.cpp b/bolt/lib/Passes/FixRISCVCallsPass.cpp index 34821ec80c1b4..963a8b04cf9db 100644 --- a/bolt/lib/Passes/FixRISCVCallsPass.cpp +++ b/bolt/lib/Passes/FixRISCVCallsPass.cpp @@ -19,6 +19,7 @@ void FixRISCVCallsPass::runOnFunction(BinaryFunction &BF) { auto *Target = MIB->getTargetSymbol(*II); assert(Target && "Cannot find call target"); + MCInst OldCall = *II; auto L = BC.scopeLock(); if (MIB->isTailCall(*II)) @@ -26,6 +27,7 @@ void FixRISCVCallsPass::runOnFunction(BinaryFunction &BF) { else MIB->createCall(*II, Target, Ctx); + MIB->moveAnnotations(std::move(OldCall), *II); ++II; continue; } @@ -39,8 +41,19 @@ void FixRISCVCallsPass::runOnFunction(BinaryFunction &BF) { auto *Target = MIB->getTargetSymbol(*II); assert(Target && "Cannot find call target"); + MCInst OldCall = *NextII; auto L = BC.scopeLock(); MIB->createCall(*II, Target, Ctx); + MIB->moveAnnotations(std::move(OldCall), *II); + + // The original offset was set on the jalr of the auipc+jalr pair. Since + // the whole pair is replaced by a call, adjust the offset by -4 (the + // size of a auipc). + if (std::optional Offset = MIB->getOffset(*II)) { + assert(*Offset >= 4 && "Illegal jalr offset"); + MIB->setOffset(*II, *Offset - 4); + } + II = BB.eraseInstruction(NextII); continue; } diff --git a/bolt/test/RISCV/call-annotations.s b/bolt/test/RISCV/call-annotations.s new file mode 100644 index 0000000000000..e2c5a1040faee --- /dev/null +++ b/bolt/test/RISCV/call-annotations.s @@ -0,0 +1,33 @@ +/// Test that annotations are properly carried over to fixed calls. +/// Note that --enable-bat is used to force offsets to be kept. + +// RUN: llvm-mc -triple riscv64 -filetype obj -o %t.o %s +// RUN: ld.lld --emit-relocs -o %t %t.o +// RUN: llvm-bolt --enable-bat --print-cfg --print-fix-riscv-calls \ +// RUN: --print-only=_start -o /dev/null %t | FileCheck %s + + .text + .global f + .p2align 1 +f: + ret + .size f, .-f + +// CHECK-LABEL: Binary Function "_start" after building cfg { +// CHECK: auipc ra, f +// CHECK-NEXT: jalr ra, -4(ra) # Offset: 4 +// CHECK-NEXT: jal ra, f # Offset: 8 +// CHECK-NEXT: jal zero, f # TAILCALL # Offset: 12 + +// CHECK-LABEL: Binary Function "_start" after fix-riscv-calls { +// CHECK: call f # Offset: 0 +// CHECK-NEXT: call f # Offset: 8 +// CHECK-NEXT: tail f # TAILCALL # Offset: 12 + + .globl _start + .p2align 1 +_start: + call f + jal f + jal zero, f + .size _start, .-_start