1//===- bolt/Passes/VeneerElimination.cpp ----------------------------------===//
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 class implements a pass that removes linker-inserted veneers from the
10// code and redirects veneer callers to call to veneers destinations
11//
12//===----------------------------------------------------------------------===//
13
14#include "bolt/Passes/VeneerElimination.h"
15#define DEBUG_TYPE "veneer-elim"
16
17using namespace llvm;
18
19namespace opts {
20
21extern cl::OptionCategory BoltOptCategory;
22
23static llvm::cl::opt<bool>
24 EliminateVeneers("elim-link-veneers",
25 cl::desc("run veneer elimination pass"), cl::init(Val: true),
26 cl::Hidden, cl::cat(BoltOptCategory));
27} // namespace opts
28
29namespace llvm {
30namespace bolt {
31
32static bool isPossibleVeneer(const BinaryFunction &BF) {
33 return BF.isAArch64Veneer() || BF.getOneName().starts_with(Prefix: "__AArch64");
34}
35
36Error VeneerElimination::runOnFunctions(BinaryContext &BC) {
37 if (!opts::EliminateVeneers || !BC.isAArch64())
38 return Error::success();
39
40 std::unordered_map<const MCSymbol *, const MCSymbol *> VeneerDestinations;
41 uint64_t NumEliminatedVeneers = 0;
42 for (BinaryFunction &BF : llvm::make_second_range(c&: BC.getBinaryFunctions())) {
43 if (!isPossibleVeneer(BF))
44 continue;
45
46 if (BF.isIgnored())
47 continue;
48
49 MCInst &FirstInstruction = *(BF.begin()->begin());
50 const MCSymbol *VeneerTargetSymbol = 0;
51 uint64_t TargetAddress;
52 if (BC.MIB->isTailCall(Inst: FirstInstruction)) {
53 VeneerTargetSymbol = BC.MIB->getTargetSymbol(Inst: FirstInstruction);
54 } else if (BC.MIB->matchAbsLongVeneer(BF, TargetAddress)) {
55 if (BinaryFunction *TargetBF =
56 BC.getBinaryFunctionAtAddress(Address: TargetAddress))
57 VeneerTargetSymbol = TargetBF->getSymbol();
58 } else if (BC.MIB->hasAnnotation(Inst: FirstInstruction, Name: "AArch64Veneer")) {
59 VeneerTargetSymbol = BC.MIB->getTargetSymbol(Inst: FirstInstruction, OpNum: 1);
60 }
61
62 if (!VeneerTargetSymbol)
63 continue;
64
65 for (const MCSymbol *Symbol : BF.getSymbols())
66 VeneerDestinations[Symbol] = VeneerTargetSymbol;
67
68 NumEliminatedVeneers++;
69 BF.setPseudo(true);
70 }
71
72 BC.outs() << "BOLT-INFO: number of removed linker-inserted veneers: "
73 << NumEliminatedVeneers << '\n';
74
75 // Handle veneers to veneers in case they occur
76 for (auto &Entry : VeneerDestinations) {
77 const MCSymbol *Src = Entry.first;
78 const MCSymbol *Dest = Entry.second;
79 while (VeneerDestinations.find(x: Dest) != VeneerDestinations.end())
80 Dest = VeneerDestinations[Dest];
81
82 VeneerDestinations[Src] = Dest;
83 }
84
85 uint64_t VeneerCallers = 0;
86 for (BinaryFunction &BF : llvm::make_second_range(c&: BC.getBinaryFunctions())) {
87 for (BinaryBasicBlock &BB : BF) {
88 for (MCInst &Instr : BB) {
89 if (!BC.MIB->isCall(Inst: Instr) || BC.MIB->isIndirectCall(Inst: Instr))
90 continue;
91
92 const MCSymbol *TargetSymbol = BC.MIB->getTargetSymbol(Inst: Instr, OpNum: 0);
93 auto It = VeneerDestinations.find(x: TargetSymbol);
94 if (It == VeneerDestinations.end())
95 continue;
96
97 VeneerCallers++;
98 BC.MIB->replaceBranchTarget(Inst&: Instr, TBB: It->second, Ctx: BC.Ctx.get());
99 }
100 }
101 }
102
103 LLVM_DEBUG(
104 dbgs() << "BOLT-INFO: number of linker-inserted veneers call sites: "
105 << VeneerCallers << "\n");
106 (void)VeneerCallers;
107 return Error::success();
108}
109
110} // namespace bolt
111} // namespace llvm
112

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of bolt/lib/Passes/VeneerElimination.cpp