diff options
author | Chris Lattner <sabre@nondot.org> | 2008-01-02 23:42:30 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-01-02 23:42:30 +0000 |
commit | 50ee9ddc8f0633af6cb0a5693a2c706e98f944da (patch) | |
tree | e9d758370876a5e6235f5f0ac307f9b5d598c1cb | |
parent | a114b14e5dd1869b8dfcf79736fe05a3616b520a (diff) |
Split param attr implementation out from Function.cpp into its
own file. Don't #include ParameterAttributes.h into any major
public header files: just move methods out of line as appropriate.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45517 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/Function.h | 27 | ||||
-rw-r--r-- | include/llvm/Instructions.h | 51 | ||||
-rw-r--r-- | include/llvm/ParameterAttributes.h | 2 | ||||
-rw-r--r-- | include/llvm/Support/CallSite.h | 3 | ||||
-rw-r--r-- | lib/VMCore/Function.cpp | 247 | ||||
-rw-r--r-- | lib/VMCore/Instructions.cpp | 75 | ||||
-rw-r--r-- | lib/VMCore/ParameterAttributes.cpp | 226 |
7 files changed, 349 insertions, 282 deletions
diff --git a/include/llvm/Function.h b/include/llvm/Function.h index d68d5133dc..31ee6d7544 100644 --- a/include/llvm/Function.h +++ b/include/llvm/Function.h @@ -21,7 +21,6 @@ #include "llvm/GlobalValue.h" #include "llvm/BasicBlock.h" #include "llvm/Argument.h" -#include "llvm/ParameterAttributes.h" #include "llvm/Support/Annotation.h" namespace llvm { @@ -161,34 +160,22 @@ public: void clearCollector(); /// @brief Determine whether the function has the given attribute. - bool paramHasAttr(uint16_t i, ParameterAttributes attr) const { - return ParamAttrs && ParamAttrs->paramHasAttr(i, attr); - } - + bool paramHasAttr(uint16_t i, unsigned attr) const; + /// @brief Determine if the function cannot return. - bool doesNotReturn() const { - return paramHasAttr(0, ParamAttr::NoReturn); - } + bool doesNotReturn() const; /// @brief Determine if the function cannot unwind. - bool doesNotThrow() const { - return paramHasAttr(0, ParamAttr::NoUnwind); - } + bool doesNotThrow() const; /// @brief Determine if the function does not access memory. - bool doesNotAccessMemory() const { - return paramHasAttr(0, ParamAttr::ReadNone); - } + bool doesNotAccessMemory() const; /// @brief Determine if the function does not access or only reads memory. - bool onlyReadsMemory() const { - return doesNotAccessMemory() || paramHasAttr(0, ParamAttr::ReadOnly); - } + bool onlyReadsMemory() const; /// @brief Determine if the function returns a structure. - bool isStructReturn() const { - return paramHasAttr(1, ParamAttr::StructRet); - } + bool isStructReturn() const; /// deleteBody - This method deletes the body of the function, and converts /// the linkage to external. diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index 8b86792a44..1594a0ace6 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -20,7 +20,6 @@ #include "llvm/InstrTypes.h" #include "llvm/DerivedTypes.h" -#include "llvm/ParameterAttributes.h" namespace llvm { @@ -927,34 +926,23 @@ public: void setParamAttrs(const ParamAttrsList *attrs); /// @brief Determine whether the call or the callee has the given attribute. - bool paramHasAttr(uint16_t i, ParameterAttributes attr) const; + bool paramHasAttr(uint16_t i, unsigned attr) const; /// @brief Determine if the call does not access memory. - bool doesNotAccessMemory() const { - return paramHasAttr(0, ParamAttr::ReadNone); - } - + bool doesNotAccessMemory() const; + /// @brief Determine if the call does not access or only reads memory. - bool onlyReadsMemory() const { - return doesNotAccessMemory() || paramHasAttr(0, ParamAttr::ReadOnly); - } - + bool onlyReadsMemory() const; + /// @brief Determine if the call cannot return. - bool doesNotReturn() const { - return paramHasAttr(0, ParamAttr::NoReturn); - } + bool doesNotReturn() const; /// @brief Determine if the call cannot unwind. - bool doesNotThrow() const { - return paramHasAttr(0, ParamAttr::NoUnwind); - } + bool doesNotThrow() const; void setDoesNotThrow(bool doesNotThrow = true); /// @brief Determine if the call returns a structure. - bool isStructReturn() const { - // Be friendly and also check the callee. - return paramHasAttr(1, ParamAttr::StructRet); - } + bool isStructReturn() const; /// getCalledFunction - Return the function being called by this instruction /// if it is a direct call. If it is a call through a function pointer, @@ -1732,34 +1720,23 @@ public: void setParamAttrs(const ParamAttrsList *attrs); /// @brief Determine whether the call or the callee has the given attribute. - bool paramHasAttr(uint16_t i, ParameterAttributes attr) const; + bool paramHasAttr(uint16_t i, unsigned attr) const; /// @brief Determine if the call does not access memory. - bool doesNotAccessMemory() const { - return paramHasAttr(0, ParamAttr::ReadNone); - } + bool doesNotAccessMemory() const; /// @brief Determine if the call does not access or only reads memory. - bool onlyReadsMemory() const { - return doesNotAccessMemory() || paramHasAttr(0, ParamAttr::ReadOnly); - } + bool onlyReadsMemory() const; /// @brief Determine if the call cannot return. - bool doesNotReturn() const { - return paramHasAttr(0, ParamAttr::NoReturn); - } + bool doesNotReturn() const; /// @brief Determine if the call cannot unwind. - bool doesNotThrow() const { - return paramHasAttr(0, ParamAttr::NoUnwind); - } + bool doesNotThrow() const; void setDoesNotThrow(bool doesNotThrow = true); /// @brief Determine if the call returns a structure. - bool isStructReturn() const { - // Be friendly and also check the callee. - return paramHasAttr(1, ParamAttr::StructRet); - } + bool isStructReturn() const; /// getCalledFunction - Return the function called, or null if this is an /// indirect function invocation. diff --git a/include/llvm/ParameterAttributes.h b/include/llvm/ParameterAttributes.h index caeb556a3f..080de46935 100644 --- a/include/llvm/ParameterAttributes.h +++ b/include/llvm/ParameterAttributes.h @@ -73,7 +73,7 @@ const uint16_t MutuallyIncompatible[3] = { ReadNone | ReadOnly }; -} +} // end namespace ParamAttr /// This is just a pair of values to associate a set of parameter attributes /// with a parameter index. diff --git a/include/llvm/Support/CallSite.h b/include/llvm/Support/CallSite.h index eb678ed0f0..f7d8db6086 100644 --- a/include/llvm/Support/CallSite.h +++ b/include/llvm/Support/CallSite.h @@ -22,7 +22,6 @@ #include "llvm/Instruction.h" #include "llvm/BasicBlock.h" -#include "llvm/ParameterAttributes.h" namespace llvm { @@ -65,7 +64,7 @@ public: void setParamAttrs(const ParamAttrsList *PAL); /// paramHasAttr - whether the call or the callee has the given attribute. - bool paramHasAttr(uint16_t i, ParameterAttributes attr) const; + bool paramHasAttr(uint16_t i, unsigned attr) const; /// @brief Determine if the call does not access memory. bool doesNotAccessMemory() const; diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index f3169e1c54..b9a139d75b 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -14,9 +14,9 @@ #include "llvm/Module.h" #include "llvm/DerivedTypes.h" #include "llvm/IntrinsicInst.h" +#include "llvm/ParameterAttributes.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/Support/LeakDetector.h" -#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/StringPool.h" #include "SymbolTableListTraitsImpl.h" #include "llvm/ADT/BitVector.h" @@ -76,216 +76,57 @@ void Argument::setParent(Function *parent) { } //===----------------------------------------------------------------------===// -// ParamAttrsList Implementation +// Helper Methods in Function //===----------------------------------------------------------------------===// -uint16_t -ParamAttrsList::getParamAttrs(uint16_t Index) const { - unsigned limit = attrs.size(); - for (unsigned i = 0; i < limit && attrs[i].index <= Index; ++i) - if (attrs[i].index == Index) - return attrs[i].attrs; - return ParamAttr::None; -} - -std::string -ParamAttrsList::getParamAttrsText(uint16_t Attrs) { - std::string Result; - if (Attrs & ParamAttr::ZExt) - Result += "zeroext "; - if (Attrs & ParamAttr::SExt) - Result += "signext "; - if (Attrs & ParamAttr::NoReturn) - Result += "noreturn "; - if (Attrs & ParamAttr::NoUnwind) - Result += "nounwind "; - if (Attrs & ParamAttr::InReg) - Result += "inreg "; - if (Attrs & ParamAttr::NoAlias) - Result += "noalias "; - if (Attrs & ParamAttr::StructRet) - Result += "sret "; - if (Attrs & ParamAttr::ByVal) - Result += "byval "; - if (Attrs & ParamAttr::Nest) - Result += "nest "; - if (Attrs & ParamAttr::ReadNone) - Result += "readnone "; - if (Attrs & ParamAttr::ReadOnly) - Result += "readonly "; - return Result; +const FunctionType *Function::getFunctionType() const { + return cast<FunctionType>(getType()->getElementType()); } -/// onlyInformative - Returns whether only informative attributes are set. -static inline bool onlyInformative(uint16_t attrs) { - return !(attrs & ~ParamAttr::Informative); -} - -bool -ParamAttrsList::areCompatible(const ParamAttrsList *A, const ParamAttrsList *B){ - if (A == B) - return true; - unsigned ASize = A ? A->size() : 0; - unsigned BSize = B ? B->size() : 0; - unsigned AIndex = 0; - unsigned BIndex = 0; - - while (AIndex < ASize && BIndex < BSize) { - uint16_t AIdx = A->getParamIndex(AIndex); - uint16_t BIdx = B->getParamIndex(BIndex); - uint16_t AAttrs = A->getParamAttrsAtIndex(AIndex); - uint16_t BAttrs = B->getParamAttrsAtIndex(AIndex); - - if (AIdx < BIdx) { - if (!onlyInformative(AAttrs)) - return false; - ++AIndex; - } else if (BIdx < AIdx) { - if (!onlyInformative(BAttrs)) - return false; - ++BIndex; - } else { - if (!onlyInformative(AAttrs ^ BAttrs)) - return false; - ++AIndex; - ++BIndex; - } - } - for (; AIndex < ASize; ++AIndex) - if (!onlyInformative(A->getParamAttrsAtIndex(AIndex))) - return false; - for (; BIndex < BSize; ++BIndex) - if (!onlyInformative(B->getParamAttrsAtIndex(AIndex))) - return false; - return true; +bool Function::isVarArg() const { + return getFunctionType()->isVarArg(); } -void ParamAttrsList::Profile(FoldingSetNodeID &ID) const { - for (unsigned i = 0; i < attrs.size(); ++i) - ID.AddInteger(unsigned(attrs[i].attrs) << 16 | unsigned(attrs[i].index)); +const Type *Function::getReturnType() const { + return getFunctionType()->getReturnType(); } -static ManagedStatic<FoldingSet<ParamAttrsList> > ParamAttrsLists; - -const ParamAttrsList * -ParamAttrsList::get(const ParamAttrsVector &attrVec) { - // If there are no attributes then return a null ParamAttrsList pointer. - if (attrVec.empty()) - return 0; - -#ifndef NDEBUG - for (unsigned i = 0, e = attrVec.size(); i < e; ++i) { - assert(attrVec[i].attrs != ParamAttr::None - && "Pointless parameter attribute!"); - assert((!i || attrVec[i-1].index < attrVec[i].index) - && "Misordered ParamAttrsList!"); - } -#endif - - // Otherwise, build a key to look up the existing attributes. - ParamAttrsList key(attrVec); - FoldingSetNodeID ID; - key.Profile(ID); - void *InsertPos; - ParamAttrsList* PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos); - - // If we didn't find any existing attributes of the same shape then - // create a new one and insert it. - if (!PAL) { - PAL = new ParamAttrsList(attrVec); - ParamAttrsLists->InsertNode(PAL, InsertPos); - } - - // Return the ParamAttrsList that we found or created. - 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; - } - } +void Function::removeFromParent() { + getParent()->getFunctionList().remove(this); +} - for (; oldI < oldE; ++oldI) - newVec.push_back(oldVec[oldI]); - for (; modI < modE; ++modI) - if (modVec[modI].attrs != ParamAttr::None) - newVec.push_back(modVec[modI]); +void Function::eraseFromParent() { + getParent()->getFunctionList().erase(this); +} - return get(newVec); +/// @brief Determine whether the function has the given attribute. +bool Function::paramHasAttr(uint16_t i, unsigned attr) const { + return ParamAttrs && ParamAttrs->paramHasAttr(i, (ParameterAttributes)attr); } -const ParamAttrsList * -ParamAttrsList::includeAttrs(const ParamAttrsList *PAL, - uint16_t idx, uint16_t attrs) { - uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0; - uint16_t NewAttrs = OldAttrs | attrs; - if (NewAttrs == OldAttrs) - return PAL; +/// @brief Determine if the function cannot return. +bool Function::doesNotReturn() const { + return paramHasAttr(0, ParamAttr::NoReturn); +} - ParamAttrsVector modVec; - modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs)); - return getModified(PAL, modVec); +/// @brief Determine if the function cannot unwind. +bool Function::doesNotThrow() const { + return paramHasAttr(0, ParamAttr::NoUnwind); } -const ParamAttrsList * -ParamAttrsList::excludeAttrs(const ParamAttrsList *PAL, - uint16_t idx, uint16_t attrs) { - uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0; - uint16_t NewAttrs = OldAttrs & ~attrs; - if (NewAttrs == OldAttrs) - return PAL; +/// @brief Determine if the function does not access memory. +bool Function::doesNotAccessMemory() const { + return paramHasAttr(0, ParamAttr::ReadNone); +} - ParamAttrsVector modVec; - modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs)); - return getModified(PAL, modVec); +/// @brief Determine if the function does not access or only reads memory. +bool Function::onlyReadsMemory() const { + return doesNotAccessMemory() || paramHasAttr(0, ParamAttr::ReadOnly); } -ParamAttrsList::~ParamAttrsList() { - ParamAttrsLists->RemoveNode(this); +/// @brief Determine if the function returns a structure. +bool Function::isStructReturn() const { + return paramHasAttr(1, ParamAttr::StructRet); } //===----------------------------------------------------------------------===// @@ -374,26 +215,6 @@ void Function::setParamAttrs(const ParamAttrsList *attrs) { ParamAttrs = attrs; } -const FunctionType *Function::getFunctionType() const { - return cast<FunctionType>(getType()->getElementType()); -} - -bool Function::isVarArg() const { - return getFunctionType()->isVarArg(); -} - -const Type *Function::getReturnType() const { - return getFunctionType()->getReturnType(); -} - -void Function::removeFromParent() { - getParent()->getFunctionList().remove(this); -} - -void Function::eraseFromParent() { - getParent()->getFunctionList().erase(this); -} - // dropAllReferences() - This function causes all the subinstructions to "let // go" of all references that they are maintaining. This allows one to // 'delete' a whole class at a time, even though there may be circular diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index cae6413910..5179f04f01 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -23,6 +23,10 @@ #include "llvm/Support/MathExtras.h" using namespace llvm; +//===----------------------------------------------------------------------===// +// CallSite Class +//===----------------------------------------------------------------------===// + unsigned CallSite::getCallingConv() const { if (CallInst *CI = dyn_cast<CallInst>(I)) return CI->getCallingConv(); @@ -47,11 +51,11 @@ void CallSite::setParamAttrs(const ParamAttrsList *PAL) { else cast<InvokeInst>(I)->setParamAttrs(PAL); } -bool CallSite::paramHasAttr(uint16_t i, ParameterAttributes attr) const { +bool CallSite::paramHasAttr(uint16_t i, unsigned attr) const { if (CallInst *CI = dyn_cast<CallInst>(I)) - return CI->paramHasAttr(i, attr); + return CI->paramHasAttr(i, (ParameterAttributes)attr); else - return cast<InvokeInst>(I)->paramHasAttr(i, attr); + return cast<InvokeInst>(I)->paramHasAttr(i, (ParameterAttributes)attr); } bool CallSite::doesNotAccessMemory() const { if (CallInst *CI = dyn_cast<CallInst>(I)) @@ -366,14 +370,40 @@ void CallInst::setParamAttrs(const ParamAttrsList *newAttrs) { ParamAttrs = newAttrs; } -bool CallInst::paramHasAttr(uint16_t i, ParameterAttributes attr) const { - if (ParamAttrs && ParamAttrs->paramHasAttr(i, attr)) +bool CallInst::paramHasAttr(uint16_t i, unsigned attr) const { + if (ParamAttrs && ParamAttrs->paramHasAttr(i, (ParameterAttributes)attr)) return true; if (const Function *F = getCalledFunction()) - return F->paramHasAttr(i, attr); + return F->paramHasAttr(i, (ParameterAttributes)attr); return false; } +/// @brief Determine if the call does not access memory. +bool CallInst::doesNotAccessMemory() const { + return paramHasAttr(0, ParamAttr::ReadNone); +} + +/// @brief Determine if the call does not access or only reads memory. +bool CallInst::onlyReadsMemory() const { + return doesNotAccessMemory() || paramHasAttr(0, ParamAttr::ReadOnly); +} + +/// @brief Determine if the call cannot return. +bool CallInst::doesNotReturn() const { + return paramHasAttr(0, ParamAttr::NoReturn); +} + +/// @brief Determine if the call cannot unwind. +bool CallInst::doesNotThrow() const { + return paramHasAttr(0, ParamAttr::NoUnwind); +} + +/// @brief Determine if the call returns a structure. +bool CallInst::isStructReturn() const { + // Be friendly and also check the callee. + return paramHasAttr(1, ParamAttr::StructRet); +} + void CallInst::setDoesNotThrow(bool doesNotThrow) { const ParamAttrsList *PAL = getParamAttrs(); if (doesNotThrow) @@ -453,14 +483,35 @@ void InvokeInst::setParamAttrs(const ParamAttrsList *newAttrs) { ParamAttrs = newAttrs; } -bool InvokeInst::paramHasAttr(uint16_t i, ParameterAttributes attr) const { - if (ParamAttrs && ParamAttrs->paramHasAttr(i, attr)) +bool InvokeInst::paramHasAttr(uint16_t i, unsigned attr) const { + if (ParamAttrs && ParamAttrs->paramHasAttr(i, (ParameterAttributes)attr)) return true; if (const Function *F = getCalledFunction()) - return F->paramHasAttr(i, attr); + return F->paramHasAttr(i, (ParameterAttributes)attr); return false; } + +/// @brief Determine if the call does not access memory. +bool InvokeInst::doesNotAccessMemory() const { + return paramHasAttr(0, ParamAttr::ReadNone); +} + +/// @brief Determine if the call does not access or only reads memory. +bool InvokeInst::onlyReadsMemory() const { + return doesNotAccessMemory() || paramHasAttr(0, ParamAttr::ReadOnly); +} + +/// @brief Determine if the call cannot return. +bool InvokeInst::doesNotReturn() const { + return paramHasAttr(0, ParamAttr::NoReturn); +} + +/// @brief Determine if the call cannot unwind. +bool InvokeInst::doesNotThrow() const { + return paramHasAttr(0, ParamAttr::NoUnwind); +} + void InvokeInst::setDoesNotThrow(bool doesNotThrow) { const ParamAttrsList *PAL = getParamAttrs(); if (doesNotThrow) @@ -470,6 +521,12 @@ void InvokeInst::setDoesNotThrow(bool doesNotThrow) { setParamAttrs(PAL); } +/// @brief Determine if the call returns a structure. +bool InvokeInst::isStructReturn() const { + // Be friendly and also check the callee. + return paramHasAttr(1, ParamAttr::StructRet); +} + //===----------------------------------------------------------------------===// // ReturnInst Implementation diff --git a/lib/VMCore/ParameterAttributes.cpp b/lib/VMCore/ParameterAttributes.cpp new file mode 100644 index 0000000000..37a2819d86 --- /dev/null +++ b/lib/VMCore/ParameterAttributes.cpp @@ -0,0 +1,226 @@ +//===-- ParameterAttributes.cpp - Implement ParameterAttrs ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the ParamAttrsList class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ParameterAttributes.h" +#include "llvm/Support/ManagedStatic.h" +using namespace llvm; + +uint16_t +ParamAttrsList::getParamAttrs(uint16_t Index) const { + unsigned limit = attrs.size(); + for (unsigned i = 0; i < limit && attrs[i].index <= Index; ++i) + if (attrs[i].index == Index) + return attrs[i].attrs; + return ParamAttr::None; +} + +std::string +ParamAttrsList::getParamAttrsText(uint16_t Attrs) { + std::string Result; + if (Attrs & ParamAttr::ZExt) + Result += "zeroext "; + if (Attrs & ParamAttr::SExt) + Result += "signext "; + if (Attrs & ParamAttr::NoReturn) + Result += "noreturn "; + if (Attrs & ParamAttr::NoUnwind) + Result += "nounwind "; + if (Attrs & ParamAttr::InReg) + Result += "inreg "; + if (Attrs & ParamAttr::NoAlias) + Result += "noalias "; + if (Attrs & ParamAttr::StructRet) + Result += "sret "; + if (Attrs & ParamAttr::ByVal) + Result += "byval "; + if (Attrs & ParamAttr::Nest) + Result += "nest "; + if (Attrs & ParamAttr::ReadNone) + Result += "readnone "; + if (Attrs & ParamAttr::ReadOnly) + Result += "readonly "; + return Result; +} + +/// onlyInformative - Returns whether only informative attributes are set. +static inline bool onlyInformative(uint16_t attrs) { + return !(attrs & ~ParamAttr::Informative); +} + +bool +ParamAttrsList::areCompatible(const ParamAttrsList *A, const ParamAttrsList *B){ + if (A == B) + return true; + unsigned ASize = A ? A->size() : 0; + unsigned BSize = B ? B->size() : 0; + unsigned AIndex = 0; + unsigned BIndex = 0; + + while (AIndex < ASize && BIndex < BSize) { + uint16_t AIdx = A->getParamIndex(AIndex); + uint16_t BIdx = B->getParamIndex(BIndex); + uint16_t AAttrs = A->getParamAttrsAtIndex(AIndex); + uint16_t BAttrs = B->getParamAttrsAtIndex(AIndex); + + if (AIdx < BIdx) { + if (!onlyInformative(AAttrs)) + return false; + ++AIndex; + } else if (BIdx < AIdx) { + if (!onlyInformative(BAttrs)) + return false; + ++BIndex; + } else { + if (!onlyInformative(AAttrs ^ BAttrs)) + return false; + ++AIndex; + ++BIndex; + } + } + for (; AIndex < ASize; ++AIndex) + if (!onlyInformative(A->getParamAttrsAtIndex(AIndex))) + return false; + for (; BIndex < BSize; ++BIndex) + if (!onlyInformative(B->getParamAttrsAtIndex(AIndex))) + return false; + return true; +} + +void ParamAttrsList::Profile(FoldingSetNodeID &ID) const { + for (unsigned i = 0; i < attrs.size(); ++i) + ID.AddInteger(unsigned(attrs[i].attrs) << 16 | unsigned(attrs[i].index)); +} + +static ManagedStatic<FoldingSet<ParamAttrsList> > ParamAttrsLists; + +const ParamAttrsList * +ParamAttrsList::get(const ParamAttrsVector &attrVec) { + // If there are no attributes then return a null ParamAttrsList pointer. + if (attrVec.empty()) + return 0; + +#ifndef NDEBUG + for (unsigned i = 0, e = attrVec.size(); i < e; ++i) { + assert(attrVec[i].attrs != ParamAttr::None + && "Pointless parameter attribute!"); + assert((!i || attrVec[i-1].index < attrVec[i].index) + && "Misordered ParamAttrsList!"); + } +#endif + + // Otherwise, build a key to look up the existing attributes. + ParamAttrsList key(attrVec); + FoldingSetNodeID ID; + key.Profile(ID); + void *InsertPos; + ParamAttrsList* PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos); + + // If we didn't find any existing attributes of the same shape then + // create a new one and insert it. + if (!PAL) { + PAL = new ParamAttrsList(attrVec); + ParamAttrsLists->InsertNode(PAL, InsertPos); + } + + // Return the ParamAttrsList that we found or created. + 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); +} + +const ParamAttrsList * +ParamAttrsList::includeAttrs(const ParamAttrsList *PAL, + uint16_t idx, uint16_t attrs) { + uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0; + uint16_t NewAttrs = OldAttrs | attrs; + if (NewAttrs == OldAttrs) + return PAL; + + ParamAttrsVector modVec; + modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs)); + return getModified(PAL, modVec); +} + +const ParamAttrsList * +ParamAttrsList::excludeAttrs(const ParamAttrsList *PAL, + uint16_t idx, uint16_t attrs) { + uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0; + uint16_t NewAttrs = OldAttrs & ~attrs; + if (NewAttrs == OldAttrs) + return PAL; + + ParamAttrsVector modVec; + modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs)); + return getModified(PAL, modVec); +} + +ParamAttrsList::~ParamAttrsList() { + ParamAttrsLists->RemoveNode(this); +} + |