Attributes.cpp revision 28d65722d6f283b327b5815914382077fe9c0ab4
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" 26using namespace llvm; 27 28//===----------------------------------------------------------------------===// 29// Attribute Implementation 30//===----------------------------------------------------------------------===// 31 32Attribute 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 40Attribute 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 64bool Attribute::hasAttribute(AttrKind Val) const { 65 return pImpl && pImpl->hasAttribute(Val); 66} 67 68bool Attribute::hasAttributes() const { 69 return pImpl && pImpl->hasAttributes(); 70} 71 72/// This returns the alignment field of an attribute as a byte alignment value. 73unsigned Attribute::getAlignment() const { 74 if (!hasAttribute(Attribute::Alignment)) 75 return 0; 76 return 1U << ((pImpl->getAlignment() >> 16) - 1); 77} 78 79void 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. 87unsigned Attribute::getStackAlignment() const { 88 if (!hasAttribute(Attribute::StackAlignment)) 89 return 0; 90 return 1U << ((pImpl->getStackAlignment() >> 26) - 1); 91} 92 93void 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 99bool Attribute::operator==(AttrKind K) const { 100 return pImpl && *pImpl == K; 101} 102bool Attribute::operator!=(AttrKind K) const { 103 return !(*this == K); 104} 105 106uint64_t Attribute::Raw() const { 107 return pImpl ? pImpl->Raw() : 0; 108} 109 110Attribute 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. 132uint64_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'. 152Attribute 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 167std::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 243AttrBuilder::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 if (!AWI) return; 257 258 uint64_t Mask = AWI->Attrs.Raw(); 259 260 for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds; 261 I = Attribute::AttrKind(I + 1)) { 262 if (uint64_t A = (Mask & AttributeImpl::getAttrMask(I))) { 263 Attrs.insert(I); 264 265 if (I == Attribute::Alignment) 266 Alignment = 1ULL << ((A >> 16) - 1); 267 else if (I == Attribute::StackAlignment) 268 StackAlignment = 1ULL << ((A >> 26)-1); 269 } 270 } 271} 272 273void AttrBuilder::clear() { 274 Attrs.clear(); 275 Alignment = StackAlignment = 0; 276} 277 278AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) { 279 Attrs.insert(Val); 280 return *this; 281} 282 283AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) { 284 Attrs.erase(Val); 285 if (Val == Attribute::Alignment) 286 Alignment = 0; 287 else if (Val == Attribute::StackAlignment) 288 StackAlignment = 0; 289 290 return *this; 291} 292 293AttrBuilder &AttrBuilder::addAlignmentAttr(unsigned Align) { 294 if (Align == 0) return *this; 295 296 assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); 297 assert(Align <= 0x40000000 && "Alignment too large."); 298 299 Attrs.insert(Attribute::Alignment); 300 Alignment = Align; 301 return *this; 302} 303 304AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align) { 305 // Default alignment, allow the target to define how to align it. 306 if (Align == 0) return *this; 307 308 assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); 309 assert(Align <= 0x100 && "Alignment too large."); 310 311 Attrs.insert(Attribute::StackAlignment); 312 StackAlignment = Align; 313 return *this; 314} 315 316AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) { 317 for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds; 318 I = Attribute::AttrKind(I + 1)) { 319 if (uint64_t A = (Val & AttributeImpl::getAttrMask(I))) { 320 Attrs.insert(I); 321 322 if (I == Attribute::Alignment) 323 Alignment = 1ULL << ((A >> 16) - 1); 324 else if (I == Attribute::StackAlignment) 325 StackAlignment = 1ULL << ((A >> 26)-1); 326 } 327 } 328 329 return *this; 330} 331 332AttrBuilder &AttrBuilder::addAttributes(const Attribute &Attr) { 333 uint64_t Mask = Attr.Raw(); 334 335 for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds; 336 I = Attribute::AttrKind(I + 1)) 337 if ((Mask & AttributeImpl::getAttrMask(I)) != 0) 338 Attrs.insert(I); 339 340 if (Attr.getAlignment()) 341 Alignment = Attr.getAlignment(); 342 if (Attr.getStackAlignment()) 343 StackAlignment = Attr.getStackAlignment(); 344 return *this; 345} 346 347AttrBuilder &AttrBuilder::removeAttributes(const Attribute &A){ 348 uint64_t Mask = A.Raw(); 349 350 for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds; 351 I = Attribute::AttrKind(I + 1)) { 352 if (Mask & AttributeImpl::getAttrMask(I)) { 353 Attrs.erase(I); 354 355 if (I == Attribute::Alignment) 356 Alignment = 0; 357 else if (I == Attribute::StackAlignment) 358 StackAlignment = 0; 359 } 360 } 361 362 return *this; 363} 364 365bool AttrBuilder::contains(Attribute::AttrKind A) const { 366 return Attrs.count(A); 367} 368 369bool AttrBuilder::hasAttributes() const { 370 return !Attrs.empty(); 371} 372 373bool AttrBuilder::hasAttributes(const Attribute &A) const { 374 return Raw() & A.Raw(); 375} 376 377bool AttrBuilder::hasAlignmentAttr() const { 378 return Alignment != 0; 379} 380 381uint64_t AttrBuilder::Raw() const { 382 uint64_t Mask = 0; 383 384 for (DenseSet<Attribute::AttrKind>::const_iterator I = Attrs.begin(), 385 E = Attrs.end(); I != E; ++I) { 386 Attribute::AttrKind Kind = *I; 387 388 if (Kind == Attribute::Alignment) 389 Mask |= (Log2_32(Alignment) + 1) << 16; 390 else if (Kind == Attribute::StackAlignment) 391 Mask |= (Log2_32(StackAlignment) + 1) << 26; 392 else 393 Mask |= AttributeImpl::getAttrMask(Kind); 394 } 395 396 return Mask; 397} 398 399bool AttrBuilder::operator==(const AttrBuilder &B) { 400 SmallVector<Attribute::AttrKind, 8> This(Attrs.begin(), Attrs.end()); 401 SmallVector<Attribute::AttrKind, 8> That(B.Attrs.begin(), B.Attrs.end()); 402 return This == That; 403} 404 405//===----------------------------------------------------------------------===// 406// AttributeImpl Definition 407//===----------------------------------------------------------------------===// 408 409AttributeImpl::AttributeImpl(LLVMContext &C, uint64_t data) 410 : Context(C) { 411 Data = ConstantInt::get(Type::getInt64Ty(C), data); 412} 413AttributeImpl::AttributeImpl(LLVMContext &C, Attribute::AttrKind data) 414 : Context(C) { 415 Data = ConstantInt::get(Type::getInt64Ty(C), data); 416} 417AttributeImpl::AttributeImpl(LLVMContext &C, Attribute::AttrKind data, 418 ArrayRef<Constant*> values) 419 : Context(C) { 420 Data = ConstantInt::get(Type::getInt64Ty(C), data); 421 Vals.reserve(values.size()); 422 Vals.append(values.begin(), values.end()); 423} 424AttributeImpl::AttributeImpl(LLVMContext &C, StringRef data) 425 : Context(C) { 426 Data = ConstantDataArray::getString(C, data); 427} 428 429bool AttributeImpl::operator==(Attribute::AttrKind Kind) const { 430 if (ConstantInt *CI = dyn_cast<ConstantInt>(Data)) 431 return CI->getZExtValue() == Kind; 432 return false; 433} 434bool AttributeImpl::operator!=(Attribute::AttrKind Kind) const { 435 return !(*this == Kind); 436} 437 438bool AttributeImpl::operator==(StringRef Kind) const { 439 if (ConstantDataArray *CDA = dyn_cast<ConstantDataArray>(Data)) 440 if (CDA->isString()) 441 return CDA->getAsString() == Kind; 442 return false; 443} 444bool AttributeImpl::operator!=(StringRef Kind) const { 445 return !(*this == Kind); 446} 447 448uint64_t AttributeImpl::Raw() const { 449 // FIXME: Remove this. 450 return cast<ConstantInt>(Data)->getZExtValue(); 451} 452 453uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) { 454 switch (Val) { 455 case Attribute::EndAttrKinds: 456 case Attribute::AttrKindEmptyKey: 457 case Attribute::AttrKindTombstoneKey: 458 llvm_unreachable("Synthetic enumerators which should never get here"); 459 460 case Attribute::None: return 0; 461 case Attribute::ZExt: return 1 << 0; 462 case Attribute::SExt: return 1 << 1; 463 case Attribute::NoReturn: return 1 << 2; 464 case Attribute::InReg: return 1 << 3; 465 case Attribute::StructRet: return 1 << 4; 466 case Attribute::NoUnwind: return 1 << 5; 467 case Attribute::NoAlias: return 1 << 6; 468 case Attribute::ByVal: return 1 << 7; 469 case Attribute::Nest: return 1 << 8; 470 case Attribute::ReadNone: return 1 << 9; 471 case Attribute::ReadOnly: return 1 << 10; 472 case Attribute::NoInline: return 1 << 11; 473 case Attribute::AlwaysInline: return 1 << 12; 474 case Attribute::OptimizeForSize: return 1 << 13; 475 case Attribute::StackProtect: return 1 << 14; 476 case Attribute::StackProtectReq: return 1 << 15; 477 case Attribute::Alignment: return 31 << 16; 478 case Attribute::NoCapture: return 1 << 21; 479 case Attribute::NoRedZone: return 1 << 22; 480 case Attribute::NoImplicitFloat: return 1 << 23; 481 case Attribute::Naked: return 1 << 24; 482 case Attribute::InlineHint: return 1 << 25; 483 case Attribute::StackAlignment: return 7 << 26; 484 case Attribute::ReturnsTwice: return 1 << 29; 485 case Attribute::UWTable: return 1 << 30; 486 case Attribute::NonLazyBind: return 1U << 31; 487 case Attribute::AddressSafety: return 1ULL << 32; 488 case Attribute::MinSize: return 1ULL << 33; 489 case Attribute::NoDuplicate: return 1ULL << 34; 490 } 491 llvm_unreachable("Unsupported attribute type"); 492} 493 494bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const { 495 return (Raw() & getAttrMask(A)) != 0; 496} 497 498bool AttributeImpl::hasAttributes() const { 499 return Raw() != 0; 500} 501 502uint64_t AttributeImpl::getAlignment() const { 503 return Raw() & getAttrMask(Attribute::Alignment); 504} 505 506void AttributeImpl::setAlignment(unsigned Align) { 507 Vals.push_back(ConstantInt::get(Type::getInt64Ty(Context), Align)); 508} 509 510uint64_t AttributeImpl::getStackAlignment() const { 511 return Raw() & getAttrMask(Attribute::StackAlignment); 512} 513 514void AttributeImpl::setStackAlignment(unsigned Align) { 515 Vals.push_back(ConstantInt::get(Type::getInt64Ty(Context), Align)); 516} 517 518void AttributeImpl::Profile(FoldingSetNodeID &ID, Constant *Data, 519 ArrayRef<Constant*> Vals) { 520 ID.AddInteger(cast<ConstantInt>(Data)->getZExtValue()); 521#if 0 522 // FIXME: Not yet supported. 523 for (ArrayRef<Constant*>::iterator I = Vals.begin(), E = Vals.end(); 524 I != E; ++I) 525 ID.AddPointer(*I); 526#endif 527} 528 529//===----------------------------------------------------------------------===// 530// AttributeWithIndex Definition 531//===----------------------------------------------------------------------===// 532 533AttributeWithIndex AttributeWithIndex::get(LLVMContext &C, unsigned Idx, 534 AttributeSet AS) { 535 // FIXME: This is temporary, but necessary for the conversion. 536 AttrBuilder B(AS, Idx); 537 return get(Idx, Attribute::get(C, B)); 538} 539 540//===----------------------------------------------------------------------===// 541// AttributeSetImpl Definition 542//===----------------------------------------------------------------------===// 543 544AttributeSet AttributeSet::getParamAttributes(unsigned Idx) const { 545 // FIXME: Remove. 546 return AttrList && hasAttributes(Idx) ? 547 AttributeSet::get(AttrList->getContext(), 548 AttributeWithIndex::get(Idx, getAttributes(Idx))) : 549 AttributeSet(); 550} 551 552AttributeSet AttributeSet::getRetAttributes() const { 553 // FIXME: Remove. 554 return AttrList && hasAttributes(ReturnIndex) ? 555 AttributeSet::get(AttrList->getContext(), 556 AttributeWithIndex::get(ReturnIndex, 557 getAttributes(ReturnIndex))) : 558 AttributeSet(); 559} 560 561AttributeSet AttributeSet::getFnAttributes() const { 562 // FIXME: Remove. 563 return AttrList && hasAttributes(FunctionIndex) ? 564 AttributeSet::get(AttrList->getContext(), 565 AttributeWithIndex::get(FunctionIndex, 566 getAttributes(FunctionIndex))) : 567 AttributeSet(); 568} 569 570AttributeSet AttributeSet::get(LLVMContext &C, 571 ArrayRef<AttributeWithIndex> Attrs) { 572 // If there are no attributes then return a null AttributesList pointer. 573 if (Attrs.empty()) 574 return AttributeSet(); 575 576#ifndef NDEBUG 577 for (unsigned i = 0, e = Attrs.size(); i != e; ++i) { 578 assert(Attrs[i].Attrs.hasAttributes() && 579 "Pointless attribute!"); 580 assert((!i || Attrs[i-1].Index < Attrs[i].Index) && 581 "Misordered AttributesList!"); 582 } 583#endif 584 585 // Otherwise, build a key to look up the existing attributes. 586 LLVMContextImpl *pImpl = C.pImpl; 587 FoldingSetNodeID ID; 588 AttributeSetImpl::Profile(ID, Attrs); 589 590 void *InsertPoint; 591 AttributeSetImpl *PA = pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint); 592 593 // If we didn't find any existing attributes of the same shape then 594 // create a new one and insert it. 595 if (!PA) { 596 PA = new AttributeSetImpl(C, Attrs); 597 pImpl->AttrsLists.InsertNode(PA, InsertPoint); 598 } 599 600 // Return the AttributesList that we found or created. 601 return AttributeSet(PA); 602} 603 604AttributeSet AttributeSet::get(LLVMContext &C, unsigned Idx, AttrBuilder &B) { 605 // FIXME: This should be implemented as a loop that creates the 606 // AttributeWithIndexes that then are used to create the AttributeSet. 607 if (!B.hasAttributes()) 608 return AttributeSet(); 609 return get(C, AttributeWithIndex::get(Idx, Attribute::get(C, B))); 610} 611 612AttributeSet AttributeSet::get(LLVMContext &C, unsigned Idx, 613 Attribute::AttrKind Kind) { 614 return get(C, AttributeWithIndex::get(Idx, Attribute::get(C, Kind))); 615} 616 617//===----------------------------------------------------------------------===// 618// AttributeSet Method Implementations 619//===----------------------------------------------------------------------===// 620 621const AttributeSet &AttributeSet::operator=(const AttributeSet &RHS) { 622 AttrList = RHS.AttrList; 623 return *this; 624} 625 626/// getNumSlots - Return the number of slots used in this attribute list. 627/// This is the number of arguments that have an attribute set on them 628/// (including the function itself). 629unsigned AttributeSet::getNumSlots() const { 630 return AttrList ? AttrList->getNumAttributes() : 0; 631} 632 633/// getSlot - Return the AttributeWithIndex at the specified slot. This 634/// holds a number plus a set of attributes. 635const AttributeWithIndex &AttributeSet::getSlot(unsigned Slot) const { 636 assert(AttrList && Slot < AttrList->getNumAttributes() && 637 "Slot # out of range!"); 638 return AttrList->getAttributes()[Slot]; 639} 640 641bool AttributeSet::hasAttribute(unsigned Index, Attribute::AttrKind Kind) const{ 642 return getAttributes(Index).hasAttribute(Kind); 643} 644 645bool AttributeSet::hasAttributes(unsigned Index) const { 646 return getAttributes(Index).hasAttributes(); 647} 648 649std::string AttributeSet::getAsString(unsigned Index) const { 650 return getAttributes(Index).getAsString(); 651} 652 653unsigned AttributeSet::getParamAlignment(unsigned Idx) const { 654 return getAttributes(Idx).getAlignment(); 655} 656 657unsigned AttributeSet::getStackAlignment(unsigned Index) const { 658 return getAttributes(Index).getStackAlignment(); 659} 660 661uint64_t AttributeSet::Raw(unsigned Index) const { 662 // FIXME: Remove this. 663 return getAttributes(Index).Raw(); 664} 665 666/// getAttributes - The attributes for the specified index are returned. 667Attribute AttributeSet::getAttributes(unsigned Idx) const { 668 if (AttrList == 0) return Attribute(); 669 670 ArrayRef<AttributeWithIndex> Attrs = AttrList->getAttributes(); 671 for (unsigned i = 0, e = Attrs.size(); i != e && Attrs[i].Index <= Idx; ++i) 672 if (Attrs[i].Index == Idx) 673 return Attrs[i].Attrs; 674 675 return Attribute(); 676} 677 678/// hasAttrSomewhere - Return true if the specified attribute is set for at 679/// least one parameter or for the return value. 680bool AttributeSet::hasAttrSomewhere(Attribute::AttrKind Attr) const { 681 if (AttrList == 0) return false; 682 683 ArrayRef<AttributeWithIndex> Attrs = AttrList->getAttributes(); 684 for (unsigned i = 0, e = Attrs.size(); i != e; ++i) 685 if (Attrs[i].Attrs.hasAttribute(Attr)) 686 return true; 687 688 return false; 689} 690 691AttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Idx, 692 Attribute::AttrKind Attr) const { 693 return addAttr(C, Idx, Attribute::get(C, Attr)); 694} 695 696AttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Idx, 697 AttributeSet Attrs) const { 698 return addAttr(C, Idx, Attrs.getAttributes(Idx)); 699} 700 701AttributeSet AttributeSet::addAttr(LLVMContext &C, unsigned Idx, 702 Attribute Attrs) const { 703 Attribute OldAttrs = getAttributes(Idx); 704#ifndef NDEBUG 705 // FIXME it is not obvious how this should work for alignment. 706 // For now, say we can't change a known alignment. 707 unsigned OldAlign = OldAttrs.getAlignment(); 708 unsigned NewAlign = Attrs.getAlignment(); 709 assert((!OldAlign || !NewAlign || OldAlign == NewAlign) && 710 "Attempt to change alignment!"); 711#endif 712 713 AttrBuilder NewAttrs = 714 AttrBuilder(OldAttrs).addAttributes(Attrs); 715 if (NewAttrs == AttrBuilder(OldAttrs)) 716 return *this; 717 718 SmallVector<AttributeWithIndex, 8> NewAttrList; 719 if (AttrList == 0) 720 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs)); 721 else { 722 ArrayRef<AttributeWithIndex> OldAttrList = AttrList->getAttributes(); 723 unsigned i = 0, e = OldAttrList.size(); 724 // Copy attributes for arguments before this one. 725 for (; i != e && OldAttrList[i].Index < Idx; ++i) 726 NewAttrList.push_back(OldAttrList[i]); 727 728 // If there are attributes already at this index, merge them in. 729 if (i != e && OldAttrList[i].Index == Idx) { 730 Attrs = 731 Attribute::get(C, AttrBuilder(Attrs). 732 addAttributes(OldAttrList[i].Attrs)); 733 ++i; 734 } 735 736 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs)); 737 738 // Copy attributes for arguments after this one. 739 NewAttrList.insert(NewAttrList.end(), 740 OldAttrList.begin()+i, OldAttrList.end()); 741 } 742 743 return get(C, NewAttrList); 744} 745 746AttributeSet AttributeSet::removeAttribute(LLVMContext &C, unsigned Idx, 747 Attribute::AttrKind Attr) const { 748 return removeAttr(C, Idx, Attribute::get(C, Attr)); 749} 750 751AttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Idx, 752 AttributeSet Attrs) const { 753 return removeAttr(C, Idx, Attrs.getAttributes(Idx)); 754} 755 756AttributeSet AttributeSet::removeAttr(LLVMContext &C, unsigned Idx, 757 Attribute Attrs) const { 758#ifndef NDEBUG 759 // FIXME it is not obvious how this should work for alignment. 760 // For now, say we can't pass in alignment, which no current use does. 761 assert(!Attrs.hasAttribute(Attribute::Alignment) && 762 "Attempt to exclude alignment!"); 763#endif 764 if (AttrList == 0) return AttributeSet(); 765 766 Attribute OldAttrs = getAttributes(Idx); 767 AttrBuilder NewAttrs = 768 AttrBuilder(OldAttrs).removeAttributes(Attrs); 769 if (NewAttrs == AttrBuilder(OldAttrs)) 770 return *this; 771 772 SmallVector<AttributeWithIndex, 8> NewAttrList; 773 ArrayRef<AttributeWithIndex> OldAttrList = AttrList->getAttributes(); 774 unsigned i = 0, e = OldAttrList.size(); 775 776 // Copy attributes for arguments before this one. 777 for (; i != e && OldAttrList[i].Index < Idx; ++i) 778 NewAttrList.push_back(OldAttrList[i]); 779 780 // If there are attributes already at this index, merge them in. 781 assert(OldAttrList[i].Index == Idx && "Attribute isn't set?"); 782 Attrs = Attribute::get(C, AttrBuilder(OldAttrList[i].Attrs). 783 removeAttributes(Attrs)); 784 ++i; 785 if (Attrs.hasAttributes()) // If any attributes left for this param, add them. 786 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs)); 787 788 // Copy attributes for arguments after this one. 789 NewAttrList.insert(NewAttrList.end(), 790 OldAttrList.begin()+i, OldAttrList.end()); 791 792 return get(C, NewAttrList); 793} 794 795void AttributeSet::dump() const { 796 dbgs() << "PAL[ "; 797 for (unsigned i = 0; i < getNumSlots(); ++i) { 798 const AttributeWithIndex &PAWI = getSlot(i); 799 dbgs() << "{ " << PAWI.Index << ", " << PAWI.Attrs.getAsString() << " } "; 800 } 801 802 dbgs() << "]\n"; 803} 804