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
This commit is contained in:
Chris Lattner 2008-01-02 23:42:30 +00:00
parent a114b14e5d
commit 50ee9ddc8f
7 changed files with 347 additions and 280 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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;

View File

@ -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;
const FunctionType *Function::getFunctionType() const {
return cast<FunctionType>(getType()->getElementType());
}
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;
bool Function::isVarArg() const {
return getFunctionType()->isVarArg();
}
/// onlyInformative - Returns whether only informative attributes are set.
static inline bool onlyInformative(uint16_t attrs) {
return !(attrs & ~ParamAttr::Informative);
const Type *Function::getReturnType() const {
return getFunctionType()->getReturnType();
}
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 Function::removeFromParent() {
getParent()->getFunctionList().remove(this);
}
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));
void Function::eraseFromParent() {
getParent()->getFunctionList().erase(this);
}
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;
/// @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::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);
/// @brief Determine if the function cannot return.
bool Function::doesNotReturn() const {
return paramHasAttr(0, ParamAttr::NoReturn);
}
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);
/// @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;
ParamAttrsVector modVec;
modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
return getModified(PAL, modVec);
/// @brief Determine if the function does not access memory.
bool Function::doesNotAccessMemory() const {
return paramHasAttr(0, ParamAttr::ReadNone);
}
ParamAttrsList::~ParamAttrsList() {
ParamAttrsLists->RemoveNode(this);
/// @brief Determine if the function does not access or only reads memory.
bool Function::onlyReadsMemory() const {
return doesNotAccessMemory() || paramHasAttr(0, ParamAttr::ReadOnly);
}
/// @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

View File

@ -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

View File

@ -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);
}