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"
18 static ManagedStatic<FoldingSet<ParamAttrsList> > ParamAttrsLists;
20 ParamAttrsList::ParamAttrsList(const ParamAttrsVector &attrVec)
21 : attrs(attrVec), refCount(0) {
24 ParamAttrsList::~ParamAttrsList() {
25 ParamAttrsLists->RemoveNode(this);
29 ParamAttrsList::getParamAttrs(uint16_t Index) const {
30 unsigned limit = attrs.size();
31 for (unsigned i = 0; i < limit && attrs[i].index <= Index; ++i)
32 if (attrs[i].index == Index)
33 return attrs[i].attrs;
34 return ParamAttr::None;
38 ParamAttrsList::getParamAttrsText(uint16_t Attrs) {
40 if (Attrs & ParamAttr::ZExt)
42 if (Attrs & ParamAttr::SExt)
44 if (Attrs & ParamAttr::NoReturn)
45 Result += "noreturn ";
46 if (Attrs & ParamAttr::NoUnwind)
47 Result += "nounwind ";
48 if (Attrs & ParamAttr::InReg)
50 if (Attrs & ParamAttr::NoAlias)
52 if (Attrs & ParamAttr::StructRet)
54 if (Attrs & ParamAttr::ByVal)
56 if (Attrs & ParamAttr::Nest)
58 if (Attrs & ParamAttr::ReadNone)
59 Result += "readnone ";
60 if (Attrs & ParamAttr::ReadOnly)
61 Result += "readonly ";
65 /// onlyInformative - Returns whether only informative attributes are set.
66 static inline bool onlyInformative(uint16_t attrs) {
67 return !(attrs & ~ParamAttr::Informative);
71 ParamAttrsList::areCompatible(const ParamAttrsList *A, const ParamAttrsList *B){
74 unsigned ASize = A ? A->size() : 0;
75 unsigned BSize = B ? B->size() : 0;
79 while (AIndex < ASize && BIndex < BSize) {
80 uint16_t AIdx = A->getParamIndex(AIndex);
81 uint16_t BIdx = B->getParamIndex(BIndex);
82 uint16_t AAttrs = A->getParamAttrsAtIndex(AIndex);
83 uint16_t BAttrs = B->getParamAttrsAtIndex(AIndex);
86 if (!onlyInformative(AAttrs))
89 } else if (BIdx < AIdx) {
90 if (!onlyInformative(BAttrs))
94 if (!onlyInformative(AAttrs ^ BAttrs))
100 for (; AIndex < ASize; ++AIndex)
101 if (!onlyInformative(A->getParamAttrsAtIndex(AIndex)))
103 for (; BIndex < BSize; ++BIndex)
104 if (!onlyInformative(B->getParamAttrsAtIndex(AIndex)))
109 void ParamAttrsList::Profile(FoldingSetNodeID &ID,
110 const ParamAttrsVector &Attrs) {
111 for (unsigned i = 0; i < Attrs.size(); ++i)
112 ID.AddInteger(unsigned(Attrs[i].attrs) << 16 | unsigned(Attrs[i].index));
115 const ParamAttrsList *
116 ParamAttrsList::get(const ParamAttrsVector &attrVec) {
117 // If there are no attributes then return a null ParamAttrsList pointer.
122 for (unsigned i = 0, e = attrVec.size(); i < e; ++i) {
123 assert(attrVec[i].attrs != ParamAttr::None
124 && "Pointless parameter attribute!");
125 assert((!i || attrVec[i-1].index < attrVec[i].index)
126 && "Misordered ParamAttrsList!");
130 // Otherwise, build a key to look up the existing attributes.
132 ParamAttrsList::Profile(ID, attrVec);
134 ParamAttrsList *PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos);
136 // If we didn't find any existing attributes of the same shape then
137 // create a new one and insert it.
139 PAL = new ParamAttrsList(attrVec);
140 ParamAttrsLists->InsertNode(PAL, InsertPos);
143 // Return the ParamAttrsList that we found or created.
147 const ParamAttrsList *
148 ParamAttrsList::getModified(const ParamAttrsList *PAL,
149 const ParamAttrsVector &modVec) {
154 for (unsigned i = 0, e = modVec.size(); i < e; ++i)
155 assert((!i || modVec[i-1].index < modVec[i].index)
156 && "Misordered ParamAttrsList!");
160 // Strip any instances of ParamAttr::None from modVec before calling 'get'.
161 ParamAttrsVector newVec;
162 for (unsigned i = 0, e = modVec.size(); i < e; ++i)
163 if (modVec[i].attrs != ParamAttr::None)
164 newVec.push_back(modVec[i]);
168 const ParamAttrsVector &oldVec = PAL->attrs;
170 ParamAttrsVector newVec;
173 unsigned oldE = oldVec.size();
174 unsigned modE = modVec.size();
176 while (oldI < oldE && modI < modE) {
177 uint16_t oldIndex = oldVec[oldI].index;
178 uint16_t modIndex = modVec[modI].index;
180 if (oldIndex < modIndex) {
181 newVec.push_back(oldVec[oldI]);
183 } else if (modIndex < oldIndex) {
184 if (modVec[modI].attrs != ParamAttr::None)
185 newVec.push_back(modVec[modI]);
188 // Same index - overwrite or delete existing attributes.
189 if (modVec[modI].attrs != ParamAttr::None)
190 newVec.push_back(modVec[modI]);
196 for (; oldI < oldE; ++oldI)
197 newVec.push_back(oldVec[oldI]);
198 for (; modI < modE; ++modI)
199 if (modVec[modI].attrs != ParamAttr::None)
200 newVec.push_back(modVec[modI]);
205 const ParamAttrsList *
206 ParamAttrsList::includeAttrs(const ParamAttrsList *PAL,
207 uint16_t idx, uint16_t attrs) {
208 uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
209 uint16_t NewAttrs = OldAttrs | attrs;
210 if (NewAttrs == OldAttrs)
213 ParamAttrsVector modVec;
214 modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
215 return getModified(PAL, modVec);
218 const ParamAttrsList *
219 ParamAttrsList::excludeAttrs(const ParamAttrsList *PAL,
220 uint16_t idx, uint16_t attrs) {
221 uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
222 uint16_t NewAttrs = OldAttrs & ~attrs;
223 if (NewAttrs == OldAttrs)
226 ParamAttrsVector modVec;
227 modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
228 return getModified(PAL, modVec);