brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.6 KiB · 99d0ffe Raw
112 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This class implements a pass that removes linker-inserted veneers from the10// code and redirects veneer callers to call to veneers destinations11//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(true),26                     cl::Hidden, cl::cat(BoltOptCategory));27} // namespace opts28 29namespace llvm {30namespace bolt {31 32static bool isPossibleVeneer(const BinaryFunction &BF) {33  return BF.isAArch64Veneer() || BF.getOneName().starts_with("__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(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(FirstInstruction)) {53      VeneerTargetSymbol = BC.MIB->getTargetSymbol(FirstInstruction);54    } else if (BC.MIB->matchAbsLongVeneer(BF, TargetAddress)) {55      if (BinaryFunction *TargetBF =56              BC.getBinaryFunctionAtAddress(TargetAddress))57        VeneerTargetSymbol = TargetBF->getSymbol();58    } else if (BC.MIB->hasAnnotation(FirstInstruction, "AArch64Veneer")) {59      VeneerTargetSymbol = BC.MIB->getTargetSymbol(FirstInstruction, 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 occur76  for (auto &Entry : VeneerDestinations) {77    const MCSymbol *Src = Entry.first;78    const MCSymbol *Dest = Entry.second;79    while (VeneerDestinations.find(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(BC.getBinaryFunctions())) {87    for (BinaryBasicBlock &BB : BF) {88      for (MCInst &Instr : BB) {89        if (!BC.MIB->isCall(Instr) || BC.MIB->isIndirectCall(Instr))90          continue;91 92        const MCSymbol *TargetSymbol = BC.MIB->getTargetSymbol(Instr, 0);93        auto It = VeneerDestinations.find(TargetSymbol);94        if (It == VeneerDestinations.end())95          continue;96 97        VeneerCallers++;98        BC.MIB->replaceBranchTarget(Instr, It->second, 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 bolt111} // namespace llvm112