/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/IR/Attributes.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- Attributes.cpp - Implement AttributesList --------------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // \file |
10 | | // This file implements the Attribute, AttributeImpl, AttrBuilder, |
11 | | // AttributeListImpl, and AttributeList classes. |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #include "llvm/IR/Attributes.h" |
16 | | #include "AttributeImpl.h" |
17 | | #include "LLVMContextImpl.h" |
18 | | #include "llvm/ADT/ArrayRef.h" |
19 | | #include "llvm/ADT/FoldingSet.h" |
20 | | #include "llvm/ADT/Optional.h" |
21 | | #include "llvm/ADT/STLExtras.h" |
22 | | #include "llvm/ADT/SmallVector.h" |
23 | | #include "llvm/ADT/StringExtras.h" |
24 | | #include "llvm/ADT/StringRef.h" |
25 | | #include "llvm/ADT/Twine.h" |
26 | | #include "llvm/Config/llvm-config.h" |
27 | | #include "llvm/IR/Function.h" |
28 | | #include "llvm/IR/LLVMContext.h" |
29 | | #include "llvm/IR/Type.h" |
30 | | #include "llvm/Support/Compiler.h" |
31 | | #include "llvm/Support/Debug.h" |
32 | | #include "llvm/Support/ErrorHandling.h" |
33 | | #include "llvm/Support/MathExtras.h" |
34 | | #include "llvm/Support/raw_ostream.h" |
35 | | #include <algorithm> |
36 | | #include <cassert> |
37 | | #include <climits> |
38 | | #include <cstddef> |
39 | | #include <cstdint> |
40 | | #include <limits> |
41 | | #include <string> |
42 | | #include <tuple> |
43 | | #include <utility> |
44 | | |
45 | | using namespace llvm; |
46 | | |
47 | | //===----------------------------------------------------------------------===// |
48 | | // Attribute Construction Methods |
49 | | //===----------------------------------------------------------------------===// |
50 | | |
51 | | // allocsize has two integer arguments, but because they're both 32 bits, we can |
52 | | // pack them into one 64-bit value, at the cost of making said value |
53 | | // nonsensical. |
54 | | // |
55 | | // In order to do this, we need to reserve one value of the second (optional) |
56 | | // allocsize argument to signify "not present." |
57 | | static const unsigned AllocSizeNumElemsNotPresent = -1; |
58 | | |
59 | | static uint64_t packAllocSizeArgs(unsigned ElemSizeArg, |
60 | 8.59k | const Optional<unsigned> &NumElemsArg) { |
61 | 8.59k | assert((!NumElemsArg.hasValue() || |
62 | 8.59k | *NumElemsArg != AllocSizeNumElemsNotPresent) && |
63 | 8.59k | "Attempting to pack a reserved value"); |
64 | 8.59k | |
65 | 8.59k | return uint64_t(ElemSizeArg) << 32 | |
66 | 8.59k | NumElemsArg.getValueOr(AllocSizeNumElemsNotPresent); |
67 | 8.59k | } |
68 | | |
69 | | static std::pair<unsigned, Optional<unsigned>> |
70 | 5.95k | unpackAllocSizeArgs(uint64_t Num) { |
71 | 5.95k | unsigned NumElems = Num & std::numeric_limits<unsigned>::max(); |
72 | 5.95k | unsigned ElemSizeArg = Num >> 32; |
73 | 5.95k | |
74 | 5.95k | Optional<unsigned> NumElemsArg; |
75 | 5.95k | if (NumElems != AllocSizeNumElemsNotPresent) |
76 | 1.31k | NumElemsArg = NumElems; |
77 | 5.95k | return std::make_pair(ElemSizeArg, NumElemsArg); |
78 | 5.95k | } |
79 | | |
80 | | Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, |
81 | 11.8M | uint64_t Val) { |
82 | 11.8M | LLVMContextImpl *pImpl = Context.pImpl; |
83 | 11.8M | FoldingSetNodeID ID; |
84 | 11.8M | ID.AddInteger(Kind); |
85 | 11.8M | if (Val) ID.AddInteger(Val)885k ; |
86 | 11.8M | |
87 | 11.8M | void *InsertPoint; |
88 | 11.8M | AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint); |
89 | 11.8M | |
90 | 11.8M | if (!PA) { |
91 | 298k | // If we didn't find any existing attributes of the same shape then create a |
92 | 298k | // new one and insert it. |
93 | 298k | if (!Val) |
94 | 269k | PA = new EnumAttributeImpl(Kind); |
95 | 29.4k | else |
96 | 29.4k | PA = new IntAttributeImpl(Kind, Val); |
97 | 298k | pImpl->AttrsSet.InsertNode(PA, InsertPoint); |
98 | 298k | } |
99 | 11.8M | |
100 | 11.8M | // Return the Attribute that we found or created. |
101 | 11.8M | return Attribute(PA); |
102 | 11.8M | } |
103 | | |
104 | 41.7M | Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) { |
105 | 41.7M | LLVMContextImpl *pImpl = Context.pImpl; |
106 | 41.7M | FoldingSetNodeID ID; |
107 | 41.7M | ID.AddString(Kind); |
108 | 41.7M | if (!Val.empty()) ID.AddString(Val)41.6M ; |
109 | 41.7M | |
110 | 41.7M | void *InsertPoint; |
111 | 41.7M | AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint); |
112 | 41.7M | |
113 | 41.7M | if (!PA) { |
114 | 311k | // If we didn't find any existing attributes of the same shape then create a |
115 | 311k | // new one and insert it. |
116 | 311k | PA = new StringAttributeImpl(Kind, Val); |
117 | 311k | pImpl->AttrsSet.InsertNode(PA, InsertPoint); |
118 | 311k | } |
119 | 41.7M | |
120 | 41.7M | // Return the Attribute that we found or created. |
121 | 41.7M | return Attribute(PA); |
122 | 41.7M | } |
123 | | |
124 | | Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, |
125 | 6.06k | Type *Ty) { |
126 | 6.06k | LLVMContextImpl *pImpl = Context.pImpl; |
127 | 6.06k | FoldingSetNodeID ID; |
128 | 6.06k | ID.AddInteger(Kind); |
129 | 6.06k | ID.AddPointer(Ty); |
130 | 6.06k | |
131 | 6.06k | void *InsertPoint; |
132 | 6.06k | AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint); |
133 | 6.06k | |
134 | 6.06k | if (!PA) { |
135 | 1.08k | // If we didn't find any existing attributes of the same shape then create a |
136 | 1.08k | // new one and insert it. |
137 | 1.08k | PA = new TypeAttributeImpl(Kind, Ty); |
138 | 1.08k | pImpl->AttrsSet.InsertNode(PA, InsertPoint); |
139 | 1.08k | } |
140 | 6.06k | |
141 | 6.06k | // Return the Attribute that we found or created. |
142 | 6.06k | return Attribute(PA); |
143 | 6.06k | } |
144 | | |
145 | 289k | Attribute Attribute::getWithAlignment(LLVMContext &Context, uint64_t Align) { |
146 | 289k | assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); |
147 | 289k | assert(Align <= 0x40000000 && "Alignment too large."); |
148 | 289k | return get(Context, Alignment, Align); |
149 | 289k | } |
150 | | |
151 | | Attribute Attribute::getWithStackAlignment(LLVMContext &Context, |
152 | 212 | uint64_t Align) { |
153 | 212 | assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); |
154 | 212 | assert(Align <= 0x100 && "Alignment too large."); |
155 | 212 | return get(Context, StackAlignment, Align); |
156 | 212 | } |
157 | | |
158 | | Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context, |
159 | 589k | uint64_t Bytes) { |
160 | 589k | assert(Bytes && "Bytes must be non-zero."); |
161 | 589k | return get(Context, Dereferenceable, Bytes); |
162 | 589k | } |
163 | | |
164 | | Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context, |
165 | 135 | uint64_t Bytes) { |
166 | 135 | assert(Bytes && "Bytes must be non-zero."); |
167 | 135 | return get(Context, DereferenceableOrNull, Bytes); |
168 | 135 | } |
169 | | |
170 | 6.05k | Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) { |
171 | 6.05k | return get(Context, ByVal, Ty); |
172 | 6.05k | } |
173 | | |
174 | | Attribute |
175 | | Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, |
176 | 5.54k | const Optional<unsigned> &NumElemsArg) { |
177 | 5.54k | assert(!(ElemSizeArg == 0 && NumElemsArg && *NumElemsArg == 0) && |
178 | 5.54k | "Invalid allocsize arguments -- given allocsize(0, 0)"); |
179 | 5.54k | return get(Context, AllocSize, packAllocSizeArgs(ElemSizeArg, NumElemsArg)); |
180 | 5.54k | } |
181 | | |
182 | | //===----------------------------------------------------------------------===// |
183 | | // Attribute Accessor Methods |
184 | | //===----------------------------------------------------------------------===// |
185 | | |
186 | 21.6k | bool Attribute::isEnumAttribute() const { |
187 | 21.6k | return pImpl && pImpl->isEnumAttribute(); |
188 | 21.6k | } |
189 | | |
190 | 13.7k | bool Attribute::isIntAttribute() const { |
191 | 13.7k | return pImpl && pImpl->isIntAttribute(); |
192 | 13.7k | } |
193 | | |
194 | 2.68G | bool Attribute::isStringAttribute() const { |
195 | 2.68G | return pImpl && pImpl->isStringAttribute()2.68G ; |
196 | 2.68G | } |
197 | | |
198 | 94 | bool Attribute::isTypeAttribute() const { |
199 | 94 | return pImpl && pImpl->isTypeAttribute(); |
200 | 94 | } |
201 | | |
202 | 9.17M | Attribute::AttrKind Attribute::getKindAsEnum() const { |
203 | 9.17M | if (!pImpl) return None0 ; |
204 | 9.17M | assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute()) && |
205 | 9.17M | "Invalid attribute type to get the kind as an enum!"); |
206 | 9.17M | return pImpl->getKindAsEnum(); |
207 | 9.17M | } |
208 | | |
209 | 45.2k | uint64_t Attribute::getValueAsInt() const { |
210 | 45.2k | if (!pImpl) return 00 ; |
211 | 45.2k | assert(isIntAttribute() && |
212 | 45.2k | "Expected the attribute to be an integer attribute!"); |
213 | 45.2k | return pImpl->getValueAsInt(); |
214 | 45.2k | } |
215 | | |
216 | 34.8M | StringRef Attribute::getKindAsString() const { |
217 | 34.8M | if (!pImpl) return {}0 ; |
218 | 34.8M | assert(isStringAttribute() && |
219 | 34.8M | "Invalid attribute type to get the kind as a string!"); |
220 | 34.8M | return pImpl->getKindAsString(); |
221 | 34.8M | } |
222 | | |
223 | 177M | StringRef Attribute::getValueAsString() const { |
224 | 177M | if (!pImpl) return {}95.7M ; |
225 | 81.7M | assert(isStringAttribute() && |
226 | 81.7M | "Invalid attribute type to get the value as a string!"); |
227 | 81.7M | return pImpl->getValueAsString(); |
228 | 81.7M | } |
229 | | |
230 | 20.2k | Type *Attribute::getValueAsType() const { |
231 | 20.2k | if (!pImpl) return {}0 ; |
232 | 20.2k | assert(isTypeAttribute() && |
233 | 20.2k | "Invalid attribute type to get the value as a type!"); |
234 | 20.2k | return pImpl->getValueAsType(); |
235 | 20.2k | } |
236 | | |
237 | | |
238 | 113M | bool Attribute::hasAttribute(AttrKind Kind) const { |
239 | 113M | return (pImpl && pImpl->hasAttribute(Kind)84.5M ) || (111M !pImpl111M && Kind == None29.4M ); |
240 | 113M | } |
241 | | |
242 | 2.62G | bool Attribute::hasAttribute(StringRef Kind) const { |
243 | 2.62G | if (!isStringAttribute()) return false425M ; |
244 | 2.19G | return 2.19G pImpl2.19G && pImpl->hasAttribute(Kind); |
245 | 2.19G | } |
246 | | |
247 | 1.45M | unsigned Attribute::getAlignment() const { |
248 | 1.45M | assert(hasAttribute(Attribute::Alignment) && |
249 | 1.45M | "Trying to get alignment from non-alignment attribute!"); |
250 | 1.45M | return pImpl->getValueAsInt(); |
251 | 1.45M | } |
252 | | |
253 | 193 | unsigned Attribute::getStackAlignment() const { |
254 | 193 | assert(hasAttribute(Attribute::StackAlignment) && |
255 | 193 | "Trying to get alignment from non-alignment attribute!"); |
256 | 193 | return pImpl->getValueAsInt(); |
257 | 193 | } |
258 | | |
259 | 1.32M | uint64_t Attribute::getDereferenceableBytes() const { |
260 | 1.32M | assert(hasAttribute(Attribute::Dereferenceable) && |
261 | 1.32M | "Trying to get dereferenceable bytes from " |
262 | 1.32M | "non-dereferenceable attribute!"); |
263 | 1.32M | return pImpl->getValueAsInt(); |
264 | 1.32M | } |
265 | | |
266 | 229 | uint64_t Attribute::getDereferenceableOrNullBytes() const { |
267 | 229 | assert(hasAttribute(Attribute::DereferenceableOrNull) && |
268 | 229 | "Trying to get dereferenceable bytes from " |
269 | 229 | "non-dereferenceable attribute!"); |
270 | 229 | return pImpl->getValueAsInt(); |
271 | 229 | } |
272 | | |
273 | 408 | std::pair<unsigned, Optional<unsigned>> Attribute::getAllocSizeArgs() const { |
274 | 408 | assert(hasAttribute(Attribute::AllocSize) && |
275 | 408 | "Trying to get allocsize args from non-allocsize attribute"); |
276 | 408 | return unpackAllocSizeArgs(pImpl->getValueAsInt()); |
277 | 408 | } |
278 | | |
279 | 825k | std::string Attribute::getAsString(bool InAttrGrp) const { |
280 | 825k | if (!pImpl) return {}0 ; |
281 | 825k | |
282 | 825k | if (hasAttribute(Attribute::SanitizeAddress)) |
283 | 1.14k | return "sanitize_address"; |
284 | 824k | if (hasAttribute(Attribute::SanitizeHWAddress)) |
285 | 316 | return "sanitize_hwaddress"; |
286 | 823k | if (hasAttribute(Attribute::SanitizeMemTag)) |
287 | 31 | return "sanitize_memtag"; |
288 | 823k | if (hasAttribute(Attribute::AlwaysInline)) |
289 | 2.24k | return "alwaysinline"; |
290 | 821k | if (hasAttribute(Attribute::ArgMemOnly)) |
291 | 7.79k | return "argmemonly"; |
292 | 813k | if (hasAttribute(Attribute::Builtin)) |
293 | 397 | return "builtin"; |
294 | 813k | if (hasAttribute(Attribute::Convergent)) |
295 | 2.57k | return "convergent"; |
296 | 810k | if (hasAttribute(Attribute::SwiftError)) |
297 | 78 | return "swifterror"; |
298 | 810k | if (hasAttribute(Attribute::SwiftSelf)) |
299 | 46 | return "swiftself"; |
300 | 810k | if (hasAttribute(Attribute::InaccessibleMemOnly)) |
301 | 363 | return "inaccessiblememonly"; |
302 | 810k | if (hasAttribute(Attribute::InaccessibleMemOrArgMemOnly)) |
303 | 122 | return "inaccessiblemem_or_argmemonly"; |
304 | 810k | if (hasAttribute(Attribute::InAlloca)) |
305 | 210 | return "inalloca"; |
306 | 809k | if (hasAttribute(Attribute::InlineHint)) |
307 | 1.39k | return "inlinehint"; |
308 | 808k | if (hasAttribute(Attribute::InReg)) |
309 | 1.22k | return "inreg"; |
310 | 807k | if (hasAttribute(Attribute::JumpTable)) |
311 | 28 | return "jumptable"; |
312 | 807k | if (hasAttribute(Attribute::MinSize)) |
313 | 798 | return "minsize"; |
314 | 806k | if (hasAttribute(Attribute::Naked)) |
315 | 120 | return "naked"; |
316 | 806k | if (hasAttribute(Attribute::Nest)) |
317 | 81 | return "nest"; |
318 | 806k | if (hasAttribute(Attribute::NoAlias)) |
319 | 18.6k | return "noalias"; |
320 | 787k | if (hasAttribute(Attribute::NoBuiltin)) |
321 | 1.04k | return "nobuiltin"; |
322 | 786k | if (hasAttribute(Attribute::NoCapture)) |
323 | 12.4k | return "nocapture"; |
324 | 774k | if (hasAttribute(Attribute::NoDuplicate)) |
325 | 212 | return "noduplicate"; |
326 | 773k | if (hasAttribute(Attribute::NoFree)) |
327 | 3.20k | return "nofree"; |
328 | 770k | if (hasAttribute(Attribute::NoImplicitFloat)) |
329 | 81 | return "noimplicitfloat"; |
330 | 770k | if (hasAttribute(Attribute::NoInline)) |
331 | 112k | return "noinline"; |
332 | 658k | if (hasAttribute(Attribute::NonLazyBind)) |
333 | 642 | return "nonlazybind"; |
334 | 658k | if (hasAttribute(Attribute::NonNull)) |
335 | 6.20k | return "nonnull"; |
336 | 651k | if (hasAttribute(Attribute::NoRedZone)) |
337 | 216 | return "noredzone"; |
338 | 651k | if (hasAttribute(Attribute::NoReturn)) |
339 | 1.78k | return "noreturn"; |
340 | 649k | if (hasAttribute(Attribute::NoSync)) |
341 | 207 | return "nosync"; |
342 | 649k | if (hasAttribute(Attribute::WillReturn)) |
343 | 104 | return "willreturn"; |
344 | 649k | if (hasAttribute(Attribute::NoCfCheck)) |
345 | 3 | return "nocf_check"; |
346 | 649k | if (hasAttribute(Attribute::NoRecurse)) |
347 | 20.5k | return "norecurse"; |
348 | 628k | if (hasAttribute(Attribute::NoUnwind)) |
349 | 179k | return "nounwind"; |
350 | 449k | if (hasAttribute(Attribute::OptForFuzzing)) |
351 | 2 | return "optforfuzzing"; |
352 | 449k | if (hasAttribute(Attribute::OptimizeNone)) |
353 | 85.1k | return "optnone"; |
354 | 364k | if (hasAttribute(Attribute::OptimizeForSize)) |
355 | 1.23k | return "optsize"; |
356 | 363k | if (hasAttribute(Attribute::ReadNone)) |
357 | 23.6k | return "readnone"; |
358 | 339k | if (hasAttribute(Attribute::ReadOnly)) |
359 | 7.88k | return "readonly"; |
360 | 331k | if (hasAttribute(Attribute::WriteOnly)) |
361 | 2.97k | return "writeonly"; |
362 | 328k | if (hasAttribute(Attribute::Returned)) |
363 | 1.97k | return "returned"; |
364 | 326k | if (hasAttribute(Attribute::ReturnsTwice)) |
365 | 146 | return "returns_twice"; |
366 | 326k | if (hasAttribute(Attribute::SExt)) |
367 | 10.2k | return "signext"; |
368 | 316k | if (hasAttribute(Attribute::SpeculativeLoadHardening)) |
369 | 30 | return "speculative_load_hardening"; |
370 | 316k | if (hasAttribute(Attribute::Speculatable)) |
371 | 7.16k | return "speculatable"; |
372 | 309k | if (hasAttribute(Attribute::StackProtect)) |
373 | 1.69k | return "ssp"; |
374 | 307k | if (hasAttribute(Attribute::StackProtectReq)) |
375 | 86 | return "sspreq"; |
376 | 307k | if (hasAttribute(Attribute::StackProtectStrong)) |
377 | 114 | return "sspstrong"; |
378 | 307k | if (hasAttribute(Attribute::SafeStack)) |
379 | 334 | return "safestack"; |
380 | 306k | if (hasAttribute(Attribute::ShadowCallStack)) |
381 | 12 | return "shadowcallstack"; |
382 | 306k | if (hasAttribute(Attribute::StrictFP)) |
383 | 10 | return "strictfp"; |
384 | 306k | if (hasAttribute(Attribute::StructRet)) |
385 | 2.90k | return "sret"; |
386 | 303k | if (hasAttribute(Attribute::SanitizeThread)) |
387 | 186 | return "sanitize_thread"; |
388 | 303k | if (hasAttribute(Attribute::SanitizeMemory)) |
389 | 1.12k | return "sanitize_memory"; |
390 | 302k | if (hasAttribute(Attribute::UWTable)) |
391 | 4.09k | return "uwtable"; |
392 | 298k | if (hasAttribute(Attribute::ZExt)) |
393 | 9.04k | return "zeroext"; |
394 | 289k | if (hasAttribute(Attribute::Cold)) |
395 | 553 | return "cold"; |
396 | 288k | if (hasAttribute(Attribute::ImmArg)) |
397 | 7.23k | return "immarg"; |
398 | 281k | |
399 | 281k | if (hasAttribute(Attribute::ByVal)) { |
400 | 1.48k | std::string Result; |
401 | 1.48k | Result += "byval"; |
402 | 1.48k | if (Type *Ty = getValueAsType()) { |
403 | 1.27k | raw_string_ostream OS(Result); |
404 | 1.27k | Result += '('; |
405 | 1.27k | Ty->print(OS, false, true); |
406 | 1.27k | OS.flush(); |
407 | 1.27k | Result += ')'; |
408 | 1.27k | } |
409 | 1.48k | return Result; |
410 | 1.48k | } |
411 | 280k | |
412 | 280k | // FIXME: These should be output like this: |
413 | 280k | // |
414 | 280k | // align=4 |
415 | 280k | // alignstack=8 |
416 | 280k | // |
417 | 280k | if (hasAttribute(Attribute::Alignment)) { |
418 | 21.6k | std::string Result; |
419 | 21.6k | Result += "align"; |
420 | 21.6k | Result += (InAttrGrp) ? "="1 : " "21.6k ; |
421 | 21.6k | Result += utostr(getValueAsInt()); |
422 | 21.6k | return Result; |
423 | 21.6k | } |
424 | 258k | |
425 | 258k | auto AttrWithBytesToString = [&](const char *Name) { |
426 | 20.0k | std::string Result; |
427 | 20.0k | Result += Name; |
428 | 20.0k | if (InAttrGrp) { |
429 | 37 | Result += "="; |
430 | 37 | Result += utostr(getValueAsInt()); |
431 | 19.9k | } else { |
432 | 19.9k | Result += "("; |
433 | 19.9k | Result += utostr(getValueAsInt()); |
434 | 19.9k | Result += ")"; |
435 | 19.9k | } |
436 | 20.0k | return Result; |
437 | 20.0k | }; |
438 | 258k | |
439 | 258k | if (hasAttribute(Attribute::StackAlignment)) |
440 | 74 | return AttrWithBytesToString("alignstack"); |
441 | 258k | |
442 | 258k | if (hasAttribute(Attribute::Dereferenceable)) |
443 | 19.8k | return AttrWithBytesToString("dereferenceable"); |
444 | 238k | |
445 | 238k | if (hasAttribute(Attribute::DereferenceableOrNull)) |
446 | 88 | return AttrWithBytesToString("dereferenceable_or_null"); |
447 | 238k | |
448 | 238k | if (hasAttribute(Attribute::AllocSize)) { |
449 | 57 | unsigned ElemSize; |
450 | 57 | Optional<unsigned> NumElems; |
451 | 57 | std::tie(ElemSize, NumElems) = getAllocSizeArgs(); |
452 | 57 | |
453 | 57 | std::string Result = "allocsize("; |
454 | 57 | Result += utostr(ElemSize); |
455 | 57 | if (NumElems.hasValue()) { |
456 | 25 | Result += ','; |
457 | 25 | Result += utostr(*NumElems); |
458 | 25 | } |
459 | 57 | Result += ')'; |
460 | 57 | return Result; |
461 | 57 | } |
462 | 238k | |
463 | 238k | // Convert target-dependent attributes to strings of the form: |
464 | 238k | // |
465 | 238k | // "kind" |
466 | 238k | // "kind" = "value" |
467 | 238k | // |
468 | 238k | if (isStringAttribute()) { |
469 | 238k | std::string Result; |
470 | 238k | Result += (Twine('"') + getKindAsString() + Twine('"')).str(); |
471 | 238k | |
472 | 238k | std::string AttrVal = pImpl->getValueAsString(); |
473 | 238k | if (AttrVal.empty()) return Result1.86k ; |
474 | 236k | |
475 | 236k | // Since some attribute strings contain special characters that cannot be |
476 | 236k | // printable, those have to be escaped to make the attribute value printable |
477 | 236k | // as is. e.g. "\01__gnu_mcount_nc" |
478 | 236k | { |
479 | 236k | raw_string_ostream OS(Result); |
480 | 236k | OS << "=\""; |
481 | 236k | printEscapedString(AttrVal, OS); |
482 | 236k | OS << "\""; |
483 | 236k | } |
484 | 236k | return Result; |
485 | 236k | } |
486 | 0 | |
487 | 0 | llvm_unreachable("Unknown attribute"); |
488 | 0 | } |
489 | | |
490 | 43.1M | bool Attribute::operator<(Attribute A) const { |
491 | 43.1M | if (!pImpl && !A.pImpl0 ) return false0 ; |
492 | 43.1M | if (!pImpl) return true0 ; |
493 | 43.1M | if (!A.pImpl) return false0 ; |
494 | 43.1M | return *pImpl < *A.pImpl; |
495 | 43.1M | } |
496 | | |
497 | | //===----------------------------------------------------------------------===// |
498 | | // AttributeImpl Definition |
499 | | //===----------------------------------------------------------------------===// |
500 | | |
501 | | // Pin the vtables to this file. |
502 | 299k | AttributeImpl::~AttributeImpl() = default; |
503 | | |
504 | 0 | void EnumAttributeImpl::anchor() {} |
505 | | |
506 | 0 | void IntAttributeImpl::anchor() {} |
507 | | |
508 | 0 | void StringAttributeImpl::anchor() {} |
509 | | |
510 | 0 | void TypeAttributeImpl::anchor() {} |
511 | | |
512 | 84.5M | bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const { |
513 | 84.5M | if (isStringAttribute()) return false36.8M ; |
514 | 47.6M | return getKindAsEnum() == A; |
515 | 47.6M | } |
516 | | |
517 | 2.19G | bool AttributeImpl::hasAttribute(StringRef Kind) const { |
518 | 2.19G | if (!isStringAttribute()) return false0 ; |
519 | 2.19G | return getKindAsString() == Kind; |
520 | 2.19G | } |
521 | | |
522 | 89.0M | Attribute::AttrKind AttributeImpl::getKindAsEnum() const { |
523 | 89.0M | assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute()); |
524 | 89.0M | return static_cast<const EnumAttributeImpl *>(this)->getEnumKind(); |
525 | 89.0M | } |
526 | | |
527 | 9.39M | uint64_t AttributeImpl::getValueAsInt() const { |
528 | 9.39M | assert(isIntAttribute()); |
529 | 9.39M | return static_cast<const IntAttributeImpl *>(this)->getValue(); |
530 | 9.39M | } |
531 | | |
532 | 2.42G | StringRef AttributeImpl::getKindAsString() const { |
533 | 2.42G | assert(isStringAttribute()); |
534 | 2.42G | return static_cast<const StringAttributeImpl *>(this)->getStringKind(); |
535 | 2.42G | } |
536 | | |
537 | 124M | StringRef AttributeImpl::getValueAsString() const { |
538 | 124M | assert(isStringAttribute()); |
539 | 124M | return static_cast<const StringAttributeImpl *>(this)->getStringValue(); |
540 | 124M | } |
541 | | |
542 | 86.1k | Type *AttributeImpl::getValueAsType() const { |
543 | 86.1k | assert(isTypeAttribute()); |
544 | 86.1k | return static_cast<const TypeAttributeImpl *>(this)->getTypeValue(); |
545 | 86.1k | } |
546 | | |
547 | 43.1M | bool AttributeImpl::operator<(const AttributeImpl &AI) const { |
548 | 43.1M | // This sorts the attributes with Attribute::AttrKinds coming first (sorted |
549 | 43.1M | // relative to their enum value) and then strings. |
550 | 43.1M | if (isEnumAttribute()) { |
551 | 3.63M | if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum()3.38M ; |
552 | 249k | if (AI.isIntAttribute()) return true247k ; |
553 | 2.33k | if (AI.isStringAttribute()) return true74 ; |
554 | 2.26k | if (2.26k AI.isTypeAttribute()2.26k ) return true; |
555 | 39.4M | } |
556 | 39.4M | |
557 | 39.4M | if (isTypeAttribute()) { |
558 | 4.88k | if (AI.isEnumAttribute()) return false1 ; |
559 | 4.88k | if (AI.isTypeAttribute()) { |
560 | 0 | assert(getKindAsEnum() != AI.getKindAsEnum() && |
561 | 0 | "Comparison of types would be unstable"); |
562 | 0 | return getKindAsEnum() < AI.getKindAsEnum(); |
563 | 0 | } |
564 | 4.88k | if (AI.isIntAttribute()) return true; |
565 | 0 | if (AI.isStringAttribute()) return true; |
566 | 39.4M | } |
567 | 39.4M | |
568 | 39.4M | if (isIntAttribute()) { |
569 | 18.2k | if (AI.isEnumAttribute()) return false61 ; |
570 | 18.1k | if (AI.isTypeAttribute()) return false1 ; |
571 | 18.1k | if (AI.isIntAttribute()) { |
572 | 18.1k | if (getKindAsEnum() == AI.getKindAsEnum()) |
573 | 1 | return getValueAsInt() < AI.getValueAsInt(); |
574 | 18.1k | return getKindAsEnum() < AI.getKindAsEnum(); |
575 | 18.1k | } |
576 | 0 | if (AI.isStringAttribute()) return true; |
577 | 39.4M | } |
578 | 39.4M | |
579 | 39.4M | assert(isStringAttribute()); |
580 | 39.4M | if (AI.isEnumAttribute()) return false1.71M ; |
581 | 37.7M | if (AI.isTypeAttribute()) return false0 ; |
582 | 37.7M | if (AI.isIntAttribute()) return false1.95k ; |
583 | 37.7M | if (getKindAsString() == AI.getKindAsString()) |
584 | 204 | return getValueAsString() < AI.getValueAsString(); |
585 | 37.7M | return getKindAsString() < AI.getKindAsString(); |
586 | 37.7M | } |
587 | | |
588 | | //===----------------------------------------------------------------------===// |
589 | | // AttributeSet Definition |
590 | | //===----------------------------------------------------------------------===// |
591 | | |
592 | 12.2M | AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) { |
593 | 12.2M | return AttributeSet(AttributeSetNode::get(C, B)); |
594 | 12.2M | } |
595 | | |
596 | 948k | AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) { |
597 | 948k | return AttributeSet(AttributeSetNode::get(C, Attrs)); |
598 | 948k | } |
599 | | |
600 | | AttributeSet AttributeSet::addAttribute(LLVMContext &C, |
601 | 0 | Attribute::AttrKind Kind) const { |
602 | 0 | if (hasAttribute(Kind)) return *this; |
603 | 0 | AttrBuilder B; |
604 | 0 | B.addAttribute(Kind); |
605 | 0 | return addAttributes(C, AttributeSet::get(C, B)); |
606 | 0 | } |
607 | | |
608 | | AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind, |
609 | 711 | StringRef Value) const { |
610 | 711 | AttrBuilder B; |
611 | 711 | B.addAttribute(Kind, Value); |
612 | 711 | return addAttributes(C, AttributeSet::get(C, B)); |
613 | 711 | } |
614 | | |
615 | | AttributeSet AttributeSet::addAttributes(LLVMContext &C, |
616 | 710 | const AttributeSet AS) const { |
617 | 710 | if (!hasAttributes()) |
618 | 685 | return AS; |
619 | 25 | |
620 | 25 | if (!AS.hasAttributes()) |
621 | 0 | return *this; |
622 | 25 | |
623 | 25 | AttrBuilder B(AS); |
624 | 25 | for (const auto I : *this) |
625 | 34 | B.addAttribute(I); |
626 | 25 | |
627 | 25 | return get(C, B); |
628 | 25 | } |
629 | | |
630 | | AttributeSet AttributeSet::removeAttribute(LLVMContext &C, |
631 | 38.3k | Attribute::AttrKind Kind) const { |
632 | 38.3k | if (!hasAttribute(Kind)) return *this33.3k ; |
633 | 4.98k | AttrBuilder B(*this); |
634 | 4.98k | B.removeAttribute(Kind); |
635 | 4.98k | return get(C, B); |
636 | 4.98k | } |
637 | | |
638 | | AttributeSet AttributeSet::removeAttribute(LLVMContext &C, |
639 | 637k | StringRef Kind) const { |
640 | 637k | if (!hasAttribute(Kind)) return *this0 ; |
641 | 637k | AttrBuilder B(*this); |
642 | 637k | B.removeAttribute(Kind); |
643 | 637k | return get(C, B); |
644 | 637k | } |
645 | | |
646 | | AttributeSet AttributeSet::removeAttributes(LLVMContext &C, |
647 | 1.01k | const AttrBuilder &Attrs) const { |
648 | 1.01k | AttrBuilder B(*this); |
649 | 1.01k | B.remove(Attrs); |
650 | 1.01k | return get(C, B); |
651 | 1.01k | } |
652 | | |
653 | 50.7k | unsigned AttributeSet::getNumAttributes() const { |
654 | 50.7k | return SetNode ? SetNode->getNumAttributes()50.7k : 04 ; |
655 | 50.7k | } |
656 | | |
657 | 2.07G | bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const { |
658 | 2.07G | return SetNode ? SetNode->hasAttribute(Kind)1.59G : false480M ; |
659 | 2.07G | } |
660 | | |
661 | 68.9M | bool AttributeSet::hasAttribute(StringRef Kind) const { |
662 | 68.9M | return SetNode ? SetNode->hasAttribute(Kind)64.0M : false4.99M ; |
663 | 68.9M | } |
664 | | |
665 | 22.4M | Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const { |
666 | 22.4M | return SetNode ? SetNode->getAttribute(Kind)22.4M : Attribute()20.3k ; |
667 | 22.4M | } |
668 | | |
669 | 173M | Attribute AttributeSet::getAttribute(StringRef Kind) const { |
670 | 173M | return SetNode ? SetNode->getAttribute(Kind)171M : Attribute()2.10M ; |
671 | 173M | } |
672 | | |
673 | 43.1M | unsigned AttributeSet::getAlignment() const { |
674 | 43.1M | return SetNode ? SetNode->getAlignment()10.7M : 032.4M ; |
675 | 43.1M | } |
676 | | |
677 | 69 | unsigned AttributeSet::getStackAlignment() const { |
678 | 69 | return SetNode ? SetNode->getStackAlignment() : 00 ; |
679 | 69 | } |
680 | | |
681 | 62.5M | uint64_t AttributeSet::getDereferenceableBytes() const { |
682 | 62.5M | return SetNode ? SetNode->getDereferenceableBytes()9.85M : 052.7M ; |
683 | 62.5M | } |
684 | | |
685 | 1.18M | uint64_t AttributeSet::getDereferenceableOrNullBytes() const { |
686 | 1.18M | return SetNode ? SetNode->getDereferenceableOrNullBytes()332k : 0852k ; |
687 | 1.18M | } |
688 | | |
689 | 10.8k | Type *AttributeSet::getByValType() const { |
690 | 10.8k | return SetNode ? SetNode->getByValType()10.7k : nullptr103 ; |
691 | 10.8k | } |
692 | | |
693 | 117 | std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const { |
694 | 117 | return SetNode ? SetNode->getAllocSizeArgs() |
695 | 117 | : std::pair<unsigned, Optional<unsigned>>(0, 0)0 ; |
696 | 117 | } |
697 | | |
698 | 143k | std::string AttributeSet::getAsString(bool InAttrGrp) const { |
699 | 143k | return SetNode ? SetNode->getAsString(InAttrGrp) : ""0 ; |
700 | 143k | } |
701 | | |
702 | 11.4M | AttributeSet::iterator AttributeSet::begin() const { |
703 | 11.4M | return SetNode ? SetNode->begin()6.63M : nullptr4.78M ; |
704 | 11.4M | } |
705 | | |
706 | 11.4M | AttributeSet::iterator AttributeSet::end() const { |
707 | 11.4M | return SetNode ? SetNode->end()6.63M : nullptr4.78M ; |
708 | 11.4M | } |
709 | | |
710 | | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
711 | | LLVM_DUMP_METHOD void AttributeSet::dump() const { |
712 | | dbgs() << "AS =\n"; |
713 | | dbgs() << " { "; |
714 | | dbgs() << getAsString(true) << " }\n"; |
715 | | } |
716 | | #endif |
717 | | |
718 | | //===----------------------------------------------------------------------===// |
719 | | // AttributeSetNode Definition |
720 | | //===----------------------------------------------------------------------===// |
721 | | |
722 | | AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs) |
723 | 491k | : NumAttrs(Attrs.size()) { |
724 | 491k | // There's memory after the node where we can store the entries in. |
725 | 491k | llvm::copy(Attrs, getTrailingObjects<Attribute>()); |
726 | 491k | |
727 | 491k | static_assert(Attribute::EndAttrKinds <= |
728 | 491k | sizeof(AvailableAttrs) * CHAR_BIT, |
729 | 491k | "Too many attributes"); |
730 | 491k | |
731 | 3.45M | for (const auto I : *this) { |
732 | 3.45M | if (!I.isStringAttribute()) { |
733 | 767k | Attribute::AttrKind Kind = I.getKindAsEnum(); |
734 | 767k | AvailableAttrs[Kind / 8] |= 1ULL << (Kind % 8); |
735 | 767k | } |
736 | 3.45M | } |
737 | 491k | } |
738 | | |
739 | | AttributeSetNode *AttributeSetNode::get(LLVMContext &C, |
740 | 13.2M | ArrayRef<Attribute> Attrs) { |
741 | 13.2M | if (Attrs.empty()) |
742 | 4.39M | return nullptr; |
743 | 8.83M | |
744 | 8.83M | // Otherwise, build a key to look up the existing attributes. |
745 | 8.83M | LLVMContextImpl *pImpl = C.pImpl; |
746 | 8.83M | FoldingSetNodeID ID; |
747 | 8.83M | |
748 | 8.83M | SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end()); |
749 | 8.83M | llvm::sort(SortedAttrs); |
750 | 8.83M | |
751 | 8.83M | for (const auto Attr : SortedAttrs) |
752 | 51.6M | Attr.Profile(ID); |
753 | 8.83M | |
754 | 8.83M | void *InsertPoint; |
755 | 8.83M | AttributeSetNode *PA = |
756 | 8.83M | pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint); |
757 | 8.83M | |
758 | 8.83M | // If we didn't find any existing attributes of the same shape then create a |
759 | 8.83M | // new one and insert it. |
760 | 8.83M | if (!PA) { |
761 | 491k | // Coallocate entries after the AttributeSetNode itself. |
762 | 491k | void *Mem = ::operator new(totalSizeToAlloc<Attribute>(SortedAttrs.size())); |
763 | 491k | PA = new (Mem) AttributeSetNode(SortedAttrs); |
764 | 491k | pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint); |
765 | 491k | } |
766 | 8.83M | |
767 | 8.83M | // Return the AttributeSetNode that we found or created. |
768 | 8.83M | return PA; |
769 | 8.83M | } |
770 | | |
771 | 12.2M | AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) { |
772 | 12.2M | // Add target-independent attributes. |
773 | 12.2M | SmallVector<Attribute, 8> Attrs; |
774 | 12.2M | for (Attribute::AttrKind Kind = Attribute::None; |
775 | 810M | Kind != Attribute::EndAttrKinds; Kind = Attribute::AttrKind(Kind + 1)798M ) { |
776 | 798M | if (!B.contains(Kind)) |
777 | 789M | continue; |
778 | 8.81M | |
779 | 8.81M | Attribute Attr; |
780 | 8.81M | switch (Kind) { |
781 | 8.81M | case Attribute::ByVal: |
782 | 6.00k | Attr = Attribute::getWithByValType(C, B.getByValType()); |
783 | 6.00k | break; |
784 | 8.81M | case Attribute::Alignment: |
785 | 166k | Attr = Attribute::getWithAlignment(C, B.getAlignment()); |
786 | 166k | break; |
787 | 8.81M | case Attribute::StackAlignment: |
788 | 211 | Attr = Attribute::getWithStackAlignment(C, B.getStackAlignment()); |
789 | 211 | break; |
790 | 8.81M | case Attribute::Dereferenceable: |
791 | 571k | Attr = Attribute::getWithDereferenceableBytes( |
792 | 571k | C, B.getDereferenceableBytes()); |
793 | 571k | break; |
794 | 8.81M | case Attribute::DereferenceableOrNull: |
795 | 132 | Attr = Attribute::getWithDereferenceableOrNullBytes( |
796 | 132 | C, B.getDereferenceableOrNullBytes()); |
797 | 132 | break; |
798 | 8.81M | case Attribute::AllocSize: { |
799 | 5.54k | auto A = B.getAllocSizeArgs(); |
800 | 5.54k | Attr = Attribute::getWithAllocSizeArgs(C, A.first, A.second); |
801 | 5.54k | break; |
802 | 8.81M | } |
803 | 8.81M | default: |
804 | 8.06M | Attr = Attribute::get(C, Kind); |
805 | 8.81M | } |
806 | 8.81M | Attrs.push_back(Attr); |
807 | 8.81M | } |
808 | 12.2M | |
809 | 12.2M | // Add target-dependent (string) attributes. |
810 | 12.2M | for (const auto &TDA : B.td_attrs()) |
811 | 40.9M | Attrs.emplace_back(Attribute::get(C, TDA.first, TDA.second)); |
812 | 12.2M | |
813 | 12.2M | return get(C, Attrs); |
814 | 12.2M | } |
815 | | |
816 | 64.0M | bool AttributeSetNode::hasAttribute(StringRef Kind) const { |
817 | 64.0M | for (const auto I : *this) |
818 | 569M | if (I.hasAttribute(Kind)) |
819 | 9.65M | return true; |
820 | 64.0M | return false54.3M ; |
821 | 64.0M | } |
822 | | |
823 | 22.4M | Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const { |
824 | 22.4M | if (hasAttribute(Kind)) { |
825 | 740 | for (const auto I : *this) |
826 | 1.36k | if (I.hasAttribute(Kind)) |
827 | 740 | return I; |
828 | 740 | } |
829 | 22.4M | return {}22.4M ; |
830 | 22.4M | } |
831 | | |
832 | 171M | Attribute AttributeSetNode::getAttribute(StringRef Kind) const { |
833 | 171M | for (const auto I : *this) |
834 | 2.05G | if (I.hasAttribute(Kind)) |
835 | 47.2M | return I; |
836 | 171M | return {}123M ; |
837 | 171M | } |
838 | | |
839 | 10.7M | unsigned AttributeSetNode::getAlignment() const { |
840 | 10.7M | for (const auto I : *this) |
841 | 14.6M | if (I.hasAttribute(Attribute::Alignment)) |
842 | 1.24M | return I.getAlignment(); |
843 | 10.7M | return 09.53M ; |
844 | 10.7M | } |
845 | | |
846 | 69 | unsigned AttributeSetNode::getStackAlignment() const { |
847 | 69 | for (const auto I : *this) |
848 | 98 | if (I.hasAttribute(Attribute::StackAlignment)) |
849 | 69 | return I.getStackAlignment(); |
850 | 69 | return 00 ; |
851 | 69 | } |
852 | | |
853 | 10.7k | Type *AttributeSetNode::getByValType() const { |
854 | 10.7k | for (const auto I : *this) |
855 | 13.5k | if (I.hasAttribute(Attribute::ByVal)) |
856 | 10.7k | return I.getValueAsType(); |
857 | 10.7k | return 044 ; |
858 | 10.7k | } |
859 | | |
860 | 9.85M | uint64_t AttributeSetNode::getDereferenceableBytes() const { |
861 | 9.85M | for (const auto I : *this) |
862 | 12.5M | if (I.hasAttribute(Attribute::Dereferenceable)) |
863 | 1.08M | return I.getDereferenceableBytes(); |
864 | 9.85M | return 08.77M ; |
865 | 9.85M | } |
866 | | |
867 | 332k | uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const { |
868 | 332k | for (const auto I : *this) |
869 | 380k | if (I.hasAttribute(Attribute::DereferenceableOrNull)) |
870 | 45 | return I.getDereferenceableOrNullBytes(); |
871 | 332k | return 0332k ; |
872 | 332k | } |
873 | | |
874 | | std::pair<unsigned, Optional<unsigned>> |
875 | 117 | AttributeSetNode::getAllocSizeArgs() const { |
876 | 117 | for (const auto I : *this) |
877 | 117 | if (I.hasAttribute(Attribute::AllocSize)) |
878 | 117 | return I.getAllocSizeArgs(); |
879 | 117 | return std::make_pair(0, 0)0 ; |
880 | 117 | } |
881 | | |
882 | 143k | std::string AttributeSetNode::getAsString(bool InAttrGrp) const { |
883 | 143k | std::string Str; |
884 | 574k | for (iterator I = begin(), E = end(); I != E; ++I431k ) { |
885 | 431k | if (I != begin()) |
886 | 288k | Str += ' '; |
887 | 431k | Str += I->getAsString(InAttrGrp); |
888 | 431k | } |
889 | 143k | return Str; |
890 | 143k | } |
891 | | |
892 | | //===----------------------------------------------------------------------===// |
893 | | // AttributeListImpl Definition |
894 | | //===----------------------------------------------------------------------===// |
895 | | |
896 | | /// Map from AttributeList index to the internal array index. Adding one happens |
897 | | /// to work, but it relies on unsigned integer wrapping. MSVC warns about |
898 | | /// unsigned wrapping in constexpr functions, so write out the conditional. LLVM |
899 | | /// folds it to add anyway. |
900 | 2.43G | static constexpr unsigned attrIdxToArrayIdx(unsigned Index) { |
901 | 2.43G | return Index == AttributeList::FunctionIndex ? 01.74G : Index + 1689M ; |
902 | 2.43G | } |
903 | | |
904 | | AttributeListImpl::AttributeListImpl(LLVMContext &C, |
905 | | ArrayRef<AttributeSet> Sets) |
906 | 1.04M | : Context(C), NumAttrSets(Sets.size()) { |
907 | 1.04M | assert(!Sets.empty() && "pointless AttributeListImpl"); |
908 | 1.04M | |
909 | 1.04M | // There's memory after the node where we can store the entries in. |
910 | 1.04M | llvm::copy(Sets, getTrailingObjects<AttributeSet>()); |
911 | 1.04M | |
912 | 1.04M | // Initialize AvailableFunctionAttrs summary bitset. |
913 | 1.04M | static_assert(Attribute::EndAttrKinds <= |
914 | 1.04M | sizeof(AvailableFunctionAttrs) * CHAR_BIT, |
915 | 1.04M | "Too many attributes"); |
916 | 1.04M | static_assert(attrIdxToArrayIdx(AttributeList::FunctionIndex) == 0U, |
917 | 1.04M | "function should be stored in slot 0"); |
918 | 8.18M | for (const auto I : Sets[0]) { |
919 | 8.18M | if (!I.isStringAttribute()) { |
920 | 1.24M | Attribute::AttrKind Kind = I.getKindAsEnum(); |
921 | 1.24M | AvailableFunctionAttrs[Kind / 8] |= 1ULL << (Kind % 8); |
922 | 1.24M | } |
923 | 8.18M | } |
924 | 1.04M | } |
925 | | |
926 | 10.8M | void AttributeListImpl::Profile(FoldingSetNodeID &ID) const { |
927 | 10.8M | Profile(ID, makeArrayRef(begin(), end())); |
928 | 10.8M | } |
929 | | |
930 | | void AttributeListImpl::Profile(FoldingSetNodeID &ID, |
931 | 18.8M | ArrayRef<AttributeSet> Sets) { |
932 | 18.8M | for (const auto &Set : Sets) |
933 | 45.3M | ID.AddPointer(Set.SetNode); |
934 | 18.8M | } |
935 | | |
936 | | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
937 | | LLVM_DUMP_METHOD void AttributeListImpl::dump() const { |
938 | | AttributeList(const_cast<AttributeListImpl *>(this)).dump(); |
939 | | } |
940 | | #endif |
941 | | |
942 | | //===----------------------------------------------------------------------===// |
943 | | // AttributeList Construction and Mutation Methods |
944 | | //===----------------------------------------------------------------------===// |
945 | | |
946 | | AttributeList AttributeList::getImpl(LLVMContext &C, |
947 | 7.96M | ArrayRef<AttributeSet> AttrSets) { |
948 | 7.96M | assert(!AttrSets.empty() && "pointless AttributeListImpl"); |
949 | 7.96M | |
950 | 7.96M | LLVMContextImpl *pImpl = C.pImpl; |
951 | 7.96M | FoldingSetNodeID ID; |
952 | 7.96M | AttributeListImpl::Profile(ID, AttrSets); |
953 | 7.96M | |
954 | 7.96M | void *InsertPoint; |
955 | 7.96M | AttributeListImpl *PA = |
956 | 7.96M | pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint); |
957 | 7.96M | |
958 | 7.96M | // If we didn't find any existing attributes of the same shape then |
959 | 7.96M | // create a new one and insert it. |
960 | 7.96M | if (!PA) { |
961 | 1.04M | // Coallocate entries after the AttributeListImpl itself. |
962 | 1.04M | void *Mem = ::operator new( |
963 | 1.04M | AttributeListImpl::totalSizeToAlloc<AttributeSet>(AttrSets.size())); |
964 | 1.04M | PA = new (Mem) AttributeListImpl(C, AttrSets); |
965 | 1.04M | pImpl->AttrsLists.InsertNode(PA, InsertPoint); |
966 | 1.04M | } |
967 | 7.96M | |
968 | 7.96M | // Return the AttributesList that we found or created. |
969 | 7.96M | return AttributeList(PA); |
970 | 7.96M | } |
971 | | |
972 | | AttributeList |
973 | | AttributeList::get(LLVMContext &C, |
974 | 1.38M | ArrayRef<std::pair<unsigned, Attribute>> Attrs) { |
975 | 1.38M | // If there are no attributes then return a null AttributesList pointer. |
976 | 1.38M | if (Attrs.empty()) |
977 | 433k | return {}; |
978 | 948k | |
979 | 948k | assert(std::is_sorted(Attrs.begin(), Attrs.end(), |
980 | 948k | [](const std::pair<unsigned, Attribute> &LHS, |
981 | 948k | const std::pair<unsigned, Attribute> &RHS) { |
982 | 948k | return LHS.first < RHS.first; |
983 | 948k | }) && "Misordered Attributes list!"); |
984 | 948k | assert(llvm::none_of(Attrs, |
985 | 948k | [](const std::pair<unsigned, Attribute> &Pair) { |
986 | 948k | return Pair.second.hasAttribute(Attribute::None); |
987 | 948k | }) && |
988 | 948k | "Pointless attribute!"); |
989 | 948k | |
990 | 948k | // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes |
991 | 948k | // list. |
992 | 948k | SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec; |
993 | 948k | for (ArrayRef<std::pair<unsigned, Attribute>>::iterator I = Attrs.begin(), |
994 | 1.89M | E = Attrs.end(); I != E; ) { |
995 | 948k | unsigned Index = I->first; |
996 | 948k | SmallVector<Attribute, 4> AttrVec; |
997 | 2.84M | while (I != E && I->first == Index1.89M ) { |
998 | 1.89M | AttrVec.push_back(I->second); |
999 | 1.89M | ++I; |
1000 | 1.89M | } |
1001 | 948k | |
1002 | 948k | AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec)); |
1003 | 948k | } |
1004 | 948k | |
1005 | 948k | return get(C, AttrPairVec); |
1006 | 948k | } |
1007 | | |
1008 | | AttributeList |
1009 | | AttributeList::get(LLVMContext &C, |
1010 | 2.02M | ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) { |
1011 | 2.02M | // If there are no attributes then return a null AttributesList pointer. |
1012 | 2.02M | if (Attrs.empty()) |
1013 | 0 | return {}; |
1014 | 2.02M | |
1015 | 2.02M | assert(std::is_sorted(Attrs.begin(), Attrs.end(), |
1016 | 2.02M | [](const std::pair<unsigned, AttributeSet> &LHS, |
1017 | 2.02M | const std::pair<unsigned, AttributeSet> &RHS) { |
1018 | 2.02M | return LHS.first < RHS.first; |
1019 | 2.02M | }) && |
1020 | 2.02M | "Misordered Attributes list!"); |
1021 | 2.02M | assert(llvm::none_of(Attrs, |
1022 | 2.02M | [](const std::pair<unsigned, AttributeSet> &Pair) { |
1023 | 2.02M | return !Pair.second.hasAttributes(); |
1024 | 2.02M | }) && |
1025 | 2.02M | "Pointless attribute!"); |
1026 | 2.02M | |
1027 | 2.02M | unsigned MaxIndex = Attrs.back().first; |
1028 | 2.02M | // If the MaxIndex is FunctionIndex and there are other indices in front |
1029 | 2.02M | // of it, we need to use the largest of those to get the right size. |
1030 | 2.02M | if (MaxIndex == FunctionIndex && Attrs.size() > 11.77M ) |
1031 | 1 | MaxIndex = Attrs[Attrs.size() - 2].first; |
1032 | 2.02M | |
1033 | 2.02M | SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1); |
1034 | 2.02M | for (const auto Pair : Attrs) |
1035 | 2.02M | AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second; |
1036 | 2.02M | |
1037 | 2.02M | return getImpl(C, AttrVec); |
1038 | 2.02M | } |
1039 | | |
1040 | | AttributeList AttributeList::get(LLVMContext &C, AttributeSet FnAttrs, |
1041 | | AttributeSet RetAttrs, |
1042 | 1.99M | ArrayRef<AttributeSet> ArgAttrs) { |
1043 | 1.99M | // Scan from the end to find the last argument with attributes. Most |
1044 | 1.99M | // arguments don't have attributes, so it's nice if we can have fewer unique |
1045 | 1.99M | // AttributeListImpls by dropping empty attribute sets at the end of the list. |
1046 | 1.99M | unsigned NumSets = 0; |
1047 | 4.92M | for (size_t I = ArgAttrs.size(); I != 0; --I2.93M ) { |
1048 | 3.20M | if (ArgAttrs[I - 1].hasAttributes()) { |
1049 | 275k | NumSets = I + 2; |
1050 | 275k | break; |
1051 | 275k | } |
1052 | 3.20M | } |
1053 | 1.99M | if (NumSets == 0) { |
1054 | 1.71M | // Check function and return attributes if we didn't have argument |
1055 | 1.71M | // attributes. |
1056 | 1.71M | if (RetAttrs.hasAttributes()) |
1057 | 138k | NumSets = 2; |
1058 | 1.57M | else if (FnAttrs.hasAttributes()) |
1059 | 808k | NumSets = 1; |
1060 | 1.71M | } |
1061 | 1.99M | |
1062 | 1.99M | // If all attribute sets were empty, we can use the empty attribute list. |
1063 | 1.99M | if (NumSets == 0) |
1064 | 767k | return {}; |
1065 | 1.22M | |
1066 | 1.22M | SmallVector<AttributeSet, 8> AttrSets; |
1067 | 1.22M | AttrSets.reserve(NumSets); |
1068 | 1.22M | // If we have any attributes, we always have function attributes. |
1069 | 1.22M | AttrSets.push_back(FnAttrs); |
1070 | 1.22M | if (NumSets > 1) |
1071 | 414k | AttrSets.push_back(RetAttrs); |
1072 | 1.22M | if (NumSets > 2) { |
1073 | 275k | // Drop the empty argument attribute sets at the end. |
1074 | 275k | ArgAttrs = ArgAttrs.take_front(NumSets - 2); |
1075 | 275k | AttrSets.insert(AttrSets.end(), ArgAttrs.begin(), ArgAttrs.end()); |
1076 | 275k | } |
1077 | 1.22M | |
1078 | 1.22M | return getImpl(C, AttrSets); |
1079 | 1.22M | } |
1080 | | |
1081 | | AttributeList AttributeList::get(LLVMContext &C, unsigned Index, |
1082 | 103k | const AttrBuilder &B) { |
1083 | 103k | if (!B.hasAttributes()) |
1084 | 40 | return {}; |
1085 | 103k | Index = attrIdxToArrayIdx(Index); |
1086 | 103k | SmallVector<AttributeSet, 8> AttrSets(Index + 1); |
1087 | 103k | AttrSets[Index] = AttributeSet::get(C, B); |
1088 | 103k | return getImpl(C, AttrSets); |
1089 | 103k | } |
1090 | | |
1091 | | AttributeList AttributeList::get(LLVMContext &C, unsigned Index, |
1092 | 1.38M | ArrayRef<Attribute::AttrKind> Kinds) { |
1093 | 1.38M | SmallVector<std::pair<unsigned, Attribute>, 8> Attrs; |
1094 | 1.38M | for (const auto K : Kinds) |
1095 | 1.89M | Attrs.emplace_back(Index, Attribute::get(C, K)); |
1096 | 1.38M | return get(C, Attrs); |
1097 | 1.38M | } |
1098 | | |
1099 | | AttributeList AttributeList::get(LLVMContext &C, unsigned Index, |
1100 | 0 | ArrayRef<StringRef> Kinds) { |
1101 | 0 | SmallVector<std::pair<unsigned, Attribute>, 8> Attrs; |
1102 | 0 | for (const auto K : Kinds) |
1103 | 0 | Attrs.emplace_back(Index, Attribute::get(C, K)); |
1104 | 0 | return get(C, Attrs); |
1105 | 0 | } |
1106 | | |
1107 | | AttributeList AttributeList::get(LLVMContext &C, |
1108 | 794k | ArrayRef<AttributeList> Attrs) { |
1109 | 794k | if (Attrs.empty()) |
1110 | 0 | return {}; |
1111 | 794k | if (Attrs.size() == 1) |
1112 | 615k | return Attrs[0]; |
1113 | 178k | |
1114 | 178k | unsigned MaxSize = 0; |
1115 | 178k | for (const auto List : Attrs) |
1116 | 484k | MaxSize = std::max(MaxSize, List.getNumAttrSets()); |
1117 | 178k | |
1118 | 178k | // If every list was empty, there is no point in merging the lists. |
1119 | 178k | if (MaxSize == 0) |
1120 | 1 | return {}; |
1121 | 178k | |
1122 | 178k | SmallVector<AttributeSet, 8> NewAttrSets(MaxSize); |
1123 | 963k | for (unsigned I = 0; I < MaxSize; ++I784k ) { |
1124 | 784k | AttrBuilder CurBuilder; |
1125 | 784k | for (const auto List : Attrs) |
1126 | 2.47M | CurBuilder.merge(List.getAttributes(I - 1)); |
1127 | 784k | NewAttrSets[I] = AttributeSet::get(C, CurBuilder); |
1128 | 784k | } |
1129 | 178k | |
1130 | 178k | return getImpl(C, NewAttrSets); |
1131 | 178k | } |
1132 | | |
1133 | | AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index, |
1134 | 2.27M | Attribute::AttrKind Kind) const { |
1135 | 2.27M | if (hasAttribute(Index, Kind)) return *this577k ; |
1136 | 1.69M | AttrBuilder B; |
1137 | 1.69M | B.addAttribute(Kind); |
1138 | 1.69M | return addAttributes(C, Index, B); |
1139 | 1.69M | } |
1140 | | |
1141 | | AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index, |
1142 | | StringRef Kind, |
1143 | 40 | StringRef Value) const { |
1144 | 40 | AttrBuilder B; |
1145 | 40 | B.addAttribute(Kind, Value); |
1146 | 40 | return addAttributes(C, Index, B); |
1147 | 40 | } |
1148 | | |
1149 | | AttributeList AttributeList::addAttribute(LLVMContext &C, unsigned Index, |
1150 | 838k | Attribute A) const { |
1151 | 838k | AttrBuilder B; |
1152 | 838k | B.addAttribute(A); |
1153 | 838k | return addAttributes(C, Index, B); |
1154 | 838k | } |
1155 | | |
1156 | | AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index, |
1157 | 4.22M | const AttrBuilder &B) const { |
1158 | 4.22M | if (!B.hasAttributes()) |
1159 | 555k | return *this; |
1160 | 3.67M | |
1161 | 3.67M | if (!pImpl) |
1162 | 1.07M | return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}}); |
1163 | 2.59M | |
1164 | | #ifndef NDEBUG |
1165 | | // FIXME it is not obvious how this should work for alignment. For now, say |
1166 | | // we can't change a known alignment. |
1167 | | unsigned OldAlign = getAttributes(Index).getAlignment(); |
1168 | | unsigned NewAlign = B.getAlignment(); |
1169 | | assert((!OldAlign || !NewAlign || OldAlign == NewAlign) && |
1170 | | "Attempt to change alignment!"); |
1171 | | #endif |
1172 | | |
1173 | 2.59M | Index = attrIdxToArrayIdx(Index); |
1174 | 2.59M | SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); |
1175 | 2.59M | if (Index >= AttrSets.size()) |
1176 | 119k | AttrSets.resize(Index + 1); |
1177 | 2.59M | |
1178 | 2.59M | AttrBuilder Merged(AttrSets[Index]); |
1179 | 2.59M | Merged.merge(B); |
1180 | 2.59M | AttrSets[Index] = AttributeSet::get(C, Merged); |
1181 | 2.59M | |
1182 | 2.59M | return getImpl(C, AttrSets); |
1183 | 2.59M | } |
1184 | | |
1185 | | AttributeList AttributeList::addParamAttribute(LLVMContext &C, |
1186 | | ArrayRef<unsigned> ArgNos, |
1187 | 1.06M | Attribute A) const { |
1188 | 1.06M | assert(std::is_sorted(ArgNos.begin(), ArgNos.end())); |
1189 | 1.06M | |
1190 | 1.06M | SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); |
1191 | 1.06M | unsigned MaxIndex = attrIdxToArrayIdx(ArgNos.back() + FirstArgIndex); |
1192 | 1.06M | if (MaxIndex >= AttrSets.size()) |
1193 | 896k | AttrSets.resize(MaxIndex + 1); |
1194 | 1.06M | |
1195 | 1.20M | for (unsigned ArgNo : ArgNos) { |
1196 | 1.20M | unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex); |
1197 | 1.20M | AttrBuilder B(AttrSets[Index]); |
1198 | 1.20M | B.addAttribute(A); |
1199 | 1.20M | AttrSets[Index] = AttributeSet::get(C, B); |
1200 | 1.20M | } |
1201 | 1.06M | |
1202 | 1.06M | return getImpl(C, AttrSets); |
1203 | 1.06M | } |
1204 | | |
1205 | | AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index, |
1206 | 409k | Attribute::AttrKind Kind) const { |
1207 | 409k | if (!hasAttribute(Index, Kind)) return *this404k ; |
1208 | 4.98k | |
1209 | 4.98k | Index = attrIdxToArrayIdx(Index); |
1210 | 4.98k | SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); |
1211 | 4.98k | assert(Index < AttrSets.size()); |
1212 | 4.98k | |
1213 | 4.98k | AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind); |
1214 | 4.98k | |
1215 | 4.98k | return getImpl(C, AttrSets); |
1216 | 4.98k | } |
1217 | | |
1218 | | AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index, |
1219 | 750k | StringRef Kind) const { |
1220 | 750k | if (!hasAttribute(Index, Kind)) return *this112k ; |
1221 | 637k | |
1222 | 637k | Index = attrIdxToArrayIdx(Index); |
1223 | 637k | SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); |
1224 | 637k | assert(Index < AttrSets.size()); |
1225 | 637k | |
1226 | 637k | AttrSets[Index] = AttrSets[Index].removeAttribute(C, Kind); |
1227 | 637k | |
1228 | 637k | return getImpl(C, AttrSets); |
1229 | 637k | } |
1230 | | |
1231 | | AttributeList |
1232 | | AttributeList::removeAttributes(LLVMContext &C, unsigned Index, |
1233 | 1.40k | const AttrBuilder &AttrsToRemove) const { |
1234 | 1.40k | if (!pImpl) |
1235 | 389 | return {}; |
1236 | 1.01k | |
1237 | 1.01k | Index = attrIdxToArrayIdx(Index); |
1238 | 1.01k | SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); |
1239 | 1.01k | if (Index >= AttrSets.size()) |
1240 | 44 | AttrSets.resize(Index + 1); |
1241 | 1.01k | |
1242 | 1.01k | AttrSets[Index] = AttrSets[Index].removeAttributes(C, AttrsToRemove); |
1243 | 1.01k | |
1244 | 1.01k | return getImpl(C, AttrSets); |
1245 | 1.01k | } |
1246 | | |
1247 | | AttributeList AttributeList::removeAttributes(LLVMContext &C, |
1248 | 569k | unsigned WithoutIndex) const { |
1249 | 569k | if (!pImpl) |
1250 | 442k | return {}; |
1251 | 127k | WithoutIndex = attrIdxToArrayIdx(WithoutIndex); |
1252 | 127k | if (WithoutIndex >= getNumAttrSets()) |
1253 | 0 | return *this; |
1254 | 127k | SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); |
1255 | 127k | AttrSets[WithoutIndex] = AttributeSet(); |
1256 | 127k | return getImpl(C, AttrSets); |
1257 | 127k | } |
1258 | | |
1259 | | AttributeList AttributeList::addDereferenceableAttr(LLVMContext &C, |
1260 | | unsigned Index, |
1261 | 64 | uint64_t Bytes) const { |
1262 | 64 | AttrBuilder B; |
1263 | 64 | B.addDereferenceableAttr(Bytes); |
1264 | 64 | return addAttributes(C, Index, B); |
1265 | 64 | } |
1266 | | |
1267 | | AttributeList |
1268 | | AttributeList::addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index, |
1269 | 0 | uint64_t Bytes) const { |
1270 | 0 | AttrBuilder B; |
1271 | 0 | B.addDereferenceableOrNullAttr(Bytes); |
1272 | 0 | return addAttributes(C, Index, B); |
1273 | 0 | } |
1274 | | |
1275 | | AttributeList |
1276 | | AttributeList::addAllocSizeAttr(LLVMContext &C, unsigned Index, |
1277 | | unsigned ElemSizeArg, |
1278 | 0 | const Optional<unsigned> &NumElemsArg) { |
1279 | 0 | AttrBuilder B; |
1280 | 0 | B.addAllocSizeAttr(ElemSizeArg, NumElemsArg); |
1281 | 0 | return addAttributes(C, Index, B); |
1282 | 0 | } |
1283 | | |
1284 | | //===----------------------------------------------------------------------===// |
1285 | | // AttributeList Accessor Methods |
1286 | | //===----------------------------------------------------------------------===// |
1287 | | |
1288 | 10 | LLVMContext &AttributeList::getContext() const { return pImpl->getContext(); } |
1289 | | |
1290 | 3.00M | AttributeSet AttributeList::getParamAttributes(unsigned ArgNo) const { |
1291 | 3.00M | return getAttributes(ArgNo + FirstArgIndex); |
1292 | 3.00M | } |
1293 | | |
1294 | 1.17M | AttributeSet AttributeList::getRetAttributes() const { |
1295 | 1.17M | return getAttributes(ReturnIndex); |
1296 | 1.17M | } |
1297 | | |
1298 | 2.78M | AttributeSet AttributeList::getFnAttributes() const { |
1299 | 2.78M | return getAttributes(FunctionIndex); |
1300 | 2.78M | } |
1301 | | |
1302 | | bool AttributeList::hasAttribute(unsigned Index, |
1303 | 2.03G | Attribute::AttrKind Kind) const { |
1304 | 2.03G | return getAttributes(Index).hasAttribute(Kind); |
1305 | 2.03G | } |
1306 | | |
1307 | 65.5M | bool AttributeList::hasAttribute(unsigned Index, StringRef Kind) const { |
1308 | 65.5M | return getAttributes(Index).hasAttribute(Kind); |
1309 | 65.5M | } |
1310 | | |
1311 | 2.78M | bool AttributeList::hasAttributes(unsigned Index) const { |
1312 | 2.78M | return getAttributes(Index).hasAttributes(); |
1313 | 2.78M | } |
1314 | | |
1315 | 383M | bool AttributeList::hasFnAttribute(Attribute::AttrKind Kind) const { |
1316 | 383M | return pImpl && pImpl->hasFnAttribute(Kind)379M ; |
1317 | 383M | } |
1318 | | |
1319 | 64.5M | bool AttributeList::hasFnAttribute(StringRef Kind) const { |
1320 | 64.5M | return hasAttribute(AttributeList::FunctionIndex, Kind); |
1321 | 64.5M | } |
1322 | | |
1323 | | bool AttributeList::hasParamAttribute(unsigned ArgNo, |
1324 | 364M | Attribute::AttrKind Kind) const { |
1325 | 364M | return hasAttribute(ArgNo + FirstArgIndex, Kind); |
1326 | 364M | } |
1327 | | |
1328 | | bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr, |
1329 | 155M | unsigned *Index) const { |
1330 | 155M | if (!pImpl) return false4.99M ; |
1331 | 150M | |
1332 | 418M | for (unsigned I = index_begin(), E = index_end(); 150M I != E; ++I268M ) { |
1333 | 268M | if (hasAttribute(I, Attr)) { |
1334 | 18.2k | if (Index) |
1335 | 14.3k | *Index = I; |
1336 | 18.2k | return true; |
1337 | 18.2k | } |
1338 | 268M | } |
1339 | 150M | |
1340 | 150M | return false150M ; |
1341 | 150M | } |
1342 | | |
1343 | | Attribute AttributeList::getAttribute(unsigned Index, |
1344 | 22.4M | Attribute::AttrKind Kind) const { |
1345 | 22.4M | return getAttributes(Index).getAttribute(Kind); |
1346 | 22.4M | } |
1347 | | |
1348 | 173M | Attribute AttributeList::getAttribute(unsigned Index, StringRef Kind) const { |
1349 | 173M | return getAttributes(Index).getAttribute(Kind); |
1350 | 173M | } |
1351 | | |
1352 | 14.8M | unsigned AttributeList::getRetAlignment() const { |
1353 | 14.8M | return getAttributes(ReturnIndex).getAlignment(); |
1354 | 14.8M | } |
1355 | | |
1356 | 28.3M | unsigned AttributeList::getParamAlignment(unsigned ArgNo) const { |
1357 | 28.3M | return getAttributes(ArgNo + FirstArgIndex).getAlignment(); |
1358 | 28.3M | } |
1359 | | |
1360 | 3.32k | Type *AttributeList::getParamByValType(unsigned Index) const { |
1361 | 3.32k | return getAttributes(Index+FirstArgIndex).getByValType(); |
1362 | 3.32k | } |
1363 | | |
1364 | | |
1365 | 69 | unsigned AttributeList::getStackAlignment(unsigned Index) const { |
1366 | 69 | return getAttributes(Index).getStackAlignment(); |
1367 | 69 | } |
1368 | | |
1369 | 62.5M | uint64_t AttributeList::getDereferenceableBytes(unsigned Index) const { |
1370 | 62.5M | return getAttributes(Index).getDereferenceableBytes(); |
1371 | 62.5M | } |
1372 | | |
1373 | 1.18M | uint64_t AttributeList::getDereferenceableOrNullBytes(unsigned Index) const { |
1374 | 1.18M | return getAttributes(Index).getDereferenceableOrNullBytes(); |
1375 | 1.18M | } |
1376 | | |
1377 | | std::pair<unsigned, Optional<unsigned>> |
1378 | 117 | AttributeList::getAllocSizeArgs(unsigned Index) const { |
1379 | 117 | return getAttributes(Index).getAllocSizeArgs(); |
1380 | 117 | } |
1381 | | |
1382 | 10.0k | std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const { |
1383 | 10.0k | return getAttributes(Index).getAsString(InAttrGrp); |
1384 | 10.0k | } |
1385 | | |
1386 | 2.42G | AttributeSet AttributeList::getAttributes(unsigned Index) const { |
1387 | 2.42G | Index = attrIdxToArrayIdx(Index); |
1388 | 2.42G | if (!pImpl || Index >= getNumAttrSets()2.34G ) |
1389 | 396M | return {}; |
1390 | 2.02G | return pImpl->begin()[Index]; |
1391 | 2.02G | } |
1392 | | |
1393 | 4.43M | AttributeList::iterator AttributeList::begin() const { |
1394 | 4.43M | return pImpl ? pImpl->begin()4.29M : nullptr136k ; |
1395 | 4.43M | } |
1396 | | |
1397 | 4.43M | AttributeList::iterator AttributeList::end() const { |
1398 | 4.43M | return pImpl ? pImpl->end()4.29M : nullptr136k ; |
1399 | 4.43M | } |
1400 | | |
1401 | | //===----------------------------------------------------------------------===// |
1402 | | // AttributeList Introspection Methods |
1403 | | //===----------------------------------------------------------------------===// |
1404 | | |
1405 | 2.49G | unsigned AttributeList::getNumAttrSets() const { |
1406 | 2.49G | return pImpl ? pImpl->NumAttrSets2.49G : 0905k ; |
1407 | 2.49G | } |
1408 | | |
1409 | | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
1410 | | LLVM_DUMP_METHOD void AttributeList::dump() const { |
1411 | | dbgs() << "PAL[\n"; |
1412 | | |
1413 | | for (unsigned i = index_begin(), e = index_end(); i != e; ++i) { |
1414 | | if (getAttributes(i).hasAttributes()) |
1415 | | dbgs() << " { " << i << " => " << getAsString(i) << " }\n"; |
1416 | | } |
1417 | | |
1418 | | dbgs() << "]\n"; |
1419 | | } |
1420 | | #endif |
1421 | | |
1422 | | //===----------------------------------------------------------------------===// |
1423 | | // AttrBuilder Method Implementations |
1424 | | //===----------------------------------------------------------------------===// |
1425 | | |
1426 | | // FIXME: Remove this ctor, use AttributeSet. |
1427 | 355k | AttrBuilder::AttrBuilder(AttributeList AL, unsigned Index) { |
1428 | 355k | AttributeSet AS = AL.getAttributes(Index); |
1429 | 355k | for (const auto &A : AS) |
1430 | 2.59k | addAttribute(A); |
1431 | 355k | } |
1432 | | |
1433 | 8.44M | AttrBuilder::AttrBuilder(AttributeSet AS) { |
1434 | 8.44M | for (const auto &A : AS) |
1435 | 37.6M | addAttribute(A); |
1436 | 8.44M | } |
1437 | | |
1438 | 2.22M | void AttrBuilder::clear() { |
1439 | 2.22M | Attrs.reset(); |
1440 | 2.22M | TargetDepAttrs.clear(); |
1441 | 2.22M | Alignment = StackAlignment = DerefBytes = DerefOrNullBytes = 0; |
1442 | 2.22M | AllocSizeArgs = 0; |
1443 | 2.22M | ByValType = nullptr; |
1444 | 2.22M | } |
1445 | | |
1446 | 7.61M | AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) { |
1447 | 7.61M | assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!"); |
1448 | 7.61M | assert(Val != Attribute::Alignment && Val != Attribute::StackAlignment && |
1449 | 7.61M | Val != Attribute::Dereferenceable && Val != Attribute::AllocSize && |
1450 | 7.61M | "Adding integer attribute without adding a value!"); |
1451 | 7.61M | Attrs[Val] = true; |
1452 | 7.61M | return *this; |
1453 | 7.61M | } |
1454 | | |
1455 | 39.7M | AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) { |
1456 | 39.7M | if (Attr.isStringAttribute()) { |
1457 | 34.5M | addAttribute(Attr.getKindAsString(), Attr.getValueAsString()); |
1458 | 34.5M | return *this; |
1459 | 34.5M | } |
1460 | 5.15M | |
1461 | 5.15M | Attribute::AttrKind Kind = Attr.getKindAsEnum(); |
1462 | 5.15M | Attrs[Kind] = true; |
1463 | 5.15M | |
1464 | 5.15M | if (Kind == Attribute::Alignment) |
1465 | 214k | Alignment = Attr.getAlignment(); |
1466 | 4.93M | else if (Kind == Attribute::StackAlignment) |
1467 | 124 | StackAlignment = Attr.getStackAlignment(); |
1468 | 4.93M | else if (Kind == Attribute::ByVal) |
1469 | 7.94k | ByValType = Attr.getValueAsType(); |
1470 | 4.93M | else if (Kind == Attribute::Dereferenceable) |
1471 | 245k | DerefBytes = Attr.getDereferenceableBytes(); |
1472 | 4.68M | else if (Kind == Attribute::DereferenceableOrNull) |
1473 | 184 | DerefOrNullBytes = Attr.getDereferenceableOrNullBytes(); |
1474 | 4.68M | else if (Kind == Attribute::AllocSize) |
1475 | 2.48k | AllocSizeArgs = Attr.getValueAsInt(); |
1476 | 5.15M | return *this; |
1477 | 5.15M | } |
1478 | | |
1479 | 41.4M | AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) { |
1480 | 41.4M | TargetDepAttrs[A] = V; |
1481 | 41.4M | return *this; |
1482 | 41.4M | } |
1483 | | |
1484 | 783k | AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) { |
1485 | 783k | assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!"); |
1486 | 783k | Attrs[Val] = false; |
1487 | 783k | |
1488 | 783k | if (Val == Attribute::Alignment) |
1489 | 4.49k | Alignment = 0; |
1490 | 779k | else if (Val == Attribute::StackAlignment) |
1491 | 1 | StackAlignment = 0; |
1492 | 779k | else if (Val == Attribute::ByVal) |
1493 | 55 | ByValType = nullptr; |
1494 | 778k | else if (Val == Attribute::Dereferenceable) |
1495 | 1 | DerefBytes = 0; |
1496 | 778k | else if (Val == Attribute::DereferenceableOrNull) |
1497 | 0 | DerefOrNullBytes = 0; |
1498 | 778k | else if (Val == Attribute::AllocSize) |
1499 | 2 | AllocSizeArgs = 0; |
1500 | 783k | |
1501 | 783k | return *this; |
1502 | 783k | } |
1503 | | |
1504 | 0 | AttrBuilder &AttrBuilder::removeAttributes(AttributeList A, uint64_t Index) { |
1505 | 0 | remove(A.getAttributes(Index)); |
1506 | 0 | return *this; |
1507 | 0 | } |
1508 | | |
1509 | 637k | AttrBuilder &AttrBuilder::removeAttribute(StringRef A) { |
1510 | 637k | auto I = TargetDepAttrs.find(A); |
1511 | 637k | if (I != TargetDepAttrs.end()) |
1512 | 637k | TargetDepAttrs.erase(I); |
1513 | 637k | return *this; |
1514 | 637k | } |
1515 | | |
1516 | 5.54k | std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const { |
1517 | 5.54k | return unpackAllocSizeArgs(AllocSizeArgs); |
1518 | 5.54k | } |
1519 | | |
1520 | 9.52k | AttrBuilder &AttrBuilder::addAlignmentAttr(unsigned Align) { |
1521 | 9.52k | if (Align == 0) return *this0 ; |
1522 | 9.52k | |
1523 | 9.52k | assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); |
1524 | 9.52k | assert(Align <= 0x40000000 && "Alignment too large."); |
1525 | 9.52k | |
1526 | 9.52k | Attrs[Attribute::Alignment] = true; |
1527 | 9.52k | Alignment = Align; |
1528 | 9.52k | return *this; |
1529 | 9.52k | } |
1530 | | |
1531 | 89 | AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align) { |
1532 | 89 | // Default alignment, allow the target to define how to align it. |
1533 | 89 | if (Align == 0) return *this0 ; |
1534 | 89 | |
1535 | 89 | assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); |
1536 | 89 | assert(Align <= 0x100 && "Alignment too large."); |
1537 | 89 | |
1538 | 89 | Attrs[Attribute::StackAlignment] = true; |
1539 | 89 | StackAlignment = Align; |
1540 | 89 | return *this; |
1541 | 89 | } |
1542 | | |
1543 | 560k | AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) { |
1544 | 560k | if (Bytes == 0) return *this263 ; |
1545 | 560k | |
1546 | 560k | Attrs[Attribute::Dereferenceable] = true; |
1547 | 560k | DerefBytes = Bytes; |
1548 | 560k | return *this; |
1549 | 560k | } |
1550 | | |
1551 | 195k | AttrBuilder &AttrBuilder::addDereferenceableOrNullAttr(uint64_t Bytes) { |
1552 | 195k | if (Bytes == 0) |
1553 | 0 | return *this; |
1554 | 195k | |
1555 | 195k | Attrs[Attribute::DereferenceableOrNull] = true; |
1556 | 195k | DerefOrNullBytes = Bytes; |
1557 | 195k | return *this; |
1558 | 195k | } |
1559 | | |
1560 | | AttrBuilder &AttrBuilder::addAllocSizeAttr(unsigned ElemSize, |
1561 | 3.04k | const Optional<unsigned> &NumElems) { |
1562 | 3.04k | return addAllocSizeAttrFromRawRepr(packAllocSizeArgs(ElemSize, NumElems)); |
1563 | 3.04k | } |
1564 | | |
1565 | 3.05k | AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) { |
1566 | 3.05k | // (0, 0) is our "not present" value, so we need to check for it here. |
1567 | 3.05k | assert(RawArgs && "Invalid allocsize arguments -- given allocsize(0, 0)"); |
1568 | 3.05k | |
1569 | 3.05k | Attrs[Attribute::AllocSize] = true; |
1570 | 3.05k | // Reuse existing machinery to store this as a single 64-bit integer so we can |
1571 | 3.05k | // save a few bytes over using a pair<unsigned, Optional<unsigned>>. |
1572 | 3.05k | AllocSizeArgs = RawArgs; |
1573 | 3.05k | return *this; |
1574 | 3.05k | } |
1575 | | |
1576 | 4.32k | AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) { |
1577 | 4.32k | Attrs[Attribute::ByVal] = true; |
1578 | 4.32k | ByValType = Ty; |
1579 | 4.32k | return *this; |
1580 | 4.32k | } |
1581 | | |
1582 | 5.70M | AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { |
1583 | 5.70M | // FIXME: What if both have alignments, but they don't match?! |
1584 | 5.70M | if (!Alignment) |
1585 | 5.70M | Alignment = B.Alignment; |
1586 | 5.70M | |
1587 | 5.70M | if (!StackAlignment) |
1588 | 5.70M | StackAlignment = B.StackAlignment; |
1589 | 5.70M | |
1590 | 5.70M | if (!DerefBytes) |
1591 | 5.64M | DerefBytes = B.DerefBytes; |
1592 | 5.70M | |
1593 | 5.70M | if (!DerefOrNullBytes) |
1594 | 5.70M | DerefOrNullBytes = B.DerefOrNullBytes; |
1595 | 5.70M | |
1596 | 5.70M | if (!AllocSizeArgs) |
1597 | 5.70M | AllocSizeArgs = B.AllocSizeArgs; |
1598 | 5.70M | |
1599 | 5.70M | if (!ByValType) |
1600 | 5.70M | ByValType = B.ByValType; |
1601 | 5.70M | |
1602 | 5.70M | Attrs |= B.Attrs; |
1603 | 5.70M | |
1604 | 5.70M | for (auto I : B.td_attrs()) |
1605 | 2.11M | TargetDepAttrs[I.first] = I.second; |
1606 | 5.70M | |
1607 | 5.70M | return *this; |
1608 | 5.70M | } |
1609 | | |
1610 | 17.7k | AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) { |
1611 | 17.7k | // FIXME: What if both have alignments, but they don't match?! |
1612 | 17.7k | if (B.Alignment) |
1613 | 2 | Alignment = 0; |
1614 | 17.7k | |
1615 | 17.7k | if (B.StackAlignment) |
1616 | 1 | StackAlignment = 0; |
1617 | 17.7k | |
1618 | 17.7k | if (B.DerefBytes) |
1619 | 16.5k | DerefBytes = 0; |
1620 | 17.7k | |
1621 | 17.7k | if (B.DerefOrNullBytes) |
1622 | 16.5k | DerefOrNullBytes = 0; |
1623 | 17.7k | |
1624 | 17.7k | if (B.AllocSizeArgs) |
1625 | 0 | AllocSizeArgs = 0; |
1626 | 17.7k | |
1627 | 17.7k | if (B.ByValType) |
1628 | 0 | ByValType = nullptr; |
1629 | 17.7k | |
1630 | 17.7k | Attrs &= ~B.Attrs; |
1631 | 17.7k | |
1632 | 17.7k | for (auto I : B.td_attrs()) |
1633 | 32 | TargetDepAttrs.erase(I.first); |
1634 | 17.7k | |
1635 | 17.7k | return *this; |
1636 | 17.7k | } |
1637 | | |
1638 | 359k | bool AttrBuilder::overlaps(const AttrBuilder &B) const { |
1639 | 359k | // First check if any of the target independent attributes overlap. |
1640 | 359k | if ((Attrs & B.Attrs).any()) |
1641 | 5 | return true; |
1642 | 359k | |
1643 | 359k | // Then check if any target dependent ones do. |
1644 | 359k | for (const auto &I : td_attrs()) |
1645 | 66 | if (B.contains(I.first)) |
1646 | 0 | return true; |
1647 | 359k | |
1648 | 359k | return false; |
1649 | 359k | } |
1650 | | |
1651 | 66 | bool AttrBuilder::contains(StringRef A) const { |
1652 | 66 | return TargetDepAttrs.find(A) != TargetDepAttrs.end(); |
1653 | 66 | } |
1654 | | |
1655 | 6.81M | bool AttrBuilder::hasAttributes() const { |
1656 | 6.81M | return !Attrs.none() || !TargetDepAttrs.empty()4.12M ; |
1657 | 6.81M | } |
1658 | | |
1659 | 0 | bool AttrBuilder::hasAttributes(AttributeList AL, uint64_t Index) const { |
1660 | 0 | AttributeSet AS = AL.getAttributes(Index); |
1661 | 0 |
|
1662 | 0 | for (const auto Attr : AS) { |
1663 | 0 | if (Attr.isEnumAttribute() || Attr.isIntAttribute()) { |
1664 | 0 | if (contains(Attr.getKindAsEnum())) |
1665 | 0 | return true; |
1666 | 0 | } else { |
1667 | 0 | assert(Attr.isStringAttribute() && "Invalid attribute kind!"); |
1668 | 0 | return contains(Attr.getKindAsString()); |
1669 | 0 | } |
1670 | 0 | } |
1671 | 0 |
|
1672 | 0 | return false; |
1673 | 0 | } |
1674 | | |
1675 | 948k | bool AttrBuilder::hasAlignmentAttr() const { |
1676 | 948k | return Alignment != 0; |
1677 | 948k | } |
1678 | | |
1679 | 174k | bool AttrBuilder::operator==(const AttrBuilder &B) { |
1680 | 174k | if (Attrs != B.Attrs) |
1681 | 176 | return false; |
1682 | 174k | |
1683 | 174k | for (td_const_iterator I = TargetDepAttrs.begin(), |
1684 | 174k | E = TargetDepAttrs.end(); I != E; ++I0 ) |
1685 | 0 | if (B.TargetDepAttrs.find(I->first) == B.TargetDepAttrs.end()) |
1686 | 0 | return false; |
1687 | 174k | |
1688 | 174k | return Alignment == B.Alignment && StackAlignment == B.StackAlignment174k && |
1689 | 174k | DerefBytes == B.DerefBytes174k && ByValType == B.ByValType174k ; |
1690 | 174k | } |
1691 | | |
1692 | | //===----------------------------------------------------------------------===// |
1693 | | // AttributeFuncs Function Defintions |
1694 | | //===----------------------------------------------------------------------===// |
1695 | | |
1696 | | /// Which attributes cannot be applied to a type. |
1697 | 376k | AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) { |
1698 | 376k | AttrBuilder Incompatible; |
1699 | 376k | |
1700 | 376k | if (!Ty->isIntegerTy()) |
1701 | 206k | // Attribute that only apply to integers. |
1702 | 206k | Incompatible.addAttribute(Attribute::SExt) |
1703 | 206k | .addAttribute(Attribute::ZExt); |
1704 | 376k | |
1705 | 376k | if (!Ty->isPointerTy()) |
1706 | 195k | // Attribute that only apply to pointers. |
1707 | 195k | Incompatible.addAttribute(Attribute::ByVal) |
1708 | 195k | .addAttribute(Attribute::Nest) |
1709 | 195k | .addAttribute(Attribute::NoAlias) |
1710 | 195k | .addAttribute(Attribute::NoCapture) |
1711 | 195k | .addAttribute(Attribute::NonNull) |
1712 | 195k | .addDereferenceableAttr(1) // the int here is ignored |
1713 | 195k | .addDereferenceableOrNullAttr(1) // the int here is ignored |
1714 | 195k | .addAttribute(Attribute::ReadNone) |
1715 | 195k | .addAttribute(Attribute::ReadOnly) |
1716 | 195k | .addAttribute(Attribute::StructRet) |
1717 | 195k | .addAttribute(Attribute::InAlloca); |
1718 | 376k | |
1719 | 376k | return Incompatible; |
1720 | 376k | } |
1721 | | |
1722 | | template<typename AttrClass> |
1723 | 11.0M | static bool isEqual(const Function &Caller, const Function &Callee) { |
1724 | 11.0M | return Caller.getFnAttribute(AttrClass::getKind()) == |
1725 | 11.0M | Callee.getFnAttribute(AttrClass::getKind()); |
1726 | 11.0M | } Attributes.cpp:bool isEqual<SanitizeAddressAttr>(llvm::Function const&, llvm::Function const&) Line | Count | Source | 1723 | 1.57M | static bool isEqual(const Function &Caller, const Function &Callee) { | 1724 | 1.57M | return Caller.getFnAttribute(AttrClass::getKind()) == | 1725 | 1.57M | Callee.getFnAttribute(AttrClass::getKind()); | 1726 | 1.57M | } |
Attributes.cpp:bool isEqual<SanitizeThreadAttr>(llvm::Function const&, llvm::Function const&) Line | Count | Source | 1723 | 1.57M | static bool isEqual(const Function &Caller, const Function &Callee) { | 1724 | 1.57M | return Caller.getFnAttribute(AttrClass::getKind()) == | 1725 | 1.57M | Callee.getFnAttribute(AttrClass::getKind()); | 1726 | 1.57M | } |
Attributes.cpp:bool isEqual<SanitizeMemoryAttr>(llvm::Function const&, llvm::Function const&) Line | Count | Source | 1723 | 1.57M | static bool isEqual(const Function &Caller, const Function &Callee) { | 1724 | 1.57M | return Caller.getFnAttribute(AttrClass::getKind()) == | 1725 | 1.57M | Callee.getFnAttribute(AttrClass::getKind()); | 1726 | 1.57M | } |
Attributes.cpp:bool isEqual<SanitizeHWAddressAttr>(llvm::Function const&, llvm::Function const&) Line | Count | Source | 1723 | 1.57M | static bool isEqual(const Function &Caller, const Function &Callee) { | 1724 | 1.57M | return Caller.getFnAttribute(AttrClass::getKind()) == | 1725 | 1.57M | Callee.getFnAttribute(AttrClass::getKind()); | 1726 | 1.57M | } |
Attributes.cpp:bool isEqual<SanitizeMemTagAttr>(llvm::Function const&, llvm::Function const&) Line | Count | Source | 1723 | 1.57M | static bool isEqual(const Function &Caller, const Function &Callee) { | 1724 | 1.57M | return Caller.getFnAttribute(AttrClass::getKind()) == | 1725 | 1.57M | Callee.getFnAttribute(AttrClass::getKind()); | 1726 | 1.57M | } |
Attributes.cpp:bool isEqual<SafeStackAttr>(llvm::Function const&, llvm::Function const&) Line | Count | Source | 1723 | 1.57M | static bool isEqual(const Function &Caller, const Function &Callee) { | 1724 | 1.57M | return Caller.getFnAttribute(AttrClass::getKind()) == | 1725 | 1.57M | Callee.getFnAttribute(AttrClass::getKind()); | 1726 | 1.57M | } |
Attributes.cpp:bool isEqual<ShadowCallStackAttr>(llvm::Function const&, llvm::Function const&) Line | Count | Source | 1723 | 1.57M | static bool isEqual(const Function &Caller, const Function &Callee) { | 1724 | 1.57M | return Caller.getFnAttribute(AttrClass::getKind()) == | 1725 | 1.57M | Callee.getFnAttribute(AttrClass::getKind()); | 1726 | 1.57M | } |
|
1727 | | |
1728 | | /// Compute the logical AND of the attributes of the caller and the |
1729 | | /// callee. |
1730 | | /// |
1731 | | /// This function sets the caller's attribute to false if the callee's attribute |
1732 | | /// is false. |
1733 | | template<typename AttrClass> |
1734 | 2.16M | static void setAND(Function &Caller, const Function &Callee) { |
1735 | 2.16M | if (AttrClass::isSet(Caller, AttrClass::getKind()) && |
1736 | 2.16M | !AttrClass::isSet(Callee, AttrClass::getKind())1.85k ) |
1737 | 8 | AttrClass::set(Caller, AttrClass::getKind(), false); |
1738 | 2.16M | } Attributes.cpp:void setAND<UnsafeFPMathAttr>(llvm::Function&, llvm::Function const&) Line | Count | Source | 1734 | 540k | static void setAND(Function &Caller, const Function &Callee) { | 1735 | 540k | if (AttrClass::isSet(Caller, AttrClass::getKind()) && | 1736 | 540k | !AttrClass::isSet(Callee, AttrClass::getKind())616 ) | 1737 | 2 | AttrClass::set(Caller, AttrClass::getKind(), false); | 1738 | 540k | } |
Attributes.cpp:void setAND<LessPreciseFPMADAttr>(llvm::Function&, llvm::Function const&) Line | Count | Source | 1734 | 540k | static void setAND(Function &Caller, const Function &Callee) { | 1735 | 540k | if (AttrClass::isSet(Caller, AttrClass::getKind()) && | 1736 | 540k | !AttrClass::isSet(Callee, AttrClass::getKind())7 ) | 1737 | 4 | AttrClass::set(Caller, AttrClass::getKind(), false); | 1738 | 540k | } |
Attributes.cpp:void setAND<NoInfsFPMathAttr>(llvm::Function&, llvm::Function const&) Line | Count | Source | 1734 | 540k | static void setAND(Function &Caller, const Function &Callee) { | 1735 | 540k | if (AttrClass::isSet(Caller, AttrClass::getKind()) && | 1736 | 540k | !AttrClass::isSet(Callee, AttrClass::getKind())616 ) | 1737 | 1 | AttrClass::set(Caller, AttrClass::getKind(), false); | 1738 | 540k | } |
Attributes.cpp:void setAND<NoNansFPMathAttr>(llvm::Function&, llvm::Function const&) Line | Count | Source | 1734 | 540k | static void setAND(Function &Caller, const Function &Callee) { | 1735 | 540k | if (AttrClass::isSet(Caller, AttrClass::getKind()) && | 1736 | 540k | !AttrClass::isSet(Callee, AttrClass::getKind())616 ) | 1737 | 1 | AttrClass::set(Caller, AttrClass::getKind(), false); | 1738 | 540k | } |
|
1739 | | |
1740 | | /// Compute the logical OR of the attributes of the caller and the |
1741 | | /// callee. |
1742 | | /// |
1743 | | /// This function sets the caller's attribute to true if the callee's attribute |
1744 | | /// is true. |
1745 | | template<typename AttrClass> |
1746 | 2.16M | static void setOR(Function &Caller, const Function &Callee) { |
1747 | 2.16M | if (!AttrClass::isSet(Caller, AttrClass::getKind()) && |
1748 | 2.16M | AttrClass::isSet(Callee, AttrClass::getKind())2.16M ) |
1749 | 6 | AttrClass::set(Caller, AttrClass::getKind(), true); |
1750 | 2.16M | } Attributes.cpp:void setOR<NoImplicitFloatAttr>(llvm::Function&, llvm::Function const&) Line | Count | Source | 1746 | 540k | static void setOR(Function &Caller, const Function &Callee) { | 1747 | 540k | if (!AttrClass::isSet(Caller, AttrClass::getKind()) && | 1748 | 540k | AttrClass::isSet(Callee, AttrClass::getKind())540k ) | 1749 | 2 | AttrClass::set(Caller, AttrClass::getKind(), true); | 1750 | 540k | } |
Attributes.cpp:void setOR<NoJumpTablesAttr>(llvm::Function&, llvm::Function const&) Line | Count | Source | 1746 | 540k | static void setOR(Function &Caller, const Function &Callee) { | 1747 | 540k | if (!AttrClass::isSet(Caller, AttrClass::getKind()) && | 1748 | 540k | AttrClass::isSet(Callee, AttrClass::getKind())540k ) | 1749 | 2 | AttrClass::set(Caller, AttrClass::getKind(), true); | 1750 | 540k | } |
Attributes.cpp:void setOR<ProfileSampleAccurateAttr>(llvm::Function&, llvm::Function const&) Line | Count | Source | 1746 | 540k | static void setOR(Function &Caller, const Function &Callee) { | 1747 | 540k | if (!AttrClass::isSet(Caller, AttrClass::getKind()) && | 1748 | 540k | AttrClass::isSet(Callee, AttrClass::getKind())540k ) | 1749 | 0 | AttrClass::set(Caller, AttrClass::getKind(), true); | 1750 | 540k | } |
Attributes.cpp:void setOR<SpeculativeLoadHardeningAttr>(llvm::Function&, llvm::Function const&) Line | Count | Source | 1746 | 540k | static void setOR(Function &Caller, const Function &Callee) { | 1747 | 540k | if (!AttrClass::isSet(Caller, AttrClass::getKind()) && | 1748 | 540k | AttrClass::isSet(Callee, AttrClass::getKind())540k ) | 1749 | 2 | AttrClass::set(Caller, AttrClass::getKind(), true); | 1750 | 540k | } |
|
1751 | | |
1752 | | /// If the inlined function had a higher stack protection level than the |
1753 | | /// calling function, then bump up the caller's stack protection level. |
1754 | 540k | static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) { |
1755 | 540k | // If upgrading the SSP attribute, clear out the old SSP Attributes first. |
1756 | 540k | // Having multiple SSP attributes doesn't actually hurt, but it adds useless |
1757 | 540k | // clutter to the IR. |
1758 | 540k | AttrBuilder OldSSPAttr; |
1759 | 540k | OldSSPAttr.addAttribute(Attribute::StackProtect) |
1760 | 540k | .addAttribute(Attribute::StackProtectStrong) |
1761 | 540k | .addAttribute(Attribute::StackProtectReq); |
1762 | 540k | |
1763 | 540k | if (Callee.hasFnAttribute(Attribute::StackProtectReq)) { |
1764 | 8 | Caller.removeAttributes(AttributeList::FunctionIndex, OldSSPAttr); |
1765 | 8 | Caller.addFnAttr(Attribute::StackProtectReq); |
1766 | 540k | } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) && |
1767 | 540k | !Caller.hasFnAttribute(Attribute::StackProtectReq)10 ) { |
1768 | 8 | Caller.removeAttributes(AttributeList::FunctionIndex, OldSSPAttr); |
1769 | 8 | Caller.addFnAttr(Attribute::StackProtectStrong); |
1770 | 540k | } else if (Callee.hasFnAttribute(Attribute::StackProtect) && |
1771 | 540k | !Caller.hasFnAttribute(Attribute::StackProtectReq)307k && |
1772 | 540k | !Caller.hasFnAttribute(Attribute::StackProtectStrong)307k ) |
1773 | 307k | Caller.addFnAttr(Attribute::StackProtect); |
1774 | 540k | } |
1775 | | |
1776 | | /// If the inlined function required stack probes, then ensure that |
1777 | | /// the calling function has those too. |
1778 | 540k | static void adjustCallerStackProbes(Function &Caller, const Function &Callee) { |
1779 | 540k | if (!Caller.hasFnAttribute("probe-stack") && |
1780 | 540k | Callee.hasFnAttribute("probe-stack")540k ) { |
1781 | 1 | Caller.addFnAttr(Callee.getFnAttribute("probe-stack")); |
1782 | 1 | } |
1783 | 540k | } |
1784 | | |
1785 | | /// If the inlined function defines the size of guard region |
1786 | | /// on the stack, then ensure that the calling function defines a guard region |
1787 | | /// that is no larger. |
1788 | | static void |
1789 | 540k | adjustCallerStackProbeSize(Function &Caller, const Function &Callee) { |
1790 | 540k | if (Callee.hasFnAttribute("stack-probe-size")) { |
1791 | 3 | uint64_t CalleeStackProbeSize; |
1792 | 3 | Callee.getFnAttribute("stack-probe-size") |
1793 | 3 | .getValueAsString() |
1794 | 3 | .getAsInteger(0, CalleeStackProbeSize); |
1795 | 3 | if (Caller.hasFnAttribute("stack-probe-size")) { |
1796 | 2 | uint64_t CallerStackProbeSize; |
1797 | 2 | Caller.getFnAttribute("stack-probe-size") |
1798 | 2 | .getValueAsString() |
1799 | 2 | .getAsInteger(0, CallerStackProbeSize); |
1800 | 2 | if (CallerStackProbeSize > CalleeStackProbeSize) { |
1801 | 1 | Caller.addFnAttr(Callee.getFnAttribute("stack-probe-size")); |
1802 | 1 | } |
1803 | 2 | } else { |
1804 | 1 | Caller.addFnAttr(Callee.getFnAttribute("stack-probe-size")); |
1805 | 1 | } |
1806 | 3 | } |
1807 | 540k | } |
1808 | | |
1809 | | /// If the inlined function defines a min legal vector width, then ensure |
1810 | | /// the calling function has the same or larger min legal vector width. If the |
1811 | | /// caller has the attribute, but the callee doesn't, we need to remove the |
1812 | | /// attribute from the caller since we can't make any guarantees about the |
1813 | | /// caller's requirements. |
1814 | | /// This function is called after the inlining decision has been made so we have |
1815 | | /// to merge the attribute this way. Heuristics that would use |
1816 | | /// min-legal-vector-width to determine inline compatibility would need to be |
1817 | | /// handled as part of inline cost analysis. |
1818 | | static void |
1819 | 540k | adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) { |
1820 | 540k | if (Caller.hasFnAttribute("min-legal-vector-width")) { |
1821 | 538k | if (Callee.hasFnAttribute("min-legal-vector-width")) { |
1822 | 538k | uint64_t CallerVectorWidth; |
1823 | 538k | Caller.getFnAttribute("min-legal-vector-width") |
1824 | 538k | .getValueAsString() |
1825 | 538k | .getAsInteger(0, CallerVectorWidth); |
1826 | 538k | uint64_t CalleeVectorWidth; |
1827 | 538k | Callee.getFnAttribute("min-legal-vector-width") |
1828 | 538k | .getValueAsString() |
1829 | 538k | .getAsInteger(0, CalleeVectorWidth); |
1830 | 538k | if (CallerVectorWidth < CalleeVectorWidth) |
1831 | 408 | Caller.addFnAttr(Callee.getFnAttribute("min-legal-vector-width")); |
1832 | 538k | } else { |
1833 | 1 | // If the callee doesn't have the attribute then we don't know anything |
1834 | 1 | // and must drop the attribute from the caller. |
1835 | 1 | Caller.removeFnAttr("min-legal-vector-width"); |
1836 | 1 | } |
1837 | 538k | } |
1838 | 540k | } |
1839 | | |
1840 | | /// If the inlined function has "null-pointer-is-valid=true" attribute, |
1841 | | /// set this attribute in the caller post inlining. |
1842 | | static void |
1843 | 540k | adjustNullPointerValidAttr(Function &Caller, const Function &Callee) { |
1844 | 540k | if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()2 ) { |
1845 | 2 | Caller.addFnAttr(Callee.getFnAttribute("null-pointer-is-valid")); |
1846 | 2 | } |
1847 | 540k | } |
1848 | | |
1849 | | #define GET_ATTR_COMPAT_FUNC |
1850 | | #include "AttributesCompatFunc.inc" |
1851 | | |
1852 | | bool AttributeFuncs::areInlineCompatible(const Function &Caller, |
1853 | 1.57M | const Function &Callee) { |
1854 | 1.57M | return hasCompatibleFnAttrs(Caller, Callee); |
1855 | 1.57M | } |
1856 | | |
1857 | | void AttributeFuncs::mergeAttributesForInlining(Function &Caller, |
1858 | 540k | const Function &Callee) { |
1859 | 540k | mergeFnAttrs(Caller, Callee); |
1860 | 540k | } |