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