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