diff options
Diffstat (limited to 'lib/CodeGen/MachineVerifier.cpp')
| -rw-r--r-- | lib/CodeGen/MachineVerifier.cpp | 157 | 
1 files changed, 147 insertions, 10 deletions
| diff --git a/lib/CodeGen/MachineVerifier.cpp b/lib/CodeGen/MachineVerifier.cpp index f745b41c16fe..69a3ae84ec99 100644 --- a/lib/CodeGen/MachineVerifier.cpp +++ b/lib/CodeGen/MachineVerifier.cpp @@ -23,8 +23,9 @@  // the verifier errors.  //===----------------------------------------------------------------------===// +#include "llvm/BasicBlock.h" +#include "llvm/InlineAsm.h"  #include "llvm/Instructions.h" -#include "llvm/Function.h"  #include "llvm/CodeGen/LiveIntervalAnalysis.h"  #include "llvm/CodeGen/LiveVariables.h"  #include "llvm/CodeGen/LiveStackAnalysis.h" @@ -73,11 +74,12 @@ namespace {      typedef SmallVector<const uint32_t*, 4> RegMaskVector;      typedef DenseSet<unsigned> RegSet;      typedef DenseMap<unsigned, const MachineInstr*> RegMap; +    typedef SmallPtrSet<const MachineBasicBlock*, 8> BlockSet;      const MachineInstr *FirstTerminator; +    BlockSet FunctionBlocks;      BitVector regsReserved; -    BitVector regsAllocatable;      RegSet regsLive;      RegVector regsDefined, regsDead, regsKilled;      RegMaskVector regMasks; @@ -117,6 +119,9 @@ namespace {        // block. This set is disjoint from regsLiveOut.        RegSet vregsRequired; +      // Set versions of block's predecessor and successor lists. +      BlockSet Preds, Succs; +        BBInfo() : reachable(false) {}        // Add register to vregsPassed if it belongs there. Return true if @@ -180,7 +185,7 @@ namespace {      }      bool isAllocatable(unsigned Reg) { -      return Reg < regsAllocatable.size() && regsAllocatable.test(Reg); +      return Reg < TRI->getNumRegs() && MRI->isAllocatable(Reg);      }      // Analysis information if available @@ -208,6 +213,8 @@ namespace {      void report(const char *msg, const MachineBasicBlock *MBB,                  const LiveInterval &LI); +    void verifyInlineAsm(const MachineInstr *MI); +      void checkLiveness(const MachineOperand *MO, unsigned MONum);      void markReachable(const MachineBasicBlock *MBB);      void calcRegsPassed(); @@ -352,7 +359,7 @@ void MachineVerifier::report(const char *msg, const MachineFunction *MF) {      MF->print(*OS, Indexes);    }    *OS << "*** Bad machine code: " << msg << " ***\n" -      << "- function:    " << MF->getFunction()->getName() << "\n"; +      << "- function:    " << MF->getName() << "\n";  }  void MachineVerifier::report(const char *msg, const MachineBasicBlock *MBB) { @@ -360,7 +367,7 @@ void MachineVerifier::report(const char *msg, const MachineBasicBlock *MBB) {    report(msg, MBB->getParent());    *OS << "- basic block: BB#" << MBB->getNumber()        << ' ' << MBB->getName() -      << " (" << (void*)MBB << ')'; +      << " (" << (const void*)MBB << ')';    if (Indexes)      *OS << " [" << Indexes->getMBBStartIdx(MBB)          << ';' <<  Indexes->getMBBEndIdx(MBB) << ')'; @@ -419,7 +426,7 @@ void MachineVerifier::markReachable(const MachineBasicBlock *MBB) {  void MachineVerifier::visitMachineFunctionBefore() {    lastIndex = SlotIndex(); -  regsReserved = TRI->getReservedRegs(*MF); +  regsReserved = MRI->getReservedRegs();    // A sub-register of a reserved register is also reserved    for (int Reg = regsReserved.find_first(); Reg>=0; @@ -431,9 +438,23 @@ void MachineVerifier::visitMachineFunctionBefore() {      }    } -  regsAllocatable = TRI->getAllocatableSet(*MF); -    markReachable(&MF->front()); + +  // Build a set of the basic blocks in the function. +  FunctionBlocks.clear(); +  for (MachineFunction::const_iterator +       I = MF->begin(), E = MF->end(); I != E; ++I) { +    FunctionBlocks.insert(I); +    BBInfo &MInfo = MBBInfoMap[I]; + +    MInfo.Preds.insert(I->pred_begin(), I->pred_end()); +    if (MInfo.Preds.size() != I->pred_size()) +      report("MBB has duplicate entries in its predecessor list.", I); + +    MInfo.Succs.insert(I->succ_begin(), I->succ_end()); +    if (MInfo.Succs.size() != I->succ_size()) +      report("MBB has duplicate entries in its successor list.", I); +  }  }  // Does iterator point to a and b as the first two elements? @@ -470,6 +491,25 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {         E = MBB->succ_end(); I != E; ++I) {      if ((*I)->isLandingPad())        LandingPadSuccs.insert(*I); +    if (!FunctionBlocks.count(*I)) +      report("MBB has successor that isn't part of the function.", MBB); +    if (!MBBInfoMap[*I].Preds.count(MBB)) { +      report("Inconsistent CFG", MBB); +      *OS << "MBB is not in the predecessor list of the successor BB#" +          << (*I)->getNumber() << ".\n"; +    } +  } + +  // Check the predecessor list. +  for (MachineBasicBlock::const_pred_iterator I = MBB->pred_begin(), +       E = MBB->pred_end(); I != E; ++I) { +    if (!FunctionBlocks.count(*I)) +      report("MBB has predecessor that isn't part of the function.", MBB); +    if (!MBBInfoMap[*I].Succs.count(MBB)) { +      report("Inconsistent CFG", MBB); +      *OS << "MBB is not in the successor list of the predecessor BB#" +          << (*I)->getNumber() << ".\n"; +    }    }    const MCAsmInfo *AsmInfo = TM->getMCAsmInfo(); @@ -540,7 +580,15 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {        ++MBBI;        if (MBBI == MF->end()) {          report("MBB conditionally falls through out of function!", MBB); -      } if (MBB->succ_size() != 2) { +      } if (MBB->succ_size() == 1) { +        // A conditional branch with only one successor is weird, but allowed. +        if (&*MBBI != TBB) +          report("MBB exits via conditional branch/fall-through but only has " +                 "one CFG successor!", MBB); +        else if (TBB != *MBB->succ_begin()) +          report("MBB exits via conditional branch/fall-through but the CFG " +                 "successor don't match the actual successor!", MBB); +      } else if (MBB->succ_size() != 2) {          report("MBB exits via conditional branch/fall-through but doesn't have "                 "exactly two CFG successors!", MBB);        } else if (!matchPair(MBB->succ_begin(), TBB, MBBI)) { @@ -560,7 +608,15 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {      } else if (TBB && FBB) {        // Block conditionally branches somewhere, otherwise branches        // somewhere else. -      if (MBB->succ_size() != 2) { +      if (MBB->succ_size() == 1) { +        // A conditional branch with only one successor is weird, but allowed. +        if (FBB != TBB) +          report("MBB exits via conditional branch/branch through but only has " +                 "one CFG successor!", MBB); +        else if (TBB != *MBB->succ_begin()) +          report("MBB exits via conditional branch/branch through but the CFG " +                 "successor don't match the actual successor!", MBB); +      } else if (MBB->succ_size() != 2) {          report("MBB exits via conditional branch/branch but doesn't have "                 "exactly two CFG successors!", MBB);        } else if (!matchPair(MBB->succ_begin(), TBB, FBB)) { @@ -639,6 +695,50 @@ void MachineVerifier::visitMachineBundleBefore(const MachineInstr *MI) {    }  } +// The operands on an INLINEASM instruction must follow a template. +// Verify that the flag operands make sense. +void MachineVerifier::verifyInlineAsm(const MachineInstr *MI) { +  // The first two operands on INLINEASM are the asm string and global flags. +  if (MI->getNumOperands() < 2) { +    report("Too few operands on inline asm", MI); +    return; +  } +  if (!MI->getOperand(0).isSymbol()) +    report("Asm string must be an external symbol", MI); +  if (!MI->getOperand(1).isImm()) +    report("Asm flags must be an immediate", MI); +  // Allowed flags are Extra_HasSideEffects = 1, Extra_IsAlignStack = 2, +  // Extra_AsmDialect = 4, Extra_MayLoad = 8, and Extra_MayStore = 16. +  if (!isUInt<5>(MI->getOperand(1).getImm())) +    report("Unknown asm flags", &MI->getOperand(1), 1); + +  assert(InlineAsm::MIOp_FirstOperand == 2 && "Asm format changed"); + +  unsigned OpNo = InlineAsm::MIOp_FirstOperand; +  unsigned NumOps; +  for (unsigned e = MI->getNumOperands(); OpNo < e; OpNo += NumOps) { +    const MachineOperand &MO = MI->getOperand(OpNo); +    // There may be implicit ops after the fixed operands. +    if (!MO.isImm()) +      break; +    NumOps = 1 + InlineAsm::getNumOperandRegisters(MO.getImm()); +  } + +  if (OpNo > MI->getNumOperands()) +    report("Missing operands in last group", MI); + +  // An optional MDNode follows the groups. +  if (OpNo < MI->getNumOperands() && MI->getOperand(OpNo).isMetadata()) +    ++OpNo; + +  // All trailing operands must be implicit registers. +  for (unsigned e = MI->getNumOperands(); OpNo < e; ++OpNo) { +    const MachineOperand &MO = MI->getOperand(OpNo); +    if (!MO.isReg() || !MO.isImplicit()) +      report("Expected implicit register after groups", &MO, OpNo); +  } +} +  void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {    const MCInstrDesc &MCID = MI->getDesc();    if (MI->getNumOperands() < MCID.getNumOperands()) { @@ -647,6 +747,10 @@ void MachineVerifier::visitMachineInstrBefore(const MachineInstr *MI) {          << MI->getNumExplicitOperands() << " given.\n";    } +  // Check the tied operands. +  if (MI->isInlineAsm()) +    verifyInlineAsm(MI); +    // Check the MachineMemOperands for basic consistency.    for (MachineInstr::mmo_iterator I = MI->memoperands_begin(),         E = MI->memoperands_end(); I != E; ++I) { @@ -702,6 +806,17 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {        if (MO->isImplicit())          report("Explicit operand marked as implicit", MO, MONum);      } + +    int TiedTo = MCID.getOperandConstraint(MONum, MCOI::TIED_TO); +    if (TiedTo != -1) { +      if (!MO->isReg()) +        report("Tied use must be a register", MO, MONum); +      else if (!MO->isTied()) +        report("Operand should be tied", MO, MONum); +      else if (unsigned(TiedTo) != MI->findTiedOperandIdx(MONum)) +        report("Tied def doesn't match MCInstrDesc", MO, MONum); +    } else if (MO->isReg() && MO->isTied()) +      report("Explicit operand should not be tied", MO, MONum);    } else {      // ARM adds %reg0 operands to indicate predicates. We'll allow that.      if (MO->isReg() && !MO->isImplicit() && !MI->isVariadic() && MO->getReg()) @@ -716,6 +831,28 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) {      if (MRI->tracksLiveness() && !MI->isDebugValue())        checkLiveness(MO, MONum); +    // Verify the consistency of tied operands. +    if (MO->isTied()) { +      unsigned OtherIdx = MI->findTiedOperandIdx(MONum); +      const MachineOperand &OtherMO = MI->getOperand(OtherIdx); +      if (!OtherMO.isReg()) +        report("Must be tied to a register", MO, MONum); +      if (!OtherMO.isTied()) +        report("Missing tie flags on tied operand", MO, MONum); +      if (MI->findTiedOperandIdx(OtherIdx) != MONum) +        report("Inconsistent tie links", MO, MONum); +      if (MONum < MCID.getNumDefs()) { +        if (OtherIdx < MCID.getNumOperands()) { +          if (-1 == MCID.getOperandConstraint(OtherIdx, MCOI::TIED_TO)) +            report("Explicit def tied to explicit use without tie constraint", +                   MO, MONum); +        } else { +          if (!OtherMO.isImplicit()) +            report("Explicit def should be tied to implicit use", MO, MONum); +        } +      } +    } +      // Verify two-address constraints after leaving SSA form.      unsigned DefIdx;      if (!MRI->isSSA() && MO->isUse() && | 
