diff options
author | Duncan Sands <baldrick@free.fr> | 2007-07-27 15:09:54 +0000 |
---|---|---|
committer | Duncan Sands <baldrick@free.fr> | 2007-07-27 15:09:54 +0000 |
commit | fdef00f1f7da225ad5d21f3148487e3547954a0c (patch) | |
tree | 2af2e0d7c9c69a5d9ba5df6a6f6d2b9c840e2dd5 /lib/VMCore | |
parent | 36397f50343639ce9a25996f2d790c656791ab92 (diff) | |
download | external_llvm-fdef00f1f7da225ad5d21f3148487e3547954a0c.zip external_llvm-fdef00f1f7da225ad5d21f3148487e3547954a0c.tar.gz external_llvm-fdef00f1f7da225ad5d21f3148487e3547954a0c.tar.bz2 |
As the number of parameter attributes increases,
Verifier::visitFunction is suffering a combinatorial
explosion due to the number of mutually incompatible
attributes. This patch tidies the whole thing up
using attribute masks. While there I fixed some
small bugs: (1) the ByVal attribute tests cast a
type to a pointer type, which can fail. Yes, the
fact it is of a pointer type is checked before,
but a failing check does not cause the program
to exit, it continues on outputting further errors;
(2) Nothing was checking that an sret attribute is
on the first parameter; (3) nothing was checking that
a function for which isStructReturn() is true has a
parameter with the sret attribute and vice-versa (I
don't think it is possible for this to go wrong, but
it seems right to check it).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@40553 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/VMCore')
-rw-r--r-- | lib/VMCore/Verifier.cpp | 94 |
1 files changed, 55 insertions, 39 deletions
diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index de4050d..7dc4647 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -354,67 +354,83 @@ void Verifier::visitFunction(Function &F) { F.getReturnType() == Type::VoidTy, "Functions cannot return aggregate values!", &F); - Assert1(!FT->isStructReturn() || - (FT->getReturnType() == Type::VoidTy && - FT->getNumParams() > 0 && isa<PointerType>(FT->getParamType(0))), + Assert1(!FT->isStructReturn() || FT->getReturnType() == Type::VoidTy, "Invalid struct-return function!", &F); + const uint16_t ReturnIncompatible = + ParamAttr::ByVal | ParamAttr::InReg | + ParamAttr::Nest | ParamAttr::StructRet; + + const uint16_t ParameterIncompatible = + ParamAttr::NoReturn | ParamAttr::NoUnwind; + + const uint16_t MutuallyIncompatible = + ParamAttr::ByVal | ParamAttr::Nest | ParamAttr::StructRet; + + const uint16_t IntegerTypeOnly = + ParamAttr::SExt | ParamAttr::ZExt; + + const uint16_t PointerTypeOnly = + ParamAttr::ByVal | ParamAttr::Nest | + ParamAttr::NoAlias | ParamAttr::StructRet; + + bool SawSRet = false; + if (const ParamAttrsList *Attrs = FT->getParamAttrs()) { unsigned Idx = 1; bool SawNest = false; - 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); - Assert1(!Attrs->paramHasAttr(0, ParamAttr::Nest), - "Attribute Nest should not apply to functions!", &F); + uint16_t RetI = Attrs->getParamAttrs(0) & ReturnIncompatible; + Assert1(!RetI, "Attribute " + Attrs->getParamAttrsText(RetI) + + "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<PointerType>(FT->getParamType(Idx-1)), - "Attribute NoAlias should only apply to Pointer type!", &F); - if (Attrs->paramHasAttr(Idx, ParamAttr::ByVal)) { - Assert1(isa<PointerType>(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); + uint16_t Attr = Attrs->getParamAttrs(Idx); + + uint16_t ParmI = Attr & ParameterIncompatible; + Assert1(!ParmI, "Attribute " + Attrs->getParamAttrsText(ParmI) + + "should only be applied to function!", &F); + uint16_t MutI = Attr & MutuallyIncompatible; + Assert1(!(MutI & (MutI - 1)), "Attributes " + + Attrs->getParamAttrsText(MutI) + "are incompatible!", &F); + + uint16_t IType = Attr & IntegerTypeOnly; + Assert1(!IType || FT->getParamType(Idx-1)->isInteger(), + "Attribute " + Attrs->getParamAttrsText(IType) + + "should only apply to Integer type!", &F); + + uint16_t PType = Attr & PointerTypeOnly; + Assert1(!PType || isa<PointerType>(FT->getParamType(Idx-1)), + "Attribute " + Attrs->getParamAttrsText(PType) + + "should only apply to Pointer type!", &F); + + if (Attrs->paramHasAttr(Idx, ParamAttr::ByVal)) { const PointerType *Ty = - cast<PointerType>(FT->getParamType(Idx-1)); - Assert1(isa<StructType>(Ty->getElementType()), - "Attribute ByVal should only apply to pointer to structs!", &F); + dyn_cast<PointerType>(FT->getParamType(Idx-1)); + Assert1(!Ty || isa<StructType>(Ty->getElementType()), + "Attribute byval should only apply to pointer to structs!", &F); } if (Attrs->paramHasAttr(Idx, ParamAttr::Nest)) { - Assert1(!SawNest, "More than one parameter has attribute Nest!", &F); + Assert1(!SawNest, "More than one parameter has attribute nest!", &F); SawNest = true; - - Assert1(isa<PointerType>(FT->getParamType(Idx-1)), - "Attribute Nest should only apply to Pointer type!", &F); - Assert1(!Attrs->paramHasAttr(Idx, ParamAttr::ByVal), - "Attributes Nest and ByVal are incompatible!", &F); Assert1(!Attrs->paramHasAttr(Idx, ParamAttr::InReg), - "Attributes Nest and InReg are incompatible!", &F); - Assert1(!Attrs->paramHasAttr(Idx, ParamAttr::StructRet), - "Attributes Nest and StructRet are incompatible!", &F); + "Attributes nest and inreg are incompatible!", &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); + if (Attrs->paramHasAttr(Idx, ParamAttr::StructRet)) { + SawSRet = true; + Assert1(Idx == 1, "Attribute sret not on first parameter!", &F); + } } } + Assert1(SawSRet == FT->isStructReturn(), + "StructReturn function with no sret attribute!", &F); + // Check that this function meets the restrictions on this calling convention. switch (F.getCallingConv()) { default: |