From 536a9d5ea54087f72a8f1e9f9b4c5fec80b3844b Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 31 Mar 2006 04:46:47 +0000 Subject: [PATCH] Add a new method to verify intrinsic function prototypes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27282 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/VMCore/Verifier.cpp | 62 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 0db7145421a..f6fd236bd16 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -55,6 +55,7 @@ #include "llvm/Analysis/Dominators.h" #include "llvm/Support/CFG.h" #include "llvm/Support/InstVisitor.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" #include #include @@ -196,6 +197,7 @@ namespace { // Anonymous namespace for class void visitUserOp2(Instruction &I) { visitUserOp1(I); } void visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI); + void VerifyIntrinsicPrototype(Function *F, ...); void WriteValue(const Value *V) { if (!V) return; @@ -436,8 +438,7 @@ void Verifier::visitSelectInst(SelectInst &SI) { /// a pass, if any exist, it's an error. /// void Verifier::visitUserOp1(Instruction &I) { - Assert1(0, "User-defined operators should not live outside of a pass!", - &I); + Assert1(0, "User-defined operators should not live outside of a pass!", &I); } /// visitPHINode - Ensure that a PHI node is well formed. @@ -684,6 +685,63 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { #undef GET_INTRINSIC_VERIFIER } +/// VerifyIntrinsicPrototype - TableGen emits calls to this function into +/// Intrinsics.gen. This implements a little state machine that verifies the +/// prototype of intrinsics. +void Verifier::VerifyIntrinsicPrototype(Function *F, ...) { + va_list VA; + va_start(VA, F); + + const FunctionType *FTy = F->getFunctionType(); + + // Note that "arg#0" is the return type. + for (unsigned ArgNo = 0; 1; ++ArgNo) { + int TypeID = va_arg(VA, int); + + if (TypeID == -1) { + if (ArgNo != FTy->getNumParams()+1) + CheckFailed("Intrinsic prototype has too many arguments!", F); + break; + } + + if (ArgNo == FTy->getNumParams()+1) { + CheckFailed("Intrinsic prototype has too few arguments!", F); + break; + } + + const Type *Ty; + if (ArgNo == 0) + Ty = FTy->getReturnType(); + else + Ty = FTy->getParamType(ArgNo-1); + + if (Ty->getTypeID() != TypeID) { + if (ArgNo == 0) + CheckFailed("Intrinsic prototype has incorrect result type!", F); + else + CheckFailed("Intrinsic parameter #" + utostr(ArgNo-1) + " is wrong!",F); + break; + } + + // If this is a packed argument, verify the number and type of elements. + if (TypeID == Type::PackedTyID) { + const PackedType *PTy = cast(Ty); + if (va_arg(VA, int) != PTy->getElementType()->getTypeID()) { + CheckFailed("Intrinsic prototype has incorrect vector element type!",F); + break; + } + + if ((unsigned)va_arg(VA, int) != PTy->getNumElements()) { + CheckFailed("Intrinsic prototype has incorrect number of " + "vector elements!",F); + break; + } + } + } + + va_end(VA); +} + //===----------------------------------------------------------------------===// // Implement the public interfaces to this file... -- 2.34.1