blob: 12f0699c02a3e7b22a8011151a939099778172db [file] [log] [blame]
Devang Patel4c758ea2008-09-25 21:00:45 +00001//===-- Attributes.cpp - Implement AttributesList -------------------------===//
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//
Devang Patel4c758ea2008-09-25 21:00:45 +000010// This file implements the AttributesList class and Attribute utilities.
Chris Lattner3e13b8c2008-01-02 23:42:30 +000011//
12//===----------------------------------------------------------------------===//
13
Devang Patelba3fa6c2008-09-23 23:03:40 +000014#include "llvm/Attributes.h"
Bill Wendlinge38b8042012-09-26 21:07:29 +000015#include "AttributesImpl.h"
16#include "LLVMContextImpl.h"
Chris Lattner8a923e72008-03-12 17:45:29 +000017#include "llvm/Type.h"
Dan Gohmanfc429612008-03-10 23:55:07 +000018#include "llvm/ADT/StringExtras.h"
Chris Lattner8a923e72008-03-12 17:45:29 +000019#include "llvm/ADT/FoldingSet.h"
Michael J. Spencer447762d2010-11-29 18:16:10 +000020#include "llvm/Support/Atomic.h"
21#include "llvm/Support/Mutex.h"
David Greenef7014732010-01-05 01:29:58 +000022#include "llvm/Support/Debug.h"
Chris Lattner3e13b8c2008-01-02 23:42:30 +000023#include "llvm/Support/ManagedStatic.h"
Benjamin Kramer1a25d732009-08-23 11:37:21 +000024#include "llvm/Support/raw_ostream.h"
Chris Lattner3e13b8c2008-01-02 23:42:30 +000025using namespace llvm;
26
Chris Lattner8a923e72008-03-12 17:45:29 +000027//===----------------------------------------------------------------------===//
Devang Patel4c758ea2008-09-25 21:00:45 +000028// Attribute Function Definitions
Chris Lattner8a923e72008-03-12 17:45:29 +000029//===----------------------------------------------------------------------===//
Chris Lattnerd0e1f102008-01-03 00:10:22 +000030
Bill Wendlingabf3feb2012-10-05 06:44:41 +000031bool Attributes::hasAddressSafetyAttr() const {
32 return Bits & Attribute::AddressSafety_i;
33}
34bool Attributes::hasAlignmentAttr() const {
35 return Bits & Attribute::Alignment_i;
36}
37bool Attributes::hasAlwaysInlineAttr() const {
38 return Bits & Attribute::AlwaysInline_i;
39}
40bool Attributes::hasByValAttr() const {
41 return Bits & Attribute::ByVal_i;
42}
43bool Attributes::hasInlineHintAttr() const {
44 return Bits & Attribute::InlineHint_i;
45}
46bool Attributes::hasInRegAttr() const {
47 return Bits & Attribute::InReg_i;
48}
49bool Attributes::hasNakedAttr() const {
50 return Bits & Attribute::Naked_i;
51}
52bool Attributes::hasNestAttr() const {
53 return Bits & Attribute::Nest_i;
54}
55bool Attributes::hasNoAliasAttr() const {
56 return Bits & Attribute::NoAlias_i;
57}
58bool Attributes::hasNoCaptureAttr() const {
59 return Bits & Attribute::NoCapture_i;
60}
61bool Attributes::hasNoImplicitFloatAttr() const {
62 return Bits & Attribute::NoImplicitFloat_i;
63}
64bool Attributes::hasNoInlineAttr() const {
65 return Bits & Attribute::NoInline_i;
66}
67bool Attributes::hasNonLazyBindAttr() const {
68 return Bits & Attribute::NonLazyBind_i;
69}
70bool Attributes::hasNoRedZoneAttr() const {
71 return Bits & Attribute::NoRedZone_i;
72}
73bool Attributes::hasNoReturnAttr() const {
74 return Bits & Attribute::NoReturn_i;
75}
76bool Attributes::hasNoUnwindAttr() const {
77 return Bits & Attribute::NoUnwind_i;
78}
79bool Attributes::hasOptimizeForSizeAttr() const {
80 return Bits & Attribute::OptimizeForSize_i;
81}
82bool Attributes::hasReadNoneAttr() const {
83 return Bits & Attribute::ReadNone_i;
84}
85bool Attributes::hasReadOnlyAttr() const {
86 return Bits & Attribute::ReadOnly_i;
87}
88bool Attributes::hasReturnsTwiceAttr() const {
89 return Bits & Attribute::ReturnsTwice_i;
90}
91bool Attributes::hasSExtAttr() const {
92 return Bits & Attribute::SExt_i;
93}
94bool Attributes::hasStackAlignmentAttr() const {
95 return Bits & Attribute::StackAlignment_i;
96}
97bool Attributes::hasStackProtectAttr() const {
98 return Bits & Attribute::StackProtect_i;
99}
100bool Attributes::hasStackProtectReqAttr() const {
101 return Bits & Attribute::StackProtectReq_i;
102}
103bool Attributes::hasStructRetAttr() const {
104 return Bits & Attribute::StructRet_i;
105}
106bool Attributes::hasUWTableAttr() const {
107 return Bits & Attribute::UWTable_i;
108}
109bool Attributes::hasZExtAttr() const {
110 return Bits & Attribute::ZExt_i;
111}
112
113/// This returns the alignment field of an attribute as a byte alignment value.
114unsigned Attributes::getAlignment() const {
115 if (!hasAlignmentAttr())
116 return 0;
117 return 1U << (((Bits & Attribute::Alignment_i) >> 16) - 1);
118}
119
120/// This returns the stack alignment field of an attribute as a byte alignment
121/// value.
122unsigned Attributes::getStackAlignment() const {
123 if (!hasStackAlignmentAttr())
124 return 0;
125 return 1U << (((Bits & Attribute::StackAlignment_i) >> 26) - 1);
126}
127
128Attributes Attributes::typeIncompatible(Type *Ty) {
129 Attributes::Builder Incompatible;
130
131 if (!Ty->isIntegerTy()) {
132 // Attributes that only apply to integers.
133 Incompatible.addSExtAttr();
134 Incompatible.addZExtAttr();
135 }
136
137 if (!Ty->isPointerTy()) {
138 // Attributes that only apply to pointers.
139 Incompatible.addByValAttr();
140 Incompatible.addNestAttr();
141 Incompatible.addNoAliasAttr();
142 Incompatible.addNoCaptureAttr();
143 Incompatible.addStructRetAttr();
144 }
145
146 return Attributes(Incompatible.Bits); // FIXME: Use Attributes::get().
147}
148
Bill Wendlingde74cf52012-09-20 14:44:42 +0000149std::string Attributes::getAsString() const {
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000150 std::string Result;
Bill Wendlingde74cf52012-09-20 14:44:42 +0000151 if (hasZExtAttr())
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000152 Result += "zeroext ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000153 if (hasSExtAttr())
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000154 Result += "signext ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000155 if (hasNoReturnAttr())
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000156 Result += "noreturn ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000157 if (hasNoUnwindAttr())
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000158 Result += "nounwind ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000159 if (hasUWTableAttr())
Rafael Espindolafc9bae62011-05-25 03:44:17 +0000160 Result += "uwtable ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000161 if (hasReturnsTwiceAttr())
Rafael Espindolacc349c82011-10-03 14:45:37 +0000162 Result += "returns_twice ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000163 if (hasInRegAttr())
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000164 Result += "inreg ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000165 if (hasNoAliasAttr())
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000166 Result += "noalias ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000167 if (hasNoCaptureAttr())
Nick Lewycky8d69f482008-12-19 09:38:31 +0000168 Result += "nocapture ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000169 if (hasStructRetAttr())
Anton Korobeynikovc8ce7b082009-07-17 18:07:26 +0000170 Result += "sret ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000171 if (hasByValAttr())
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000172 Result += "byval ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000173 if (hasNestAttr())
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000174 Result += "nest ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000175 if (hasReadNoneAttr())
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000176 Result += "readnone ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000177 if (hasReadOnlyAttr())
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000178 Result += "readonly ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000179 if (hasOptimizeForSizeAttr())
Devang Patela05633e2008-09-26 22:53:05 +0000180 Result += "optsize ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000181 if (hasNoInlineAttr())
Devang Patela05633e2008-09-26 22:53:05 +0000182 Result += "noinline ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000183 if (hasInlineHintAttr())
Jakob Stoklund Olesen74bb06c2010-02-06 01:16:28 +0000184 Result += "inlinehint ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000185 if (hasAlwaysInlineAttr())
Devang Patela05633e2008-09-26 22:53:05 +0000186 Result += "alwaysinline ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000187 if (hasStackProtectAttr())
Bill Wendlingccb67a3d2008-11-13 01:02:14 +0000188 Result += "ssp ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000189 if (hasStackProtectReqAttr())
Bill Wendlingccb67a3d2008-11-13 01:02:14 +0000190 Result += "sspreq ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000191 if (hasNoRedZoneAttr())
Devang Patel72a4d2f2009-06-04 22:05:33 +0000192 Result += "noredzone ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000193 if (hasNoImplicitFloatAttr())
Devang Pateld1c7d342009-06-05 21:57:13 +0000194 Result += "noimplicitfloat ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000195 if (hasNakedAttr())
Anton Korobeynikovc8ce7b082009-07-17 18:07:26 +0000196 Result += "naked ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000197 if (hasNonLazyBindAttr())
John McCall4b7a8d62011-06-15 20:36:13 +0000198 Result += "nonlazybind ";
Bill Wendlingde74cf52012-09-20 14:44:42 +0000199 if (hasAddressSafetyAttr())
Kostya Serebryanya5054ad2012-01-20 17:56:17 +0000200 Result += "address_safety ";
Bill Wendlingb4e211c2012-09-20 15:20:36 +0000201 if (hasStackAlignmentAttr()) {
Charles Davisbe5557e2010-02-12 00:31:15 +0000202 Result += "alignstack(";
Bill Wendling9be77592012-09-21 15:26:31 +0000203 Result += utostr(getStackAlignment());
Charles Davisbe5557e2010-02-12 00:31:15 +0000204 Result += ") ";
205 }
Bill Wendlingb4e211c2012-09-20 15:20:36 +0000206 if (hasAlignmentAttr()) {
Dale Johannesen11a555e2008-02-19 23:51:49 +0000207 Result += "align ";
Bill Wendling9be77592012-09-21 15:26:31 +0000208 Result += utostr(getAlignment());
Dale Johannesen11a555e2008-02-19 23:51:49 +0000209 Result += " ";
210 }
Dan Gohman1a70bcc2008-08-05 15:51:44 +0000211 // Trim the trailing space.
Nick Lewycky8d69f482008-12-19 09:38:31 +0000212 assert(!Result.empty() && "Unknown attribute!");
Dan Gohman1a70bcc2008-08-05 15:51:44 +0000213 Result.erase(Result.end()-1);
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000214 return Result;
215}
216
Bill Wendlingabf3feb2012-10-05 06:44:41 +0000217//===----------------------------------------------------------------------===//
218// Attributes::Builder Implementation
219//===----------------------------------------------------------------------===//
220
221void Attributes::Builder::addAddressSafetyAttr() {
222 Bits |= Attribute::AddressSafety_i;
223}
224void Attributes::Builder::addAlwaysInlineAttr() {
225 Bits |= Attribute::AlwaysInline_i;
226}
227void Attributes::Builder::addByValAttr() {
228 Bits |= Attribute::ByVal_i;
229}
230void Attributes::Builder::addInlineHintAttr() {
231 Bits |= Attribute::InlineHint_i;
232}
233void Attributes::Builder::addInRegAttr() {
234 Bits |= Attribute::InReg_i;
235}
236void Attributes::Builder::addNakedAttr() {
237 Bits |= Attribute::Naked_i;
238}
239void Attributes::Builder::addNestAttr() {
240 Bits |= Attribute::Nest_i;
241}
242void Attributes::Builder::addNoAliasAttr() {
243 Bits |= Attribute::NoAlias_i;
244}
245void Attributes::Builder::addNoCaptureAttr() {
246 Bits |= Attribute::NoCapture_i;
247}
248void Attributes::Builder::addNoImplicitFloatAttr() {
249 Bits |= Attribute::NoImplicitFloat_i;
250}
251void Attributes::Builder::addNoInlineAttr() {
252 Bits |= Attribute::NoInline_i;
253}
254void Attributes::Builder::addNonLazyBindAttr() {
255 Bits |= Attribute::NonLazyBind_i;
256}
257void Attributes::Builder::addNoRedZoneAttr() {
258 Bits |= Attribute::NoRedZone_i;
259}
260void Attributes::Builder::addNoReturnAttr() {
261 Bits |= Attribute::NoReturn_i;
262}
263void Attributes::Builder::addNoUnwindAttr() {
264 Bits |= Attribute::NoUnwind_i;
265}
266void Attributes::Builder::addOptimizeForSizeAttr() {
267 Bits |= Attribute::OptimizeForSize_i;
268}
269void Attributes::Builder::addReadNoneAttr() {
270 Bits |= Attribute::ReadNone_i;
271}
272void Attributes::Builder::addReadOnlyAttr() {
273 Bits |= Attribute::ReadOnly_i;
274}
275void Attributes::Builder::addReturnsTwiceAttr() {
276 Bits |= Attribute::ReturnsTwice_i;
277}
278void Attributes::Builder::addSExtAttr() {
279 Bits |= Attribute::SExt_i;
280}
281void Attributes::Builder::addStackProtectAttr() {
282 Bits |= Attribute::StackProtect_i;
283}
284void Attributes::Builder::addStackProtectReqAttr() {
285 Bits |= Attribute::StackProtectReq_i;
286}
287void Attributes::Builder::addStructRetAttr() {
288 Bits |= Attribute::StructRet_i;
289}
290void Attributes::Builder::addUWTableAttr() {
291 Bits |= Attribute::UWTable_i;
292}
293void Attributes::Builder::addZExtAttr() {
294 Bits |= Attribute::ZExt_i;
295}
296
297void Attributes::Builder::addAlignmentAttr(unsigned Align) {
298 if (Align == 0) return;
299 assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
300 assert(Align <= 0x40000000 && "Alignment too large.");
301 Bits |= (Log2_32(Align) + 1) << 16;
302}
303void Attributes::Builder::addStackAlignmentAttr(unsigned Align) {
304 // Default alignment, allow the target to define how to align it.
305 if (Align == 0) return;
306 assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
307 assert(Align <= 0x100 && "Alignment too large.");
308 Bits |= (Log2_32(Align) + 1) << 26;
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000309}
310
Chris Lattner8a923e72008-03-12 17:45:29 +0000311//===----------------------------------------------------------------------===//
Bill Wendlinge38b8042012-09-26 21:07:29 +0000312// AttributeImpl Definition
313//===----------------------------------------------------------------------===//
314
315Attributes::Attributes(AttributesImpl *A) : Bits(0) {}
316
317Attributes Attributes::get(LLVMContext &Context, Attributes::Builder &B) {
318 // If there are no attributes, return an empty Attributes class.
319 if (B.Bits == 0)
320 return Attributes();
321
322 // Otherwise, build a key to look up the existing attributes.
323 LLVMContextImpl *pImpl = Context.pImpl;
324 FoldingSetNodeID ID;
325 ID.AddInteger(B.Bits);
326
327 void *InsertPoint;
328 AttributesImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
329
330 if (!PA) {
331 // If we didn't find any existing attributes of the same shape then create a
332 // new one and insert it.
333 PA = new AttributesImpl(B.Bits);
334 pImpl->AttrsSet.InsertNode(PA, InsertPoint);
335 }
336
337 // Return the AttributesList that we found or created.
338 return Attributes(PA);
339}
340
341//===----------------------------------------------------------------------===//
Devang Patel00095052008-09-24 00:29:49 +0000342// AttributeListImpl Definition
Chris Lattner8a923e72008-03-12 17:45:29 +0000343//===----------------------------------------------------------------------===//
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000344
Owen Anderson2e831892010-11-18 18:59:13 +0000345namespace llvm {
346 class AttributeListImpl;
347}
348
349static ManagedStatic<FoldingSet<AttributeListImpl> > AttributesLists;
Owen Anderson9b14a252010-11-09 00:27:03 +0000350
Chris Lattner8a923e72008-03-12 17:45:29 +0000351namespace llvm {
Owen Anderson9b14a252010-11-09 00:27:03 +0000352static ManagedStatic<sys::SmartMutex<true> > ALMutex;
353
Devang Patel00095052008-09-24 00:29:49 +0000354class AttributeListImpl : public FoldingSetNode {
Owen Andersonc1a3a472009-08-20 19:03:20 +0000355 sys::cas_flag RefCount;
Chris Lattner8a923e72008-03-12 17:45:29 +0000356
Devang Patel4c758ea2008-09-25 21:00:45 +0000357 // AttributesList is uniqued, these should not be publicly available.
Craig Topperb1d83e82012-09-18 02:01:41 +0000358 void operator=(const AttributeListImpl &) LLVM_DELETED_FUNCTION;
359 AttributeListImpl(const AttributeListImpl &) LLVM_DELETED_FUNCTION;
Devang Patel00095052008-09-24 00:29:49 +0000360 ~AttributeListImpl(); // Private implementation
Chris Lattner8a923e72008-03-12 17:45:29 +0000361public:
Devang Patel4c758ea2008-09-25 21:00:45 +0000362 SmallVector<AttributeWithIndex, 4> Attrs;
Chris Lattner8a923e72008-03-12 17:45:29 +0000363
Chris Lattner3cb6f832012-05-28 01:47:44 +0000364 AttributeListImpl(ArrayRef<AttributeWithIndex> attrs)
365 : Attrs(attrs.begin(), attrs.end()) {
Chris Lattner8a923e72008-03-12 17:45:29 +0000366 RefCount = 0;
367 }
368
Owen Anderson9b14a252010-11-09 00:27:03 +0000369 void AddRef() {
370 sys::SmartScopedLock<true> Lock(*ALMutex);
371 ++RefCount;
372 }
Owen Andersonc1a3a472009-08-20 19:03:20 +0000373 void DropRef() {
Owen Anderson9b14a252010-11-09 00:27:03 +0000374 sys::SmartScopedLock<true> Lock(*ALMutex);
Owen Anderson2e831892010-11-18 18:59:13 +0000375 if (!AttributesLists.isConstructed())
376 return;
Owen Anderson91bfeb12010-11-09 17:47:10 +0000377 sys::cas_flag new_val = --RefCount;
Owen Anderson2d335432010-11-09 17:46:38 +0000378 if (new_val == 0)
Owen Anderson9b14a252010-11-09 00:27:03 +0000379 delete this;
Owen Andersonc1a3a472009-08-20 19:03:20 +0000380 }
Chris Lattner8a923e72008-03-12 17:45:29 +0000381
382 void Profile(FoldingSetNodeID &ID) const {
Chris Lattner3cb6f832012-05-28 01:47:44 +0000383 Profile(ID, Attrs);
Chris Lattner8a923e72008-03-12 17:45:29 +0000384 }
Chris Lattner3cb6f832012-05-28 01:47:44 +0000385 static void Profile(FoldingSetNodeID &ID, ArrayRef<AttributeWithIndex> Attrs){
386 for (unsigned i = 0, e = Attrs.size(); i != e; ++i) {
387 ID.AddInteger(Attrs[i].Attrs.Raw());
388 ID.AddInteger(Attrs[i].Index);
Kostya Serebryanya5054ad2012-01-20 17:56:17 +0000389 }
Chris Lattner8a923e72008-03-12 17:45:29 +0000390 }
391};
392}
393
Devang Patel00095052008-09-24 00:29:49 +0000394AttributeListImpl::~AttributeListImpl() {
Owen Anderson9b14a252010-11-09 00:27:03 +0000395 // NOTE: Lock must be acquired by caller.
Devang Patel4c758ea2008-09-25 21:00:45 +0000396 AttributesLists->RemoveNode(this);
Chris Lattner8a923e72008-03-12 17:45:29 +0000397}
398
399
Chris Lattner3cb6f832012-05-28 01:47:44 +0000400AttrListPtr AttrListPtr::get(ArrayRef<AttributeWithIndex> Attrs) {
Devang Patel4c758ea2008-09-25 21:00:45 +0000401 // If there are no attributes then return a null AttributesList pointer.
Chris Lattner3cb6f832012-05-28 01:47:44 +0000402 if (Attrs.empty())
Devang Patel4c758ea2008-09-25 21:00:45 +0000403 return AttrListPtr();
Chris Lattner8a923e72008-03-12 17:45:29 +0000404
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000405#ifndef NDEBUG
Chris Lattner3cb6f832012-05-28 01:47:44 +0000406 for (unsigned i = 0, e = Attrs.size(); i != e; ++i) {
Bill Wendling9be77592012-09-21 15:26:31 +0000407 assert(Attrs[i].Attrs.hasAttributes() &&
Devang Patel4c758ea2008-09-25 21:00:45 +0000408 "Pointless attribute!");
Chris Lattner8a923e72008-03-12 17:45:29 +0000409 assert((!i || Attrs[i-1].Index < Attrs[i].Index) &&
Devang Patel4c758ea2008-09-25 21:00:45 +0000410 "Misordered AttributesList!");
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000411 }
412#endif
Chris Lattner8a923e72008-03-12 17:45:29 +0000413
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000414 // Otherwise, build a key to look up the existing attributes.
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000415 FoldingSetNodeID ID;
Chris Lattner3cb6f832012-05-28 01:47:44 +0000416 AttributeListImpl::Profile(ID, Attrs);
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000417 void *InsertPos;
Owen Andersond91e6b02009-08-17 17:10:58 +0000418
419 sys::SmartScopedLock<true> Lock(*ALMutex);
420
Devang Patel00095052008-09-24 00:29:49 +0000421 AttributeListImpl *PAL =
Devang Patel4c758ea2008-09-25 21:00:45 +0000422 AttributesLists->FindNodeOrInsertPos(ID, InsertPos);
Chris Lattner8a923e72008-03-12 17:45:29 +0000423
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000424 // If we didn't find any existing attributes of the same shape then
425 // create a new one and insert it.
426 if (!PAL) {
Chris Lattner3cb6f832012-05-28 01:47:44 +0000427 PAL = new AttributeListImpl(Attrs);
Devang Patel4c758ea2008-09-25 21:00:45 +0000428 AttributesLists->InsertNode(PAL, InsertPos);
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000429 }
Chris Lattner8a923e72008-03-12 17:45:29 +0000430
Devang Patel4c758ea2008-09-25 21:00:45 +0000431 // Return the AttributesList that we found or created.
432 return AttrListPtr(PAL);
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000433}
434
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000435
Chris Lattner8a923e72008-03-12 17:45:29 +0000436//===----------------------------------------------------------------------===//
Devang Patel4c758ea2008-09-25 21:00:45 +0000437// AttrListPtr Method Implementations
Chris Lattner8a923e72008-03-12 17:45:29 +0000438//===----------------------------------------------------------------------===//
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000439
Devang Patel4c758ea2008-09-25 21:00:45 +0000440AttrListPtr::AttrListPtr(AttributeListImpl *LI) : AttrList(LI) {
Chris Lattner8a923e72008-03-12 17:45:29 +0000441 if (LI) LI->AddRef();
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000442}
443
Devang Patel4c758ea2008-09-25 21:00:45 +0000444AttrListPtr::AttrListPtr(const AttrListPtr &P) : AttrList(P.AttrList) {
445 if (AttrList) AttrList->AddRef();
Chris Lattner8a923e72008-03-12 17:45:29 +0000446}
447
Devang Patel4c758ea2008-09-25 21:00:45 +0000448const AttrListPtr &AttrListPtr::operator=(const AttrListPtr &RHS) {
Owen Anderson8dc0b042010-09-16 00:27:35 +0000449 sys::SmartScopedLock<true> Lock(*ALMutex);
Devang Patel4c758ea2008-09-25 21:00:45 +0000450 if (AttrList == RHS.AttrList) return *this;
451 if (AttrList) AttrList->DropRef();
452 AttrList = RHS.AttrList;
453 if (AttrList) AttrList->AddRef();
Chris Lattner8a923e72008-03-12 17:45:29 +0000454 return *this;
455}
456
Devang Patel4c758ea2008-09-25 21:00:45 +0000457AttrListPtr::~AttrListPtr() {
458 if (AttrList) AttrList->DropRef();
Chris Lattner8a923e72008-03-12 17:45:29 +0000459}
460
461/// getNumSlots - Return the number of slots used in this attribute list.
462/// This is the number of arguments that have an attribute set on them
463/// (including the function itself).
Devang Patel4c758ea2008-09-25 21:00:45 +0000464unsigned AttrListPtr::getNumSlots() const {
465 return AttrList ? AttrList->Attrs.size() : 0;
Chris Lattner8a923e72008-03-12 17:45:29 +0000466}
467
Devang Patel4c758ea2008-09-25 21:00:45 +0000468/// getSlot - Return the AttributeWithIndex at the specified slot. This
469/// holds a number plus a set of attributes.
470const AttributeWithIndex &AttrListPtr::getSlot(unsigned Slot) const {
471 assert(AttrList && Slot < AttrList->Attrs.size() && "Slot # out of range!");
472 return AttrList->Attrs[Slot];
Chris Lattner8a923e72008-03-12 17:45:29 +0000473}
474
475
Devang Patel4c758ea2008-09-25 21:00:45 +0000476/// getAttributes - The attributes for the specified index are
477/// returned. Attributes for the result are denoted with Idx = 0.
Devang Patel82fed672008-09-23 22:35:17 +0000478/// Function notes are denoted with idx = ~0.
Devang Patel4c758ea2008-09-25 21:00:45 +0000479Attributes AttrListPtr::getAttributes(unsigned Idx) const {
Bill Wendling9be77592012-09-21 15:26:31 +0000480 if (AttrList == 0) return Attributes();
Chris Lattner8a923e72008-03-12 17:45:29 +0000481
Devang Patel4c758ea2008-09-25 21:00:45 +0000482 const SmallVector<AttributeWithIndex, 4> &Attrs = AttrList->Attrs;
Chris Lattner8a923e72008-03-12 17:45:29 +0000483 for (unsigned i = 0, e = Attrs.size(); i != e && Attrs[i].Index <= Idx; ++i)
484 if (Attrs[i].Index == Idx)
485 return Attrs[i].Attrs;
Bill Wendling9be77592012-09-21 15:26:31 +0000486
487 return Attributes();
Chris Lattner8a923e72008-03-12 17:45:29 +0000488}
489
490/// hasAttrSomewhere - Return true if the specified attribute is set for at
491/// least one parameter or for the return value.
Devang Patel4c758ea2008-09-25 21:00:45 +0000492bool AttrListPtr::hasAttrSomewhere(Attributes Attr) const {
493 if (AttrList == 0) return false;
Chris Lattner8a923e72008-03-12 17:45:29 +0000494
Devang Patel4c758ea2008-09-25 21:00:45 +0000495 const SmallVector<AttributeWithIndex, 4> &Attrs = AttrList->Attrs;
Chris Lattner8a923e72008-03-12 17:45:29 +0000496 for (unsigned i = 0, e = Attrs.size(); i != e; ++i)
Bill Wendlingb4e211c2012-09-20 15:20:36 +0000497 if (Attrs[i].Attrs.hasAttributes(Attr))
Chris Lattner8a923e72008-03-12 17:45:29 +0000498 return true;
499 return false;
500}
501
502
Devang Patel4c758ea2008-09-25 21:00:45 +0000503AttrListPtr AttrListPtr::addAttr(unsigned Idx, Attributes Attrs) const {
504 Attributes OldAttrs = getAttributes(Idx);
Dale Johannesen11a555e2008-02-19 23:51:49 +0000505#ifndef NDEBUG
506 // FIXME it is not obvious how this should work for alignment.
507 // For now, say we can't change a known alignment.
Bill Wendling9be77592012-09-21 15:26:31 +0000508 unsigned OldAlign = OldAttrs.getAlignment();
509 unsigned NewAlign = Attrs.getAlignment();
Anton Korobeynikov18991d72008-02-20 12:07:57 +0000510 assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
Dale Johannesen11a555e2008-02-19 23:51:49 +0000511 "Attempt to change alignment!");
512#endif
Chris Lattner8a923e72008-03-12 17:45:29 +0000513
Devang Patelba3fa6c2008-09-23 23:03:40 +0000514 Attributes NewAttrs = OldAttrs | Attrs;
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000515 if (NewAttrs == OldAttrs)
Chris Lattner8a923e72008-03-12 17:45:29 +0000516 return *this;
517
Devang Patel4c758ea2008-09-25 21:00:45 +0000518 SmallVector<AttributeWithIndex, 8> NewAttrList;
519 if (AttrList == 0)
520 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
Chris Lattner8a923e72008-03-12 17:45:29 +0000521 else {
Devang Patel4c758ea2008-09-25 21:00:45 +0000522 const SmallVector<AttributeWithIndex, 4> &OldAttrList = AttrList->Attrs;
Chris Lattner8a923e72008-03-12 17:45:29 +0000523 unsigned i = 0, e = OldAttrList.size();
524 // Copy attributes for arguments before this one.
525 for (; i != e && OldAttrList[i].Index < Idx; ++i)
526 NewAttrList.push_back(OldAttrList[i]);
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000527
Chris Lattner8a923e72008-03-12 17:45:29 +0000528 // If there are attributes already at this index, merge them in.
529 if (i != e && OldAttrList[i].Index == Idx) {
530 Attrs |= OldAttrList[i].Attrs;
531 ++i;
532 }
533
Devang Patel4c758ea2008-09-25 21:00:45 +0000534 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
Chris Lattner8a923e72008-03-12 17:45:29 +0000535
536 // Copy attributes for arguments after this one.
537 NewAttrList.insert(NewAttrList.end(),
538 OldAttrList.begin()+i, OldAttrList.end());
539 }
540
Chris Lattner3cb6f832012-05-28 01:47:44 +0000541 return get(NewAttrList);
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000542}
543
Devang Patel4c758ea2008-09-25 21:00:45 +0000544AttrListPtr AttrListPtr::removeAttr(unsigned Idx, Attributes Attrs) const {
Dale Johannesen11a555e2008-02-19 23:51:49 +0000545#ifndef NDEBUG
546 // FIXME it is not obvious how this should work for alignment.
547 // For now, say we can't pass in alignment, which no current use does.
Bill Wendlingb4e211c2012-09-20 15:20:36 +0000548 assert(!Attrs.hasAlignmentAttr() && "Attempt to exclude alignment!");
Dale Johannesen11a555e2008-02-19 23:51:49 +0000549#endif
Devang Patel4c758ea2008-09-25 21:00:45 +0000550 if (AttrList == 0) return AttrListPtr();
Chris Lattner8a923e72008-03-12 17:45:29 +0000551
Devang Patel4c758ea2008-09-25 21:00:45 +0000552 Attributes OldAttrs = getAttributes(Idx);
Devang Patelba3fa6c2008-09-23 23:03:40 +0000553 Attributes NewAttrs = OldAttrs & ~Attrs;
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000554 if (NewAttrs == OldAttrs)
Chris Lattner8a923e72008-03-12 17:45:29 +0000555 return *this;
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000556
Devang Patel4c758ea2008-09-25 21:00:45 +0000557 SmallVector<AttributeWithIndex, 8> NewAttrList;
558 const SmallVector<AttributeWithIndex, 4> &OldAttrList = AttrList->Attrs;
Chris Lattner8a923e72008-03-12 17:45:29 +0000559 unsigned i = 0, e = OldAttrList.size();
560
561 // Copy attributes for arguments before this one.
562 for (; i != e && OldAttrList[i].Index < Idx; ++i)
563 NewAttrList.push_back(OldAttrList[i]);
564
565 // If there are attributes already at this index, merge them in.
566 assert(OldAttrList[i].Index == Idx && "Attribute isn't set?");
567 Attrs = OldAttrList[i].Attrs & ~Attrs;
568 ++i;
569 if (Attrs) // If any attributes left for this parameter, add them.
Devang Patel4c758ea2008-09-25 21:00:45 +0000570 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs));
Chris Lattner8a923e72008-03-12 17:45:29 +0000571
572 // Copy attributes for arguments after this one.
573 NewAttrList.insert(NewAttrList.end(),
574 OldAttrList.begin()+i, OldAttrList.end());
575
Chris Lattner3cb6f832012-05-28 01:47:44 +0000576 return get(NewAttrList);
Chris Lattner3e13b8c2008-01-02 23:42:30 +0000577}
578
Devang Patel4c758ea2008-09-25 21:00:45 +0000579void AttrListPtr::dump() const {
David Greenef7014732010-01-05 01:29:58 +0000580 dbgs() << "PAL[ ";
Chris Lattner8a923e72008-03-12 17:45:29 +0000581 for (unsigned i = 0; i < getNumSlots(); ++i) {
Devang Patel4c758ea2008-09-25 21:00:45 +0000582 const AttributeWithIndex &PAWI = getSlot(i);
David Greenef7014732010-01-05 01:29:58 +0000583 dbgs() << "{" << PAWI.Index << "," << PAWI.Attrs << "} ";
Chris Lattner8a923e72008-03-12 17:45:29 +0000584 }
585
David Greenef7014732010-01-05 01:29:58 +0000586 dbgs() << "]\n";
Duncan Sands404eb052008-01-06 18:27:01 +0000587}