1 //===- bolt/Passes/VeneerElimination.cpp ----------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This class implements a pass that removes linker-inserted veneers from the
10 // code and redirects veneer callers to call to veneers destinations
12 //===----------------------------------------------------------------------===//
14 #include "bolt/Passes/VeneerElimination.h"
15 #define DEBUG_TYPE "veneer-elim"
21 extern cl::OptionCategory BoltOptCategory
;
23 static llvm::cl::opt
<bool>
24 EliminateVeneers("elim-link-veneers",
25 cl::desc("run veneer elimination pass"), cl::init(true),
26 cl::Hidden
, cl::cat(BoltOptCategory
));
32 void VeneerElimination::runOnFunctions(BinaryContext
&BC
) {
33 if (!opts::EliminateVeneers
|| !BC
.isAArch64())
36 std::map
<uint64_t, BinaryFunction
> &BFs
= BC
.getBinaryFunctions();
37 std::unordered_map
<const MCSymbol
*, const MCSymbol
*> VeneerDestinations
;
38 uint64_t VeneersCount
= 0;
39 for (auto &It
: BFs
) {
40 BinaryFunction
&VeneerFunction
= It
.second
;
41 if (!VeneerFunction
.isAArch64Veneer())
45 VeneerFunction
.setPseudo(true);
46 MCInst
&FirstInstruction
= *(VeneerFunction
.begin()->begin());
47 const MCSymbol
*VeneerTargetSymbol
=
48 BC
.MIB
->getTargetSymbol(FirstInstruction
, 1);
49 assert(VeneerTargetSymbol
&& "Expecting target symbol for instruction");
50 for (const MCSymbol
*Symbol
: VeneerFunction
.getSymbols())
51 VeneerDestinations
[Symbol
] = VeneerTargetSymbol
;
54 outs() << "BOLT-INFO: number of removed linker-inserted veneers: "
55 << VeneersCount
<< "\n";
57 // Handle veneers to veneers in case they occur
58 for (auto &Entry
: VeneerDestinations
) {
59 const MCSymbol
*Src
= Entry
.first
;
60 const MCSymbol
*Dest
= Entry
.second
;
61 while (VeneerDestinations
.find(Dest
) != VeneerDestinations
.end())
62 Dest
= VeneerDestinations
[Dest
];
64 VeneerDestinations
[Src
] = Dest
;
67 uint64_t VeneerCallers
= 0;
68 for (auto &It
: BFs
) {
69 BinaryFunction
&Function
= It
.second
;
70 for (BinaryBasicBlock
&BB
: Function
) {
71 for (MCInst
&Instr
: BB
) {
72 if (!BC
.MIB
->isCall(Instr
) || BC
.MIB
->isIndirectCall(Instr
))
75 const MCSymbol
*TargetSymbol
= BC
.MIB
->getTargetSymbol(Instr
, 0);
76 if (VeneerDestinations
.find(TargetSymbol
) == VeneerDestinations
.end())
80 if (!BC
.MIB
->replaceBranchTarget(
81 Instr
, VeneerDestinations
[TargetSymbol
], BC
.Ctx
.get())) {
82 errs() << "BOLT-ERROR: updating veneer call destination failed\n";
90 dbgs() << "BOLT-INFO: number of linker-inserted veneers call sites: "
91 << VeneerCallers
<< "\n");