Please use GitHub pull requests for new patches. Avoid migrating existing patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
lib/CodeGen/CFIInfoVerifier.cpp
- This file was added.
//===----------- CFIInfoVerifier.cpp - CFI Information Verifier -----------===// | |||||
// | |||||
// The LLVM Compiler Infrastructure | |||||
// | |||||
// This file is distributed under the University of Illinois Open Source | |||||
// License. See LICENSE.TXT for details. | |||||
// | |||||
//===----------------------------------------------------------------------===// | |||||
// | |||||
// This pass verifies incoming and outgoing CFI information of basic blocks. CFI | |||||
// information is information about offset and register set by CFI directives, | |||||
// valid at the start and end of a basic block. This pass checks that outgoing | |||||
// information of predecessors matches incoming information of their successors. | |||||
//===----------------------------------------------------------------------===// | |||||
#include "llvm/CodeGen/MachineFunctionPass.h" | |||||
#include "llvm/CodeGen/MachineModuleInfo.h" | |||||
#include "llvm/CodeGen/Passes.h" | |||||
#include "llvm/Target/TargetFrameLowering.h" | |||||
#include "llvm/Target/TargetMachine.h" | |||||
#include "llvm/Target/TargetSubtargetInfo.h" | |||||
using namespace llvm; | |||||
namespace { | |||||
class CFIInfoVerifier : public MachineFunctionPass { | |||||
public: | |||||
static char ID; | |||||
int errorNum; | |||||
CFIInfoVerifier() : MachineFunctionPass(ID) { | |||||
initializeCFIInfoVerifierPass(*PassRegistry::getPassRegistry()); | |||||
} | |||||
void getAnalysisUsage(AnalysisUsage &AU) const override { | |||||
AU.setPreservesAll(); | |||||
MachineFunctionPass::getAnalysisUsage(AU); | |||||
} | |||||
bool runOnMachineFunction(MachineFunction &MF) override { | |||||
bool NeedsDwarfCFI = (MF.getMMI().hasDebugInfo() || | |||||
MF.getFunction()->needsUnwindTableEntry()) && | |||||
(!MF.getTarget().getTargetTriple().isOSDarwin() && | |||||
!MF.getTarget().getTargetTriple().isOSWindows()); | |||||
if (!NeedsDwarfCFI || | |||||
!MF.getSubtarget().getFrameLowering()->maintainsCFIInfo()) | |||||
return false; | |||||
applyAdjustments(MF); | |||||
int ErrorNum = verify(MF); | |||||
if (ErrorNum) | |||||
report_fatal_error("Found " + Twine(ErrorNum) + | |||||
" in/out CFI information errors."); | |||||
return false; | |||||
} | |||||
private: | |||||
// Adjust values of incoming and outgoing cfa offset with appropriate amounts | |||||
// (the sum of adjustments in effect at the entry and exit of each basic | |||||
// block). | |||||
void applyAdjustments(MachineFunction &MF); | |||||
// Go through each MBB in a function and check that outgoing offset and | |||||
// register of its predecessors match incoming offset and register of that | |||||
// MBB, as well as that incoming offset and register of its successors match | |||||
// outgoing offset and register of the MBB. | |||||
int verify(MachineFunction &MF); | |||||
void report(const char *msg, MachineBasicBlock &MBB); | |||||
}; | |||||
} | |||||
char CFIInfoVerifier::ID = 0; | |||||
INITIALIZE_PASS(CFIInfoVerifier, "cfiinfoverifier", | |||||
"Verify that corresponding in/out CFI info matches", false, | |||||
false) | |||||
FunctionPass *llvm::createCFIInfoVerifier() { return new CFIInfoVerifier(); } | |||||
int CFIInfoVerifier::verify(MachineFunction &MF) { | |||||
errorNum = 0; | |||||
for (auto &CurrMBB : MF) { | |||||
for (auto Pred : CurrMBB.predecessors()) { | |||||
// Check that outgoing offset values of predecessors match the incoming | |||||
// offset value of CurrMBB | |||||
if (Pred->getOutgoingCFAOffset() != CurrMBB.getIncomingCFAOffset()) { | |||||
report("The outgoing offset of a predecessor is inconsistent.", | |||||
CurrMBB); | |||||
errs() << "Predecessor BB#" << Pred->getNumber() | |||||
<< " has outgoing offset (" << Pred->getOutgoingCFAOffset() | |||||
<< "), while BB#" << CurrMBB.getNumber() | |||||
<< " has incoming offset (" << CurrMBB.getIncomingCFAOffset() | |||||
<< ").\n"; | |||||
} | |||||
// Check that outgoing register values of predecessors match the incoming | |||||
// register value of CurrMBB | |||||
if (Pred->getOutgoingCFARegister() != CurrMBB.getIncomingCFARegister()) { | |||||
report("The outgoing register of a predecessor is inconsistent.", | |||||
CurrMBB); | |||||
errs() << "Predecessor BB#" << Pred->getNumber() | |||||
<< " has outgoing register (" << Pred->getOutgoingCFARegister() | |||||
<< "), while BB#" << CurrMBB.getNumber() | |||||
<< " has incoming register (" << CurrMBB.getIncomingCFARegister() | |||||
<< ").\n"; | |||||
} | |||||
} | |||||
for (auto Succ : CurrMBB.successors()) { | |||||
// Check that incoming offset values of successors match the outgoing | |||||
// offset value of CurrMBB | |||||
if (Succ->getIncomingCFAOffset() != CurrMBB.getOutgoingCFAOffset()) { | |||||
report("The incoming offset of a successor is inconsistent.", CurrMBB); | |||||
errs() << "Successor BB#" << Succ->getNumber() | |||||
<< " has incoming offset (" << Succ->getIncomingCFAOffset() | |||||
<< "), while BB#" << CurrMBB.getNumber() | |||||
<< " has outgoing offset (" << CurrMBB.getOutgoingCFAOffset() | |||||
<< ").\n"; | |||||
} | |||||
// Check that incoming register values of successors match the outgoing | |||||
// register value of CurrMBB | |||||
if (Succ->getIncomingCFARegister() != CurrMBB.getOutgoingCFARegister()) { | |||||
report("The incoming register of a successor is inconsistent.", | |||||
CurrMBB); | |||||
errs() << "Successor BB#" << Succ->getNumber() | |||||
<< " has incoming register (" << Succ->getIncomingCFARegister() | |||||
<< "), while BB#" << CurrMBB.getNumber() | |||||
<< " has outgoing register (" << CurrMBB.getOutgoingCFARegister() | |||||
<< ").\n"; | |||||
} | |||||
} | |||||
} | |||||
return errorNum; | |||||
} | |||||
void CFIInfoVerifier::report(const char *msg, MachineBasicBlock &MBB) { | |||||
assert(&MBB); | |||||
errorNum++; | |||||
errs() << '\n'; | |||||
errs() << "*** " << msg << " ***\n" | |||||
<< "- function: " << MBB.getParent()->getName() << "\n"; | |||||
errs() << "- basic block: BB#" << MBB.getNumber() << ' ' << MBB.getName() | |||||
<< " (" << (const void *)&MBB << ')'; | |||||
errs() << '\n'; | |||||
} | |||||
void CFIInfoVerifier::applyAdjustments(MachineFunction &MF) { | |||||
for (auto &CurrMBB : MF) { | |||||
CurrMBB.setIncomingCFAOffset(CurrMBB.getIncomingCFAOffset() + | |||||
CurrMBB.getAdjustIncomingCFAOffset()); | |||||
CurrMBB.setOutgoingCFAOffset(CurrMBB.getOutgoingCFAOffset() + | |||||
CurrMBB.getAdjustOutgoingCFAOffset()); | |||||
} | |||||
} |