blob: 344e52c59a470eef1e21d68d7eaab431a5b4772d [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//
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
14#include "llvm/ParameterAttributes.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"
Gordon Henriksen8624d7b2008-01-03 03:21:18 +000017
Chris Lattner3e13b8c2008-01-02 23:42:30 +000018using namespace llvm;
19
Chris Lattnerd0e1f102008-01-03 00:10:22 +000020static ManagedStatic<FoldingSet<ParamAttrsList> > ParamAttrsLists;
21
22ParamAttrsList::ParamAttrsList(const ParamAttrsVector &attrVec)
23 : attrs(attrVec), refCount(0) {
24}
25
26ParamAttrsList::~ParamAttrsList() {
27 ParamAttrsLists->RemoveNode(this);
28}
29
Chris Lattner3e13b8c2008-01-02 23:42:30 +000030uint16_t
31ParamAttrsList::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
Duncan Sandsb5ca2e92008-01-14 19:52:09 +000039bool ParamAttrsList::hasAttrSomewhere(ParameterAttributes attr) const {
40 for (unsigned i = 0, e = attrs.size(); i < e; ++i)
41 if (attrs[i].attrs & attr)
42 return true;
43 return false;
44}
45
Chris Lattner3e13b8c2008-01-02 23:42:30 +000046std::string
47ParamAttrsList::getParamAttrsText(uint16_t Attrs) {
48 std::string Result;
49 if (Attrs & ParamAttr::ZExt)
50 Result += "zeroext ";
51 if (Attrs & ParamAttr::SExt)
52 Result += "signext ";
53 if (Attrs & ParamAttr::NoReturn)
54 Result += "noreturn ";
55 if (Attrs & ParamAttr::NoUnwind)
56 Result += "nounwind ";
57 if (Attrs & ParamAttr::InReg)
58 Result += "inreg ";
59 if (Attrs & ParamAttr::NoAlias)
60 Result += "noalias ";
61 if (Attrs & ParamAttr::StructRet)
62 Result += "sret ";
63 if (Attrs & ParamAttr::ByVal)
64 Result += "byval ";
65 if (Attrs & ParamAttr::Nest)
66 Result += "nest ";
67 if (Attrs & ParamAttr::ReadNone)
68 Result += "readnone ";
69 if (Attrs & ParamAttr::ReadOnly)
70 Result += "readonly ";
71 return Result;
72}
73
Chris Lattnerb18b0b92008-01-03 00:29:27 +000074void 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));
Chris Lattner3e13b8c2008-01-02 23:42:30 +000078}
79
Chris Lattner3e13b8c2008-01-02 23:42:30 +000080const ParamAttrsList *
81ParamAttrsList::get(const ParamAttrsVector &attrVec) {
82 // If there are no attributes then return a null ParamAttrsList pointer.
83 if (attrVec.empty())
84 return 0;
85
86#ifndef NDEBUG
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!");
92 }
93#endif
94
95 // Otherwise, build a key to look up the existing attributes.
Chris Lattner3e13b8c2008-01-02 23:42:30 +000096 FoldingSetNodeID ID;
Chris Lattnerb18b0b92008-01-03 00:29:27 +000097 ParamAttrsList::Profile(ID, attrVec);
Chris Lattner3e13b8c2008-01-02 23:42:30 +000098 void *InsertPos;
Chris Lattnerb18b0b92008-01-03 00:29:27 +000099 ParamAttrsList *PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos);
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000100
101 // If we didn't find any existing attributes of the same shape then
102 // create a new one and insert it.
103 if (!PAL) {
104 PAL = new ParamAttrsList(attrVec);
105 ParamAttrsLists->InsertNode(PAL, InsertPos);
106 }
107
108 // Return the ParamAttrsList that we found or created.
109 return PAL;
110}
111
112const ParamAttrsList *
113ParamAttrsList::getModified(const ParamAttrsList *PAL,
114 const ParamAttrsVector &modVec) {
115 if (modVec.empty())
116 return PAL;
117
118#ifndef NDEBUG
119 for (unsigned i = 0, e = modVec.size(); i < e; ++i)
120 assert((!i || modVec[i-1].index < modVec[i].index)
121 && "Misordered ParamAttrsList!");
122#endif
123
124 if (!PAL) {
125 // Strip any instances of ParamAttr::None from modVec before calling 'get'.
126 ParamAttrsVector newVec;
Duncan Sands2efbc7f2008-02-16 20:53:06 +0000127 newVec.reserve(modVec.size());
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000128 for (unsigned i = 0, e = modVec.size(); i < e; ++i)
129 if (modVec[i].attrs != ParamAttr::None)
130 newVec.push_back(modVec[i]);
131 return get(newVec);
132 }
133
134 const ParamAttrsVector &oldVec = PAL->attrs;
135
136 ParamAttrsVector newVec;
137 unsigned oldI = 0;
138 unsigned modI = 0;
139 unsigned oldE = oldVec.size();
140 unsigned modE = modVec.size();
141
142 while (oldI < oldE && modI < modE) {
143 uint16_t oldIndex = oldVec[oldI].index;
144 uint16_t modIndex = modVec[modI].index;
145
146 if (oldIndex < modIndex) {
147 newVec.push_back(oldVec[oldI]);
148 ++oldI;
149 } else if (modIndex < oldIndex) {
150 if (modVec[modI].attrs != ParamAttr::None)
151 newVec.push_back(modVec[modI]);
152 ++modI;
153 } else {
154 // Same index - overwrite or delete existing attributes.
155 if (modVec[modI].attrs != ParamAttr::None)
156 newVec.push_back(modVec[modI]);
157 ++oldI;
158 ++modI;
159 }
160 }
161
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]);
167
168 return get(newVec);
169}
170
171const ParamAttrsList *
172ParamAttrsList::includeAttrs(const ParamAttrsList *PAL,
173 uint16_t idx, uint16_t attrs) {
174 uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
175 uint16_t NewAttrs = OldAttrs | attrs;
176 if (NewAttrs == OldAttrs)
177 return PAL;
178
Duncan Sands2efbc7f2008-02-16 20:53:06 +0000179 ParamAttrsVector modVec(1);
180 modVec[0] = ParamAttrsWithIndex::get(idx, NewAttrs);
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000181 return getModified(PAL, modVec);
182}
183
184const ParamAttrsList *
185ParamAttrsList::excludeAttrs(const ParamAttrsList *PAL,
186 uint16_t idx, uint16_t attrs) {
187 uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
188 uint16_t NewAttrs = OldAttrs & ~attrs;
189 if (NewAttrs == OldAttrs)
190 return PAL;
191
Duncan Sands2efbc7f2008-02-16 20:53:06 +0000192 ParamAttrsVector modVec(1);
193 modVec[0] = ParamAttrsWithIndex::get(idx, NewAttrs);
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000194 return getModified(PAL, modVec);
195}
196
Duncan Sandsb18c30a2008-01-07 17:16:06 +0000197uint16_t ParamAttr::typeIncompatible (const Type *Ty) {
Duncan Sands404eb052008-01-06 18:27:01 +0000198 uint16_t Incompatible = None;
199
200 if (!Ty->isInteger())
Duncan Sandsb18c30a2008-01-07 17:16:06 +0000201 // Attributes that only apply to integers.
202 Incompatible |= SExt | ZExt;
Duncan Sands404eb052008-01-06 18:27:01 +0000203
Duncan Sands92a56b52008-01-21 21:37:41 +0000204 if (!isa<PointerType>(Ty))
Duncan Sandsb18c30a2008-01-07 17:16:06 +0000205 // Attributes that only apply to pointers.
206 Incompatible |= ByVal | Nest | NoAlias | StructRet;
Duncan Sands404eb052008-01-06 18:27:01 +0000207
Duncan Sandsb18c30a2008-01-07 17:16:06 +0000208 return Incompatible;
Duncan Sands404eb052008-01-06 18:27:01 +0000209}