X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FVerifier.cpp;h=ffca88bfabc307a67c3f4ffc196f4298434698f4;hb=bb862c042fd773354645382ad0511b165b33116e;hp=c0a0dc6e6997a7fef361c9b4c686a157298fd917;hpb=19b6dcdfa9832fbdcf69ec6db4c12d256bd709e7;p=oota-llvm.git diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index c0a0dc6e699..ffca88bfabc 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -46,6 +46,7 @@ #include "llvm/Pass.h" #include "llvm/Module.h" #include "llvm/ModuleProvider.h" +#include "llvm/ParameterAttributes.h" #include "llvm/DerivedTypes.h" #include "llvm/InlineAsm.h" #include "llvm/Instructions.h" @@ -69,12 +70,13 @@ namespace { // Anonymous namespace for class struct VISIBILITY_HIDDEN Verifier : public FunctionPass, InstVisitor { + static char ID; // Pass ID, replacement for typeid 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. Module *Mod; // Module we are verifying right now - ETForest *EF; // ET-Forest, caution can be null! + DominatorTree *DT; // Dominator Tree, caution can be null! std::stringstream msgs; // A stringstream to collect messages /// InstInThisBlock - when verifying a basic block, keep track of all of the @@ -84,18 +86,22 @@ namespace { // Anonymous namespace for class SmallPtrSet InstsInThisBlock; Verifier() - : Broken(false), RealPass(true), action(AbortProcessAction), - EF(0), msgs( std::ios::app | std::ios::out ) {} + : FunctionPass((intptr_t)&ID), + Broken(false), RealPass(true), action(AbortProcessAction), + DT(0), msgs( std::ios::app | std::ios::out ) {} Verifier( VerifierFailureAction ctn ) - : Broken(false), RealPass(true), action(ctn), EF(0), - msgs( std::ios::app | std::ios::out ) {} + : FunctionPass((intptr_t)&ID), + Broken(false), RealPass(true), action(ctn), DT(0), + msgs( std::ios::app | std::ios::out ) {} Verifier(bool AB ) - : Broken(false), RealPass(true), - action( AB ? AbortProcessAction : PrintMessageAction), EF(0), - msgs( std::ios::app | std::ios::out ) {} - Verifier(ETForest &ef) - : Broken(false), RealPass(false), action(PrintMessageAction), - EF(&ef), msgs( std::ios::app | std::ios::out ) {} + : FunctionPass((intptr_t)&ID), + Broken(false), RealPass(true), + action( AB ? AbortProcessAction : PrintMessageAction), DT(0), + msgs( std::ios::app | std::ios::out ) {} + Verifier(DominatorTree &dt) + : FunctionPass((intptr_t)&ID), + Broken(false), RealPass(false), action(PrintMessageAction), + DT(&dt), msgs( std::ios::app | std::ios::out ) {} bool doInitialization(Module &M) { @@ -112,8 +118,10 @@ namespace { // Anonymous namespace for class bool runOnFunction(Function &F) { // Get dominator information if we are being run by PassManager - if (RealPass) EF = &getAnalysis(); - + if (RealPass) DT = &getAnalysis(); + + Mod = F.getParent(); + visit(F); InstsInThisBlock.clear(); @@ -139,6 +147,10 @@ namespace { // Anonymous namespace for class I != E; ++I) visitGlobalVariable(*I); + for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); + I != E; ++I) + visitGlobalAlias(*I); + // If the module is broken, abort at this time. return abortIfBroken(); } @@ -146,7 +158,7 @@ namespace { // Anonymous namespace for class virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); if (RealPass) - AU.addRequired(); + AU.addRequired(); } /// abortIfBroken - If the module is broken and we are supposed to abort on @@ -177,6 +189,7 @@ namespace { // Anonymous namespace for class void verifyTypeSymbolTable(TypeSymbolTable &ST); void visitGlobalValue(GlobalValue &GV); void visitGlobalVariable(GlobalVariable &GV); + void visitGlobalAlias(GlobalAlias &GA); void visitFunction(Function &F); void visitBasicBlock(BasicBlock &BB); void visitTruncInst(TruncInst &I); @@ -254,6 +267,7 @@ namespace { // Anonymous namespace for class } }; + char Verifier::ID = 0; RegisterPass X("verify", "Module Verifier"); } // End anonymous namespace @@ -275,7 +289,9 @@ void Verifier::visitGlobalValue(GlobalValue &GV) { Assert1(!GV.isDeclaration() || GV.hasExternalLinkage() || GV.hasDLLImportLinkage() || - GV.hasExternalWeakLinkage(), + GV.hasExternalWeakLinkage() || + (isa(GV) && + (GV.hasInternalLinkage() || GV.hasWeakLinkage())), "Global is external, but doesn't have external or dllimport or weak linkage!", &GV); @@ -301,6 +317,26 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) { visitGlobalValue(GV); } +void Verifier::visitGlobalAlias(GlobalAlias &GA) { + Assert1(!GA.getName().empty(), + "Alias name cannot be empty!", &GA); + Assert1(GA.hasExternalLinkage() || GA.hasInternalLinkage() || + GA.hasWeakLinkage(), + "Alias should have external or external weak linkage!", &GA); + Assert1(GA.getType() == GA.getAliasee()->getType(), + "Alias and aliasee types should match!", &GA); + + if (!isa(GA.getAliasee())) { + const ConstantExpr *CE = dyn_cast(GA.getAliasee()); + Assert1(CE && CE->getOpcode() == Instruction::BitCast && + isa(CE->getOperand(0)), + "Aliasee should be either GlobalValue or bitcast of GlobalValue", + &GA); + } + + visitGlobalValue(GA); +} + void Verifier::verifyTypeSymbolTable(TypeSymbolTable &ST) { } @@ -323,6 +359,45 @@ void Verifier::visitFunction(Function &F) { FT->getNumParams() > 0 && isa(FT->getParamType(0))), "Invalid struct-return function!", &F); + if (const ParamAttrsList *Attrs = FT->getParamAttrs()) { + unsigned Idx = 1; + + Assert1(!Attrs->paramHasAttr(0, ParamAttr::ByVal), + "Attribute ByVal should not apply to functions!", &F); + Assert1(!Attrs->paramHasAttr(0, ParamAttr::StructRet), + "Attribute SRet should not apply to functions!", &F); + Assert1(!Attrs->paramHasAttr(0, ParamAttr::InReg), + "Attribute InReg should not apply to functions!", &F); + + for (FunctionType::param_iterator I = FT->param_begin(), + E = FT->param_end(); I != E; ++I, ++Idx) { + if (Attrs->paramHasAttr(Idx, ParamAttr::ZExt) || + Attrs->paramHasAttr(Idx, ParamAttr::SExt)) + Assert1(FT->getParamType(Idx-1)->isInteger(), + "Attribute ZExt should only apply to Integer type!", &F); + if (Attrs->paramHasAttr(Idx, ParamAttr::NoAlias)) + Assert1(isa(FT->getParamType(Idx-1)), + "Attribute NoAlias should only apply to Pointer type!", &F); + if (Attrs->paramHasAttr(Idx, ParamAttr::ByVal)) { + Assert1(isa(FT->getParamType(Idx-1)), + "Attribute ByVal should only apply to pointer to structs!", &F); + + Assert1(!Attrs->paramHasAttr(Idx, ParamAttr::StructRet), + "Attributes ByVal and StructRet are incompatible!", &F); + + const PointerType *Ty = + cast(FT->getParamType(Idx-1)); + Assert1(isa(Ty->getElementType()), + "Attribute ByVal should only apply to pointer to structs!", &F); + } + + Assert1(!Attrs->paramHasAttr(Idx, ParamAttr::NoReturn), + "Attribute NoReturn should only be applied to function", &F); + Assert1(!Attrs->paramHasAttr(Idx, ParamAttr::NoUnwind), + "Attribute NoUnwind should only be applied to function", &F); + } + } + // Check that this function meets the restrictions on this calling convention. switch (F.getCallingConv()) { default: @@ -829,7 +904,7 @@ void Verifier::visitInstruction(Instruction &I) { for (Value::use_iterator UI = I.use_begin(), UE = I.use_end(); UI != UE; ++UI) Assert1(*UI != (User*)&I || - !EF->dominates(&BB->getParent()->getEntryBlock(), BB), + !DT->dominates(&BB->getParent()->getEntryBlock(), BB), "Only PHI nodes may reference their own value!", &I); } @@ -898,7 +973,7 @@ void Verifier::visitInstruction(Instruction &I) { // dominates all of it's predecessors (other than the invoke) or if // the invoke value is only used by a phi in the successor. if (!OpBlock->getSinglePredecessor() && - EF->dominates(&BB->getParent()->getEntryBlock(), BB)) { + DT->dominates(&BB->getParent()->getEntryBlock(), BB)) { // The first case we allow is if the use is a PHI operand in the // normal block, and if that PHI operand corresponds to the invoke's // block. @@ -915,7 +990,7 @@ void Verifier::visitInstruction(Instruction &I) { Bad = false; for (pred_iterator PI = pred_begin(OpBlock), E = pred_end(OpBlock); PI != E; ++PI) { - if (*PI != II->getParent() && !EF->dominates(OpBlock, *PI)) { + if (*PI != II->getParent() && !DT->dominates(OpBlock, *PI)) { Bad = true; break; } @@ -929,20 +1004,20 @@ void Verifier::visitInstruction(Instruction &I) { // If they are in the same basic block, make sure that the definition // comes before the use. Assert2(InstsInThisBlock.count(Op) || - !EF->dominates(&BB->getParent()->getEntryBlock(), BB), + !DT->dominates(&BB->getParent()->getEntryBlock(), BB), "Instruction does not dominate all uses!", Op, &I); } // Definition must dominate use unless use is unreachable! - Assert2(EF->dominates(OpBlock, BB) || - !EF->dominates(&BB->getParent()->getEntryBlock(), BB), + Assert2(DT->dominates(OpBlock, BB) || + !DT->dominates(&BB->getParent()->getEntryBlock(), BB), "Instruction does not dominate all uses!", Op, &I); } else { // PHI nodes are more difficult than other nodes because they actually // "use" the value in the predecessor basic blocks they correspond to. BasicBlock *PredBB = cast(I.getOperand(i+1)); - Assert2(EF->dominates(OpBlock, PredBB) || - !EF->dominates(&BB->getParent()->getEntryBlock(), PredBB), + Assert2(DT->dominates(OpBlock, PredBB) || + !DT->dominates(&BB->getParent()->getEntryBlock(), PredBB), "Instruction does not dominate all uses!", Op, &I); } } else if (isa(I.getOperand(i))) { @@ -1047,7 +1122,7 @@ void Verifier::VerifyIntrinsicPrototype(Intrinsic::ID ID, Function *F, ...) { break; } } else if (TypeID == Type::VectorTyID) { - // If this is a packed argument, verify the number and type of elements. + // If this is a vector argument, verify the number and type of elements. const VectorType *PTy = cast(Ty); int ElemTy = va_arg(VA, int); if (ElemTy != PTy->getElementType()->getTypeID()) {