bool Broken; // Is this module found to be broken?
bool RealPass; // Are we not being run by a PassManager?
VerifierFailureAction action;
- // What to do if verification fails.
+ // What to do if verification fails.
Module *Mod; // Module we are verifying right now
DominatorSet *DS; // Dominator set, caution can be null!
std::stringstream msgs; // A stringstream to collect messages
Verifier()
- : Broken(false), RealPass(true), action(AbortProcessAction),
+ : Broken(false), RealPass(true), action(AbortProcessAction),
DS(0), msgs( std::ios_base::app | std::ios_base::out ) {}
Verifier( VerifierFailureAction ctn )
- : Broken(false), RealPass(true), action(ctn), DS(0),
+ : Broken(false), RealPass(true), action(ctn), DS(0),
msgs( std::ios_base::app | std::ios_base::out ) {}
Verifier(bool AB )
- : Broken(false), RealPass(true),
+ : Broken(false), RealPass(true),
action( AB ? AbortProcessAction : PrintMessageAction), DS(0),
- msgs( std::ios_base::app | std::ios_base::out ) {}
+ msgs( std::ios_base::app | std::ios_base::out ) {}
Verifier(DominatorSet &ds)
: Broken(false), RealPass(false), action(PrintMessageAction),
DS(&ds), msgs( std::ios_base::app | std::ios_base::out ) {}
if (Broken)
{
msgs << "Broken module found, ";
- switch (action)
- {
- case AbortProcessAction:
- msgs << "compilation aborted!\n";
- std::cerr << msgs.str();
- abort();
- case ThrowExceptionAction:
- msgs << "verification terminated.\n";
- throw msgs.str();
- case PrintMessageAction:
- msgs << "verification continues.\n";
- std::cerr << msgs.str();
- break;
- case ReturnStatusAction:
- break;
- }
+ switch (action)
+ {
+ case AbortProcessAction:
+ msgs << "compilation aborted!\n";
+ std::cerr << msgs.str();
+ abort();
+ case ThrowExceptionAction:
+ msgs << "verification terminated.\n";
+ throw msgs.str();
+ case PrintMessageAction:
+ msgs << "verification continues.\n";
+ std::cerr << msgs.str();
+ break;
+ case ReturnStatusAction:
+ break;
+ }
}
}
void visitInstruction(Instruction &I);
void visitTerminatorInst(TerminatorInst &I);
void visitReturnInst(ReturnInst &RI);
+ void visitSwitchInst(SwitchInst &SI);
void visitSelectInst(SelectInst &SI);
void visitUserOp1(Instruction &I);
void visitUserOp2(Instruction &I) { visitUserOp1(I); }
if (!V) return;
if (isa<Instruction>(V)) {
msgs << *V;
- } else if (const Type *Ty = dyn_cast<Type>(V)) {
- WriteTypeSymbolic(msgs, Ty, Mod);
} else {
WriteAsOperand (msgs, V, true, true, Mod);
msgs << "\n";
}
}
+ void WriteType(const Type* T ) {
+ if ( !T ) return;
+ WriteTypeSymbolic(msgs, T, Mod );
+ }
+
// CheckFailed - A check failed, so print out the condition and the message
// that failed. This provides a nice place to put a breakpoint if you want
WriteValue(V4);
Broken = true;
}
+
+ void CheckFailed( const std::string& Message, const Value* V1,
+ const Type* T2, const Value* V3 = 0 ) {
+ msgs << Message << "\n";
+ WriteValue(V1);
+ WriteType(T2);
+ WriteValue(V3);
+ }
};
RegisterOpt<Verifier> X("verify", "Module Verifier");
// verifySymbolTable - Verify that a function or module symbol table is ok
//
void Verifier::verifySymbolTable(SymbolTable &ST) {
- // Loop over all of the types in the symbol table...
- for (SymbolTable::iterator TI = ST.begin(), TE = ST.end(); TI != TE; ++TI)
- for (SymbolTable::type_iterator I = TI->second.begin(),
- E = TI->second.end(); I != E; ++I) {
- Value *V = I->second;
+ // Loop over all of the values in all type planes in the symbol table.
+ for (SymbolTable::plane_const_iterator PI = ST.plane_begin(),
+ PE = ST.plane_end(); PI != PE; ++PI)
+ for (SymbolTable::value_const_iterator VI = PI->second.begin(),
+ VE = PI->second.end(); VI != VE; ++VI) {
+ Value *V = VI->second;
// Check that there are no void typed values in the symbol table. Values
// with a void type cannot be put into symbol tables because they cannot
// have names!
Assert1(V->getType() != Type::VoidTy,
- "Values with void type are not allowed to have names!", V);
+ "Values with void type are not allowed to have names!", V);
}
}
-
// visitFunction - Verify that a function is ok.
//
void Verifier::visitFunction(Function &F) {
Assert1(PN->getNumIncomingValues() != 0,
"PHI nodes must have at least one entry. If the block is dead, "
"the PHI should be removed!", PN);
- Assert1(PN->getNumIncomingValues() >= Preds.size(),
- "PHINode has more entries than the basic block has predecessors!",
- PN);
- Assert1(PN->getNumIncomingValues() <= Preds.size(),
- "PHINode has less entries than the basic block has predecessors!",
- PN);
+ Assert1(PN->getNumIncomingValues() == Preds.size(),
+ "PHINode should have one entry for each predecessor of its "
+ "parent basic block!", PN);
// Get and sort all incoming values in the PHI node...
std::vector<std::pair<BasicBlock*, Value*> > Values;
visitTerminatorInst(RI);
}
+void Verifier::visitSwitchInst(SwitchInst &SI) {
+ // Check to make sure that all of the constants in the switch instruction
+ // have the same type as the switched-on value.
+ const Type *SwitchTy = SI.getCondition()->getType();
+ for (unsigned i = 1, e = SI.getNumCases(); i != e; ++i)
+ Assert1(SI.getCaseValue(i)->getType() == SwitchTy,
+ "Switch constants must all be same type as switch value!", &SI);
+
+ visitTerminatorInst(SI);
+}
+
void Verifier::visitSelectInst(SelectInst &SI) {
Assert1(SI.getCondition()->getType() == Type::BoolTy,
"Select condition type must be bool!", &SI);
// exceptional destination.
if (InvokeInst *II = dyn_cast<InvokeInst>(Op))
OpBlock = II->getNormalDest();
+ else if (OpBlock == BB) {
+ // If they are in the same basic block, make sure that the definition
+ // comes before the use.
+ Assert2(DS->dominates(Op, &I),
+ "Instruction does not dominate all uses!", Op, &I);
+ }
// Definition must dominate use unless use is unreachable!
Assert2(DS->dominates(OpBlock, BB) ||
NumArgs = 1;
break;
- case Intrinsic:: readio: {
- const Type * ParamType = FT->getParamType(0);
- const Type * ReturnType = FT->getReturnType();
+ case Intrinsic::readio: {
+ const PointerType *ParamType = dyn_cast<PointerType>(FT->getParamType(0));
+ const Type *ReturnType = FT->getReturnType();
Assert1(FT->getNumParams() == 1,
"Illegal # arguments for intrinsic function!", IF);
- Assert1(ReturnType->isFirstClassType(),
- "Return type is not a first class type!", IF);
- Assert1(ParamType->getPrimitiveID() == Type::PointerTyID,
- "First argument not a pointer!", IF);
- Assert1(((dyn_cast<PointerType>(ParamType)->getContainedType(0)) == ReturnType), "Pointer type doesn't match return type!", IF);
+ Assert1(ParamType, "First argument not a pointer!", IF);
+ Assert1(ParamType->getElementType() == ReturnType,
+ "Pointer type doesn't match return type!", IF);
NumArgs = 1;
break;
}
case Intrinsic::sigsetjmp: NumArgs = 2; break;
case Intrinsic::siglongjmp: NumArgs = 2; break;
+ case Intrinsic::gcroot:
+ Assert1(FT->getNumParams() == 2,
+ "Illegal # arguments for intrinsic function!", IF);
+ Assert1(isa<Constant>(CI.getOperand(2)) ||
+ isa<GlobalValue>(CI.getOperand(2)),
+ "Second argument to llvm.gcroot must be a constant!", &CI);
+ NumArgs = 2;
+ break;
+ case Intrinsic::gcread: NumArgs = 1; break;
+ case Intrinsic::gcwrite: NumArgs = 2; break;
+
case Intrinsic::dbg_stoppoint: NumArgs = 4; break;
case Intrinsic::dbg_region_start:NumArgs = 1; break;
case Intrinsic::dbg_region_end: NumArgs = 1; break;
PM.run((Module&)M);
return V->Broken;
}
+
+// vim: sw=2