Mercurial > hg > CbC > CbC_llvm
comparison lib/IR/Attributes.cpp @ 148:63bd29f05246
merged
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 14 Aug 2019 19:46:37 +0900 |
parents | c2174574ed3a |
children |
comparison
equal
deleted
inserted
replaced
146:3fc4d5c3e21e | 148:63bd29f05246 |
---|---|
1 //===- Attributes.cpp - Implement AttributesList --------------------------===// | 1 //===- Attributes.cpp - Implement AttributesList --------------------------===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 // | 4 // See https://llvm.org/LICENSE.txt for license information. |
5 // This file is distributed under the University of Illinois Open Source | 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 // License. See LICENSE.TXT for details. | |
7 // | 6 // |
8 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
9 // | 8 // |
10 // \file | 9 // \file |
11 // \brief This file implements the Attribute, AttributeImpl, AttrBuilder, | 10 // This file implements the Attribute, AttributeImpl, AttrBuilder, |
12 // AttributeListImpl, and AttributeList classes. | 11 // AttributeListImpl, and AttributeList classes. |
13 // | 12 // |
14 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
15 | 14 |
16 #include "llvm/IR/Attributes.h" | 15 #include "llvm/IR/Attributes.h" |
22 #include "llvm/ADT/STLExtras.h" | 21 #include "llvm/ADT/STLExtras.h" |
23 #include "llvm/ADT/SmallVector.h" | 22 #include "llvm/ADT/SmallVector.h" |
24 #include "llvm/ADT/StringExtras.h" | 23 #include "llvm/ADT/StringExtras.h" |
25 #include "llvm/ADT/StringRef.h" | 24 #include "llvm/ADT/StringRef.h" |
26 #include "llvm/ADT/Twine.h" | 25 #include "llvm/ADT/Twine.h" |
26 #include "llvm/Config/llvm-config.h" | |
27 #include "llvm/IR/Function.h" | 27 #include "llvm/IR/Function.h" |
28 #include "llvm/IR/LLVMContext.h" | 28 #include "llvm/IR/LLVMContext.h" |
29 #include "llvm/IR/Type.h" | 29 #include "llvm/IR/Type.h" |
30 #include "llvm/Support/Compiler.h" | 30 #include "llvm/Support/Compiler.h" |
31 #include "llvm/Support/Debug.h" | 31 #include "llvm/Support/Debug.h" |
36 #include <cassert> | 36 #include <cassert> |
37 #include <climits> | 37 #include <climits> |
38 #include <cstddef> | 38 #include <cstddef> |
39 #include <cstdint> | 39 #include <cstdint> |
40 #include <limits> | 40 #include <limits> |
41 #include <map> | |
42 #include <string> | 41 #include <string> |
43 #include <tuple> | 42 #include <tuple> |
44 #include <utility> | 43 #include <utility> |
45 | 44 |
46 using namespace llvm; | 45 using namespace llvm; |
120 | 119 |
121 // Return the Attribute that we found or created. | 120 // Return the Attribute that we found or created. |
122 return Attribute(PA); | 121 return Attribute(PA); |
123 } | 122 } |
124 | 123 |
124 Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, | |
125 Type *Ty) { | |
126 LLVMContextImpl *pImpl = Context.pImpl; | |
127 FoldingSetNodeID ID; | |
128 ID.AddInteger(Kind); | |
129 ID.AddPointer(Ty); | |
130 | |
131 void *InsertPoint; | |
132 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint); | |
133 | |
134 if (!PA) { | |
135 // If we didn't find any existing attributes of the same shape then create a | |
136 // new one and insert it. | |
137 PA = new TypeAttributeImpl(Kind, Ty); | |
138 pImpl->AttrsSet.InsertNode(PA, InsertPoint); | |
139 } | |
140 | |
141 // Return the Attribute that we found or created. | |
142 return Attribute(PA); | |
143 } | |
144 | |
125 Attribute Attribute::getWithAlignment(LLVMContext &Context, uint64_t Align) { | 145 Attribute Attribute::getWithAlignment(LLVMContext &Context, uint64_t Align) { |
126 assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); | 146 assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); |
127 assert(Align <= 0x40000000 && "Alignment too large."); | 147 assert(Align <= 0x40000000 && "Alignment too large."); |
128 return get(Context, Alignment, Align); | 148 return get(Context, Alignment, Align); |
129 } | 149 } |
143 | 163 |
144 Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context, | 164 Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context, |
145 uint64_t Bytes) { | 165 uint64_t Bytes) { |
146 assert(Bytes && "Bytes must be non-zero."); | 166 assert(Bytes && "Bytes must be non-zero."); |
147 return get(Context, DereferenceableOrNull, Bytes); | 167 return get(Context, DereferenceableOrNull, Bytes); |
168 } | |
169 | |
170 Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) { | |
171 return get(Context, ByVal, Ty); | |
148 } | 172 } |
149 | 173 |
150 Attribute | 174 Attribute |
151 Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, | 175 Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg, |
152 const Optional<unsigned> &NumElemsArg) { | 176 const Optional<unsigned> &NumElemsArg) { |
169 | 193 |
170 bool Attribute::isStringAttribute() const { | 194 bool Attribute::isStringAttribute() const { |
171 return pImpl && pImpl->isStringAttribute(); | 195 return pImpl && pImpl->isStringAttribute(); |
172 } | 196 } |
173 | 197 |
198 bool Attribute::isTypeAttribute() const { | |
199 return pImpl && pImpl->isTypeAttribute(); | |
200 } | |
201 | |
174 Attribute::AttrKind Attribute::getKindAsEnum() const { | 202 Attribute::AttrKind Attribute::getKindAsEnum() const { |
175 if (!pImpl) return None; | 203 if (!pImpl) return None; |
176 assert((isEnumAttribute() || isIntAttribute()) && | 204 assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute()) && |
177 "Invalid attribute type to get the kind as an enum!"); | 205 "Invalid attribute type to get the kind as an enum!"); |
178 return pImpl->getKindAsEnum(); | 206 return pImpl->getKindAsEnum(); |
179 } | 207 } |
180 | 208 |
181 uint64_t Attribute::getValueAsInt() const { | 209 uint64_t Attribute::getValueAsInt() const { |
184 "Expected the attribute to be an integer attribute!"); | 212 "Expected the attribute to be an integer attribute!"); |
185 return pImpl->getValueAsInt(); | 213 return pImpl->getValueAsInt(); |
186 } | 214 } |
187 | 215 |
188 StringRef Attribute::getKindAsString() const { | 216 StringRef Attribute::getKindAsString() const { |
189 if (!pImpl) return StringRef(); | 217 if (!pImpl) return {}; |
190 assert(isStringAttribute() && | 218 assert(isStringAttribute() && |
191 "Invalid attribute type to get the kind as a string!"); | 219 "Invalid attribute type to get the kind as a string!"); |
192 return pImpl->getKindAsString(); | 220 return pImpl->getKindAsString(); |
193 } | 221 } |
194 | 222 |
195 StringRef Attribute::getValueAsString() const { | 223 StringRef Attribute::getValueAsString() const { |
196 if (!pImpl) return StringRef(); | 224 if (!pImpl) return {}; |
197 assert(isStringAttribute() && | 225 assert(isStringAttribute() && |
198 "Invalid attribute type to get the value as a string!"); | 226 "Invalid attribute type to get the value as a string!"); |
199 return pImpl->getValueAsString(); | 227 return pImpl->getValueAsString(); |
200 } | 228 } |
229 | |
230 Type *Attribute::getValueAsType() const { | |
231 if (!pImpl) return {}; | |
232 assert(isTypeAttribute() && | |
233 "Invalid attribute type to get the value as a type!"); | |
234 return pImpl->getValueAsType(); | |
235 } | |
236 | |
201 | 237 |
202 bool Attribute::hasAttribute(AttrKind Kind) const { | 238 bool Attribute::hasAttribute(AttrKind Kind) const { |
203 return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None); | 239 return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None); |
204 } | 240 } |
205 | 241 |
239 "Trying to get allocsize args from non-allocsize attribute"); | 275 "Trying to get allocsize args from non-allocsize attribute"); |
240 return unpackAllocSizeArgs(pImpl->getValueAsInt()); | 276 return unpackAllocSizeArgs(pImpl->getValueAsInt()); |
241 } | 277 } |
242 | 278 |
243 std::string Attribute::getAsString(bool InAttrGrp) const { | 279 std::string Attribute::getAsString(bool InAttrGrp) const { |
244 if (!pImpl) return ""; | 280 if (!pImpl) return {}; |
245 | 281 |
246 if (hasAttribute(Attribute::SanitizeAddress)) | 282 if (hasAttribute(Attribute::SanitizeAddress)) |
247 return "sanitize_address"; | 283 return "sanitize_address"; |
248 if (hasAttribute(Attribute::SanitizeHWAddress)) | 284 if (hasAttribute(Attribute::SanitizeHWAddress)) |
249 return "sanitize_hwaddress"; | 285 return "sanitize_hwaddress"; |
286 if (hasAttribute(Attribute::SanitizeMemTag)) | |
287 return "sanitize_memtag"; | |
250 if (hasAttribute(Attribute::AlwaysInline)) | 288 if (hasAttribute(Attribute::AlwaysInline)) |
251 return "alwaysinline"; | 289 return "alwaysinline"; |
252 if (hasAttribute(Attribute::ArgMemOnly)) | 290 if (hasAttribute(Attribute::ArgMemOnly)) |
253 return "argmemonly"; | 291 return "argmemonly"; |
254 if (hasAttribute(Attribute::Builtin)) | 292 if (hasAttribute(Attribute::Builtin)) |
255 return "builtin"; | 293 return "builtin"; |
256 if (hasAttribute(Attribute::ByVal)) | |
257 return "byval"; | |
258 if (hasAttribute(Attribute::Convergent)) | 294 if (hasAttribute(Attribute::Convergent)) |
259 return "convergent"; | 295 return "convergent"; |
260 if (hasAttribute(Attribute::SwiftError)) | 296 if (hasAttribute(Attribute::SwiftError)) |
261 return "swifterror"; | 297 return "swifterror"; |
262 if (hasAttribute(Attribute::SwiftSelf)) | 298 if (hasAttribute(Attribute::SwiftSelf)) |
285 return "nobuiltin"; | 321 return "nobuiltin"; |
286 if (hasAttribute(Attribute::NoCapture)) | 322 if (hasAttribute(Attribute::NoCapture)) |
287 return "nocapture"; | 323 return "nocapture"; |
288 if (hasAttribute(Attribute::NoDuplicate)) | 324 if (hasAttribute(Attribute::NoDuplicate)) |
289 return "noduplicate"; | 325 return "noduplicate"; |
326 if (hasAttribute(Attribute::NoFree)) | |
327 return "nofree"; | |
290 if (hasAttribute(Attribute::NoImplicitFloat)) | 328 if (hasAttribute(Attribute::NoImplicitFloat)) |
291 return "noimplicitfloat"; | 329 return "noimplicitfloat"; |
292 if (hasAttribute(Attribute::NoInline)) | 330 if (hasAttribute(Attribute::NoInline)) |
293 return "noinline"; | 331 return "noinline"; |
294 if (hasAttribute(Attribute::NonLazyBind)) | 332 if (hasAttribute(Attribute::NonLazyBind)) |
297 return "nonnull"; | 335 return "nonnull"; |
298 if (hasAttribute(Attribute::NoRedZone)) | 336 if (hasAttribute(Attribute::NoRedZone)) |
299 return "noredzone"; | 337 return "noredzone"; |
300 if (hasAttribute(Attribute::NoReturn)) | 338 if (hasAttribute(Attribute::NoReturn)) |
301 return "noreturn"; | 339 return "noreturn"; |
340 if (hasAttribute(Attribute::NoSync)) | |
341 return "nosync"; | |
342 if (hasAttribute(Attribute::WillReturn)) | |
343 return "willreturn"; | |
344 if (hasAttribute(Attribute::NoCfCheck)) | |
345 return "nocf_check"; | |
302 if (hasAttribute(Attribute::NoRecurse)) | 346 if (hasAttribute(Attribute::NoRecurse)) |
303 return "norecurse"; | 347 return "norecurse"; |
304 if (hasAttribute(Attribute::NoUnwind)) | 348 if (hasAttribute(Attribute::NoUnwind)) |
305 return "nounwind"; | 349 return "nounwind"; |
350 if (hasAttribute(Attribute::OptForFuzzing)) | |
351 return "optforfuzzing"; | |
306 if (hasAttribute(Attribute::OptimizeNone)) | 352 if (hasAttribute(Attribute::OptimizeNone)) |
307 return "optnone"; | 353 return "optnone"; |
308 if (hasAttribute(Attribute::OptimizeForSize)) | 354 if (hasAttribute(Attribute::OptimizeForSize)) |
309 return "optsize"; | 355 return "optsize"; |
310 if (hasAttribute(Attribute::ReadNone)) | 356 if (hasAttribute(Attribute::ReadNone)) |
317 return "returned"; | 363 return "returned"; |
318 if (hasAttribute(Attribute::ReturnsTwice)) | 364 if (hasAttribute(Attribute::ReturnsTwice)) |
319 return "returns_twice"; | 365 return "returns_twice"; |
320 if (hasAttribute(Attribute::SExt)) | 366 if (hasAttribute(Attribute::SExt)) |
321 return "signext"; | 367 return "signext"; |
368 if (hasAttribute(Attribute::SpeculativeLoadHardening)) | |
369 return "speculative_load_hardening"; | |
322 if (hasAttribute(Attribute::Speculatable)) | 370 if (hasAttribute(Attribute::Speculatable)) |
323 return "speculatable"; | 371 return "speculatable"; |
324 if (hasAttribute(Attribute::StackProtect)) | 372 if (hasAttribute(Attribute::StackProtect)) |
325 return "ssp"; | 373 return "ssp"; |
326 if (hasAttribute(Attribute::StackProtectReq)) | 374 if (hasAttribute(Attribute::StackProtectReq)) |
327 return "sspreq"; | 375 return "sspreq"; |
328 if (hasAttribute(Attribute::StackProtectStrong)) | 376 if (hasAttribute(Attribute::StackProtectStrong)) |
329 return "sspstrong"; | 377 return "sspstrong"; |
330 if (hasAttribute(Attribute::SafeStack)) | 378 if (hasAttribute(Attribute::SafeStack)) |
331 return "safestack"; | 379 return "safestack"; |
380 if (hasAttribute(Attribute::ShadowCallStack)) | |
381 return "shadowcallstack"; | |
332 if (hasAttribute(Attribute::StrictFP)) | 382 if (hasAttribute(Attribute::StrictFP)) |
333 return "strictfp"; | 383 return "strictfp"; |
334 if (hasAttribute(Attribute::StructRet)) | 384 if (hasAttribute(Attribute::StructRet)) |
335 return "sret"; | 385 return "sret"; |
336 if (hasAttribute(Attribute::SanitizeThread)) | 386 if (hasAttribute(Attribute::SanitizeThread)) |
341 return "uwtable"; | 391 return "uwtable"; |
342 if (hasAttribute(Attribute::ZExt)) | 392 if (hasAttribute(Attribute::ZExt)) |
343 return "zeroext"; | 393 return "zeroext"; |
344 if (hasAttribute(Attribute::Cold)) | 394 if (hasAttribute(Attribute::Cold)) |
345 return "cold"; | 395 return "cold"; |
396 if (hasAttribute(Attribute::ImmArg)) | |
397 return "immarg"; | |
398 | |
399 if (hasAttribute(Attribute::ByVal)) { | |
400 std::string Result; | |
401 Result += "byval"; | |
402 if (Type *Ty = getValueAsType()) { | |
403 raw_string_ostream OS(Result); | |
404 Result += '('; | |
405 Ty->print(OS, false, true); | |
406 OS.flush(); | |
407 Result += ')'; | |
408 } | |
409 return Result; | |
410 } | |
346 | 411 |
347 // FIXME: These should be output like this: | 412 // FIXME: These should be output like this: |
348 // | 413 // |
349 // align=4 | 414 // align=4 |
350 // alignstack=8 | 415 // alignstack=8 |
411 // printable, those have to be escaped to make the attribute value printable | 476 // printable, those have to be escaped to make the attribute value printable |
412 // as is. e.g. "\01__gnu_mcount_nc" | 477 // as is. e.g. "\01__gnu_mcount_nc" |
413 { | 478 { |
414 raw_string_ostream OS(Result); | 479 raw_string_ostream OS(Result); |
415 OS << "=\""; | 480 OS << "=\""; |
416 PrintEscapedString(AttrVal, OS); | 481 printEscapedString(AttrVal, OS); |
417 OS << "\""; | 482 OS << "\""; |
418 } | 483 } |
419 return Result; | 484 return Result; |
420 } | 485 } |
421 | 486 |
440 | 505 |
441 void IntAttributeImpl::anchor() {} | 506 void IntAttributeImpl::anchor() {} |
442 | 507 |
443 void StringAttributeImpl::anchor() {} | 508 void StringAttributeImpl::anchor() {} |
444 | 509 |
510 void TypeAttributeImpl::anchor() {} | |
511 | |
445 bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const { | 512 bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const { |
446 if (isStringAttribute()) return false; | 513 if (isStringAttribute()) return false; |
447 return getKindAsEnum() == A; | 514 return getKindAsEnum() == A; |
448 } | 515 } |
449 | 516 |
451 if (!isStringAttribute()) return false; | 518 if (!isStringAttribute()) return false; |
452 return getKindAsString() == Kind; | 519 return getKindAsString() == Kind; |
453 } | 520 } |
454 | 521 |
455 Attribute::AttrKind AttributeImpl::getKindAsEnum() const { | 522 Attribute::AttrKind AttributeImpl::getKindAsEnum() const { |
456 assert(isEnumAttribute() || isIntAttribute()); | 523 assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute()); |
457 return static_cast<const EnumAttributeImpl *>(this)->getEnumKind(); | 524 return static_cast<const EnumAttributeImpl *>(this)->getEnumKind(); |
458 } | 525 } |
459 | 526 |
460 uint64_t AttributeImpl::getValueAsInt() const { | 527 uint64_t AttributeImpl::getValueAsInt() const { |
461 assert(isIntAttribute()); | 528 assert(isIntAttribute()); |
468 } | 535 } |
469 | 536 |
470 StringRef AttributeImpl::getValueAsString() const { | 537 StringRef AttributeImpl::getValueAsString() const { |
471 assert(isStringAttribute()); | 538 assert(isStringAttribute()); |
472 return static_cast<const StringAttributeImpl *>(this)->getStringValue(); | 539 return static_cast<const StringAttributeImpl *>(this)->getStringValue(); |
540 } | |
541 | |
542 Type *AttributeImpl::getValueAsType() const { | |
543 assert(isTypeAttribute()); | |
544 return static_cast<const TypeAttributeImpl *>(this)->getTypeValue(); | |
473 } | 545 } |
474 | 546 |
475 bool AttributeImpl::operator<(const AttributeImpl &AI) const { | 547 bool AttributeImpl::operator<(const AttributeImpl &AI) const { |
476 // This sorts the attributes with Attribute::AttrKinds coming first (sorted | 548 // This sorts the attributes with Attribute::AttrKinds coming first (sorted |
477 // relative to their enum value) and then strings. | 549 // relative to their enum value) and then strings. |
478 if (isEnumAttribute()) { | 550 if (isEnumAttribute()) { |
479 if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum(); | 551 if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum(); |
480 if (AI.isIntAttribute()) return true; | 552 if (AI.isIntAttribute()) return true; |
481 if (AI.isStringAttribute()) return true; | 553 if (AI.isStringAttribute()) return true; |
554 if (AI.isTypeAttribute()) return true; | |
555 } | |
556 | |
557 if (isTypeAttribute()) { | |
558 if (AI.isEnumAttribute()) return false; | |
559 if (AI.isTypeAttribute()) { | |
560 assert(getKindAsEnum() != AI.getKindAsEnum() && | |
561 "Comparison of types would be unstable"); | |
562 return getKindAsEnum() < AI.getKindAsEnum(); | |
563 } | |
564 if (AI.isIntAttribute()) return true; | |
565 if (AI.isStringAttribute()) return true; | |
482 } | 566 } |
483 | 567 |
484 if (isIntAttribute()) { | 568 if (isIntAttribute()) { |
485 if (AI.isEnumAttribute()) return false; | 569 if (AI.isEnumAttribute()) return false; |
570 if (AI.isTypeAttribute()) return false; | |
486 if (AI.isIntAttribute()) { | 571 if (AI.isIntAttribute()) { |
487 if (getKindAsEnum() == AI.getKindAsEnum()) | 572 if (getKindAsEnum() == AI.getKindAsEnum()) |
488 return getValueAsInt() < AI.getValueAsInt(); | 573 return getValueAsInt() < AI.getValueAsInt(); |
489 return getKindAsEnum() < AI.getKindAsEnum(); | 574 return getKindAsEnum() < AI.getKindAsEnum(); |
490 } | 575 } |
491 if (AI.isStringAttribute()) return true; | 576 if (AI.isStringAttribute()) return true; |
492 } | 577 } |
493 | 578 |
579 assert(isStringAttribute()); | |
494 if (AI.isEnumAttribute()) return false; | 580 if (AI.isEnumAttribute()) return false; |
581 if (AI.isTypeAttribute()) return false; | |
495 if (AI.isIntAttribute()) return false; | 582 if (AI.isIntAttribute()) return false; |
496 if (getKindAsString() == AI.getKindAsString()) | 583 if (getKindAsString() == AI.getKindAsString()) |
497 return getValueAsString() < AI.getValueAsString(); | 584 return getValueAsString() < AI.getValueAsString(); |
498 return getKindAsString() < AI.getKindAsString(); | 585 return getKindAsString() < AI.getKindAsString(); |
499 } | 586 } |
532 | 619 |
533 if (!AS.hasAttributes()) | 620 if (!AS.hasAttributes()) |
534 return *this; | 621 return *this; |
535 | 622 |
536 AttrBuilder B(AS); | 623 AttrBuilder B(AS); |
537 for (Attribute I : *this) | 624 for (const auto I : *this) |
538 B.addAttribute(I); | 625 B.addAttribute(I); |
539 | 626 |
540 return get(C, B); | 627 return get(C, B); |
541 } | 628 } |
542 | 629 |
597 | 684 |
598 uint64_t AttributeSet::getDereferenceableOrNullBytes() const { | 685 uint64_t AttributeSet::getDereferenceableOrNullBytes() const { |
599 return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0; | 686 return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0; |
600 } | 687 } |
601 | 688 |
689 Type *AttributeSet::getByValType() const { | |
690 return SetNode ? SetNode->getByValType() : nullptr; | |
691 } | |
692 | |
602 std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const { | 693 std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const { |
603 return SetNode ? SetNode->getAllocSizeArgs() | 694 return SetNode ? SetNode->getAllocSizeArgs() |
604 : std::pair<unsigned, Optional<unsigned>>(0, 0); | 695 : std::pair<unsigned, Optional<unsigned>>(0, 0); |
605 } | 696 } |
606 | 697 |
627 //===----------------------------------------------------------------------===// | 718 //===----------------------------------------------------------------------===// |
628 // AttributeSetNode Definition | 719 // AttributeSetNode Definition |
629 //===----------------------------------------------------------------------===// | 720 //===----------------------------------------------------------------------===// |
630 | 721 |
631 AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs) | 722 AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs) |
632 : AvailableAttrs(0), NumAttrs(Attrs.size()) { | 723 : NumAttrs(Attrs.size()) { |
633 // There's memory after the node where we can store the entries in. | 724 // There's memory after the node where we can store the entries in. |
634 std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects<Attribute>()); | 725 llvm::copy(Attrs, getTrailingObjects<Attribute>()); |
635 | 726 |
636 for (Attribute I : *this) { | 727 static_assert(Attribute::EndAttrKinds <= |
728 sizeof(AvailableAttrs) * CHAR_BIT, | |
729 "Too many attributes"); | |
730 | |
731 for (const auto I : *this) { | |
637 if (!I.isStringAttribute()) { | 732 if (!I.isStringAttribute()) { |
638 AvailableAttrs |= ((uint64_t)1) << I.getKindAsEnum(); | 733 Attribute::AttrKind Kind = I.getKindAsEnum(); |
734 AvailableAttrs[Kind / 8] |= 1ULL << (Kind % 8); | |
639 } | 735 } |
640 } | 736 } |
641 } | 737 } |
642 | 738 |
643 AttributeSetNode *AttributeSetNode::get(LLVMContext &C, | 739 AttributeSetNode *AttributeSetNode::get(LLVMContext &C, |
648 // Otherwise, build a key to look up the existing attributes. | 744 // Otherwise, build a key to look up the existing attributes. |
649 LLVMContextImpl *pImpl = C.pImpl; | 745 LLVMContextImpl *pImpl = C.pImpl; |
650 FoldingSetNodeID ID; | 746 FoldingSetNodeID ID; |
651 | 747 |
652 SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end()); | 748 SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end()); |
653 std::sort(SortedAttrs.begin(), SortedAttrs.end()); | 749 llvm::sort(SortedAttrs); |
654 | 750 |
655 for (Attribute Attr : SortedAttrs) | 751 for (const auto Attr : SortedAttrs) |
656 Attr.Profile(ID); | 752 Attr.Profile(ID); |
657 | 753 |
658 void *InsertPoint; | 754 void *InsertPoint; |
659 AttributeSetNode *PA = | 755 AttributeSetNode *PA = |
660 pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint); | 756 pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint); |
680 if (!B.contains(Kind)) | 776 if (!B.contains(Kind)) |
681 continue; | 777 continue; |
682 | 778 |
683 Attribute Attr; | 779 Attribute Attr; |
684 switch (Kind) { | 780 switch (Kind) { |
781 case Attribute::ByVal: | |
782 Attr = Attribute::getWithByValType(C, B.getByValType()); | |
783 break; | |
685 case Attribute::Alignment: | 784 case Attribute::Alignment: |
686 Attr = Attribute::getWithAlignment(C, B.getAlignment()); | 785 Attr = Attribute::getWithAlignment(C, B.getAlignment()); |
687 break; | 786 break; |
688 case Attribute::StackAlignment: | 787 case Attribute::StackAlignment: |
689 Attr = Attribute::getWithStackAlignment(C, B.getStackAlignment()); | 788 Attr = Attribute::getWithStackAlignment(C, B.getStackAlignment()); |
713 | 812 |
714 return get(C, Attrs); | 813 return get(C, Attrs); |
715 } | 814 } |
716 | 815 |
717 bool AttributeSetNode::hasAttribute(StringRef Kind) const { | 816 bool AttributeSetNode::hasAttribute(StringRef Kind) const { |
718 for (Attribute I : *this) | 817 for (const auto I : *this) |
719 if (I.hasAttribute(Kind)) | 818 if (I.hasAttribute(Kind)) |
720 return true; | 819 return true; |
721 return false; | 820 return false; |
722 } | 821 } |
723 | 822 |
724 Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const { | 823 Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const { |
725 if (hasAttribute(Kind)) { | 824 if (hasAttribute(Kind)) { |
726 for (Attribute I : *this) | 825 for (const auto I : *this) |
727 if (I.hasAttribute(Kind)) | 826 if (I.hasAttribute(Kind)) |
728 return I; | 827 return I; |
729 } | 828 } |
730 return Attribute(); | 829 return {}; |
731 } | 830 } |
732 | 831 |
733 Attribute AttributeSetNode::getAttribute(StringRef Kind) const { | 832 Attribute AttributeSetNode::getAttribute(StringRef Kind) const { |
734 for (Attribute I : *this) | 833 for (const auto I : *this) |
735 if (I.hasAttribute(Kind)) | 834 if (I.hasAttribute(Kind)) |
736 return I; | 835 return I; |
737 return Attribute(); | 836 return {}; |
738 } | 837 } |
739 | 838 |
740 unsigned AttributeSetNode::getAlignment() const { | 839 unsigned AttributeSetNode::getAlignment() const { |
741 for (Attribute I : *this) | 840 for (const auto I : *this) |
742 if (I.hasAttribute(Attribute::Alignment)) | 841 if (I.hasAttribute(Attribute::Alignment)) |
743 return I.getAlignment(); | 842 return I.getAlignment(); |
744 return 0; | 843 return 0; |
745 } | 844 } |
746 | 845 |
747 unsigned AttributeSetNode::getStackAlignment() const { | 846 unsigned AttributeSetNode::getStackAlignment() const { |
748 for (Attribute I : *this) | 847 for (const auto I : *this) |
749 if (I.hasAttribute(Attribute::StackAlignment)) | 848 if (I.hasAttribute(Attribute::StackAlignment)) |
750 return I.getStackAlignment(); | 849 return I.getStackAlignment(); |
751 return 0; | 850 return 0; |
752 } | 851 } |
753 | 852 |
853 Type *AttributeSetNode::getByValType() const { | |
854 for (const auto I : *this) | |
855 if (I.hasAttribute(Attribute::ByVal)) | |
856 return I.getValueAsType(); | |
857 return 0; | |
858 } | |
859 | |
754 uint64_t AttributeSetNode::getDereferenceableBytes() const { | 860 uint64_t AttributeSetNode::getDereferenceableBytes() const { |
755 for (Attribute I : *this) | 861 for (const auto I : *this) |
756 if (I.hasAttribute(Attribute::Dereferenceable)) | 862 if (I.hasAttribute(Attribute::Dereferenceable)) |
757 return I.getDereferenceableBytes(); | 863 return I.getDereferenceableBytes(); |
758 return 0; | 864 return 0; |
759 } | 865 } |
760 | 866 |
761 uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const { | 867 uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const { |
762 for (Attribute I : *this) | 868 for (const auto I : *this) |
763 if (I.hasAttribute(Attribute::DereferenceableOrNull)) | 869 if (I.hasAttribute(Attribute::DereferenceableOrNull)) |
764 return I.getDereferenceableOrNullBytes(); | 870 return I.getDereferenceableOrNullBytes(); |
765 return 0; | 871 return 0; |
766 } | 872 } |
767 | 873 |
768 std::pair<unsigned, Optional<unsigned>> | 874 std::pair<unsigned, Optional<unsigned>> |
769 AttributeSetNode::getAllocSizeArgs() const { | 875 AttributeSetNode::getAllocSizeArgs() const { |
770 for (Attribute I : *this) | 876 for (const auto I : *this) |
771 if (I.hasAttribute(Attribute::AllocSize)) | 877 if (I.hasAttribute(Attribute::AllocSize)) |
772 return I.getAllocSizeArgs(); | 878 return I.getAllocSizeArgs(); |
773 return std::make_pair(0, 0); | 879 return std::make_pair(0, 0); |
774 } | 880 } |
775 | 881 |
795 return Index == AttributeList::FunctionIndex ? 0 : Index + 1; | 901 return Index == AttributeList::FunctionIndex ? 0 : Index + 1; |
796 } | 902 } |
797 | 903 |
798 AttributeListImpl::AttributeListImpl(LLVMContext &C, | 904 AttributeListImpl::AttributeListImpl(LLVMContext &C, |
799 ArrayRef<AttributeSet> Sets) | 905 ArrayRef<AttributeSet> Sets) |
800 : AvailableFunctionAttrs(0), Context(C), NumAttrSets(Sets.size()) { | 906 : Context(C), NumAttrSets(Sets.size()) { |
801 assert(!Sets.empty() && "pointless AttributeListImpl"); | 907 assert(!Sets.empty() && "pointless AttributeListImpl"); |
802 | 908 |
803 // There's memory after the node where we can store the entries in. | 909 // There's memory after the node where we can store the entries in. |
804 std::copy(Sets.begin(), Sets.end(), getTrailingObjects<AttributeSet>()); | 910 llvm::copy(Sets, getTrailingObjects<AttributeSet>()); |
805 | 911 |
806 // Initialize AvailableFunctionAttrs summary bitset. | 912 // Initialize AvailableFunctionAttrs summary bitset. |
807 static_assert(Attribute::EndAttrKinds <= | 913 static_assert(Attribute::EndAttrKinds <= |
808 sizeof(AvailableFunctionAttrs) * CHAR_BIT, | 914 sizeof(AvailableFunctionAttrs) * CHAR_BIT, |
809 "Too many attributes"); | 915 "Too many attributes"); |
810 static_assert(attrIdxToArrayIdx(AttributeList::FunctionIndex) == 0U, | 916 static_assert(attrIdxToArrayIdx(AttributeList::FunctionIndex) == 0U, |
811 "function should be stored in slot 0"); | 917 "function should be stored in slot 0"); |
812 for (Attribute I : Sets[0]) { | 918 for (const auto I : Sets[0]) { |
813 if (!I.isStringAttribute()) | 919 if (!I.isStringAttribute()) { |
814 AvailableFunctionAttrs |= 1ULL << I.getKindAsEnum(); | 920 Attribute::AttrKind Kind = I.getKindAsEnum(); |
921 AvailableFunctionAttrs[Kind / 8] |= 1ULL << (Kind % 8); | |
922 } | |
815 } | 923 } |
816 } | 924 } |
817 | 925 |
818 void AttributeListImpl::Profile(FoldingSetNodeID &ID) const { | 926 void AttributeListImpl::Profile(FoldingSetNodeID &ID) const { |
819 Profile(ID, makeArrayRef(begin(), end())); | 927 Profile(ID, makeArrayRef(begin(), end())); |
864 AttributeList | 972 AttributeList |
865 AttributeList::get(LLVMContext &C, | 973 AttributeList::get(LLVMContext &C, |
866 ArrayRef<std::pair<unsigned, Attribute>> Attrs) { | 974 ArrayRef<std::pair<unsigned, Attribute>> Attrs) { |
867 // If there are no attributes then return a null AttributesList pointer. | 975 // If there are no attributes then return a null AttributesList pointer. |
868 if (Attrs.empty()) | 976 if (Attrs.empty()) |
869 return AttributeList(); | 977 return {}; |
870 | 978 |
871 assert(std::is_sorted(Attrs.begin(), Attrs.end(), | 979 assert(std::is_sorted(Attrs.begin(), Attrs.end(), |
872 [](const std::pair<unsigned, Attribute> &LHS, | 980 [](const std::pair<unsigned, Attribute> &LHS, |
873 const std::pair<unsigned, Attribute> &RHS) { | 981 const std::pair<unsigned, Attribute> &RHS) { |
874 return LHS.first < RHS.first; | 982 return LHS.first < RHS.first; |
875 }) && "Misordered Attributes list!"); | 983 }) && "Misordered Attributes list!"); |
876 assert(none_of(Attrs, | 984 assert(llvm::none_of(Attrs, |
877 [](const std::pair<unsigned, Attribute> &Pair) { | 985 [](const std::pair<unsigned, Attribute> &Pair) { |
878 return Pair.second.hasAttribute(Attribute::None); | 986 return Pair.second.hasAttribute(Attribute::None); |
879 }) && | 987 }) && |
880 "Pointless attribute!"); | 988 "Pointless attribute!"); |
881 | 989 |
882 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes | 990 // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes |
883 // list. | 991 // list. |
884 SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec; | 992 SmallVector<std::pair<unsigned, AttributeSet>, 8> AttrPairVec; |
900 AttributeList | 1008 AttributeList |
901 AttributeList::get(LLVMContext &C, | 1009 AttributeList::get(LLVMContext &C, |
902 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) { | 1010 ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) { |
903 // If there are no attributes then return a null AttributesList pointer. | 1011 // If there are no attributes then return a null AttributesList pointer. |
904 if (Attrs.empty()) | 1012 if (Attrs.empty()) |
905 return AttributeList(); | 1013 return {}; |
906 | 1014 |
907 assert(std::is_sorted(Attrs.begin(), Attrs.end(), | 1015 assert(std::is_sorted(Attrs.begin(), Attrs.end(), |
908 [](const std::pair<unsigned, AttributeSet> &LHS, | 1016 [](const std::pair<unsigned, AttributeSet> &LHS, |
909 const std::pair<unsigned, AttributeSet> &RHS) { | 1017 const std::pair<unsigned, AttributeSet> &RHS) { |
910 return LHS.first < RHS.first; | 1018 return LHS.first < RHS.first; |
911 }) && | 1019 }) && |
912 "Misordered Attributes list!"); | 1020 "Misordered Attributes list!"); |
913 assert(none_of(Attrs, | 1021 assert(llvm::none_of(Attrs, |
914 [](const std::pair<unsigned, AttributeSet> &Pair) { | 1022 [](const std::pair<unsigned, AttributeSet> &Pair) { |
915 return !Pair.second.hasAttributes(); | 1023 return !Pair.second.hasAttributes(); |
916 }) && | 1024 }) && |
917 "Pointless attribute!"); | 1025 "Pointless attribute!"); |
918 | 1026 |
919 unsigned MaxIndex = Attrs.back().first; | 1027 unsigned MaxIndex = Attrs.back().first; |
1028 // If the MaxIndex is FunctionIndex and there are other indices in front | |
1029 // of it, we need to use the largest of those to get the right size. | |
1030 if (MaxIndex == FunctionIndex && Attrs.size() > 1) | |
1031 MaxIndex = Attrs[Attrs.size() - 2].first; | |
920 | 1032 |
921 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1); | 1033 SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1); |
922 for (auto Pair : Attrs) | 1034 for (const auto Pair : Attrs) |
923 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second; | 1035 AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second; |
924 | 1036 |
925 return getImpl(C, AttrVec); | 1037 return getImpl(C, AttrVec); |
926 } | 1038 } |
927 | 1039 |
947 NumSets = 1; | 1059 NumSets = 1; |
948 } | 1060 } |
949 | 1061 |
950 // If all attribute sets were empty, we can use the empty attribute list. | 1062 // If all attribute sets were empty, we can use the empty attribute list. |
951 if (NumSets == 0) | 1063 if (NumSets == 0) |
952 return AttributeList(); | 1064 return {}; |
953 | 1065 |
954 SmallVector<AttributeSet, 8> AttrSets; | 1066 SmallVector<AttributeSet, 8> AttrSets; |
955 AttrSets.reserve(NumSets); | 1067 AttrSets.reserve(NumSets); |
956 // If we have any attributes, we always have function attributes. | 1068 // If we have any attributes, we always have function attributes. |
957 AttrSets.push_back(FnAttrs); | 1069 AttrSets.push_back(FnAttrs); |
967 } | 1079 } |
968 | 1080 |
969 AttributeList AttributeList::get(LLVMContext &C, unsigned Index, | 1081 AttributeList AttributeList::get(LLVMContext &C, unsigned Index, |
970 const AttrBuilder &B) { | 1082 const AttrBuilder &B) { |
971 if (!B.hasAttributes()) | 1083 if (!B.hasAttributes()) |
972 return AttributeList(); | 1084 return {}; |
973 Index = attrIdxToArrayIdx(Index); | 1085 Index = attrIdxToArrayIdx(Index); |
974 SmallVector<AttributeSet, 8> AttrSets(Index + 1); | 1086 SmallVector<AttributeSet, 8> AttrSets(Index + 1); |
975 AttrSets[Index] = AttributeSet::get(C, B); | 1087 AttrSets[Index] = AttributeSet::get(C, B); |
976 return getImpl(C, AttrSets); | 1088 return getImpl(C, AttrSets); |
977 } | 1089 } |
978 | 1090 |
979 AttributeList AttributeList::get(LLVMContext &C, unsigned Index, | 1091 AttributeList AttributeList::get(LLVMContext &C, unsigned Index, |
980 ArrayRef<Attribute::AttrKind> Kinds) { | 1092 ArrayRef<Attribute::AttrKind> Kinds) { |
981 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs; | 1093 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs; |
982 for (Attribute::AttrKind K : Kinds) | 1094 for (const auto K : Kinds) |
983 Attrs.emplace_back(Index, Attribute::get(C, K)); | 1095 Attrs.emplace_back(Index, Attribute::get(C, K)); |
984 return get(C, Attrs); | 1096 return get(C, Attrs); |
985 } | 1097 } |
986 | 1098 |
987 AttributeList AttributeList::get(LLVMContext &C, unsigned Index, | 1099 AttributeList AttributeList::get(LLVMContext &C, unsigned Index, |
988 ArrayRef<StringRef> Kinds) { | 1100 ArrayRef<StringRef> Kinds) { |
989 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs; | 1101 SmallVector<std::pair<unsigned, Attribute>, 8> Attrs; |
990 for (StringRef K : Kinds) | 1102 for (const auto K : Kinds) |
991 Attrs.emplace_back(Index, Attribute::get(C, K)); | 1103 Attrs.emplace_back(Index, Attribute::get(C, K)); |
992 return get(C, Attrs); | 1104 return get(C, Attrs); |
993 } | 1105 } |
994 | 1106 |
995 AttributeList AttributeList::get(LLVMContext &C, | 1107 AttributeList AttributeList::get(LLVMContext &C, |
996 ArrayRef<AttributeList> Attrs) { | 1108 ArrayRef<AttributeList> Attrs) { |
997 if (Attrs.empty()) | 1109 if (Attrs.empty()) |
998 return AttributeList(); | 1110 return {}; |
999 if (Attrs.size() == 1) | 1111 if (Attrs.size() == 1) |
1000 return Attrs[0]; | 1112 return Attrs[0]; |
1001 | 1113 |
1002 unsigned MaxSize = 0; | 1114 unsigned MaxSize = 0; |
1003 for (AttributeList List : Attrs) | 1115 for (const auto List : Attrs) |
1004 MaxSize = std::max(MaxSize, List.getNumAttrSets()); | 1116 MaxSize = std::max(MaxSize, List.getNumAttrSets()); |
1005 | 1117 |
1006 // If every list was empty, there is no point in merging the lists. | 1118 // If every list was empty, there is no point in merging the lists. |
1007 if (MaxSize == 0) | 1119 if (MaxSize == 0) |
1008 return AttributeList(); | 1120 return {}; |
1009 | 1121 |
1010 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize); | 1122 SmallVector<AttributeSet, 8> NewAttrSets(MaxSize); |
1011 for (unsigned I = 0; I < MaxSize; ++I) { | 1123 for (unsigned I = 0; I < MaxSize; ++I) { |
1012 AttrBuilder CurBuilder; | 1124 AttrBuilder CurBuilder; |
1013 for (AttributeList List : Attrs) | 1125 for (const auto List : Attrs) |
1014 CurBuilder.merge(List.getAttributes(I - 1)); | 1126 CurBuilder.merge(List.getAttributes(I - 1)); |
1015 NewAttrSets[I] = AttributeSet::get(C, CurBuilder); | 1127 NewAttrSets[I] = AttributeSet::get(C, CurBuilder); |
1016 } | 1128 } |
1017 | 1129 |
1018 return getImpl(C, NewAttrSets); | 1130 return getImpl(C, NewAttrSets); |
1118 | 1230 |
1119 AttributeList | 1231 AttributeList |
1120 AttributeList::removeAttributes(LLVMContext &C, unsigned Index, | 1232 AttributeList::removeAttributes(LLVMContext &C, unsigned Index, |
1121 const AttrBuilder &AttrsToRemove) const { | 1233 const AttrBuilder &AttrsToRemove) const { |
1122 if (!pImpl) | 1234 if (!pImpl) |
1123 return AttributeList(); | 1235 return {}; |
1124 | 1236 |
1125 Index = attrIdxToArrayIdx(Index); | 1237 Index = attrIdxToArrayIdx(Index); |
1126 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); | 1238 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); |
1127 if (Index >= AttrSets.size()) | 1239 if (Index >= AttrSets.size()) |
1128 AttrSets.resize(Index + 1); | 1240 AttrSets.resize(Index + 1); |
1133 } | 1245 } |
1134 | 1246 |
1135 AttributeList AttributeList::removeAttributes(LLVMContext &C, | 1247 AttributeList AttributeList::removeAttributes(LLVMContext &C, |
1136 unsigned WithoutIndex) const { | 1248 unsigned WithoutIndex) const { |
1137 if (!pImpl) | 1249 if (!pImpl) |
1138 return AttributeList(); | 1250 return {}; |
1139 WithoutIndex = attrIdxToArrayIdx(WithoutIndex); | 1251 WithoutIndex = attrIdxToArrayIdx(WithoutIndex); |
1140 if (WithoutIndex >= getNumAttrSets()) | 1252 if (WithoutIndex >= getNumAttrSets()) |
1141 return *this; | 1253 return *this; |
1142 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); | 1254 SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); |
1143 AttrSets[WithoutIndex] = AttributeSet(); | 1255 AttrSets[WithoutIndex] = AttributeSet(); |
1243 | 1355 |
1244 unsigned AttributeList::getParamAlignment(unsigned ArgNo) const { | 1356 unsigned AttributeList::getParamAlignment(unsigned ArgNo) const { |
1245 return getAttributes(ArgNo + FirstArgIndex).getAlignment(); | 1357 return getAttributes(ArgNo + FirstArgIndex).getAlignment(); |
1246 } | 1358 } |
1247 | 1359 |
1360 Type *AttributeList::getParamByValType(unsigned Index) const { | |
1361 return getAttributes(Index+FirstArgIndex).getByValType(); | |
1362 } | |
1363 | |
1364 | |
1248 unsigned AttributeList::getStackAlignment(unsigned Index) const { | 1365 unsigned AttributeList::getStackAlignment(unsigned Index) const { |
1249 return getAttributes(Index).getStackAlignment(); | 1366 return getAttributes(Index).getStackAlignment(); |
1250 } | 1367 } |
1251 | 1368 |
1252 uint64_t AttributeList::getDereferenceableBytes(unsigned Index) const { | 1369 uint64_t AttributeList::getDereferenceableBytes(unsigned Index) const { |
1267 } | 1384 } |
1268 | 1385 |
1269 AttributeSet AttributeList::getAttributes(unsigned Index) const { | 1386 AttributeSet AttributeList::getAttributes(unsigned Index) const { |
1270 Index = attrIdxToArrayIdx(Index); | 1387 Index = attrIdxToArrayIdx(Index); |
1271 if (!pImpl || Index >= getNumAttrSets()) | 1388 if (!pImpl || Index >= getNumAttrSets()) |
1272 return AttributeSet(); | 1389 return {}; |
1273 return pImpl->begin()[Index]; | 1390 return pImpl->begin()[Index]; |
1274 } | 1391 } |
1275 | 1392 |
1276 AttributeList::iterator AttributeList::begin() const { | 1393 AttributeList::iterator AttributeList::begin() const { |
1277 return pImpl ? pImpl->begin() : nullptr; | 1394 return pImpl ? pImpl->begin() : nullptr; |
1307 //===----------------------------------------------------------------------===// | 1424 //===----------------------------------------------------------------------===// |
1308 | 1425 |
1309 // FIXME: Remove this ctor, use AttributeSet. | 1426 // FIXME: Remove this ctor, use AttributeSet. |
1310 AttrBuilder::AttrBuilder(AttributeList AL, unsigned Index) { | 1427 AttrBuilder::AttrBuilder(AttributeList AL, unsigned Index) { |
1311 AttributeSet AS = AL.getAttributes(Index); | 1428 AttributeSet AS = AL.getAttributes(Index); |
1312 for (const Attribute &A : AS) | 1429 for (const auto &A : AS) |
1313 addAttribute(A); | 1430 addAttribute(A); |
1314 } | 1431 } |
1315 | 1432 |
1316 AttrBuilder::AttrBuilder(AttributeSet AS) { | 1433 AttrBuilder::AttrBuilder(AttributeSet AS) { |
1317 for (const Attribute &A : AS) | 1434 for (const auto &A : AS) |
1318 addAttribute(A); | 1435 addAttribute(A); |
1319 } | 1436 } |
1320 | 1437 |
1321 void AttrBuilder::clear() { | 1438 void AttrBuilder::clear() { |
1322 Attrs.reset(); | 1439 Attrs.reset(); |
1323 TargetDepAttrs.clear(); | 1440 TargetDepAttrs.clear(); |
1324 Alignment = StackAlignment = DerefBytes = DerefOrNullBytes = 0; | 1441 Alignment.reset(); |
1442 StackAlignment.reset(); | |
1443 DerefBytes = DerefOrNullBytes = 0; | |
1325 AllocSizeArgs = 0; | 1444 AllocSizeArgs = 0; |
1445 ByValType = nullptr; | |
1326 } | 1446 } |
1327 | 1447 |
1328 AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) { | 1448 AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) { |
1329 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!"); | 1449 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!"); |
1330 assert(Val != Attribute::Alignment && Val != Attribute::StackAlignment && | 1450 assert(Val != Attribute::Alignment && Val != Attribute::StackAlignment && |
1342 | 1462 |
1343 Attribute::AttrKind Kind = Attr.getKindAsEnum(); | 1463 Attribute::AttrKind Kind = Attr.getKindAsEnum(); |
1344 Attrs[Kind] = true; | 1464 Attrs[Kind] = true; |
1345 | 1465 |
1346 if (Kind == Attribute::Alignment) | 1466 if (Kind == Attribute::Alignment) |
1347 Alignment = Attr.getAlignment(); | 1467 Alignment = MaybeAlign(Attr.getAlignment()); |
1348 else if (Kind == Attribute::StackAlignment) | 1468 else if (Kind == Attribute::StackAlignment) |
1349 StackAlignment = Attr.getStackAlignment(); | 1469 StackAlignment = MaybeAlign(Attr.getStackAlignment()); |
1470 else if (Kind == Attribute::ByVal) | |
1471 ByValType = Attr.getValueAsType(); | |
1350 else if (Kind == Attribute::Dereferenceable) | 1472 else if (Kind == Attribute::Dereferenceable) |
1351 DerefBytes = Attr.getDereferenceableBytes(); | 1473 DerefBytes = Attr.getDereferenceableBytes(); |
1352 else if (Kind == Attribute::DereferenceableOrNull) | 1474 else if (Kind == Attribute::DereferenceableOrNull) |
1353 DerefOrNullBytes = Attr.getDereferenceableOrNullBytes(); | 1475 DerefOrNullBytes = Attr.getDereferenceableOrNullBytes(); |
1354 else if (Kind == Attribute::AllocSize) | 1476 else if (Kind == Attribute::AllocSize) |
1364 AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) { | 1486 AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) { |
1365 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!"); | 1487 assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!"); |
1366 Attrs[Val] = false; | 1488 Attrs[Val] = false; |
1367 | 1489 |
1368 if (Val == Attribute::Alignment) | 1490 if (Val == Attribute::Alignment) |
1369 Alignment = 0; | 1491 Alignment.reset(); |
1370 else if (Val == Attribute::StackAlignment) | 1492 else if (Val == Attribute::StackAlignment) |
1371 StackAlignment = 0; | 1493 StackAlignment.reset(); |
1494 else if (Val == Attribute::ByVal) | |
1495 ByValType = nullptr; | |
1372 else if (Val == Attribute::Dereferenceable) | 1496 else if (Val == Attribute::Dereferenceable) |
1373 DerefBytes = 0; | 1497 DerefBytes = 0; |
1374 else if (Val == Attribute::DereferenceableOrNull) | 1498 else if (Val == Attribute::DereferenceableOrNull) |
1375 DerefOrNullBytes = 0; | 1499 DerefOrNullBytes = 0; |
1376 else if (Val == Attribute::AllocSize) | 1500 else if (Val == Attribute::AllocSize) |
1383 remove(A.getAttributes(Index)); | 1507 remove(A.getAttributes(Index)); |
1384 return *this; | 1508 return *this; |
1385 } | 1509 } |
1386 | 1510 |
1387 AttrBuilder &AttrBuilder::removeAttribute(StringRef A) { | 1511 AttrBuilder &AttrBuilder::removeAttribute(StringRef A) { |
1388 std::map<std::string, std::string>::iterator I = TargetDepAttrs.find(A); | 1512 auto I = TargetDepAttrs.find(A); |
1389 if (I != TargetDepAttrs.end()) | 1513 if (I != TargetDepAttrs.end()) |
1390 TargetDepAttrs.erase(I); | 1514 TargetDepAttrs.erase(I); |
1391 return *this; | 1515 return *this; |
1392 } | 1516 } |
1393 | 1517 |
1394 std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const { | 1518 std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const { |
1395 return unpackAllocSizeArgs(AllocSizeArgs); | 1519 return unpackAllocSizeArgs(AllocSizeArgs); |
1396 } | 1520 } |
1397 | 1521 |
1398 AttrBuilder &AttrBuilder::addAlignmentAttr(unsigned Align) { | 1522 AttrBuilder &AttrBuilder::addAlignmentAttr(unsigned A) { |
1399 if (Align == 0) return *this; | 1523 MaybeAlign Align(A); |
1400 | 1524 if (!Align) |
1401 assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); | 1525 return *this; |
1402 assert(Align <= 0x40000000 && "Alignment too large."); | 1526 |
1527 assert(*Align <= 0x40000000 && "Alignment too large."); | |
1403 | 1528 |
1404 Attrs[Attribute::Alignment] = true; | 1529 Attrs[Attribute::Alignment] = true; |
1405 Alignment = Align; | 1530 Alignment = Align; |
1406 return *this; | 1531 return *this; |
1407 } | 1532 } |
1408 | 1533 |
1409 AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align) { | 1534 AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned A) { |
1535 MaybeAlign Align(A); | |
1410 // Default alignment, allow the target to define how to align it. | 1536 // Default alignment, allow the target to define how to align it. |
1411 if (Align == 0) return *this; | 1537 if (!Align) |
1412 | 1538 return *this; |
1413 assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); | 1539 |
1414 assert(Align <= 0x100 && "Alignment too large."); | 1540 assert(*Align <= 0x100 && "Alignment too large."); |
1415 | 1541 |
1416 Attrs[Attribute::StackAlignment] = true; | 1542 Attrs[Attribute::StackAlignment] = true; |
1417 StackAlignment = Align; | 1543 StackAlignment = Align; |
1418 return *this; | 1544 return *this; |
1419 } | 1545 } |
1449 // save a few bytes over using a pair<unsigned, Optional<unsigned>>. | 1575 // save a few bytes over using a pair<unsigned, Optional<unsigned>>. |
1450 AllocSizeArgs = RawArgs; | 1576 AllocSizeArgs = RawArgs; |
1451 return *this; | 1577 return *this; |
1452 } | 1578 } |
1453 | 1579 |
1580 AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) { | |
1581 Attrs[Attribute::ByVal] = true; | |
1582 ByValType = Ty; | |
1583 return *this; | |
1584 } | |
1585 | |
1454 AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { | 1586 AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { |
1455 // FIXME: What if both have alignments, but they don't match?! | 1587 // FIXME: What if both have alignments, but they don't match?! |
1456 if (!Alignment) | 1588 if (!Alignment) |
1457 Alignment = B.Alignment; | 1589 Alignment = B.Alignment; |
1458 | 1590 |
1466 DerefOrNullBytes = B.DerefOrNullBytes; | 1598 DerefOrNullBytes = B.DerefOrNullBytes; |
1467 | 1599 |
1468 if (!AllocSizeArgs) | 1600 if (!AllocSizeArgs) |
1469 AllocSizeArgs = B.AllocSizeArgs; | 1601 AllocSizeArgs = B.AllocSizeArgs; |
1470 | 1602 |
1603 if (!ByValType) | |
1604 ByValType = B.ByValType; | |
1605 | |
1471 Attrs |= B.Attrs; | 1606 Attrs |= B.Attrs; |
1472 | 1607 |
1473 for (auto I : B.td_attrs()) | 1608 for (auto I : B.td_attrs()) |
1474 TargetDepAttrs[I.first] = I.second; | 1609 TargetDepAttrs[I.first] = I.second; |
1475 | 1610 |
1477 } | 1612 } |
1478 | 1613 |
1479 AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) { | 1614 AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) { |
1480 // FIXME: What if both have alignments, but they don't match?! | 1615 // FIXME: What if both have alignments, but they don't match?! |
1481 if (B.Alignment) | 1616 if (B.Alignment) |
1482 Alignment = 0; | 1617 Alignment.reset(); |
1483 | 1618 |
1484 if (B.StackAlignment) | 1619 if (B.StackAlignment) |
1485 StackAlignment = 0; | 1620 StackAlignment.reset(); |
1486 | 1621 |
1487 if (B.DerefBytes) | 1622 if (B.DerefBytes) |
1488 DerefBytes = 0; | 1623 DerefBytes = 0; |
1489 | 1624 |
1490 if (B.DerefOrNullBytes) | 1625 if (B.DerefOrNullBytes) |
1491 DerefOrNullBytes = 0; | 1626 DerefOrNullBytes = 0; |
1492 | 1627 |
1493 if (B.AllocSizeArgs) | 1628 if (B.AllocSizeArgs) |
1494 AllocSizeArgs = 0; | 1629 AllocSizeArgs = 0; |
1630 | |
1631 if (B.ByValType) | |
1632 ByValType = nullptr; | |
1495 | 1633 |
1496 Attrs &= ~B.Attrs; | 1634 Attrs &= ~B.Attrs; |
1497 | 1635 |
1498 for (auto I : B.td_attrs()) | 1636 for (auto I : B.td_attrs()) |
1499 TargetDepAttrs.erase(I.first); | 1637 TargetDepAttrs.erase(I.first); |
1523 } | 1661 } |
1524 | 1662 |
1525 bool AttrBuilder::hasAttributes(AttributeList AL, uint64_t Index) const { | 1663 bool AttrBuilder::hasAttributes(AttributeList AL, uint64_t Index) const { |
1526 AttributeSet AS = AL.getAttributes(Index); | 1664 AttributeSet AS = AL.getAttributes(Index); |
1527 | 1665 |
1528 for (Attribute Attr : AS) { | 1666 for (const auto Attr : AS) { |
1529 if (Attr.isEnumAttribute() || Attr.isIntAttribute()) { | 1667 if (Attr.isEnumAttribute() || Attr.isIntAttribute()) { |
1530 if (contains(Attr.getKindAsEnum())) | 1668 if (contains(Attr.getKindAsEnum())) |
1531 return true; | 1669 return true; |
1532 } else { | 1670 } else { |
1533 assert(Attr.isStringAttribute() && "Invalid attribute kind!"); | 1671 assert(Attr.isStringAttribute() && "Invalid attribute kind!"); |
1550 E = TargetDepAttrs.end(); I != E; ++I) | 1688 E = TargetDepAttrs.end(); I != E; ++I) |
1551 if (B.TargetDepAttrs.find(I->first) == B.TargetDepAttrs.end()) | 1689 if (B.TargetDepAttrs.find(I->first) == B.TargetDepAttrs.end()) |
1552 return false; | 1690 return false; |
1553 | 1691 |
1554 return Alignment == B.Alignment && StackAlignment == B.StackAlignment && | 1692 return Alignment == B.Alignment && StackAlignment == B.StackAlignment && |
1555 DerefBytes == B.DerefBytes; | 1693 DerefBytes == B.DerefBytes && ByValType == B.ByValType; |
1556 } | 1694 } |
1557 | 1695 |
1558 //===----------------------------------------------------------------------===// | 1696 //===----------------------------------------------------------------------===// |
1559 // AttributeFuncs Function Defintions | 1697 // AttributeFuncs Function Defintions |
1560 //===----------------------------------------------------------------------===// | 1698 //===----------------------------------------------------------------------===// |
1561 | 1699 |
1562 /// \brief Which attributes cannot be applied to a type. | 1700 /// Which attributes cannot be applied to a type. |
1563 AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) { | 1701 AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) { |
1564 AttrBuilder Incompatible; | 1702 AttrBuilder Incompatible; |
1565 | 1703 |
1566 if (!Ty->isIntegerTy()) | 1704 if (!Ty->isIntegerTy()) |
1567 // Attribute that only apply to integers. | 1705 // Attribute that only apply to integers. |
1589 static bool isEqual(const Function &Caller, const Function &Callee) { | 1727 static bool isEqual(const Function &Caller, const Function &Callee) { |
1590 return Caller.getFnAttribute(AttrClass::getKind()) == | 1728 return Caller.getFnAttribute(AttrClass::getKind()) == |
1591 Callee.getFnAttribute(AttrClass::getKind()); | 1729 Callee.getFnAttribute(AttrClass::getKind()); |
1592 } | 1730 } |
1593 | 1731 |
1594 /// \brief Compute the logical AND of the attributes of the caller and the | 1732 /// Compute the logical AND of the attributes of the caller and the |
1595 /// callee. | 1733 /// callee. |
1596 /// | 1734 /// |
1597 /// This function sets the caller's attribute to false if the callee's attribute | 1735 /// This function sets the caller's attribute to false if the callee's attribute |
1598 /// is false. | 1736 /// is false. |
1599 template<typename AttrClass> | 1737 template<typename AttrClass> |
1601 if (AttrClass::isSet(Caller, AttrClass::getKind()) && | 1739 if (AttrClass::isSet(Caller, AttrClass::getKind()) && |
1602 !AttrClass::isSet(Callee, AttrClass::getKind())) | 1740 !AttrClass::isSet(Callee, AttrClass::getKind())) |
1603 AttrClass::set(Caller, AttrClass::getKind(), false); | 1741 AttrClass::set(Caller, AttrClass::getKind(), false); |
1604 } | 1742 } |
1605 | 1743 |
1606 /// \brief Compute the logical OR of the attributes of the caller and the | 1744 /// Compute the logical OR of the attributes of the caller and the |
1607 /// callee. | 1745 /// callee. |
1608 /// | 1746 /// |
1609 /// This function sets the caller's attribute to true if the callee's attribute | 1747 /// This function sets the caller's attribute to true if the callee's attribute |
1610 /// is true. | 1748 /// is true. |
1611 template<typename AttrClass> | 1749 template<typename AttrClass> |
1613 if (!AttrClass::isSet(Caller, AttrClass::getKind()) && | 1751 if (!AttrClass::isSet(Caller, AttrClass::getKind()) && |
1614 AttrClass::isSet(Callee, AttrClass::getKind())) | 1752 AttrClass::isSet(Callee, AttrClass::getKind())) |
1615 AttrClass::set(Caller, AttrClass::getKind(), true); | 1753 AttrClass::set(Caller, AttrClass::getKind(), true); |
1616 } | 1754 } |
1617 | 1755 |
1618 /// \brief If the inlined function had a higher stack protection level than the | 1756 /// If the inlined function had a higher stack protection level than the |
1619 /// calling function, then bump up the caller's stack protection level. | 1757 /// calling function, then bump up the caller's stack protection level. |
1620 static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) { | 1758 static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) { |
1621 // If upgrading the SSP attribute, clear out the old SSP Attributes first. | 1759 // If upgrading the SSP attribute, clear out the old SSP Attributes first. |
1622 // Having multiple SSP attributes doesn't actually hurt, but it adds useless | 1760 // Having multiple SSP attributes doesn't actually hurt, but it adds useless |
1623 // clutter to the IR. | 1761 // clutter to the IR. |
1637 !Caller.hasFnAttribute(Attribute::StackProtectReq) && | 1775 !Caller.hasFnAttribute(Attribute::StackProtectReq) && |
1638 !Caller.hasFnAttribute(Attribute::StackProtectStrong)) | 1776 !Caller.hasFnAttribute(Attribute::StackProtectStrong)) |
1639 Caller.addFnAttr(Attribute::StackProtect); | 1777 Caller.addFnAttr(Attribute::StackProtect); |
1640 } | 1778 } |
1641 | 1779 |
1642 /// \brief If the inlined function required stack probes, then ensure that | 1780 /// If the inlined function required stack probes, then ensure that |
1643 /// the calling function has those too. | 1781 /// the calling function has those too. |
1644 static void adjustCallerStackProbes(Function &Caller, const Function &Callee) { | 1782 static void adjustCallerStackProbes(Function &Caller, const Function &Callee) { |
1645 if (!Caller.hasFnAttribute("probe-stack") && | 1783 if (!Caller.hasFnAttribute("probe-stack") && |
1646 Callee.hasFnAttribute("probe-stack")) { | 1784 Callee.hasFnAttribute("probe-stack")) { |
1647 Caller.addFnAttr(Callee.getFnAttribute("probe-stack")); | 1785 Caller.addFnAttr(Callee.getFnAttribute("probe-stack")); |
1648 } | 1786 } |
1649 } | 1787 } |
1650 | 1788 |
1651 /// \brief If the inlined function defines the size of guard region | 1789 /// If the inlined function defines the size of guard region |
1652 /// on the stack, then ensure that the calling function defines a guard region | 1790 /// on the stack, then ensure that the calling function defines a guard region |
1653 /// that is no larger. | 1791 /// that is no larger. |
1654 static void | 1792 static void |
1655 adjustCallerStackProbeSize(Function &Caller, const Function &Callee) { | 1793 adjustCallerStackProbeSize(Function &Caller, const Function &Callee) { |
1656 if (Callee.hasFnAttribute("stack-probe-size")) { | 1794 if (Callee.hasFnAttribute("stack-probe-size")) { |
1670 Caller.addFnAttr(Callee.getFnAttribute("stack-probe-size")); | 1808 Caller.addFnAttr(Callee.getFnAttribute("stack-probe-size")); |
1671 } | 1809 } |
1672 } | 1810 } |
1673 } | 1811 } |
1674 | 1812 |
1813 /// If the inlined function defines a min legal vector width, then ensure | |
1814 /// the calling function has the same or larger min legal vector width. If the | |
1815 /// caller has the attribute, but the callee doesn't, we need to remove the | |
1816 /// attribute from the caller since we can't make any guarantees about the | |
1817 /// caller's requirements. | |
1818 /// This function is called after the inlining decision has been made so we have | |
1819 /// to merge the attribute this way. Heuristics that would use | |
1820 /// min-legal-vector-width to determine inline compatibility would need to be | |
1821 /// handled as part of inline cost analysis. | |
1822 static void | |
1823 adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) { | |
1824 if (Caller.hasFnAttribute("min-legal-vector-width")) { | |
1825 if (Callee.hasFnAttribute("min-legal-vector-width")) { | |
1826 uint64_t CallerVectorWidth; | |
1827 Caller.getFnAttribute("min-legal-vector-width") | |
1828 .getValueAsString() | |
1829 .getAsInteger(0, CallerVectorWidth); | |
1830 uint64_t CalleeVectorWidth; | |
1831 Callee.getFnAttribute("min-legal-vector-width") | |
1832 .getValueAsString() | |
1833 .getAsInteger(0, CalleeVectorWidth); | |
1834 if (CallerVectorWidth < CalleeVectorWidth) | |
1835 Caller.addFnAttr(Callee.getFnAttribute("min-legal-vector-width")); | |
1836 } else { | |
1837 // If the callee doesn't have the attribute then we don't know anything | |
1838 // and must drop the attribute from the caller. | |
1839 Caller.removeFnAttr("min-legal-vector-width"); | |
1840 } | |
1841 } | |
1842 } | |
1843 | |
1844 /// If the inlined function has "null-pointer-is-valid=true" attribute, | |
1845 /// set this attribute in the caller post inlining. | |
1846 static void | |
1847 adjustNullPointerValidAttr(Function &Caller, const Function &Callee) { | |
1848 if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) { | |
1849 Caller.addFnAttr(Callee.getFnAttribute("null-pointer-is-valid")); | |
1850 } | |
1851 } | |
1852 | |
1675 #define GET_ATTR_COMPAT_FUNC | 1853 #define GET_ATTR_COMPAT_FUNC |
1676 #include "AttributesCompatFunc.inc" | 1854 #include "AttributesCompatFunc.inc" |
1677 | 1855 |
1678 bool AttributeFuncs::areInlineCompatible(const Function &Caller, | 1856 bool AttributeFuncs::areInlineCompatible(const Function &Caller, |
1679 const Function &Callee) { | 1857 const Function &Callee) { |