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