1 //===-- Attribute.cpp - Implement AttributesList -------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the Attribute, AttributeImpl, AttrBuilder, 11 // AttributeSetImpl, and AttributeSet classes. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/IR/Attributes.h" 16 #include "AttributeImpl.h" 17 #include "LLVMContextImpl.h" 18 #include "llvm/ADT/FoldingSet.h" 19 #include "llvm/ADT/StringExtras.h" 20 #include "llvm/IR/Type.h" 21 #include "llvm/Support/Atomic.h" 22 #include "llvm/Support/Debug.h" 23 #include "llvm/Support/ManagedStatic.h" 24 #include "llvm/Support/Mutex.h" 25 #include "llvm/Support/raw_ostream.h" 26 using namespace llvm; 27 28 //===----------------------------------------------------------------------===// 29 // Attribute Implementation 30 //===----------------------------------------------------------------------===// 31 32 Attribute Attribute::get(LLVMContext &Context, ArrayRef<AttrKind> Vals) { 33 AttrBuilder B; 34 for (ArrayRef<AttrKind>::iterator I = Vals.begin(), E = Vals.end(); 35 I != E; ++I) 36 B.addAttribute(*I); 37 return Attribute::get(Context, B); 38 } 39 40 Attribute Attribute::get(LLVMContext &Context, AttrBuilder &B) { 41 // If there are no attributes, return an empty Attribute class. 42 if (!B.hasAttributes()) 43 return Attribute(); 44 45 // Otherwise, build a key to look up the existing attributes. 46 LLVMContextImpl *pImpl = Context.pImpl; 47 FoldingSetNodeID ID; 48 // FIXME: Don't look up ConstantInts here. 49 ID.AddPointer(ConstantInt::get(Type::getInt64Ty(Context), B.getBitMask())); 50 51 void *InsertPoint; 52 AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint); 53 54 if (!PA) { 55 // If we didn't find any existing attributes of the same shape then create a 56 // new one and insert it. 57 PA = new AttributeImpl(Context, B.getBitMask()); 58 pImpl->AttrsSet.InsertNode(PA, InsertPoint); 59 } 60 61 // Return the AttributesList that we found or created. 62 return Attribute(PA); 63 } 64 65 bool Attribute::hasAttribute(AttrKind Val) const { 66 return pImpl && pImpl->hasAttribute(Val); 67 } 68 69 bool Attribute::hasAttributes() const { 70 return pImpl && pImpl->hasAttributes(); 71 } 72 73 /// This returns the alignment field of an attribute as a byte alignment value. 74 unsigned Attribute::getAlignment() const { 75 if (!hasAttribute(Attribute::Alignment)) 76 return 0; 77 return 1U << ((pImpl->getAlignment() >> 16) - 1); 78 } 79 80 void Attribute::setAlignment(unsigned Align) { 81 assert(hasAttribute(Attribute::Alignment) && 82 "Trying to set the alignment on a non-alignment attribute!"); 83 pImpl->setAlignment(Align); 84 } 85 86 /// This returns the stack alignment field of an attribute as a byte alignment 87 /// value. 88 unsigned Attribute::getStackAlignment() const { 89 if (!hasAttribute(Attribute::StackAlignment)) 90 return 0; 91 return 1U << ((pImpl->getStackAlignment() >> 26) - 1); 92 } 93 94 void Attribute::setStackAlignment(unsigned Align) { 95 assert(hasAttribute(Attribute::StackAlignment) && 96 "Trying to set the stack alignment on a non-alignment attribute!"); 97 pImpl->setStackAlignment(Align); 98 } 99 100 bool Attribute::operator==(AttrKind K) const { 101 return pImpl && *pImpl == K; 102 } 103 bool Attribute::operator!=(AttrKind K) const { 104 return !(*this == K); 105 } 106 107 uint64_t Attribute::getBitMask() const { 108 return pImpl ? pImpl->getBitMask() : 0; 109 } 110 111 Attribute Attribute::typeIncompatible(Type *Ty) { 112 AttrBuilder Incompatible; 113 114 if (!Ty->isIntegerTy()) 115 // Attribute that only apply to integers. 116 Incompatible.addAttribute(Attribute::SExt) 117 .addAttribute(Attribute::ZExt); 118 119 if (!Ty->isPointerTy()) 120 // Attribute that only apply to pointers. 121 Incompatible.addAttribute(Attribute::ByVal) 122 .addAttribute(Attribute::Nest) 123 .addAttribute(Attribute::NoAlias) 124 .addAttribute(Attribute::NoCapture) 125 .addAttribute(Attribute::StructRet); 126 127 return Attribute::get(Ty->getContext(), Incompatible); 128 } 129 130 /// encodeLLVMAttributesForBitcode - This returns an integer containing an 131 /// encoding of all the LLVM attributes found in the given attribute bitset. 132 /// Any change to this encoding is a breaking change to bitcode compatibility. 133 uint64_t Attribute::encodeLLVMAttributesForBitcode(Attribute Attrs) { 134 // FIXME: It doesn't make sense to store the alignment information as an 135 // expanded out value, we should store it as a log2 value. However, we can't 136 // just change that here without breaking bitcode compatibility. If this ever 137 // becomes a problem in practice, we should introduce new tag numbers in the 138 // bitcode file and have those tags use a more efficiently encoded alignment 139 // field. 140 141 // Store the alignment in the bitcode as a 16-bit raw value instead of a 5-bit 142 // log2 encoded value. Shift the bits above the alignment up by 11 bits. 143 uint64_t EncodedAttrs = Attrs.getBitMask() & 0xffff; 144 if (Attrs.hasAttribute(Attribute::Alignment)) 145 EncodedAttrs |= Attrs.getAlignment() << 16; 146 EncodedAttrs |= (Attrs.getBitMask() & (0xffffULL << 21)) << 11; 147 return EncodedAttrs; 148 } 149 150 /// decodeLLVMAttributesForBitcode - This returns an attribute bitset containing 151 /// the LLVM attributes that have been decoded from the given integer. This 152 /// function must stay in sync with 'encodeLLVMAttributesForBitcode'. 153 Attribute Attribute::decodeLLVMAttributesForBitcode(LLVMContext &C, 154 uint64_t EncodedAttrs) { 155 // The alignment is stored as a 16-bit raw value from bits 31--16. We shift 156 // the bits above 31 down by 11 bits. 157 unsigned Alignment = (EncodedAttrs & (0xffffULL << 16)) >> 16; 158 assert((!Alignment || isPowerOf2_32(Alignment)) && 159 "Alignment must be a power of two."); 160 161 AttrBuilder B(EncodedAttrs & 0xffff); 162 if (Alignment) 163 B.addAlignmentAttr(Alignment); 164 B.addRawValue((EncodedAttrs & (0xffffULL << 32)) >> 11); 165 return Attribute::get(C, B); 166 } 167 168 std::string Attribute::getAsString() const { 169 std::string Result; 170 if (hasAttribute(Attribute::ZExt)) 171 Result += "zeroext "; 172 if (hasAttribute(Attribute::SExt)) 173 Result += "signext "; 174 if (hasAttribute(Attribute::NoReturn)) 175 Result += "noreturn "; 176 if (hasAttribute(Attribute::NoUnwind)) 177 Result += "nounwind "; 178 if (hasAttribute(Attribute::UWTable)) 179 Result += "uwtable "; 180 if (hasAttribute(Attribute::ReturnsTwice)) 181 Result += "returns_twice "; 182 if (hasAttribute(Attribute::InReg)) 183 Result += "inreg "; 184 if (hasAttribute(Attribute::NoAlias)) 185 Result += "noalias "; 186 if (hasAttribute(Attribute::NoCapture)) 187 Result += "nocapture "; 188 if (hasAttribute(Attribute::StructRet)) 189 Result += "sret "; 190 if (hasAttribute(Attribute::ByVal)) 191 Result += "byval "; 192 if (hasAttribute(Attribute::Nest)) 193 Result += "nest "; 194 if (hasAttribute(Attribute::ReadNone)) 195 Result += "readnone "; 196 if (hasAttribute(Attribute::ReadOnly)) 197 Result += "readonly "; 198 if (hasAttribute(Attribute::OptimizeForSize)) 199 Result += "optsize "; 200 if (hasAttribute(Attribute::NoInline)) 201 Result += "noinline "; 202 if (hasAttribute(Attribute::InlineHint)) 203 Result += "inlinehint "; 204 if (hasAttribute(Attribute::AlwaysInline)) 205 Result += "alwaysinline "; 206 if (hasAttribute(Attribute::StackProtect)) 207 Result += "ssp "; 208 if (hasAttribute(Attribute::StackProtectReq)) 209 Result += "sspreq "; 210 if (hasAttribute(Attribute::NoRedZone)) 211 Result += "noredzone "; 212 if (hasAttribute(Attribute::NoImplicitFloat)) 213 Result += "noimplicitfloat "; 214 if (hasAttribute(Attribute::Naked)) 215 Result += "naked "; 216 if (hasAttribute(Attribute::NonLazyBind)) 217 Result += "nonlazybind "; 218 if (hasAttribute(Attribute::AddressSafety)) 219 Result += "address_safety "; 220 if (hasAttribute(Attribute::MinSize)) 221 Result += "minsize "; 222 if (hasAttribute(Attribute::StackAlignment)) { 223 Result += "alignstack("; 224 Result += utostr(getStackAlignment()); 225 Result += ") "; 226 } 227 if (hasAttribute(Attribute::Alignment)) { 228 Result += "align "; 229 Result += utostr(getAlignment()); 230 Result += " "; 231 } 232 if (hasAttribute(Attribute::NoDuplicate)) 233 Result += "noduplicate "; 234 // Trim the trailing space. 235 assert(!Result.empty() && "Unknown attribute!"); 236 Result.erase(Result.end()-1); 237 return Result; 238 } 239 240 //===----------------------------------------------------------------------===// 241 // AttrBuilder Method Implementations 242 //===----------------------------------------------------------------------===// 243 244 AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Idx) 245 : Alignment(0), StackAlignment(0) { 246 AttributeSetImpl *pImpl = AS.AttrList; 247 if (!pImpl) return; 248 249 ArrayRef<AttributeWithIndex> AttrList = pImpl->getAttributes(); 250 const AttributeWithIndex *AWI = 0; 251 for (unsigned I = 0, E = AttrList.size(); I != E; ++I) 252 if (AttrList[I].Index == Idx) { 253 AWI = &AttrList[I]; 254 break; 255 } 256 257 assert(AWI && "Cannot find index in attribute set!"); 258 259 /// FIXME: This will be modified in the future. Basically, the 260 /// AttributeWithIndex class will contain the 261 262 } 263 264 void AttrBuilder::clear() { 265 Attrs.clear(); 266 Alignment = StackAlignment = 0; 267 } 268 269 AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) { 270 Attrs.insert(Val); 271 return *this; 272 } 273 274 AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) { 275 Attrs.erase(Val); 276 if (Val == Attribute::Alignment) 277 Alignment = 0; 278 else if (Val == Attribute::StackAlignment) 279 StackAlignment = 0; 280 281 return *this; 282 } 283 284 AttrBuilder &AttrBuilder::addAlignmentAttr(unsigned Align) { 285 if (Align == 0) return *this; 286 287 assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); 288 assert(Align <= 0x40000000 && "Alignment too large."); 289 290 Attrs.insert(Attribute::Alignment); 291 Alignment = Align; 292 return *this; 293 } 294 295 AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align) { 296 // Default alignment, allow the target to define how to align it. 297 if (Align == 0) return *this; 298 299 assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); 300 assert(Align <= 0x100 && "Alignment too large."); 301 302 Attrs.insert(Attribute::StackAlignment); 303 StackAlignment = Align; 304 return *this; 305 } 306 307 AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) { 308 for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds; 309 I = Attribute::AttrKind(I + 1)) { 310 if (uint64_t A = (Val & AttributeImpl::getAttrMask(I))) { 311 Attrs.insert(I); 312 313 if (I == Attribute::Alignment) 314 Alignment = 1ULL << ((A >> 16) - 1); 315 else if (I == Attribute::StackAlignment) 316 StackAlignment = 1ULL << ((A >> 26)-1); 317 } 318 } 319 320 return *this; 321 } 322 323 AttrBuilder &AttrBuilder::addAttributes(const Attribute &A) { 324 uint64_t Mask = A.getBitMask(); 325 326 for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds; 327 I = Attribute::AttrKind(I + 1)) { 328 if (uint64_t A = (Mask & AttributeImpl::getAttrMask(I))) { 329 Attrs.insert(I); 330 331 if (I == Attribute::Alignment) 332 Alignment = 1ULL << ((A >> 16) - 1); 333 else if (I == Attribute::StackAlignment) 334 StackAlignment = 1ULL << ((A >> 26)-1); 335 } 336 } 337 338 return *this; 339 } 340 341 AttrBuilder &AttrBuilder::removeAttributes(const Attribute &A){ 342 uint64_t Mask = A.getBitMask(); 343 344 for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds; 345 I = Attribute::AttrKind(I + 1)) { 346 if (Mask & AttributeImpl::getAttrMask(I)) { 347 Attrs.erase(I); 348 349 if (I == Attribute::Alignment) 350 Alignment = 0; 351 else if (I == Attribute::StackAlignment) 352 StackAlignment = 0; 353 } 354 } 355 356 return *this; 357 } 358 359 bool AttrBuilder::contains(Attribute::AttrKind A) const { 360 return Attrs.count(A); 361 } 362 363 bool AttrBuilder::hasAttributes() const { 364 return !Attrs.empty(); 365 } 366 367 bool AttrBuilder::hasAttributes(const Attribute &A) const { 368 return getBitMask() & A.getBitMask(); 369 } 370 371 bool AttrBuilder::hasAlignmentAttr() const { 372 return Alignment != 0; 373 } 374 375 uint64_t AttrBuilder::getBitMask() const { 376 uint64_t Mask = 0; 377 378 for (DenseSet<Attribute::AttrKind>::const_iterator I = Attrs.begin(), 379 E = Attrs.end(); I != E; ++I) { 380 Attribute::AttrKind Kind = *I; 381 382 if (Kind == Attribute::Alignment) 383 Mask |= (Log2_32(Alignment) + 1) << 16; 384 else if (Kind == Attribute::StackAlignment) 385 Mask |= (Log2_32(StackAlignment) + 1) << 26; 386 else 387 Mask |= AttributeImpl::getAttrMask(Kind); 388 } 389 390 return Mask; 391 } 392 393 bool AttrBuilder::operator==(const AttrBuilder &B) { 394 SmallVector<Attribute::AttrKind, 8> This(Attrs.begin(), Attrs.end()); 395 SmallVector<Attribute::AttrKind, 8> That(B.Attrs.begin(), B.Attrs.end()); 396 return This == That; 397 } 398 399 //===----------------------------------------------------------------------===// 400 // AttributeImpl Definition 401 //===----------------------------------------------------------------------===// 402 403 AttributeImpl::AttributeImpl(LLVMContext &C, uint64_t data) 404 : Context(C) { 405 Data = ConstantInt::get(Type::getInt64Ty(C), data); 406 } 407 AttributeImpl::AttributeImpl(LLVMContext &C, Attribute::AttrKind data) 408 : Context(C) { 409 Data = ConstantInt::get(Type::getInt64Ty(C), data); 410 } 411 AttributeImpl::AttributeImpl(LLVMContext &C, Attribute::AttrKind data, 412 ArrayRef<Constant*> values) 413 : Context(C) { 414 Data = ConstantInt::get(Type::getInt64Ty(C), data); 415 Vals.reserve(values.size()); 416 Vals.append(values.begin(), values.end()); 417 } 418 AttributeImpl::AttributeImpl(LLVMContext &C, StringRef data) 419 : Context(C) { 420 Data = ConstantDataArray::getString(C, data); 421 } 422 423 bool AttributeImpl::operator==(Attribute::AttrKind Kind) const { 424 if (ConstantInt *CI = dyn_cast<ConstantInt>(Data)) 425 return CI->getZExtValue() == Kind; 426 return false; 427 } 428 bool AttributeImpl::operator!=(Attribute::AttrKind Kind) const { 429 return !(*this == Kind); 430 } 431 432 bool AttributeImpl::operator==(StringRef Kind) const { 433 if (ConstantDataArray *CDA = dyn_cast<ConstantDataArray>(Data)) 434 if (CDA->isString()) 435 return CDA->getAsString() == Kind; 436 return false; 437 } 438 bool AttributeImpl::operator!=(StringRef Kind) const { 439 return !(*this == Kind); 440 } 441 442 uint64_t AttributeImpl::getBitMask() const { 443 // FIXME: Remove this. 444 return cast<ConstantInt>(Data)->getZExtValue(); 445 } 446 447 uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) { 448 switch (Val) { 449 case Attribute::EndAttrKinds: 450 case Attribute::AttrKindEmptyKey: 451 case Attribute::AttrKindTombstoneKey: 452 llvm_unreachable("Synthetic enumerators which should never get here"); 453 454 case Attribute::None: return 0; 455 case Attribute::ZExt: return 1 << 0; 456 case Attribute::SExt: return 1 << 1; 457 case Attribute::NoReturn: return 1 << 2; 458 case Attribute::InReg: return 1 << 3; 459 case Attribute::StructRet: return 1 << 4; 460 case Attribute::NoUnwind: return 1 << 5; 461 case Attribute::NoAlias: return 1 << 6; 462 case Attribute::ByVal: return 1 << 7; 463 case Attribute::Nest: return 1 << 8; 464 case Attribute::ReadNone: return 1 << 9; 465 case Attribute::ReadOnly: return 1 << 10; 466 case Attribute::NoInline: return 1 << 11; 467 case Attribute::AlwaysInline: return 1 << 12; 468 case Attribute::OptimizeForSize: return 1 << 13; 469 case Attribute::StackProtect: return 1 << 14; 470 case Attribute::StackProtectReq: return 1 << 15; 471 case Attribute::Alignment: return 31 << 16; 472 case Attribute::NoCapture: return 1 << 21; 473 case Attribute::NoRedZone: return 1 << 22; 474 case Attribute::NoImplicitFloat: return 1 << 23; 475 case Attribute::Naked: return 1 << 24; 476 case Attribute::InlineHint: return 1 << 25; 477 case Attribute::StackAlignment: return 7 << 26; 478 case Attribute::ReturnsTwice: return 1 << 29; 479 case Attribute::UWTable: return 1 << 30; 480 case Attribute::NonLazyBind: return 1U << 31; 481 case Attribute::AddressSafety: return 1ULL << 32; 482 case Attribute::MinSize: return 1ULL << 33; 483 case Attribute::NoDuplicate: return 1ULL << 34; 484 } 485 llvm_unreachable("Unsupported attribute type"); 486 } 487 488 bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const { 489 return (getBitMask() & getAttrMask(A)) != 0; 490 } 491 492 bool AttributeImpl::hasAttributes() const { 493 return getBitMask() != 0; 494 } 495 496 uint64_t AttributeImpl::getAlignment() const { 497 return getBitMask() & getAttrMask(Attribute::Alignment); 498 } 499 500 void AttributeImpl::setAlignment(unsigned Align) { 501 Vals.push_back(ConstantInt::get(Type::getInt64Ty(Context), Align)); 502 } 503 504 uint64_t AttributeImpl::getStackAlignment() const { 505 return getBitMask() & getAttrMask(Attribute::StackAlignment); 506 } 507 508 void AttributeImpl::setStackAlignment(unsigned Align) { 509 Vals.push_back(ConstantInt::get(Type::getInt64Ty(Context), Align)); 510 } 511 512 //===----------------------------------------------------------------------===// 513 // AttributeSetImpl Definition 514 //===----------------------------------------------------------------------===// 515 516 AttributeSet AttributeSet::get(LLVMContext &C, 517 ArrayRef<AttributeWithIndex> Attrs) { 518 // If there are no attributes then return a null AttributesList pointer. 519 if (Attrs.empty()) 520 return AttributeSet(); 521 522 #ifndef NDEBUG 523 for (unsigned i = 0, e = Attrs.size(); i != e; ++i) { 524 assert(Attrs[i].Attrs.hasAttributes() && 525 "Pointless attribute!"); 526 assert((!i || Attrs[i-1].Index < Attrs[i].Index) && 527 "Misordered AttributesList!"); 528 } 529 #endif 530 531 // Otherwise, build a key to look up the existing attributes. 532 LLVMContextImpl *pImpl = C.pImpl; 533 FoldingSetNodeID ID; 534 AttributeSetImpl::Profile(ID, Attrs); 535 536 void *InsertPoint; 537 AttributeSetImpl *PA = pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint); 538 539 // If we didn't find any existing attributes of the same shape then 540 // create a new one and insert it. 541 if (!PA) { 542 PA = new AttributeSetImpl(C, Attrs); 543 pImpl->AttrsLists.InsertNode(PA, InsertPoint); 544 } 545 546 // Return the AttributesList that we found or created. 547 return AttributeSet(PA); 548 } 549 550 AttributeSet AttributeSet::get(LLVMContext &C, unsigned Idx, AttrBuilder &B) { 551 SmallVector<AttributeWithIndex, 8> Attrs; 552 for (AttrBuilder::iterator I = B.begin(), E = B.end(); I != E; ++I) { 553 Attribute::AttrKind Kind = *I; 554 Attribute A = Attribute::get(C, Kind); 555 556 if (Kind == Attribute::Alignment) 557 A.setAlignment(B.getAlignment()); 558 else if (Kind == Attribute::StackAlignment) 559 A.setStackAlignment(B.getStackAlignment()); 560 561 Attrs.push_back(AttributeWithIndex::get(Idx, A)); 562 } 563 564 return get(C, Attrs); 565 } 566 567 //===----------------------------------------------------------------------===// 568 // AttributeSet Method Implementations 569 //===----------------------------------------------------------------------===// 570 571 const AttributeSet &AttributeSet::operator=(const AttributeSet &RHS) { 572 AttrList = RHS.AttrList; 573 return *this; 574 } 575 576 /// getNumSlots - Return the number of slots used in this attribute list. 577 /// This is the number of arguments that have an attribute set on them 578 /// (including the function itself). 579 unsigned AttributeSet::getNumSlots() const { 580 return AttrList ? AttrList->getNumAttributes() : 0; 581 } 582 583 /// getSlot - Return the AttributeWithIndex at the specified slot. This 584 /// holds a number plus a set of attributes. 585 const AttributeWithIndex &AttributeSet::getSlot(unsigned Slot) const { 586 assert(AttrList && Slot < AttrList->getNumAttributes() && 587 "Slot # out of range!"); 588 return AttrList->getAttributes()[Slot]; 589 } 590 591 bool AttributeSet::hasAttribute(unsigned Index, Attribute::AttrKind Kind) const{ 592 return getAttributes(Index).hasAttribute(Kind); 593 } 594 595 bool AttributeSet::hasAttributes(unsigned Index) const { 596 return getAttributes(Index).hasAttributes(); 597 } 598 599 std::string AttributeSet::getAsString(unsigned Index) const { 600 return getAttributes(Index).getAsString(); 601 } 602 603 unsigned AttributeSet::getStackAlignment(unsigned Index) const { 604 return getAttributes(Index).getStackAlignment(); 605 } 606 607 uint64_t AttributeSet::getBitMask(unsigned Index) const { 608 // FIXME: Remove this. 609 return getAttributes(Index).getBitMask(); 610 } 611 612 /// getAttributes - The attributes for the specified index are returned. 613 /// Attributes for the result are denoted with Idx = 0. Function attributes are 614 /// denoted with Idx = ~0. 615 Attribute AttributeSet::getAttributes(unsigned Idx) const { 616 if (AttrList == 0) return Attribute(); 617 618 ArrayRef<AttributeWithIndex> Attrs = AttrList->getAttributes(); 619 for (unsigned i = 0, e = Attrs.size(); i != e && Attrs[i].Index <= Idx; ++i) 620 if (Attrs[i].Index == Idx) 621 return Attrs[i].Attrs; 622 623 return Attribute(); 624 } 625 626 /// hasAttrSomewhere - Return true if the specified attribute is set for at 627 /// least one parameter or for the return value. 628 bool AttributeSet::hasAttrSomewhere(Attribute::AttrKind Attr) const { 629 if (AttrList == 0) return false; 630 631 ArrayRef<AttributeWithIndex> Attrs = AttrList->getAttributes(); 632 for (unsigned i = 0, e = Attrs.size(); i != e; ++i) 633 if (Attrs[i].Attrs.hasAttribute(Attr)) 634 return true; 635 636 return false; 637 } 638 639 AttributeSet AttributeSet::addAttr(LLVMContext &C, unsigned Idx, 640 Attribute Attrs) const { 641 Attribute OldAttrs = getAttributes(Idx); 642 #ifndef NDEBUG 643 // FIXME it is not obvious how this should work for alignment. 644 // For now, say we can't change a known alignment. 645 unsigned OldAlign = OldAttrs.getAlignment(); 646 unsigned NewAlign = Attrs.getAlignment(); 647 assert((!OldAlign || !NewAlign || OldAlign == NewAlign) && 648 "Attempt to change alignment!"); 649 #endif 650 651 AttrBuilder NewAttrs = 652 AttrBuilder(OldAttrs).addAttributes(Attrs); 653 if (NewAttrs == AttrBuilder(OldAttrs)) 654 return *this; 655 656 SmallVector<AttributeWithIndex, 8> NewAttrList; 657 if (AttrList == 0) 658 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs)); 659 else { 660 ArrayRef<AttributeWithIndex> OldAttrList = AttrList->getAttributes(); 661 unsigned i = 0, e = OldAttrList.size(); 662 // Copy attributes for arguments before this one. 663 for (; i != e && OldAttrList[i].Index < Idx; ++i) 664 NewAttrList.push_back(OldAttrList[i]); 665 666 // If there are attributes already at this index, merge them in. 667 if (i != e && OldAttrList[i].Index == Idx) { 668 Attrs = 669 Attribute::get(C, AttrBuilder(Attrs). 670 addAttributes(OldAttrList[i].Attrs)); 671 ++i; 672 } 673 674 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs)); 675 676 // Copy attributes for arguments after this one. 677 NewAttrList.insert(NewAttrList.end(), 678 OldAttrList.begin()+i, OldAttrList.end()); 679 } 680 681 return get(C, NewAttrList); 682 } 683 684 AttributeSet AttributeSet::removeAttr(LLVMContext &C, unsigned Idx, 685 Attribute Attrs) const { 686 #ifndef NDEBUG 687 // FIXME it is not obvious how this should work for alignment. 688 // For now, say we can't pass in alignment, which no current use does. 689 assert(!Attrs.hasAttribute(Attribute::Alignment) && 690 "Attempt to exclude alignment!"); 691 #endif 692 if (AttrList == 0) return AttributeSet(); 693 694 Attribute OldAttrs = getAttributes(Idx); 695 AttrBuilder NewAttrs = 696 AttrBuilder(OldAttrs).removeAttributes(Attrs); 697 if (NewAttrs == AttrBuilder(OldAttrs)) 698 return *this; 699 700 SmallVector<AttributeWithIndex, 8> NewAttrList; 701 ArrayRef<AttributeWithIndex> OldAttrList = AttrList->getAttributes(); 702 unsigned i = 0, e = OldAttrList.size(); 703 704 // Copy attributes for arguments before this one. 705 for (; i != e && OldAttrList[i].Index < Idx; ++i) 706 NewAttrList.push_back(OldAttrList[i]); 707 708 // If there are attributes already at this index, merge them in. 709 assert(OldAttrList[i].Index == Idx && "Attribute isn't set?"); 710 Attrs = Attribute::get(C, AttrBuilder(OldAttrList[i].Attrs). 711 removeAttributes(Attrs)); 712 ++i; 713 if (Attrs.hasAttributes()) // If any attributes left for this param, add them. 714 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs)); 715 716 // Copy attributes for arguments after this one. 717 NewAttrList.insert(NewAttrList.end(), 718 OldAttrList.begin()+i, OldAttrList.end()); 719 720 return get(C, NewAttrList); 721 } 722 723 void AttributeSet::dump() const { 724 dbgs() << "PAL[ "; 725 for (unsigned i = 0; i < getNumSlots(); ++i) { 726 const AttributeWithIndex &PAWI = getSlot(i); 727 dbgs() << "{ " << PAWI.Index << ", " << PAWI.Attrs.getAsString() << " } "; 728 } 729 730 dbgs() << "]\n"; 731 } 732