1 //===-- ParameterAttributes.cpp - Implement ParameterAttrs ----------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the ParamAttrsList class.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/ParameterAttributes.h"
15 #include "llvm/Support/ManagedStatic.h"
20 static ManagedStatic<FoldingSet<ParamAttrsList> > ParamAttrsLists;
22 ParamAttrsList::ParamAttrsList(const ParamAttrsVector &attrVec)
23 : attrs(attrVec), refCount(0) {
26 ParamAttrsList::~ParamAttrsList() {
27 ParamAttrsLists->RemoveNode(this);
31 ParamAttrsList::getParamAttrs(uint16_t Index) const {
32 unsigned limit = attrs.size();
33 for (unsigned i = 0; i < limit && attrs[i].index <= Index; ++i)
34 if (attrs[i].index == Index)
35 return attrs[i].attrs;
36 return ParamAttr::None;
40 ParamAttrsList::getParamAttrsText(uint16_t Attrs) {
42 if (Attrs & ParamAttr::ZExt)
44 if (Attrs & ParamAttr::SExt)
46 if (Attrs & ParamAttr::NoReturn)
47 Result += "noreturn ";
48 if (Attrs & ParamAttr::NoUnwind)
49 Result += "nounwind ";
50 if (Attrs & ParamAttr::InReg)
52 if (Attrs & ParamAttr::NoAlias)
54 if (Attrs & ParamAttr::StructRet)
56 if (Attrs & ParamAttr::ByVal)
58 if (Attrs & ParamAttr::Nest)
60 if (Attrs & ParamAttr::ReadNone)
61 Result += "readnone ";
62 if (Attrs & ParamAttr::ReadOnly)
63 Result += "readonly ";
67 /// onlyInformative - Returns whether only informative attributes are set.
68 static inline bool onlyInformative(uint16_t attrs) {
69 return !(attrs & ~ParamAttr::Informative);
73 ParamAttrsList::areCompatible(const ParamAttrsList *A, const ParamAttrsList *B){
76 unsigned ASize = A ? A->size() : 0;
77 unsigned BSize = B ? B->size() : 0;
81 while (AIndex < ASize && BIndex < BSize) {
82 uint16_t AIdx = A->getParamIndex(AIndex);
83 uint16_t BIdx = B->getParamIndex(BIndex);
84 uint16_t AAttrs = A->getParamAttrsAtIndex(AIndex);
85 uint16_t BAttrs = B->getParamAttrsAtIndex(AIndex);
88 if (!onlyInformative(AAttrs))
91 } else if (BIdx < AIdx) {
92 if (!onlyInformative(BAttrs))
96 if (!onlyInformative(AAttrs ^ BAttrs))
102 for (; AIndex < ASize; ++AIndex)
103 if (!onlyInformative(A->getParamAttrsAtIndex(AIndex)))
105 for (; BIndex < BSize; ++BIndex)
106 if (!onlyInformative(B->getParamAttrsAtIndex(AIndex)))
111 void ParamAttrsList::Profile(FoldingSetNodeID &ID,
112 const ParamAttrsVector &Attrs) {
113 for (unsigned i = 0; i < Attrs.size(); ++i)
114 ID.AddInteger(unsigned(Attrs[i].attrs) << 16 | unsigned(Attrs[i].index));
117 const ParamAttrsList *
118 ParamAttrsList::get(const ParamAttrsVector &attrVec) {
119 // If there are no attributes then return a null ParamAttrsList pointer.
124 for (unsigned i = 0, e = attrVec.size(); i < e; ++i) {
125 assert(attrVec[i].attrs != ParamAttr::None
126 && "Pointless parameter attribute!");
127 assert((!i || attrVec[i-1].index < attrVec[i].index)
128 && "Misordered ParamAttrsList!");
132 // Otherwise, build a key to look up the existing attributes.
134 ParamAttrsList::Profile(ID, attrVec);
136 ParamAttrsList *PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos);
138 // If we didn't find any existing attributes of the same shape then
139 // create a new one and insert it.
141 PAL = new ParamAttrsList(attrVec);
142 ParamAttrsLists->InsertNode(PAL, InsertPos);
145 // Return the ParamAttrsList that we found or created.
149 const ParamAttrsList *
150 ParamAttrsList::getModified(const ParamAttrsList *PAL,
151 const ParamAttrsVector &modVec) {
156 for (unsigned i = 0, e = modVec.size(); i < e; ++i)
157 assert((!i || modVec[i-1].index < modVec[i].index)
158 && "Misordered ParamAttrsList!");
162 // Strip any instances of ParamAttr::None from modVec before calling 'get'.
163 ParamAttrsVector newVec;
164 for (unsigned i = 0, e = modVec.size(); i < e; ++i)
165 if (modVec[i].attrs != ParamAttr::None)
166 newVec.push_back(modVec[i]);
170 const ParamAttrsVector &oldVec = PAL->attrs;
172 ParamAttrsVector newVec;
175 unsigned oldE = oldVec.size();
176 unsigned modE = modVec.size();
178 while (oldI < oldE && modI < modE) {
179 uint16_t oldIndex = oldVec[oldI].index;
180 uint16_t modIndex = modVec[modI].index;
182 if (oldIndex < modIndex) {
183 newVec.push_back(oldVec[oldI]);
185 } else if (modIndex < oldIndex) {
186 if (modVec[modI].attrs != ParamAttr::None)
187 newVec.push_back(modVec[modI]);
190 // Same index - overwrite or delete existing attributes.
191 if (modVec[modI].attrs != ParamAttr::None)
192 newVec.push_back(modVec[modI]);
198 for (; oldI < oldE; ++oldI)
199 newVec.push_back(oldVec[oldI]);
200 for (; modI < modE; ++modI)
201 if (modVec[modI].attrs != ParamAttr::None)
202 newVec.push_back(modVec[modI]);
207 const ParamAttrsList *
208 ParamAttrsList::includeAttrs(const ParamAttrsList *PAL,
209 uint16_t idx, uint16_t attrs) {
210 uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
211 uint16_t NewAttrs = OldAttrs | attrs;
212 if (NewAttrs == OldAttrs)
215 ParamAttrsVector modVec;
216 modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
217 return getModified(PAL, modVec);
220 const ParamAttrsList *
221 ParamAttrsList::excludeAttrs(const ParamAttrsList *PAL,
222 uint16_t idx, uint16_t attrs) {
223 uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
224 uint16_t NewAttrs = OldAttrs & ~attrs;
225 if (NewAttrs == OldAttrs)
228 ParamAttrsVector modVec;
229 modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
230 return getModified(PAL, modVec);