blob: 77a2a6e7fe3317ff91faa08e141d210a2df8a6ca [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
39std::string
40ParamAttrsList::getParamAttrsText(uint16_t Attrs) {
41 std::string Result;
42 if (Attrs & ParamAttr::ZExt)
43 Result += "zeroext ";
44 if (Attrs & ParamAttr::SExt)
45 Result += "signext ";
46 if (Attrs & ParamAttr::NoReturn)
47 Result += "noreturn ";
48 if (Attrs & ParamAttr::NoUnwind)
49 Result += "nounwind ";
50 if (Attrs & ParamAttr::InReg)
51 Result += "inreg ";
52 if (Attrs & ParamAttr::NoAlias)
53 Result += "noalias ";
54 if (Attrs & ParamAttr::StructRet)
55 Result += "sret ";
56 if (Attrs & ParamAttr::ByVal)
57 Result += "byval ";
58 if (Attrs & ParamAttr::Nest)
59 Result += "nest ";
60 if (Attrs & ParamAttr::ReadNone)
61 Result += "readnone ";
62 if (Attrs & ParamAttr::ReadOnly)
63 Result += "readonly ";
64 return Result;
65}
66
Chris Lattnerb18b0b92008-01-03 00:29:27 +000067void ParamAttrsList::Profile(FoldingSetNodeID &ID,
68 const ParamAttrsVector &Attrs) {
69 for (unsigned i = 0; i < Attrs.size(); ++i)
70 ID.AddInteger(unsigned(Attrs[i].attrs) << 16 | unsigned(Attrs[i].index));
Chris Lattner3e13b8c2008-01-02 23:42:30 +000071}
72
Chris Lattner3e13b8c2008-01-02 23:42:30 +000073const ParamAttrsList *
74ParamAttrsList::get(const ParamAttrsVector &attrVec) {
75 // If there are no attributes then return a null ParamAttrsList pointer.
76 if (attrVec.empty())
77 return 0;
78
79#ifndef NDEBUG
80 for (unsigned i = 0, e = attrVec.size(); i < e; ++i) {
81 assert(attrVec[i].attrs != ParamAttr::None
82 && "Pointless parameter attribute!");
83 assert((!i || attrVec[i-1].index < attrVec[i].index)
84 && "Misordered ParamAttrsList!");
85 }
86#endif
87
88 // Otherwise, build a key to look up the existing attributes.
Chris Lattner3e13b8c2008-01-02 23:42:30 +000089 FoldingSetNodeID ID;
Chris Lattnerb18b0b92008-01-03 00:29:27 +000090 ParamAttrsList::Profile(ID, attrVec);
Chris Lattner3e13b8c2008-01-02 23:42:30 +000091 void *InsertPos;
Chris Lattnerb18b0b92008-01-03 00:29:27 +000092 ParamAttrsList *PAL = ParamAttrsLists->FindNodeOrInsertPos(ID, InsertPos);
Chris Lattner3e13b8c2008-01-02 23:42:30 +000093
94 // If we didn't find any existing attributes of the same shape then
95 // create a new one and insert it.
96 if (!PAL) {
97 PAL = new ParamAttrsList(attrVec);
98 ParamAttrsLists->InsertNode(PAL, InsertPos);
99 }
100
101 // Return the ParamAttrsList that we found or created.
102 return PAL;
103}
104
105const ParamAttrsList *
106ParamAttrsList::getModified(const ParamAttrsList *PAL,
107 const ParamAttrsVector &modVec) {
108 if (modVec.empty())
109 return PAL;
110
111#ifndef NDEBUG
112 for (unsigned i = 0, e = modVec.size(); i < e; ++i)
113 assert((!i || modVec[i-1].index < modVec[i].index)
114 && "Misordered ParamAttrsList!");
115#endif
116
117 if (!PAL) {
118 // Strip any instances of ParamAttr::None from modVec before calling 'get'.
119 ParamAttrsVector newVec;
120 for (unsigned i = 0, e = modVec.size(); i < e; ++i)
121 if (modVec[i].attrs != ParamAttr::None)
122 newVec.push_back(modVec[i]);
123 return get(newVec);
124 }
125
126 const ParamAttrsVector &oldVec = PAL->attrs;
127
128 ParamAttrsVector newVec;
129 unsigned oldI = 0;
130 unsigned modI = 0;
131 unsigned oldE = oldVec.size();
132 unsigned modE = modVec.size();
133
134 while (oldI < oldE && modI < modE) {
135 uint16_t oldIndex = oldVec[oldI].index;
136 uint16_t modIndex = modVec[modI].index;
137
138 if (oldIndex < modIndex) {
139 newVec.push_back(oldVec[oldI]);
140 ++oldI;
141 } else if (modIndex < oldIndex) {
142 if (modVec[modI].attrs != ParamAttr::None)
143 newVec.push_back(modVec[modI]);
144 ++modI;
145 } else {
146 // Same index - overwrite or delete existing attributes.
147 if (modVec[modI].attrs != ParamAttr::None)
148 newVec.push_back(modVec[modI]);
149 ++oldI;
150 ++modI;
151 }
152 }
153
154 for (; oldI < oldE; ++oldI)
155 newVec.push_back(oldVec[oldI]);
156 for (; modI < modE; ++modI)
157 if (modVec[modI].attrs != ParamAttr::None)
158 newVec.push_back(modVec[modI]);
159
160 return get(newVec);
161}
162
163const ParamAttrsList *
164ParamAttrsList::includeAttrs(const ParamAttrsList *PAL,
165 uint16_t idx, uint16_t attrs) {
166 uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
167 uint16_t NewAttrs = OldAttrs | attrs;
168 if (NewAttrs == OldAttrs)
169 return PAL;
170
171 ParamAttrsVector modVec;
172 modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
173 return getModified(PAL, modVec);
174}
175
176const ParamAttrsList *
177ParamAttrsList::excludeAttrs(const ParamAttrsList *PAL,
178 uint16_t idx, uint16_t attrs) {
179 uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
180 uint16_t NewAttrs = OldAttrs & ~attrs;
181 if (NewAttrs == OldAttrs)
182 return PAL;
183
184 ParamAttrsVector modVec;
185 modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
186 return getModified(PAL, modVec);
187}
188
Duncan Sandsb18c30a2008-01-07 17:16:06 +0000189uint16_t ParamAttr::typeIncompatible (const Type *Ty) {
Duncan Sands404eb052008-01-06 18:27:01 +0000190 uint16_t Incompatible = None;
191
192 if (!Ty->isInteger())
Duncan Sandsb18c30a2008-01-07 17:16:06 +0000193 // Attributes that only apply to integers.
194 Incompatible |= SExt | ZExt;
Duncan Sands404eb052008-01-06 18:27:01 +0000195
Duncan Sandsb18c30a2008-01-07 17:16:06 +0000196 if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
Duncan Sands404eb052008-01-06 18:27:01 +0000197 if (!isa<StructType>(PTy->getElementType()))
Duncan Sandsb18c30a2008-01-07 17:16:06 +0000198 // Attributes that only apply to pointers to structs.
Duncan Sands404eb052008-01-06 18:27:01 +0000199 Incompatible |= ParamAttr::ByVal;
Duncan Sandsb18c30a2008-01-07 17:16:06 +0000200 } else {
201 // Attributes that only apply to pointers.
202 Incompatible |= ByVal | Nest | NoAlias | StructRet;
Duncan Sands404eb052008-01-06 18:27:01 +0000203 }
204
Duncan Sandsb18c30a2008-01-07 17:16:06 +0000205 return Incompatible;
Duncan Sands404eb052008-01-06 18:27:01 +0000206}