b6c29922a61eeba22bd0480b3cf841707d42a141
[oota-llvm.git] / lib / VMCore / ParameterAttributes.cpp
1 //===-- ParameterAttributes.cpp - Implement ParameterAttrs ----------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the ParamAttrsList class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/ParameterAttributes.h"
15 #include "llvm/Support/ManagedStatic.h"
16 using namespace llvm;
17
18 static ManagedStatic<FoldingSet<ParamAttrsList> > ParamAttrsLists;
19
20 ParamAttrsList::ParamAttrsList(const ParamAttrsVector &attrVec) 
21   : attrs(attrVec), refCount(0) {
22 }
23
24 ParamAttrsList::~ParamAttrsList() {
25   ParamAttrsLists->RemoveNode(this);
26 }
27
28 uint16_t
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;
35 }
36
37 std::string 
38 ParamAttrsList::getParamAttrsText(uint16_t Attrs) {
39   std::string Result;
40   if (Attrs & ParamAttr::ZExt)
41     Result += "zeroext ";
42   if (Attrs & ParamAttr::SExt)
43     Result += "signext ";
44   if (Attrs & ParamAttr::NoReturn)
45     Result += "noreturn ";
46   if (Attrs & ParamAttr::NoUnwind)
47     Result += "nounwind ";
48   if (Attrs & ParamAttr::InReg)
49     Result += "inreg ";
50   if (Attrs & ParamAttr::NoAlias)
51     Result += "noalias ";
52   if (Attrs & ParamAttr::StructRet)
53     Result += "sret ";  
54   if (Attrs & ParamAttr::ByVal)
55     Result += "byval ";
56   if (Attrs & ParamAttr::Nest)
57     Result += "nest ";
58   if (Attrs & ParamAttr::ReadNone)
59     Result += "readnone ";
60   if (Attrs & ParamAttr::ReadOnly)
61     Result += "readonly ";
62   return Result;
63 }
64
65 /// onlyInformative - Returns whether only informative attributes are set.
66 static inline bool onlyInformative(uint16_t attrs) {
67   return !(attrs & ~ParamAttr::Informative);
68 }
69
70 bool
71 ParamAttrsList::areCompatible(const ParamAttrsList *A, const ParamAttrsList *B){
72   if (A == B)
73     return true;
74   unsigned ASize = A ? A->size() : 0;
75   unsigned BSize = B ? B->size() : 0;
76   unsigned AIndex = 0;
77   unsigned BIndex = 0;
78
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);
84
85     if (AIdx < BIdx) {
86       if (!onlyInformative(AAttrs))
87         return false;
88       ++AIndex;
89     } else if (BIdx < AIdx) {
90       if (!onlyInformative(BAttrs))
91         return false;
92       ++BIndex;
93     } else {
94       if (!onlyInformative(AAttrs ^ BAttrs))
95         return false;
96       ++AIndex;
97       ++BIndex;
98     }
99   }
100   for (; AIndex < ASize; ++AIndex)
101     if (!onlyInformative(A->getParamAttrsAtIndex(AIndex)))
102       return false;
103   for (; BIndex < BSize; ++BIndex)
104     if (!onlyInformative(B->getParamAttrsAtIndex(AIndex)))
105       return false;
106   return true;
107 }
108
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));
113 }
114
115 const ParamAttrsList *
116 ParamAttrsList::get(const ParamAttrsVector &attrVec) {
117   // If there are no attributes then return a null ParamAttrsList pointer.
118   if (attrVec.empty())
119     return 0;
120
121 #ifndef NDEBUG
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!");
127   }
128 #endif
129
130   // Otherwise, build a key to look up the existing attributes.
131   FoldingSetNodeID ID;
132   ParamAttrsList::Profile(ID, attrVec);
133   void *InsertPos;
134   ParamAttrsList *PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos);
135
136   // If we didn't find any existing attributes of the same shape then
137   // create a new one and insert it.
138   if (!PAL) {
139     PAL = new ParamAttrsList(attrVec);
140     ParamAttrsLists->InsertNode(PAL, InsertPos);
141   }
142
143   // Return the ParamAttrsList that we found or created.
144   return PAL;
145 }
146
147 const ParamAttrsList *
148 ParamAttrsList::getModified(const ParamAttrsList *PAL,
149                             const ParamAttrsVector &modVec) {
150   if (modVec.empty())
151     return PAL;
152
153 #ifndef NDEBUG
154   for (unsigned i = 0, e = modVec.size(); i < e; ++i)
155     assert((!i || modVec[i-1].index < modVec[i].index)
156            && "Misordered ParamAttrsList!");
157 #endif
158
159   if (!PAL) {
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]);
165     return get(newVec);
166   }
167
168   const ParamAttrsVector &oldVec = PAL->attrs;
169
170   ParamAttrsVector newVec;
171   unsigned oldI = 0;
172   unsigned modI = 0;
173   unsigned oldE = oldVec.size();
174   unsigned modE = modVec.size();
175
176   while (oldI < oldE && modI < modE) {
177     uint16_t oldIndex = oldVec[oldI].index;
178     uint16_t modIndex = modVec[modI].index;
179
180     if (oldIndex < modIndex) {
181       newVec.push_back(oldVec[oldI]);
182       ++oldI;
183     } else if (modIndex < oldIndex) {
184       if (modVec[modI].attrs != ParamAttr::None)
185         newVec.push_back(modVec[modI]);
186       ++modI;
187     } else {
188       // Same index - overwrite or delete existing attributes.
189       if (modVec[modI].attrs != ParamAttr::None)
190         newVec.push_back(modVec[modI]);
191       ++oldI;
192       ++modI;
193     }
194   }
195
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]);
201
202   return get(newVec);
203 }
204
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)
211     return PAL;
212
213   ParamAttrsVector modVec;
214   modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
215   return getModified(PAL, modVec);
216 }
217
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)
224     return PAL;
225
226   ParamAttrsVector modVec;
227   modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
228   return getModified(PAL, modVec);
229 }
230