LCOV - code coverage report
Current view: top level - lib/CodeGen - CFIInstrInserter.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 68 110 61.8 %
Date: 2018-10-20 13:21:21 Functions: 10 12 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===------ CFIInstrInserter.cpp - Insert additional CFI instructions -----===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : /// \file This pass verifies incoming and outgoing CFA information of basic
      11             : /// blocks. CFA information is information about offset and register set by CFI
      12             : /// directives, valid at the start and end of a basic block. This pass checks
      13             : /// that outgoing information of predecessors matches incoming information of
      14             : /// their successors. Then it checks if blocks have correct CFA calculation rule
      15             : /// set and inserts additional CFI instruction at their beginnings if they
      16             : /// don't. CFI instructions are inserted if basic blocks have incorrect offset
      17             : /// or register set by previous blocks, as a result of a non-linear layout of
      18             : /// blocks in a function.
      19             : //===----------------------------------------------------------------------===//
      20             : 
      21             : #include "llvm/ADT/DepthFirstIterator.h"
      22             : #include "llvm/CodeGen/MachineFunctionPass.h"
      23             : #include "llvm/CodeGen/MachineInstrBuilder.h"
      24             : #include "llvm/CodeGen/MachineModuleInfo.h"
      25             : #include "llvm/CodeGen/Passes.h"
      26             : #include "llvm/CodeGen/TargetFrameLowering.h"
      27             : #include "llvm/CodeGen/TargetInstrInfo.h"
      28             : #include "llvm/CodeGen/TargetSubtargetInfo.h"
      29             : #include "llvm/Target/TargetMachine.h"
      30             : using namespace llvm;
      31             : 
      32             : static cl::opt<bool> VerifyCFI("verify-cfiinstrs",
      33             :     cl::desc("Verify Call Frame Information instructions"),
      34             :     cl::init(false),
      35             :     cl::Hidden);
      36             : 
      37             : namespace {
      38             : class CFIInstrInserter : public MachineFunctionPass {
      39             :  public:
      40             :   static char ID;
      41             : 
      42       12692 :   CFIInstrInserter() : MachineFunctionPass(ID) {
      43       12692 :     initializeCFIInstrInserterPass(*PassRegistry::getPassRegistry());
      44       12692 :   }
      45             : 
      46       12652 :   void getAnalysisUsage(AnalysisUsage &AU) const override {
      47             :     AU.setPreservesAll();
      48       12652 :     MachineFunctionPass::getAnalysisUsage(AU);
      49       12652 :   }
      50             : 
      51      297527 :   bool runOnMachineFunction(MachineFunction &MF) override {
      52      585200 :     if (!MF.getMMI().hasDebugInfo() &&
      53      287673 :         !MF.getFunction().needsUnwindTableEntry())
      54             :       return false;
      55             : 
      56      546080 :     MBBVector.resize(MF.getNumBlockIDs());
      57      273040 :     calculateCFAInfo(MF);
      58             : 
      59      273040 :     if (VerifyCFI) {
      60           4 :       if (unsigned ErrorNum = verify(MF))
      61           2 :         report_fatal_error("Found " + Twine(ErrorNum) +
      62             :                            " in/out CFI information errors.");
      63             :     }
      64      273038 :     bool insertedCFI = insertCFIInstrs(MF);
      65             :     MBBVector.clear();
      66             :     return insertedCFI;
      67             :   }
      68             : 
      69             :  private:
      70     3114220 :   struct MBBCFAInfo {
      71             :     MachineBasicBlock *MBB;
      72             :     /// Value of cfa offset valid at basic block entry.
      73             :     int IncomingCFAOffset = -1;
      74             :     /// Value of cfa offset valid at basic block exit.
      75             :     int OutgoingCFAOffset = -1;
      76             :     /// Value of cfa register valid at basic block entry.
      77             :     unsigned IncomingCFARegister = 0;
      78             :     /// Value of cfa register valid at basic block exit.
      79             :     unsigned OutgoingCFARegister = 0;
      80             :     /// If in/out cfa offset and register values for this block have already
      81             :     /// been set or not.
      82             :     bool Processed = false;
      83             :   };
      84             : 
      85             :   /// Contains cfa offset and register values valid at entry and exit of basic
      86             :   /// blocks.
      87             :   std::vector<MBBCFAInfo> MBBVector;
      88             : 
      89             :   /// Calculate cfa offset and register values valid at entry and exit for all
      90             :   /// basic blocks in a function.
      91             :   void calculateCFAInfo(MachineFunction &MF);
      92             :   /// Calculate cfa offset and register values valid at basic block exit by
      93             :   /// checking the block for CFI instructions. Block's incoming CFA info remains
      94             :   /// the same.
      95             :   void calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo);
      96             :   /// Update in/out cfa offset and register values for successors of the basic
      97             :   /// block.
      98             :   void updateSuccCFAInfo(MBBCFAInfo &MBBInfo);
      99             : 
     100             :   /// Check if incoming CFA information of a basic block matches outgoing CFA
     101             :   /// information of the previous block. If it doesn't, insert CFI instruction
     102             :   /// at the beginning of the block that corrects the CFA calculation rule for
     103             :   /// that block.
     104             :   bool insertCFIInstrs(MachineFunction &MF);
     105             :   /// Return the cfa offset value that should be set at the beginning of a MBB
     106             :   /// if needed. The negated value is needed when creating CFI instructions that
     107             :   /// set absolute offset.
     108             :   int getCorrectCFAOffset(MachineBasicBlock *MBB) {
     109       80322 :     return -MBBVector[MBB->getNumber()].IncomingCFAOffset;
     110             :   }
     111             : 
     112             :   void report(const MBBCFAInfo &Pred, const MBBCFAInfo &Succ);
     113             :   /// Go through each MBB in a function and check that outgoing offset and
     114             :   /// register of its predecessors match incoming offset and register of that
     115             :   /// MBB, as well as that incoming offset and register of its successors match
     116             :   /// outgoing offset and register of the MBB.
     117             :   unsigned verify(MachineFunction &MF);
     118             : };
     119             : }  // namespace
     120             : 
     121             : char CFIInstrInserter::ID = 0;
     122       97839 : INITIALIZE_PASS(CFIInstrInserter, "cfi-instr-inserter",
     123             :                 "Check CFA info and insert CFI instructions if needed", false,
     124             :                 false)
     125       12688 : FunctionPass *llvm::createCFIInstrInserter() { return new CFIInstrInserter(); }
     126             : 
     127      273040 : void CFIInstrInserter::calculateCFAInfo(MachineFunction &MF) {
     128             :   // Initial CFA offset value i.e. the one valid at the beginning of the
     129             :   // function.
     130             :   int InitialOffset =
     131      273040 :       MF.getSubtarget().getFrameLowering()->getInitialCFAOffset(MF);
     132             :   // Initial CFA register value i.e. the one valid at the beginning of the
     133             :   // function.
     134             :   unsigned InitialRegister =
     135      273040 :       MF.getSubtarget().getFrameLowering()->getInitialCFARegister(MF);
     136             : 
     137             :   // Initialize MBBMap.
     138     3385608 :   for (MachineBasicBlock &MBB : MF) {
     139             :     MBBCFAInfo MBBInfo;
     140             :     MBBInfo.MBB = &MBB;
     141             :     MBBInfo.IncomingCFAOffset = InitialOffset;
     142             :     MBBInfo.OutgoingCFAOffset = InitialOffset;
     143             :     MBBInfo.IncomingCFARegister = InitialRegister;
     144             :     MBBInfo.OutgoingCFARegister = InitialRegister;
     145     6225136 :     MBBVector[MBB.getNumber()] = MBBInfo;
     146             :   }
     147             : 
     148             :   // Set in/out cfa info for all blocks in the function. This traversal is based
     149             :   // on the assumption that the first block in the function is the entry block
     150             :   // i.e. that it has initial cfa offset and register values as incoming CFA
     151             :   // information.
     152     3385608 :   for (MachineBasicBlock &MBB : MF) {
     153     6225136 :     if (MBBVector[MBB.getNumber()].Processed) continue;
     154      273087 :     updateSuccCFAInfo(MBBVector[MBB.getNumber()]);
     155             :   }
     156      273040 : }
     157             : 
     158           0 : void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
     159             :   // Outgoing cfa offset set by the block.
     160           0 :   int SetOffset = MBBInfo.IncomingCFAOffset;
     161             :   // Outgoing cfa register set by the block.
     162           0 :   unsigned SetRegister = MBBInfo.IncomingCFARegister;
     163             :   const std::vector<MCCFIInstruction> &Instrs =
     164           0 :       MBBInfo.MBB->getParent()->getFrameInstructions();
     165             : 
     166             :   // Determine cfa offset and register set by the block.
     167           0 :   for (MachineInstr &MI : *MBBInfo.MBB) {
     168           0 :     if (MI.isCFIInstruction()) {
     169           0 :       unsigned CFIIndex = MI.getOperand(0).getCFIIndex();
     170           0 :       const MCCFIInstruction &CFI = Instrs[CFIIndex];
     171           0 :       switch (CFI.getOperation()) {
     172           0 :       case MCCFIInstruction::OpDefCfaRegister:
     173           0 :         SetRegister = CFI.getRegister();
     174           0 :         break;
     175           0 :       case MCCFIInstruction::OpDefCfaOffset:
     176           0 :         SetOffset = CFI.getOffset();
     177           0 :         break;
     178           0 :       case MCCFIInstruction::OpAdjustCfaOffset:
     179           0 :         SetOffset += CFI.getOffset();
     180           0 :         break;
     181           0 :       case MCCFIInstruction::OpDefCfa:
     182           0 :         SetRegister = CFI.getRegister();
     183           0 :         SetOffset = CFI.getOffset();
     184           0 :         break;
     185             :       case MCCFIInstruction::OpRememberState:
     186             :         // TODO: Add support for handling cfi_remember_state.
     187             : #ifndef NDEBUG
     188             :         report_fatal_error(
     189             :             "Support for cfi_remember_state not implemented! Value of CFA "
     190             :             "may be incorrect!\n");
     191             : #endif
     192             :         break;
     193             :       case MCCFIInstruction::OpRestoreState:
     194             :         // TODO: Add support for handling cfi_restore_state.
     195             : #ifndef NDEBUG
     196             :         report_fatal_error(
     197             :             "Support for cfi_restore_state not implemented! Value of CFA may "
     198             :             "be incorrect!\n");
     199             : #endif
     200             :         break;
     201             :       // Other CFI directives do not affect CFA value.
     202             :       case MCCFIInstruction::OpSameValue:
     203             :       case MCCFIInstruction::OpOffset:
     204             :       case MCCFIInstruction::OpRelOffset:
     205             :       case MCCFIInstruction::OpEscape:
     206             :       case MCCFIInstruction::OpRestore:
     207             :       case MCCFIInstruction::OpUndefined:
     208             :       case MCCFIInstruction::OpRegister:
     209             :       case MCCFIInstruction::OpWindowSave:
     210             :       case MCCFIInstruction::OpGnuArgsSize:
     211             :         break;
     212             :       }
     213             :     }
     214             :   }
     215             : 
     216           0 :   MBBInfo.Processed = true;
     217             : 
     218             :   // Update outgoing CFA info.
     219           0 :   MBBInfo.OutgoingCFAOffset = SetOffset;
     220           0 :   MBBInfo.OutgoingCFARegister = SetRegister;
     221           0 : }
     222             : 
     223      273087 : void CFIInstrInserter::updateSuccCFAInfo(MBBCFAInfo &MBBInfo) {
     224             :   SmallVector<MachineBasicBlock *, 4> Stack;
     225      273087 :   Stack.push_back(MBBInfo.MBB);
     226             : 
     227             :   do {
     228             :     MachineBasicBlock *Current = Stack.pop_back_val();
     229     3248734 :     MBBCFAInfo &CurrentInfo = MBBVector[Current->getNumber()];
     230     3248734 :     if (CurrentInfo.Processed)
     231             :       continue;
     232             : 
     233     3112568 :     calculateOutgoingCFAInfo(CurrentInfo);
     234     6841994 :     for (auto *Succ : CurrentInfo.MBB->successors()) {
     235     3729426 :       MBBCFAInfo &SuccInfo = MBBVector[Succ->getNumber()];
     236     3729426 :       if (!SuccInfo.Processed) {
     237     2975647 :         SuccInfo.IncomingCFAOffset = CurrentInfo.OutgoingCFAOffset;
     238     2975647 :         SuccInfo.IncomingCFARegister = CurrentInfo.OutgoingCFARegister;
     239     2975647 :         Stack.push_back(Succ);
     240             :       }
     241             :     }
     242     3248734 :   } while (!Stack.empty());
     243      273087 : }
     244             : 
     245      273038 : bool CFIInstrInserter::insertCFIInstrs(MachineFunction &MF) {
     246      273038 :   const MBBCFAInfo *PrevMBBInfo = &MBBVector[MF.front().getNumber()];
     247      273038 :   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
     248             :   bool InsertedCFIInstr = false;
     249             : 
     250     3385600 :   for (MachineBasicBlock &MBB : MF) {
     251             :     // Skip the first MBB in a function
     252     6225124 :     if (MBB.getNumber() == MF.front().getNumber()) continue;
     253             : 
     254     2839524 :     const MBBCFAInfo &MBBInfo = MBBVector[MBB.getNumber()];
     255     2839524 :     auto MBBI = MBBInfo.MBB->begin();
     256             :     DebugLoc DL = MBBInfo.MBB->findDebugLoc(MBBI);
     257             : 
     258     2839524 :     if (PrevMBBInfo->OutgoingCFAOffset != MBBInfo.IncomingCFAOffset) {
     259             :       // If both outgoing offset and register of a previous block don't match
     260             :       // incoming offset and register of this block, add a def_cfa instruction
     261             :       // with the correct offset and register for this block.
     262       40161 :       if (PrevMBBInfo->OutgoingCFARegister != MBBInfo.IncomingCFARegister) {
     263       34778 :         unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfa(
     264             :             nullptr, MBBInfo.IncomingCFARegister, getCorrectCFAOffset(&MBB)));
     265      104334 :         BuildMI(*MBBInfo.MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
     266             :             .addCFIIndex(CFIIndex);
     267             :         // If outgoing offset of a previous block doesn't match incoming offset
     268             :         // of this block, add a def_cfa_offset instruction with the correct
     269             :         // offset for this block.
     270             :       } else {
     271             :         unsigned CFIIndex =
     272        5383 :             MF.addFrameInst(MCCFIInstruction::createDefCfaOffset(
     273             :                 nullptr, getCorrectCFAOffset(&MBB)));
     274       16149 :         BuildMI(*MBBInfo.MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
     275             :             .addCFIIndex(CFIIndex);
     276             :       }
     277             :       InsertedCFIInstr = true;
     278             :       // If outgoing register of a previous block doesn't match incoming
     279             :       // register of this block, add a def_cfa_register instruction with the
     280             :       // correct register for this block.
     281     5598726 :     } else if (PrevMBBInfo->OutgoingCFARegister !=
     282     2799363 :                MBBInfo.IncomingCFARegister) {
     283             :       unsigned CFIIndex =
     284           0 :           MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(
     285             :               nullptr, MBBInfo.IncomingCFARegister));
     286           0 :       BuildMI(*MBBInfo.MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
     287             :           .addCFIIndex(CFIIndex);
     288             :       InsertedCFIInstr = true;
     289             :     }
     290             :     PrevMBBInfo = &MBBInfo;
     291             :   }
     292      273038 :   return InsertedCFIInstr;
     293             : }
     294             : 
     295           0 : void CFIInstrInserter::report(const MBBCFAInfo &Pred, const MBBCFAInfo &Succ) {
     296           0 :   errs() << "*** Inconsistent CFA register and/or offset between pred and succ "
     297           0 :             "***\n";
     298           0 :   errs() << "Pred: " << Pred.MBB->getName() << " #" << Pred.MBB->getNumber()
     299           0 :          << " in " << Pred.MBB->getParent()->getName()
     300           0 :          << " outgoing CFA Reg:" << Pred.OutgoingCFARegister << "\n";
     301           0 :   errs() << "Pred: " << Pred.MBB->getName() << " #" << Pred.MBB->getNumber()
     302           0 :          << " in " << Pred.MBB->getParent()->getName()
     303           0 :          << " outgoing CFA Offset:" << Pred.OutgoingCFAOffset << "\n";
     304           0 :   errs() << "Succ: " << Succ.MBB->getName() << " #" << Succ.MBB->getNumber()
     305           0 :          << " incoming CFA Reg:" << Succ.IncomingCFARegister << "\n";
     306           0 :   errs() << "Succ: " << Succ.MBB->getName() << " #" << Succ.MBB->getNumber()
     307           0 :          << " incoming CFA Offset:" << Succ.IncomingCFAOffset << "\n";
     308           0 : }
     309             : 
     310           4 : unsigned CFIInstrInserter::verify(MachineFunction &MF) {
     311             :   unsigned ErrorNum = 0;
     312          21 :   for (auto *CurrMBB : depth_first(&MF)) {
     313          13 :     const MBBCFAInfo &CurrMBBInfo = MBBVector[CurrMBB->getNumber()];
     314          26 :     for (MachineBasicBlock *Succ : CurrMBB->successors()) {
     315          13 :       const MBBCFAInfo &SuccMBBInfo = MBBVector[Succ->getNumber()];
     316             :       // Check that incoming offset and register values of successors match the
     317             :       // outgoing offset and register values of CurrMBB
     318          13 :       if (SuccMBBInfo.IncomingCFAOffset != CurrMBBInfo.OutgoingCFAOffset ||
     319          11 :           SuccMBBInfo.IncomingCFARegister != CurrMBBInfo.OutgoingCFARegister) {
     320             :         // Inconsistent offsets/registers are ok for 'noreturn' blocks because
     321             :         // we don't generate epilogues inside such blocks.
     322           6 :         if (SuccMBBInfo.MBB->succ_empty() && !SuccMBBInfo.MBB->isReturnBlock())
     323             :           continue;
     324           2 :         report(CurrMBBInfo, SuccMBBInfo);
     325           2 :         ErrorNum++;
     326             :       }
     327             :     }
     328             :   }
     329           4 :   return ErrorNum;
     330             : }

Generated by: LCOV version 1.13