brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.0 KiB · 9da460a Raw
195 lines · cpp
1//===- bolt/Passes/StokeInfo.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 file implements the StokeInfo class.10//11//===----------------------------------------------------------------------===//12 13#include "bolt/Passes/StokeInfo.h"14#include "bolt/Core/BinaryFunctionCallGraph.h"15#include "bolt/Passes/DataflowInfoManager.h"16#include "llvm/Support/CommandLine.h"17 18#define DEBUG_TYPE "stoke"19 20using namespace llvm;21using namespace bolt;22 23namespace opts {24static cl::OptionCategory StokeOptCategory("STOKE pass options");25 26static cl::opt<std::string>27StokeOutputDataFilename("stoke-out",28  cl::desc("output data (.csv) for Stoke's use"),29  cl::Optional,30  cl::cat(StokeOptCategory));31}32 33namespace llvm {34namespace bolt {35 36void getRegNameFromBitVec(const BinaryContext &BC, const BitVector &RegV,37                          std::set<std::string> *NameVec = nullptr) {38  for (int RegIdx : RegV.set_bits()) {39    LLVM_DEBUG(dbgs() << BC.MRI->getName(RegIdx) << " ");40    if (NameVec)41      NameVec->insert(std::string(BC.MRI->getName(RegIdx)));42  }43  LLVM_DEBUG(dbgs() << "\n");44}45 46void StokeInfo::checkInstr(const BinaryFunction &BF, StokeFuncInfo &FuncInfo) {47  MCPlusBuilder *MIB = BF.getBinaryContext().MIB.get();48  BitVector RegV(NumRegs, false);49  for (const BinaryBasicBlock *BB : BF.getLayout().blocks()) {50    if (BB->empty())51      continue;52 53    // Skip function with exception handling.54    if (BB->throw_size() || BB->lp_size()) {55      FuncInfo.Omitted = true;56      return;57    }58 59    for (const MCInst &It : *BB) {60      if (MIB->isPseudo(It))61        continue;62      // skip function with exception handling yet63      if (MIB->isInvoke(It)) {64        FuncInfo.Omitted = true;65        return;66      }67      // check if this function contains call instruction68      if (MIB->isCall(It)) {69        FuncInfo.HasCall = true;70        const MCSymbol *TargetSymbol = MIB->getTargetSymbol(It);71        // if it is an indirect call, skip72        if (TargetSymbol == nullptr) {73          FuncInfo.Omitted = true;74          return;75        }76      }77      // check if this function modify stack or heap78      // TODO: more accurate analysis79      bool IsPush = MIB->isPush(It);80      bool IsRipAddr = MIB->hasPCRelOperand(It);81      if (IsPush)82        FuncInfo.StackOut = true;83 84      if (MIB->mayStore(It) && !IsPush && !IsRipAddr)85        FuncInfo.HeapOut = true;86 87      if (IsRipAddr)88        FuncInfo.HasRipAddr = true;89    } // end of for (auto &It : ...)90  }   // end of for (auto *BB : ...)91}92 93bool StokeInfo::checkFunction(BinaryFunction &BF, DataflowInfoManager &DInfo,94                              RegAnalysis &RA, StokeFuncInfo &FuncInfo) {95 96  std::string Name = BF.getSymbol()->getName().str();97 98  if (!BF.isSimple() || BF.isMultiEntry() || BF.empty())99    return false;100  BF.getBinaryContext().outs()101      << " STOKE-INFO: analyzing function " << Name << "\n";102 103  FuncInfo.FuncName = Name;104  FuncInfo.Offset = BF.getFileOffset();105  FuncInfo.Size = BF.getMaxSize();106  FuncInfo.NumInstrs = BF.getNumNonPseudos();107  FuncInfo.NumBlocks = BF.size();108  // early stop for large functions109  if (FuncInfo.NumInstrs > 500)110    return false;111 112  FuncInfo.IsLoopFree = BF.isLoopFree();113  if (!FuncInfo.IsLoopFree) {114    const BinaryLoopInfo &BLI = BF.getLoopInfo();115    FuncInfo.NumLoops = BLI.OuterLoops;116    FuncInfo.MaxLoopDepth = BLI.MaximumDepth;117  }118 119  FuncInfo.HotSize = BF.estimateHotSize();120  FuncInfo.TotalSize = BF.estimateSize();121  FuncInfo.Score = BF.getFunctionScore();122 123  checkInstr(BF, FuncInfo);124 125  // register analysis126  BinaryBasicBlock &EntryBB = BF.front();127  assert(EntryBB.isEntryPoint() && "Weird, this should be the entry block!");128 129  MCInst *FirstNonPseudo = EntryBB.getFirstNonPseudoInstr();130  if (!FirstNonPseudo)131    return false;132 133  LLVM_DEBUG(dbgs() << "\t [DefIn]\n\t ");134  BitVector LiveInBV =135      *(DInfo.getLivenessAnalysis().getStateAt(FirstNonPseudo));136  LiveInBV &= DefaultDefInMask;137  getRegNameFromBitVec(BF.getBinaryContext(), LiveInBV, &FuncInfo.DefIn);138 139  LLVM_DEBUG(dbgs() << "\t [LiveOut]\n\t ");140  BitVector LiveOutBV = RA.getFunctionClobberList(&BF);141  LiveOutBV &= DefaultLiveOutMask;142  getRegNameFromBitVec(BF.getBinaryContext(), LiveOutBV, &FuncInfo.LiveOut);143 144  BF.getBinaryContext().outs() << " STOKE-INFO: end function \n";145  return true;146}147 148Error StokeInfo::runOnFunctions(BinaryContext &BC) {149  BC.outs() << "STOKE-INFO: begin of stoke pass\n";150 151  std::ofstream Outfile;152  if (!opts::StokeOutputDataFilename.empty()) {153    Outfile.open(opts::StokeOutputDataFilename);154  } else {155    BC.errs() << "STOKE-INFO: output file is required\n";156    return Error::success();157  }158 159  // check some context meta data160  LLVM_DEBUG(dbgs() << "\tTarget: " << BC.TheTarget->getName() << "\n");161  LLVM_DEBUG(dbgs() << "\tTripleName " << BC.TripleName << "\n");162  LLVM_DEBUG(dbgs() << "\tgetNumRegs " << BC.MRI->getNumRegs() << "\n");163 164  BinaryFunctionCallGraph CG = buildCallGraph(BC);165  RegAnalysis RA(BC, &BC.getBinaryFunctions(), &CG);166 167  NumRegs = BC.MRI->getNumRegs();168  assert(NumRegs > 0 && "STOKE-INFO: the target register number is incorrect!");169 170  DefaultDefInMask.resize(NumRegs, false);171  DefaultLiveOutMask.resize(NumRegs, false);172 173  BC.MIB->getDefaultDefIn(DefaultDefInMask);174  BC.MIB->getDefaultLiveOut(DefaultLiveOutMask);175 176  getRegNameFromBitVec(BC, DefaultDefInMask);177  getRegNameFromBitVec(BC, DefaultLiveOutMask);178 179  StokeFuncInfo FuncInfo;180  // analyze all functions181  FuncInfo.printCsvHeader(Outfile);182  for (auto &BF : BC.getBinaryFunctions()) {183    DataflowInfoManager DInfo(BF.second, &RA, nullptr);184    FuncInfo.reset();185    if (checkFunction(BF.second, DInfo, RA, FuncInfo))186      FuncInfo.printData(Outfile);187  }188 189  BC.outs() << "STOKE-INFO: end of stoke pass\n";190  return Error::success();191}192 193} // namespace bolt194} // namespace llvm195