blob: 2f754306babb6dec19a080a65277b47b80ff6cac [file] [log] [blame]
Dale Johannesen09f410b2008-02-22 22:17:59 +00001//===-- ParameterAttributes.cpp - Implement ParamAttrsList ----------------===//
Chris Lattner3e13b8c2008-01-02 23:42:30 +00002//
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//
Duncan Sands404eb052008-01-06 18:27:01 +000010// This file implements the ParamAttrsList class and ParamAttr utilities.
Chris Lattner3e13b8c2008-01-02 23:42:30 +000011//
12//===----------------------------------------------------------------------===//
13
Dale Johannesen09f410b2008-02-22 22:17:59 +000014#include "llvm/ParamAttrsList.h"
Duncan Sands404eb052008-01-06 18:27:01 +000015#include "llvm/DerivedTypes.h"
Chris Lattner3e13b8c2008-01-02 23:42:30 +000016#include "llvm/Support/ManagedStatic.h"
Dale Johannesen11a555e2008-02-19 23:51:49 +000017#include <sstream>
Gordon Henriksen8624d7b2008-01-03 03:21:18 +000018
Chris Lattner3e13b8c2008-01-02 23:42:30 +000019using namespace llvm;
20
Chris Lattnerd0e1f102008-01-03 00:10:22 +000021static ManagedStatic<FoldingSet<ParamAttrsList> > ParamAttrsLists;
22
23ParamAttrsList::ParamAttrsList(const ParamAttrsVector &attrVec)
24 : attrs(attrVec), refCount(0) {
25}
26
27ParamAttrsList::~ParamAttrsList() {
28 ParamAttrsLists->RemoveNode(this);
29}
30
Dale Johannesen89268bc2008-02-19 21:38:47 +000031ParameterAttributes
Chris Lattner3e13b8c2008-01-02 23:42:30 +000032ParamAttrsList::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
Duncan Sandsb5ca2e92008-01-14 19:52:09 +000040bool 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
Chris Lattner3e13b8c2008-01-02 23:42:30 +000047std::string
Dale Johannesen89268bc2008-02-19 21:38:47 +000048ParamAttrsList::getParamAttrsText(ParameterAttributes Attrs) {
Chris Lattner3e13b8c2008-01-02 23:42:30 +000049 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 ";
Dale Johannesen11a555e2008-02-19 23:51:49 +000072 if (Attrs & ParamAttr::Alignment) {
73 std::stringstream s;
74 s << ((Attrs & ParamAttr::Alignment) >> 16);
75 Result += "align ";
76 Result += s.str();
77 Result += " ";
78 }
Chris Lattner3e13b8c2008-01-02 23:42:30 +000079 return Result;
80}
81
Chris Lattnerb18b0b92008-01-03 00:29:27 +000082void ParamAttrsList::Profile(FoldingSetNodeID &ID,
83 const ParamAttrsVector &Attrs) {
84 for (unsigned i = 0; i < Attrs.size(); ++i)
Dale Johannesen11a555e2008-02-19 23:51:49 +000085 ID.AddInteger(uint64_t(Attrs[i].attrs) << 16 | unsigned(Attrs[i].index));
Chris Lattner3e13b8c2008-01-02 23:42:30 +000086}
87
Chris Lattner3e13b8c2008-01-02 23:42:30 +000088const ParamAttrsList *
89ParamAttrsList::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.
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000104 FoldingSetNodeID ID;
Chris Lattnerb18b0b92008-01-03 00:29:27 +0000105 ParamAttrsList::Profile(ID, attrVec);
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000106 void *InsertPos;
Chris Lattnerb18b0b92008-01-03 00:29:27 +0000107 ParamAttrsList *PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos);
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000108
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
120const ParamAttrsList *
121ParamAttrsList::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;
Duncan Sands2efbc7f2008-02-16 20:53:06 +0000135 newVec.reserve(modVec.size());
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000136 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
179const ParamAttrsList *
180ParamAttrsList::includeAttrs(const ParamAttrsList *PAL,
Dale Johannesen89268bc2008-02-19 21:38:47 +0000181 uint16_t idx, ParameterAttributes attrs) {
182 ParameterAttributes OldAttrs = PAL ? PAL->getParamAttrs(idx) :
183 ParamAttr::None;
Dale Johannesen11a555e2008-02-19 23:51:49 +0000184#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;
Anton Korobeynikov18991d72008-02-20 12:07:57 +0000189 assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
Dale Johannesen11a555e2008-02-19 23:51:49 +0000190 "Attempt to change alignment!");
191#endif
192
Dale Johannesen89268bc2008-02-19 21:38:47 +0000193 ParameterAttributes NewAttrs = OldAttrs | attrs;
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000194 if (NewAttrs == OldAttrs)
195 return PAL;
196
Duncan Sands2efbc7f2008-02-16 20:53:06 +0000197 ParamAttrsVector modVec(1);
198 modVec[0] = ParamAttrsWithIndex::get(idx, NewAttrs);
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000199 return getModified(PAL, modVec);
200}
201
202const ParamAttrsList *
203ParamAttrsList::excludeAttrs(const ParamAttrsList *PAL,
Dale Johannesen89268bc2008-02-19 21:38:47 +0000204 uint16_t idx, ParameterAttributes attrs) {
Dale Johannesen11a555e2008-02-19 23:51:49 +0000205#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
Dale Johannesen89268bc2008-02-19 21:38:47 +0000210 ParameterAttributes OldAttrs = PAL ? PAL->getParamAttrs(idx) :
211 ParamAttr::None;
212 ParameterAttributes NewAttrs = OldAttrs & ~attrs;
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000213 if (NewAttrs == OldAttrs)
214 return PAL;
215
Duncan Sands2efbc7f2008-02-16 20:53:06 +0000216 ParamAttrsVector modVec(1);
217 modVec[0] = ParamAttrsWithIndex::get(idx, NewAttrs);
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000218 return getModified(PAL, modVec);
219}
220
Dale Johannesen89268bc2008-02-19 21:38:47 +0000221ParameterAttributes ParamAttr::typeIncompatible (const Type *Ty) {
222 ParameterAttributes Incompatible = None;
Duncan Sands404eb052008-01-06 18:27:01 +0000223
224 if (!Ty->isInteger())
Duncan Sandsb18c30a2008-01-07 17:16:06 +0000225 // Attributes that only apply to integers.
226 Incompatible |= SExt | ZExt;
Duncan Sands404eb052008-01-06 18:27:01 +0000227
Duncan Sands92a56b52008-01-21 21:37:41 +0000228 if (!isa<PointerType>(Ty))
Duncan Sandsb18c30a2008-01-07 17:16:06 +0000229 // Attributes that only apply to pointers.
230 Incompatible |= ByVal | Nest | NoAlias | StructRet;
Duncan Sands404eb052008-01-06 18:27:01 +0000231
Duncan Sandsb18c30a2008-01-07 17:16:06 +0000232 return Incompatible;
Duncan Sands404eb052008-01-06 18:27:01 +0000233}