Make load->store deletion a bit smarter. This allows us to compile this:
[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 and ParamAttr utilities.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/ParameterAttributes.h"
15 #include "llvm/DerivedTypes.h"
16 #include "llvm/Support/ManagedStatic.h"
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 void ParamAttrsList::Profile(FoldingSetNodeID &ID,
68                              const ParamAttrsVector &Attrs) {
69   for (unsigned i = 0; i < Attrs.size(); ++i)
70     ID.AddInteger(unsigned(Attrs[i].attrs) << 16 | unsigned(Attrs[i].index));
71 }
72
73 const ParamAttrsList *
74 ParamAttrsList::get(const ParamAttrsVector &attrVec) {
75   // If there are no attributes then return a null ParamAttrsList pointer.
76   if (attrVec.empty())
77     return 0;
78
79 #ifndef NDEBUG
80   for (unsigned i = 0, e = attrVec.size(); i < e; ++i) {
81     assert(attrVec[i].attrs != ParamAttr::None
82            && "Pointless parameter attribute!");
83     assert((!i || attrVec[i-1].index < attrVec[i].index)
84            && "Misordered ParamAttrsList!");
85   }
86 #endif
87
88   // Otherwise, build a key to look up the existing attributes.
89   FoldingSetNodeID ID;
90   ParamAttrsList::Profile(ID, attrVec);
91   void *InsertPos;
92   ParamAttrsList *PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos);
93
94   // If we didn't find any existing attributes of the same shape then
95   // create a new one and insert it.
96   if (!PAL) {
97     PAL = new ParamAttrsList(attrVec);
98     ParamAttrsLists->InsertNode(PAL, InsertPos);
99   }
100
101   // Return the ParamAttrsList that we found or created.
102   return PAL;
103 }
104
105 const ParamAttrsList *
106 ParamAttrsList::getModified(const ParamAttrsList *PAL,
107                             const ParamAttrsVector &modVec) {
108   if (modVec.empty())
109     return PAL;
110
111 #ifndef NDEBUG
112   for (unsigned i = 0, e = modVec.size(); i < e; ++i)
113     assert((!i || modVec[i-1].index < modVec[i].index)
114            && "Misordered ParamAttrsList!");
115 #endif
116
117   if (!PAL) {
118     // Strip any instances of ParamAttr::None from modVec before calling 'get'.
119     ParamAttrsVector newVec;
120     for (unsigned i = 0, e = modVec.size(); i < e; ++i)
121       if (modVec[i].attrs != ParamAttr::None)
122         newVec.push_back(modVec[i]);
123     return get(newVec);
124   }
125
126   const ParamAttrsVector &oldVec = PAL->attrs;
127
128   ParamAttrsVector newVec;
129   unsigned oldI = 0;
130   unsigned modI = 0;
131   unsigned oldE = oldVec.size();
132   unsigned modE = modVec.size();
133
134   while (oldI < oldE && modI < modE) {
135     uint16_t oldIndex = oldVec[oldI].index;
136     uint16_t modIndex = modVec[modI].index;
137
138     if (oldIndex < modIndex) {
139       newVec.push_back(oldVec[oldI]);
140       ++oldI;
141     } else if (modIndex < oldIndex) {
142       if (modVec[modI].attrs != ParamAttr::None)
143         newVec.push_back(modVec[modI]);
144       ++modI;
145     } else {
146       // Same index - overwrite or delete existing attributes.
147       if (modVec[modI].attrs != ParamAttr::None)
148         newVec.push_back(modVec[modI]);
149       ++oldI;
150       ++modI;
151     }
152   }
153
154   for (; oldI < oldE; ++oldI)
155     newVec.push_back(oldVec[oldI]);
156   for (; modI < modE; ++modI)
157     if (modVec[modI].attrs != ParamAttr::None)
158       newVec.push_back(modVec[modI]);
159
160   return get(newVec);
161 }
162
163 const ParamAttrsList *
164 ParamAttrsList::includeAttrs(const ParamAttrsList *PAL,
165                              uint16_t idx, uint16_t attrs) {
166   uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
167   uint16_t NewAttrs = OldAttrs | attrs;
168   if (NewAttrs == OldAttrs)
169     return PAL;
170
171   ParamAttrsVector modVec;
172   modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
173   return getModified(PAL, modVec);
174 }
175
176 const ParamAttrsList *
177 ParamAttrsList::excludeAttrs(const ParamAttrsList *PAL,
178                              uint16_t idx, uint16_t attrs) {
179   uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
180   uint16_t NewAttrs = OldAttrs & ~attrs;
181   if (NewAttrs == OldAttrs)
182     return PAL;
183
184   ParamAttrsVector modVec;
185   modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
186   return getModified(PAL, modVec);
187 }
188
189 uint16_t ParamAttr::typeIncompatible (const Type *Ty) {
190   uint16_t Incompatible = None;
191
192   if (!Ty->isInteger())
193     // Attributes that only apply to integers.
194     Incompatible |= SExt | ZExt;
195
196   if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
197     if (!isa<StructType>(PTy->getElementType()))
198       // Attributes that only apply to pointers to structs.
199       Incompatible |= ParamAttr::ByVal;
200   } else {
201     // Attributes that only apply to pointers.
202     Incompatible |= ByVal | Nest | NoAlias | StructRet;
203   }
204
205   return Incompatible;
206 }