diff --git a/include/llvm/ParameterAttributes.h b/include/llvm/ParameterAttributes.h index 79b5d0c2a61..29bbd23abc1 100644 --- a/include/llvm/ParameterAttributes.h +++ b/include/llvm/ParameterAttributes.h @@ -130,13 +130,24 @@ class ParamAttrsList : public FoldingSetNode { : attrs(attrVec), refCount(0) {} public: - /// This method ensures the uniqueness of ParamAttrsList instances. The + /// This method ensures the uniqueness of ParamAttrsList instances. The /// argument is a vector of attribute/index pairs as represented by the - /// ParamAttrsWithIndex structure. The vector is used in the construction of - /// the ParamAttrsList instance. If an instance with identical vector pairs - /// exists, it will be returned instead of creating a new instance. + /// ParamAttrsWithIndex structure. The index values must be in strictly + /// increasing order and ParamAttr::None is not allowed. The vector is + /// used to construct the ParamAttrsList instance. If an instance with + /// identical vector pairs exists, it will be returned instead of creating + /// a new instance. /// @brief Get a ParamAttrsList instance. - static ParamAttrsList *get(const ParamAttrsVector &attrVec); + static const ParamAttrsList *get(const ParamAttrsVector &attrVec); + + /// Returns the ParamAttrsList obtained by modifying PAL using the supplied + /// list of attribute/index pairs. Any existing attributes for the given + /// index are replaced by the given attributes. If there were no attributes + /// then the new ones are inserted. Attributes can be deleted by replacing + /// them with ParamAttr::None. Index values must be strictly increasing. + /// @brief Get a new ParamAttrsList instance by modifying an existing one. + static const ParamAttrsList *getModified(const ParamAttrsList *PAL, + const ParamAttrsVector &modVec); /// Returns whether each of the specified lists of attributes can be safely /// replaced with the other in a function or a function call. diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index 683b95b8fba..31fd6190827 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -2243,7 +2243,7 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')' bool isVarArg = ParamTypeList.size() && ParamTypeList.back() == Type::VoidTy; if (isVarArg) ParamTypeList.pop_back(); - ParamAttrsList *PAL = 0; + const ParamAttrsList *PAL = 0; if (!Attrs.empty()) PAL = ParamAttrsList::get(Attrs); @@ -2645,7 +2645,7 @@ BBTerminatorInst : RET ResolvedVal { // Return with a result... GEN_ERROR("Invalid number of parameters detected"); } - ParamAttrsList *PAL = 0; + const ParamAttrsList *PAL = 0; if (!Attrs.empty()) PAL = ParamAttrsList::get(Attrs); @@ -2977,7 +2977,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef { } // Finish off the ParamAttrs and check them - ParamAttrsList *PAL = 0; + const ParamAttrsList *PAL = 0; if (!Attrs.empty()) PAL = ParamAttrsList::get(Attrs); diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index 92853e30f9b..16728f6a0ca 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -167,7 +167,7 @@ ParamAttrsList::Profile(FoldingSetNodeID &ID) const { static ManagedStatic > ParamAttrsLists; -ParamAttrsList * +const ParamAttrsList * ParamAttrsList::get(const ParamAttrsVector &attrVec) { // If there are no attributes then return a null ParamAttrsList pointer. if (attrVec.empty()) @@ -200,6 +200,64 @@ ParamAttrsList::get(const ParamAttrsVector &attrVec) { return PAL; } +const ParamAttrsList * +ParamAttrsList::getModified(const ParamAttrsList *PAL, + const ParamAttrsVector &modVec) { + if (modVec.empty()) + return PAL; + +#ifndef NDEBUG + for (unsigned i = 0, e = modVec.size(); i < e; ++i) + assert((!i || modVec[i-1].index < modVec[i].index) + && "Misordered ParamAttrsList!"); +#endif + + if (!PAL) { + // Strip any instances of ParamAttr::None from modVec before calling 'get'. + ParamAttrsVector newVec; + for (unsigned i = 0, e = modVec.size(); i < e; ++i) + if (modVec[i].attrs != ParamAttr::None) + newVec.push_back(modVec[i]); + return get(newVec); + } + + const ParamAttrsVector &oldVec = PAL->attrs; + + ParamAttrsVector newVec; + unsigned oldI = 0; + unsigned modI = 0; + unsigned oldE = oldVec.size(); + unsigned modE = modVec.size(); + + while (oldI < oldE && modI < modE) { + uint16_t oldIndex = oldVec[oldI].index; + uint16_t modIndex = modVec[modI].index; + + if (oldIndex < modIndex) { + newVec.push_back(oldVec[oldI]); + ++oldI; + } else if (modIndex < oldIndex) { + if (modVec[modI].attrs != ParamAttr::None) + newVec.push_back(modVec[modI]); + ++modI; + } else { + // Same index - overwrite or delete existing attributes. + if (modVec[modI].attrs != ParamAttr::None) + newVec.push_back(modVec[modI]); + ++oldI; + ++modI; + } + } + + for (; oldI < oldE; ++oldI) + newVec.push_back(oldVec[oldI]); + for (; modI < modE; ++modI) + if (modVec[modI].attrs != ParamAttr::None) + newVec.push_back(modVec[modI]); + + return get(newVec); +} + ParamAttrsList::~ParamAttrsList() { ParamAttrsLists->RemoveNode(this); } diff --git a/tools/llvm-upgrade/UpgradeParser.y b/tools/llvm-upgrade/UpgradeParser.y index b9a26cb9572..7a6e3efc7b0 100644 --- a/tools/llvm-upgrade/UpgradeParser.y +++ b/tools/llvm-upgrade/UpgradeParser.y @@ -2055,7 +2055,7 @@ UpRTypes bool isVarArg = Params.size() && Params.back() == Type::VoidTy; if (isVarArg) Params.pop_back(); - ParamAttrsList *PAL = 0; + const ParamAttrsList *PAL = 0; if (lastCallingConv == OldCallingConv::CSRet) { ParamAttrsVector Attrs; ParamAttrsWithIndex PAWI;