1 //===-- ParameterAttributes.cpp - Implement ParameterAttrs ----------------===//
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/ParameterAttributes.h"
15 #include "llvm/DerivedTypes.h"
16 #include "llvm/Support/ManagedStatic.h"
20 static ManagedStatic<FoldingSet<ParamAttrsList> > ParamAttrsLists;
22 ParamAttrsList::ParamAttrsList(const ParamAttrsVector &attrVec)
23 : attrs(attrVec), refCount(0) {
26 ParamAttrsList::~ParamAttrsList() {
27 ParamAttrsLists->RemoveNode(this);
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;
39 bool ParamAttrsList::hasAttrSomewhere(ParameterAttributes attr) const {
40 for (unsigned i = 0, e = attrs.size(); i < e; ++i)
41 if (attrs[i].attrs & attr)
47 ParamAttrsList::getParamAttrsText(ParameterAttributes Attrs) {
49 if (Attrs & ParamAttr::ZExt)
51 if (Attrs & ParamAttr::SExt)
53 if (Attrs & ParamAttr::NoReturn)
54 Result += "noreturn ";
55 if (Attrs & ParamAttr::NoUnwind)
56 Result += "nounwind ";
57 if (Attrs & ParamAttr::InReg)
59 if (Attrs & ParamAttr::NoAlias)
61 if (Attrs & ParamAttr::StructRet)
63 if (Attrs & ParamAttr::ByVal)
65 if (Attrs & ParamAttr::Nest)
67 if (Attrs & ParamAttr::ReadNone)
68 Result += "readnone ";
69 if (Attrs & ParamAttr::ReadOnly)
70 Result += "readonly ";
74 void ParamAttrsList::Profile(FoldingSetNodeID &ID,
75 const ParamAttrsVector &Attrs) {
76 for (unsigned i = 0; i < Attrs.size(); ++i)
77 ID.AddInteger(unsigned(Attrs[i].attrs) << 16 | unsigned(Attrs[i].index));
80 const ParamAttrsList *
81 ParamAttrsList::get(const ParamAttrsVector &attrVec) {
82 // If there are no attributes then return a null ParamAttrsList pointer.
87 for (unsigned i = 0, e = attrVec.size(); i < e; ++i) {
88 assert(attrVec[i].attrs != ParamAttr::None
89 && "Pointless parameter attribute!");
90 assert((!i || attrVec[i-1].index < attrVec[i].index)
91 && "Misordered ParamAttrsList!");
95 // Otherwise, build a key to look up the existing attributes.
97 ParamAttrsList::Profile(ID, attrVec);
99 ParamAttrsList *PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos);
101 // If we didn't find any existing attributes of the same shape then
102 // create a new one and insert it.
104 PAL = new ParamAttrsList(attrVec);
105 ParamAttrsLists->InsertNode(PAL, InsertPos);
108 // Return the ParamAttrsList that we found or created.
112 const ParamAttrsList *
113 ParamAttrsList::getModified(const ParamAttrsList *PAL,
114 const ParamAttrsVector &modVec) {
119 for (unsigned i = 0, e = modVec.size(); i < e; ++i)
120 assert((!i || modVec[i-1].index < modVec[i].index)
121 && "Misordered ParamAttrsList!");
125 // Strip any instances of ParamAttr::None from modVec before calling 'get'.
126 ParamAttrsVector newVec;
127 newVec.reserve(modVec.size());
128 for (unsigned i = 0, e = modVec.size(); i < e; ++i)
129 if (modVec[i].attrs != ParamAttr::None)
130 newVec.push_back(modVec[i]);
134 const ParamAttrsVector &oldVec = PAL->attrs;
136 ParamAttrsVector newVec;
139 unsigned oldE = oldVec.size();
140 unsigned modE = modVec.size();
142 while (oldI < oldE && modI < modE) {
143 uint16_t oldIndex = oldVec[oldI].index;
144 uint16_t modIndex = modVec[modI].index;
146 if (oldIndex < modIndex) {
147 newVec.push_back(oldVec[oldI]);
149 } else if (modIndex < oldIndex) {
150 if (modVec[modI].attrs != ParamAttr::None)
151 newVec.push_back(modVec[modI]);
154 // Same index - overwrite or delete existing attributes.
155 if (modVec[modI].attrs != ParamAttr::None)
156 newVec.push_back(modVec[modI]);
162 for (; oldI < oldE; ++oldI)
163 newVec.push_back(oldVec[oldI]);
164 for (; modI < modE; ++modI)
165 if (modVec[modI].attrs != ParamAttr::None)
166 newVec.push_back(modVec[modI]);
171 const ParamAttrsList *
172 ParamAttrsList::includeAttrs(const ParamAttrsList *PAL,
173 uint16_t idx, ParameterAttributes attrs) {
174 ParameterAttributes OldAttrs = PAL ? PAL->getParamAttrs(idx) :
176 ParameterAttributes NewAttrs = OldAttrs | attrs;
177 if (NewAttrs == OldAttrs)
180 ParamAttrsVector modVec(1);
181 modVec[0] = ParamAttrsWithIndex::get(idx, NewAttrs);
182 return getModified(PAL, modVec);
185 const ParamAttrsList *
186 ParamAttrsList::excludeAttrs(const ParamAttrsList *PAL,
187 uint16_t idx, ParameterAttributes attrs) {
188 ParameterAttributes OldAttrs = PAL ? PAL->getParamAttrs(idx) :
190 ParameterAttributes NewAttrs = OldAttrs & ~attrs;
191 if (NewAttrs == OldAttrs)
194 ParamAttrsVector modVec(1);
195 modVec[0] = ParamAttrsWithIndex::get(idx, NewAttrs);
196 return getModified(PAL, modVec);
199 ParameterAttributes ParamAttr::typeIncompatible (const Type *Ty) {
200 ParameterAttributes Incompatible = None;
202 if (!Ty->isInteger())
203 // Attributes that only apply to integers.
204 Incompatible |= SExt | ZExt;
206 if (!isa<PointerType>(Ty))
207 // Attributes that only apply to pointers.
208 Incompatible |= ByVal | Nest | NoAlias | StructRet;