Fix a compile error on Windows.
[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 #include <cassert>
17
18 using namespace llvm;
19
20 static ManagedStatic<FoldingSet<ParamAttrsList> > ParamAttrsLists;
21
22 ParamAttrsList::ParamAttrsList(const ParamAttrsVector &attrVec) 
23   : attrs(attrVec), refCount(0) {
24 }
25
26 ParamAttrsList::~ParamAttrsList() {
27   ParamAttrsLists->RemoveNode(this);
28 }
29
30 uint16_t
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;
37 }
38
39 std::string 
40 ParamAttrsList::getParamAttrsText(uint16_t Attrs) {
41   std::string Result;
42   if (Attrs & ParamAttr::ZExt)
43     Result += "zeroext ";
44   if (Attrs & ParamAttr::SExt)
45     Result += "signext ";
46   if (Attrs & ParamAttr::NoReturn)
47     Result += "noreturn ";
48   if (Attrs & ParamAttr::NoUnwind)
49     Result += "nounwind ";
50   if (Attrs & ParamAttr::InReg)
51     Result += "inreg ";
52   if (Attrs & ParamAttr::NoAlias)
53     Result += "noalias ";
54   if (Attrs & ParamAttr::StructRet)
55     Result += "sret ";  
56   if (Attrs & ParamAttr::ByVal)
57     Result += "byval ";
58   if (Attrs & ParamAttr::Nest)
59     Result += "nest ";
60   if (Attrs & ParamAttr::ReadNone)
61     Result += "readnone ";
62   if (Attrs & ParamAttr::ReadOnly)
63     Result += "readonly ";
64   return Result;
65 }
66
67 /// onlyInformative - Returns whether only informative attributes are set.
68 static inline bool onlyInformative(uint16_t attrs) {
69   return !(attrs & ~ParamAttr::Informative);
70 }
71
72 bool
73 ParamAttrsList::areCompatible(const ParamAttrsList *A, const ParamAttrsList *B){
74   if (A == B)
75     return true;
76   unsigned ASize = A ? A->size() : 0;
77   unsigned BSize = B ? B->size() : 0;
78   unsigned AIndex = 0;
79   unsigned BIndex = 0;
80
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);
86
87     if (AIdx < BIdx) {
88       if (!onlyInformative(AAttrs))
89         return false;
90       ++AIndex;
91     } else if (BIdx < AIdx) {
92       if (!onlyInformative(BAttrs))
93         return false;
94       ++BIndex;
95     } else {
96       if (!onlyInformative(AAttrs ^ BAttrs))
97         return false;
98       ++AIndex;
99       ++BIndex;
100     }
101   }
102   for (; AIndex < ASize; ++AIndex)
103     if (!onlyInformative(A->getParamAttrsAtIndex(AIndex)))
104       return false;
105   for (; BIndex < BSize; ++BIndex)
106     if (!onlyInformative(B->getParamAttrsAtIndex(AIndex)))
107       return false;
108   return true;
109 }
110
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));
115 }
116
117 const ParamAttrsList *
118 ParamAttrsList::get(const ParamAttrsVector &attrVec) {
119   // If there are no attributes then return a null ParamAttrsList pointer.
120   if (attrVec.empty())
121     return 0;
122
123 #ifndef NDEBUG
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!");
129   }
130 #endif
131
132   // Otherwise, build a key to look up the existing attributes.
133   FoldingSetNodeID ID;
134   ParamAttrsList::Profile(ID, attrVec);
135   void *InsertPos;
136   ParamAttrsList *PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos);
137
138   // If we didn't find any existing attributes of the same shape then
139   // create a new one and insert it.
140   if (!PAL) {
141     PAL = new ParamAttrsList(attrVec);
142     ParamAttrsLists->InsertNode(PAL, InsertPos);
143   }
144
145   // Return the ParamAttrsList that we found or created.
146   return PAL;
147 }
148
149 const ParamAttrsList *
150 ParamAttrsList::getModified(const ParamAttrsList *PAL,
151                             const ParamAttrsVector &modVec) {
152   if (modVec.empty())
153     return PAL;
154
155 #ifndef NDEBUG
156   for (unsigned i = 0, e = modVec.size(); i < e; ++i)
157     assert((!i || modVec[i-1].index < modVec[i].index)
158            && "Misordered ParamAttrsList!");
159 #endif
160
161   if (!PAL) {
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]);
167     return get(newVec);
168   }
169
170   const ParamAttrsVector &oldVec = PAL->attrs;
171
172   ParamAttrsVector newVec;
173   unsigned oldI = 0;
174   unsigned modI = 0;
175   unsigned oldE = oldVec.size();
176   unsigned modE = modVec.size();
177
178   while (oldI < oldE && modI < modE) {
179     uint16_t oldIndex = oldVec[oldI].index;
180     uint16_t modIndex = modVec[modI].index;
181
182     if (oldIndex < modIndex) {
183       newVec.push_back(oldVec[oldI]);
184       ++oldI;
185     } else if (modIndex < oldIndex) {
186       if (modVec[modI].attrs != ParamAttr::None)
187         newVec.push_back(modVec[modI]);
188       ++modI;
189     } else {
190       // Same index - overwrite or delete existing attributes.
191       if (modVec[modI].attrs != ParamAttr::None)
192         newVec.push_back(modVec[modI]);
193       ++oldI;
194       ++modI;
195     }
196   }
197
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]);
203
204   return get(newVec);
205 }
206
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)
213     return PAL;
214
215   ParamAttrsVector modVec;
216   modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
217   return getModified(PAL, modVec);
218 }
219
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)
226     return PAL;
227
228   ParamAttrsVector modVec;
229   modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
230   return getModified(PAL, modVec);
231 }
232