1 //===-- ParameterAttributes.cpp - Implement ParamAttrsList ----------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the ParamAttrsList class and ParamAttr utilities.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/ParamAttrsList.h"
15 #include "llvm/DerivedTypes.h"
16 #include "llvm/Support/ManagedStatic.h"
21 static ManagedStatic<FoldingSet<ParamAttrsList> > ParamAttrsLists;
23 ParamAttrsList::ParamAttrsList(const ParamAttrsVector &attrVec)
24 : attrs(attrVec), refCount(0) {
27 ParamAttrsList::~ParamAttrsList() {
28 ParamAttrsLists->RemoveNode(this);
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;
40 bool ParamAttrsList::hasAttrSomewhere(ParameterAttributes attr) const {
41 for (unsigned i = 0, e = attrs.size(); i < e; ++i)
42 if (attrs[i].attrs & attr)
48 ParamAttrsList::getParamAttrsText(ParameterAttributes Attrs) {
50 if (Attrs & ParamAttr::ZExt)
52 if (Attrs & ParamAttr::SExt)
54 if (Attrs & ParamAttr::NoReturn)
55 Result += "noreturn ";
56 if (Attrs & ParamAttr::NoUnwind)
57 Result += "nounwind ";
58 if (Attrs & ParamAttr::InReg)
60 if (Attrs & ParamAttr::NoAlias)
62 if (Attrs & ParamAttr::StructRet)
64 if (Attrs & ParamAttr::ByVal)
66 if (Attrs & ParamAttr::Nest)
68 if (Attrs & ParamAttr::ReadNone)
69 Result += "readnone ";
70 if (Attrs & ParamAttr::ReadOnly)
71 Result += "readonly ";
72 if (Attrs & ParamAttr::Alignment) {
74 s << ((Attrs & ParamAttr::Alignment) >> 16);
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));
88 const ParamAttrsList *
89 ParamAttrsList::get(const ParamAttrsVector &attrVec) {
90 // If there are no attributes then return a null ParamAttrsList pointer.
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!");
103 // Otherwise, build a key to look up the existing attributes.
105 ParamAttrsList::Profile(ID, attrVec);
107 ParamAttrsList *PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos);
109 // If we didn't find any existing attributes of the same shape then
110 // create a new one and insert it.
112 PAL = new ParamAttrsList(attrVec);
113 ParamAttrsLists->InsertNode(PAL, InsertPos);
116 // Return the ParamAttrsList that we found or created.
120 const ParamAttrsList *
121 ParamAttrsList::getModified(const ParamAttrsList *PAL,
122 const ParamAttrsVector &modVec) {
127 for (unsigned i = 0, e = modVec.size(); i < e; ++i)
128 assert((!i || modVec[i-1].index < modVec[i].index)
129 && "Misordered ParamAttrsList!");
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]);
142 const ParamAttrsVector &oldVec = PAL->attrs;
144 ParamAttrsVector newVec;
147 unsigned oldE = oldVec.size();
148 unsigned modE = modVec.size();
150 while (oldI < oldE && modI < modE) {
151 uint16_t oldIndex = oldVec[oldI].index;
152 uint16_t modIndex = modVec[modI].index;
154 if (oldIndex < modIndex) {
155 newVec.push_back(oldVec[oldI]);
157 } else if (modIndex < oldIndex) {
158 if (modVec[modI].attrs != ParamAttr::None)
159 newVec.push_back(modVec[modI]);
162 // Same index - overwrite or delete existing attributes.
163 if (modVec[modI].attrs != ParamAttr::None)
164 newVec.push_back(modVec[modI]);
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]);
179 const ParamAttrsList *
180 ParamAttrsList::includeAttrs(const ParamAttrsList *PAL,
181 uint16_t idx, ParameterAttributes attrs) {
182 ParameterAttributes OldAttrs = PAL ? PAL->getParamAttrs(idx) :
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!");
193 ParameterAttributes NewAttrs = OldAttrs | attrs;
194 if (NewAttrs == OldAttrs)
197 ParamAttrsVector modVec(1);
198 modVec[0] = ParamAttrsWithIndex::get(idx, NewAttrs);
199 return getModified(PAL, modVec);
202 const ParamAttrsList *
203 ParamAttrsList::excludeAttrs(const ParamAttrsList *PAL,
204 uint16_t idx, ParameterAttributes attrs) {
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!");
210 ParameterAttributes OldAttrs = PAL ? PAL->getParamAttrs(idx) :
212 ParameterAttributes NewAttrs = OldAttrs & ~attrs;
213 if (NewAttrs == OldAttrs)
216 ParamAttrsVector modVec(1);
217 modVec[0] = ParamAttrsWithIndex::get(idx, NewAttrs);
218 return getModified(PAL, modVec);
221 ParameterAttributes ParamAttr::typeIncompatible (const Type *Ty) {
222 ParameterAttributes Incompatible = None;
224 if (!Ty->isInteger())
225 // Attributes that only apply to integers.
226 Incompatible |= SExt | ZExt;
228 if (!isa<PointerType>(Ty))
229 // Attributes that only apply to pointers.
230 Incompatible |= ByVal | Nest | NoAlias | StructRet;