Increment counter that keeps track of total number of sret promoted.
[oota-llvm.git] / lib / VMCore / ParameterAttributes.cpp
1 //===-- ParameterAttributes.cpp - Implement ParamAttrsList ----------------===//
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 and ParamAttr utilities.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/ParamAttrsList.h"
15 #include "llvm/DerivedTypes.h"
16 #include "llvm/Support/ManagedStatic.h"
17 #include <sstream>
18
19 using namespace llvm;
20
21 static ManagedStatic<FoldingSet<ParamAttrsList> > ParamAttrsLists;
22
23 ParamAttrsList::ParamAttrsList(const ParamAttrsVector &attrVec) 
24   : attrs(attrVec), refCount(0) {
25 }
26
27 ParamAttrsList::~ParamAttrsList() {
28   ParamAttrsLists->RemoveNode(this);
29 }
30
31 ParameterAttributes
32 ParamAttrsList::getParamAttrs(uint16_t Index) const {
33   unsigned limit = attrs.size();
34   for (unsigned i = 0; i < limit && attrs[i].index <= Index; ++i)
35     if (attrs[i].index == Index)
36       return attrs[i].attrs;
37   return ParamAttr::None;
38 }
39
40 bool ParamAttrsList::hasAttrSomewhere(ParameterAttributes attr) const {
41   for (unsigned i = 0, e = attrs.size(); i < e; ++i)
42     if (attrs[i].attrs & attr)
43       return true;
44   return false;
45 }
46
47 std::string 
48 ParamAttrsList::getParamAttrsText(ParameterAttributes Attrs) {
49   std::string Result;
50   if (Attrs & ParamAttr::ZExt)
51     Result += "zeroext ";
52   if (Attrs & ParamAttr::SExt)
53     Result += "signext ";
54   if (Attrs & ParamAttr::NoReturn)
55     Result += "noreturn ";
56   if (Attrs & ParamAttr::NoUnwind)
57     Result += "nounwind ";
58   if (Attrs & ParamAttr::InReg)
59     Result += "inreg ";
60   if (Attrs & ParamAttr::NoAlias)
61     Result += "noalias ";
62   if (Attrs & ParamAttr::StructRet)
63     Result += "sret ";  
64   if (Attrs & ParamAttr::ByVal)
65     Result += "byval ";
66   if (Attrs & ParamAttr::Nest)
67     Result += "nest ";
68   if (Attrs & ParamAttr::ReadNone)
69     Result += "readnone ";
70   if (Attrs & ParamAttr::ReadOnly)
71     Result += "readonly ";
72   if (Attrs & ParamAttr::Alignment) {
73     std::stringstream s;
74     s << ((Attrs & ParamAttr::Alignment) >> 16);
75     Result += "align ";
76     Result += s.str();
77     Result += " ";
78   }
79   return Result;
80 }
81
82 void ParamAttrsList::Profile(FoldingSetNodeID &ID,
83                              const ParamAttrsVector &Attrs) {
84   for (unsigned i = 0; i < Attrs.size(); ++i)
85     ID.AddInteger(uint64_t(Attrs[i].attrs) << 16 | unsigned(Attrs[i].index));
86 }
87
88 const ParamAttrsList *
89 ParamAttrsList::get(const ParamAttrsVector &attrVec) {
90   // If there are no attributes then return a null ParamAttrsList pointer.
91   if (attrVec.empty())
92     return 0;
93
94 #ifndef NDEBUG
95   for (unsigned i = 0, e = attrVec.size(); i < e; ++i) {
96     assert(attrVec[i].attrs != ParamAttr::None
97            && "Pointless parameter attribute!");
98     assert((!i || attrVec[i-1].index < attrVec[i].index)
99            && "Misordered ParamAttrsList!");
100   }
101 #endif
102
103   // Otherwise, build a key to look up the existing attributes.
104   FoldingSetNodeID ID;
105   ParamAttrsList::Profile(ID, attrVec);
106   void *InsertPos;
107   ParamAttrsList *PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos);
108
109   // If we didn't find any existing attributes of the same shape then
110   // create a new one and insert it.
111   if (!PAL) {
112     PAL = new ParamAttrsList(attrVec);
113     ParamAttrsLists->InsertNode(PAL, InsertPos);
114   }
115
116   // Return the ParamAttrsList that we found or created.
117   return PAL;
118 }
119
120 const ParamAttrsList *
121 ParamAttrsList::getModified(const ParamAttrsList *PAL,
122                             const ParamAttrsVector &modVec) {
123   if (modVec.empty())
124     return PAL;
125
126 #ifndef NDEBUG
127   for (unsigned i = 0, e = modVec.size(); i < e; ++i)
128     assert((!i || modVec[i-1].index < modVec[i].index)
129            && "Misordered ParamAttrsList!");
130 #endif
131
132   if (!PAL) {
133     // Strip any instances of ParamAttr::None from modVec before calling 'get'.
134     ParamAttrsVector newVec;
135     newVec.reserve(modVec.size());
136     for (unsigned i = 0, e = modVec.size(); i < e; ++i)
137       if (modVec[i].attrs != ParamAttr::None)
138         newVec.push_back(modVec[i]);
139     return get(newVec);
140   }
141
142   const ParamAttrsVector &oldVec = PAL->attrs;
143
144   ParamAttrsVector newVec;
145   unsigned oldI = 0;
146   unsigned modI = 0;
147   unsigned oldE = oldVec.size();
148   unsigned modE = modVec.size();
149
150   while (oldI < oldE && modI < modE) {
151     uint16_t oldIndex = oldVec[oldI].index;
152     uint16_t modIndex = modVec[modI].index;
153
154     if (oldIndex < modIndex) {
155       newVec.push_back(oldVec[oldI]);
156       ++oldI;
157     } else if (modIndex < oldIndex) {
158       if (modVec[modI].attrs != ParamAttr::None)
159         newVec.push_back(modVec[modI]);
160       ++modI;
161     } else {
162       // Same index - overwrite or delete existing attributes.
163       if (modVec[modI].attrs != ParamAttr::None)
164         newVec.push_back(modVec[modI]);
165       ++oldI;
166       ++modI;
167     }
168   }
169
170   for (; oldI < oldE; ++oldI)
171     newVec.push_back(oldVec[oldI]);
172   for (; modI < modE; ++modI)
173     if (modVec[modI].attrs != ParamAttr::None)
174       newVec.push_back(modVec[modI]);
175
176   return get(newVec);
177 }
178
179 const ParamAttrsList *
180 ParamAttrsList::includeAttrs(const ParamAttrsList *PAL,
181                              uint16_t idx, ParameterAttributes attrs) {
182   ParameterAttributes OldAttrs = PAL ? PAL->getParamAttrs(idx) : 
183                                        ParamAttr::None;
184 #ifndef NDEBUG
185   // FIXME it is not obvious how this should work for alignment.
186   // For now, say we can't change a known alignment.
187   ParameterAttributes OldAlign = OldAttrs & ParamAttr::Alignment;
188   ParameterAttributes NewAlign = attrs & ParamAttr::Alignment;
189   assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
190          "Attempt to change alignment!");
191 #endif
192
193   ParameterAttributes NewAttrs = OldAttrs | attrs;
194   if (NewAttrs == OldAttrs)
195     return PAL;
196
197   ParamAttrsVector modVec(1);
198   modVec[0] = ParamAttrsWithIndex::get(idx, NewAttrs);
199   return getModified(PAL, modVec);
200 }
201
202 const ParamAttrsList *
203 ParamAttrsList::excludeAttrs(const ParamAttrsList *PAL,
204                              uint16_t idx, ParameterAttributes attrs) {
205 #ifndef NDEBUG
206   // FIXME it is not obvious how this should work for alignment.
207   // For now, say we can't pass in alignment, which no current use does.
208   assert(!(attrs & ParamAttr::Alignment) && "Attempt to exclude alignment!");
209 #endif
210   ParameterAttributes OldAttrs = PAL ? PAL->getParamAttrs(idx) : 
211                                        ParamAttr::None;
212   ParameterAttributes NewAttrs = OldAttrs & ~attrs;
213   if (NewAttrs == OldAttrs)
214     return PAL;
215
216   ParamAttrsVector modVec(1);
217   modVec[0] = ParamAttrsWithIndex::get(idx, NewAttrs);
218   return getModified(PAL, modVec);
219 }
220
221 ParameterAttributes ParamAttr::typeIncompatible (const Type *Ty) {
222   ParameterAttributes Incompatible = None;
223
224   if (!Ty->isInteger())
225     // Attributes that only apply to integers.
226     Incompatible |= SExt | ZExt;
227
228   if (!isa<PointerType>(Ty))
229     // Attributes that only apply to pointers.
230     Incompatible |= ByVal | Nest | NoAlias | StructRet;
231
232   return Incompatible;
233 }