1249259Sdim//===-- Attributes.cpp - Implement AttributesList -------------------------===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim// 10249259Sdim// \file 11249259Sdim// \brief This file implements the Attribute, AttributeImpl, AttrBuilder, 12249259Sdim// AttributeSetImpl, and AttributeSet classes. 13249259Sdim// 14249259Sdim//===----------------------------------------------------------------------===// 15249259Sdim 16249259Sdim#include "llvm/IR/Attributes.h" 17249259Sdim#include "AttributeImpl.h" 18249259Sdim#include "LLVMContextImpl.h" 19249259Sdim#include "llvm/ADT/StringExtras.h" 20249259Sdim#include "llvm/IR/Type.h" 21249259Sdim#include "llvm/Support/Atomic.h" 22249259Sdim#include "llvm/Support/Debug.h" 23249259Sdim#include "llvm/Support/ManagedStatic.h" 24249259Sdim#include "llvm/Support/Mutex.h" 25249259Sdim#include "llvm/Support/raw_ostream.h" 26249259Sdim#include <algorithm> 27249259Sdimusing namespace llvm; 28249259Sdim 29249259Sdim//===----------------------------------------------------------------------===// 30249259Sdim// Attribute Construction Methods 31249259Sdim//===----------------------------------------------------------------------===// 32249259Sdim 33249259SdimAttribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind, 34249259Sdim uint64_t Val) { 35249259Sdim LLVMContextImpl *pImpl = Context.pImpl; 36249259Sdim FoldingSetNodeID ID; 37249259Sdim ID.AddInteger(Kind); 38249259Sdim if (Val) ID.AddInteger(Val); 39249259Sdim 40249259Sdim void *InsertPoint; 41249259Sdim AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint); 42249259Sdim 43249259Sdim if (!PA) { 44249259Sdim // If we didn't find any existing attributes of the same shape then create a 45249259Sdim // new one and insert it. 46263508Sdim if (!Val) 47263508Sdim PA = new EnumAttributeImpl(Kind); 48263508Sdim else 49263508Sdim PA = new AlignAttributeImpl(Kind, Val); 50249259Sdim pImpl->AttrsSet.InsertNode(PA, InsertPoint); 51249259Sdim } 52249259Sdim 53249259Sdim // Return the Attribute that we found or created. 54249259Sdim return Attribute(PA); 55249259Sdim} 56249259Sdim 57249259SdimAttribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) { 58249259Sdim LLVMContextImpl *pImpl = Context.pImpl; 59249259Sdim FoldingSetNodeID ID; 60249259Sdim ID.AddString(Kind); 61249259Sdim if (!Val.empty()) ID.AddString(Val); 62249259Sdim 63249259Sdim void *InsertPoint; 64249259Sdim AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint); 65249259Sdim 66249259Sdim if (!PA) { 67249259Sdim // If we didn't find any existing attributes of the same shape then create a 68249259Sdim // new one and insert it. 69263508Sdim PA = new StringAttributeImpl(Kind, Val); 70249259Sdim pImpl->AttrsSet.InsertNode(PA, InsertPoint); 71249259Sdim } 72249259Sdim 73249259Sdim // Return the Attribute that we found or created. 74249259Sdim return Attribute(PA); 75249259Sdim} 76249259Sdim 77249259SdimAttribute Attribute::getWithAlignment(LLVMContext &Context, uint64_t Align) { 78249259Sdim assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); 79249259Sdim assert(Align <= 0x40000000 && "Alignment too large."); 80249259Sdim return get(Context, Alignment, Align); 81249259Sdim} 82249259Sdim 83249259SdimAttribute Attribute::getWithStackAlignment(LLVMContext &Context, 84249259Sdim uint64_t Align) { 85249259Sdim assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); 86249259Sdim assert(Align <= 0x100 && "Alignment too large."); 87249259Sdim return get(Context, StackAlignment, Align); 88249259Sdim} 89249259Sdim 90249259Sdim//===----------------------------------------------------------------------===// 91249259Sdim// Attribute Accessor Methods 92249259Sdim//===----------------------------------------------------------------------===// 93249259Sdim 94249259Sdimbool Attribute::isEnumAttribute() const { 95249259Sdim return pImpl && pImpl->isEnumAttribute(); 96249259Sdim} 97249259Sdim 98249259Sdimbool Attribute::isAlignAttribute() const { 99249259Sdim return pImpl && pImpl->isAlignAttribute(); 100249259Sdim} 101249259Sdim 102249259Sdimbool Attribute::isStringAttribute() const { 103249259Sdim return pImpl && pImpl->isStringAttribute(); 104249259Sdim} 105249259Sdim 106249259SdimAttribute::AttrKind Attribute::getKindAsEnum() const { 107263508Sdim if (!pImpl) return None; 108249259Sdim assert((isEnumAttribute() || isAlignAttribute()) && 109249259Sdim "Invalid attribute type to get the kind as an enum!"); 110249259Sdim return pImpl ? pImpl->getKindAsEnum() : None; 111249259Sdim} 112249259Sdim 113249259Sdimuint64_t Attribute::getValueAsInt() const { 114263508Sdim if (!pImpl) return 0; 115249259Sdim assert(isAlignAttribute() && 116249259Sdim "Expected the attribute to be an alignment attribute!"); 117249259Sdim return pImpl ? pImpl->getValueAsInt() : 0; 118249259Sdim} 119249259Sdim 120249259SdimStringRef Attribute::getKindAsString() const { 121263508Sdim if (!pImpl) return StringRef(); 122249259Sdim assert(isStringAttribute() && 123249259Sdim "Invalid attribute type to get the kind as a string!"); 124249259Sdim return pImpl ? pImpl->getKindAsString() : StringRef(); 125249259Sdim} 126249259Sdim 127249259SdimStringRef Attribute::getValueAsString() const { 128263508Sdim if (!pImpl) return StringRef(); 129249259Sdim assert(isStringAttribute() && 130249259Sdim "Invalid attribute type to get the value as a string!"); 131249259Sdim return pImpl ? pImpl->getValueAsString() : StringRef(); 132249259Sdim} 133249259Sdim 134249259Sdimbool Attribute::hasAttribute(AttrKind Kind) const { 135249259Sdim return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None); 136249259Sdim} 137249259Sdim 138249259Sdimbool Attribute::hasAttribute(StringRef Kind) const { 139249259Sdim if (!isStringAttribute()) return false; 140249259Sdim return pImpl && pImpl->hasAttribute(Kind); 141249259Sdim} 142249259Sdim 143249259Sdim/// This returns the alignment field of an attribute as a byte alignment value. 144249259Sdimunsigned Attribute::getAlignment() const { 145249259Sdim assert(hasAttribute(Attribute::Alignment) && 146249259Sdim "Trying to get alignment from non-alignment attribute!"); 147249259Sdim return pImpl->getValueAsInt(); 148249259Sdim} 149249259Sdim 150249259Sdim/// This returns the stack alignment field of an attribute as a byte alignment 151249259Sdim/// value. 152249259Sdimunsigned Attribute::getStackAlignment() const { 153249259Sdim assert(hasAttribute(Attribute::StackAlignment) && 154249259Sdim "Trying to get alignment from non-alignment attribute!"); 155249259Sdim return pImpl->getValueAsInt(); 156249259Sdim} 157249259Sdim 158249259Sdimstd::string Attribute::getAsString(bool InAttrGrp) const { 159249259Sdim if (!pImpl) return ""; 160249259Sdim 161249259Sdim if (hasAttribute(Attribute::SanitizeAddress)) 162249259Sdim return "sanitize_address"; 163249259Sdim if (hasAttribute(Attribute::AlwaysInline)) 164249259Sdim return "alwaysinline"; 165263508Sdim if (hasAttribute(Attribute::Builtin)) 166263508Sdim return "builtin"; 167249259Sdim if (hasAttribute(Attribute::ByVal)) 168249259Sdim return "byval"; 169249259Sdim if (hasAttribute(Attribute::InlineHint)) 170249259Sdim return "inlinehint"; 171249259Sdim if (hasAttribute(Attribute::InReg)) 172249259Sdim return "inreg"; 173249259Sdim if (hasAttribute(Attribute::MinSize)) 174249259Sdim return "minsize"; 175249259Sdim if (hasAttribute(Attribute::Naked)) 176249259Sdim return "naked"; 177249259Sdim if (hasAttribute(Attribute::Nest)) 178249259Sdim return "nest"; 179249259Sdim if (hasAttribute(Attribute::NoAlias)) 180249259Sdim return "noalias"; 181249259Sdim if (hasAttribute(Attribute::NoBuiltin)) 182249259Sdim return "nobuiltin"; 183249259Sdim if (hasAttribute(Attribute::NoCapture)) 184249259Sdim return "nocapture"; 185249259Sdim if (hasAttribute(Attribute::NoDuplicate)) 186249259Sdim return "noduplicate"; 187249259Sdim if (hasAttribute(Attribute::NoImplicitFloat)) 188249259Sdim return "noimplicitfloat"; 189249259Sdim if (hasAttribute(Attribute::NoInline)) 190249259Sdim return "noinline"; 191249259Sdim if (hasAttribute(Attribute::NonLazyBind)) 192249259Sdim return "nonlazybind"; 193249259Sdim if (hasAttribute(Attribute::NoRedZone)) 194249259Sdim return "noredzone"; 195249259Sdim if (hasAttribute(Attribute::NoReturn)) 196249259Sdim return "noreturn"; 197249259Sdim if (hasAttribute(Attribute::NoUnwind)) 198249259Sdim return "nounwind"; 199263508Sdim if (hasAttribute(Attribute::OptimizeNone)) 200263508Sdim return "optnone"; 201249259Sdim if (hasAttribute(Attribute::OptimizeForSize)) 202249259Sdim return "optsize"; 203249259Sdim if (hasAttribute(Attribute::ReadNone)) 204249259Sdim return "readnone"; 205249259Sdim if (hasAttribute(Attribute::ReadOnly)) 206249259Sdim return "readonly"; 207251662Sdim if (hasAttribute(Attribute::Returned)) 208251662Sdim return "returned"; 209249259Sdim if (hasAttribute(Attribute::ReturnsTwice)) 210249259Sdim return "returns_twice"; 211249259Sdim if (hasAttribute(Attribute::SExt)) 212249259Sdim return "signext"; 213249259Sdim if (hasAttribute(Attribute::StackProtect)) 214249259Sdim return "ssp"; 215249259Sdim if (hasAttribute(Attribute::StackProtectReq)) 216249259Sdim return "sspreq"; 217249259Sdim if (hasAttribute(Attribute::StackProtectStrong)) 218249259Sdim return "sspstrong"; 219249259Sdim if (hasAttribute(Attribute::StructRet)) 220249259Sdim return "sret"; 221249259Sdim if (hasAttribute(Attribute::SanitizeThread)) 222249259Sdim return "sanitize_thread"; 223249259Sdim if (hasAttribute(Attribute::SanitizeMemory)) 224249259Sdim return "sanitize_memory"; 225249259Sdim if (hasAttribute(Attribute::UWTable)) 226249259Sdim return "uwtable"; 227249259Sdim if (hasAttribute(Attribute::ZExt)) 228249259Sdim return "zeroext"; 229263508Sdim if (hasAttribute(Attribute::Cold)) 230263508Sdim return "cold"; 231249259Sdim 232249259Sdim // FIXME: These should be output like this: 233249259Sdim // 234249259Sdim // align=4 235249259Sdim // alignstack=8 236249259Sdim // 237249259Sdim if (hasAttribute(Attribute::Alignment)) { 238249259Sdim std::string Result; 239249259Sdim Result += "align"; 240249259Sdim Result += (InAttrGrp) ? "=" : " "; 241249259Sdim Result += utostr(getValueAsInt()); 242249259Sdim return Result; 243249259Sdim } 244249259Sdim 245249259Sdim if (hasAttribute(Attribute::StackAlignment)) { 246249259Sdim std::string Result; 247249259Sdim Result += "alignstack"; 248249259Sdim if (InAttrGrp) { 249249259Sdim Result += "="; 250249259Sdim Result += utostr(getValueAsInt()); 251249259Sdim } else { 252249259Sdim Result += "("; 253249259Sdim Result += utostr(getValueAsInt()); 254249259Sdim Result += ")"; 255249259Sdim } 256249259Sdim return Result; 257249259Sdim } 258249259Sdim 259249259Sdim // Convert target-dependent attributes to strings of the form: 260249259Sdim // 261249259Sdim // "kind" 262249259Sdim // "kind" = "value" 263249259Sdim // 264249259Sdim if (isStringAttribute()) { 265249259Sdim std::string Result; 266249259Sdim Result += '\"' + getKindAsString().str() + '"'; 267249259Sdim 268249259Sdim StringRef Val = pImpl->getValueAsString(); 269249259Sdim if (Val.empty()) return Result; 270249259Sdim 271249259Sdim Result += "=\"" + Val.str() + '"'; 272249259Sdim return Result; 273249259Sdim } 274249259Sdim 275249259Sdim llvm_unreachable("Unknown attribute"); 276249259Sdim} 277249259Sdim 278249259Sdimbool Attribute::operator<(Attribute A) const { 279249259Sdim if (!pImpl && !A.pImpl) return false; 280249259Sdim if (!pImpl) return true; 281249259Sdim if (!A.pImpl) return false; 282249259Sdim return *pImpl < *A.pImpl; 283249259Sdim} 284249259Sdim 285249259Sdim//===----------------------------------------------------------------------===// 286249259Sdim// AttributeImpl Definition 287249259Sdim//===----------------------------------------------------------------------===// 288249259Sdim 289263508Sdim// Pin the vtabels to this file. 290263508SdimAttributeImpl::~AttributeImpl() {} 291263508Sdimvoid EnumAttributeImpl::anchor() {} 292263508Sdimvoid AlignAttributeImpl::anchor() {} 293263508Sdimvoid StringAttributeImpl::anchor() {} 294249259Sdim 295249259Sdimbool AttributeImpl::hasAttribute(Attribute::AttrKind A) const { 296249259Sdim if (isStringAttribute()) return false; 297249259Sdim return getKindAsEnum() == A; 298249259Sdim} 299249259Sdim 300249259Sdimbool AttributeImpl::hasAttribute(StringRef Kind) const { 301249259Sdim if (!isStringAttribute()) return false; 302249259Sdim return getKindAsString() == Kind; 303249259Sdim} 304249259Sdim 305249259SdimAttribute::AttrKind AttributeImpl::getKindAsEnum() const { 306263508Sdim assert(isEnumAttribute() || isAlignAttribute()); 307263508Sdim return static_cast<const EnumAttributeImpl *>(this)->getEnumKind(); 308249259Sdim} 309249259Sdim 310249259Sdimuint64_t AttributeImpl::getValueAsInt() const { 311263508Sdim assert(isAlignAttribute()); 312263508Sdim return static_cast<const AlignAttributeImpl *>(this)->getAlignment(); 313249259Sdim} 314249259Sdim 315249259SdimStringRef AttributeImpl::getKindAsString() const { 316263508Sdim assert(isStringAttribute()); 317263508Sdim return static_cast<const StringAttributeImpl *>(this)->getStringKind(); 318249259Sdim} 319249259Sdim 320249259SdimStringRef AttributeImpl::getValueAsString() const { 321263508Sdim assert(isStringAttribute()); 322263508Sdim return static_cast<const StringAttributeImpl *>(this)->getStringValue(); 323249259Sdim} 324249259Sdim 325249259Sdimbool AttributeImpl::operator<(const AttributeImpl &AI) const { 326249259Sdim // This sorts the attributes with Attribute::AttrKinds coming first (sorted 327249259Sdim // relative to their enum value) and then strings. 328249259Sdim if (isEnumAttribute()) { 329249259Sdim if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum(); 330249259Sdim if (AI.isAlignAttribute()) return true; 331249259Sdim if (AI.isStringAttribute()) return true; 332249259Sdim } 333249259Sdim 334249259Sdim if (isAlignAttribute()) { 335249259Sdim if (AI.isEnumAttribute()) return false; 336249259Sdim if (AI.isAlignAttribute()) return getValueAsInt() < AI.getValueAsInt(); 337249259Sdim if (AI.isStringAttribute()) return true; 338249259Sdim } 339249259Sdim 340249259Sdim if (AI.isEnumAttribute()) return false; 341249259Sdim if (AI.isAlignAttribute()) return false; 342249259Sdim if (getKindAsString() == AI.getKindAsString()) 343249259Sdim return getValueAsString() < AI.getValueAsString(); 344249259Sdim return getKindAsString() < AI.getKindAsString(); 345249259Sdim} 346249259Sdim 347249259Sdimuint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) { 348249259Sdim // FIXME: Remove this. 349249259Sdim switch (Val) { 350249259Sdim case Attribute::EndAttrKinds: 351249259Sdim llvm_unreachable("Synthetic enumerators which should never get here"); 352249259Sdim 353249259Sdim case Attribute::None: return 0; 354249259Sdim case Attribute::ZExt: return 1 << 0; 355249259Sdim case Attribute::SExt: return 1 << 1; 356249259Sdim case Attribute::NoReturn: return 1 << 2; 357249259Sdim case Attribute::InReg: return 1 << 3; 358249259Sdim case Attribute::StructRet: return 1 << 4; 359249259Sdim case Attribute::NoUnwind: return 1 << 5; 360249259Sdim case Attribute::NoAlias: return 1 << 6; 361249259Sdim case Attribute::ByVal: return 1 << 7; 362249259Sdim case Attribute::Nest: return 1 << 8; 363249259Sdim case Attribute::ReadNone: return 1 << 9; 364249259Sdim case Attribute::ReadOnly: return 1 << 10; 365249259Sdim case Attribute::NoInline: return 1 << 11; 366249259Sdim case Attribute::AlwaysInline: return 1 << 12; 367249259Sdim case Attribute::OptimizeForSize: return 1 << 13; 368249259Sdim case Attribute::StackProtect: return 1 << 14; 369249259Sdim case Attribute::StackProtectReq: return 1 << 15; 370249259Sdim case Attribute::Alignment: return 31 << 16; 371249259Sdim case Attribute::NoCapture: return 1 << 21; 372249259Sdim case Attribute::NoRedZone: return 1 << 22; 373249259Sdim case Attribute::NoImplicitFloat: return 1 << 23; 374249259Sdim case Attribute::Naked: return 1 << 24; 375249259Sdim case Attribute::InlineHint: return 1 << 25; 376249259Sdim case Attribute::StackAlignment: return 7 << 26; 377249259Sdim case Attribute::ReturnsTwice: return 1 << 29; 378249259Sdim case Attribute::UWTable: return 1 << 30; 379249259Sdim case Attribute::NonLazyBind: return 1U << 31; 380249259Sdim case Attribute::SanitizeAddress: return 1ULL << 32; 381249259Sdim case Attribute::MinSize: return 1ULL << 33; 382249259Sdim case Attribute::NoDuplicate: return 1ULL << 34; 383249259Sdim case Attribute::StackProtectStrong: return 1ULL << 35; 384249259Sdim case Attribute::SanitizeThread: return 1ULL << 36; 385249259Sdim case Attribute::SanitizeMemory: return 1ULL << 37; 386249259Sdim case Attribute::NoBuiltin: return 1ULL << 38; 387251662Sdim case Attribute::Returned: return 1ULL << 39; 388263508Sdim case Attribute::Cold: return 1ULL << 40; 389263508Sdim case Attribute::Builtin: return 1ULL << 41; 390263508Sdim case Attribute::OptimizeNone: return 1ULL << 42; 391249259Sdim } 392249259Sdim llvm_unreachable("Unsupported attribute type"); 393249259Sdim} 394249259Sdim 395249259Sdim//===----------------------------------------------------------------------===// 396249259Sdim// AttributeSetNode Definition 397249259Sdim//===----------------------------------------------------------------------===// 398249259Sdim 399249259SdimAttributeSetNode *AttributeSetNode::get(LLVMContext &C, 400249259Sdim ArrayRef<Attribute> Attrs) { 401249259Sdim if (Attrs.empty()) 402249259Sdim return 0; 403249259Sdim 404249259Sdim // Otherwise, build a key to look up the existing attributes. 405249259Sdim LLVMContextImpl *pImpl = C.pImpl; 406249259Sdim FoldingSetNodeID ID; 407249259Sdim 408249259Sdim SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end()); 409249259Sdim array_pod_sort(SortedAttrs.begin(), SortedAttrs.end()); 410249259Sdim 411249259Sdim for (SmallVectorImpl<Attribute>::iterator I = SortedAttrs.begin(), 412249259Sdim E = SortedAttrs.end(); I != E; ++I) 413249259Sdim I->Profile(ID); 414249259Sdim 415249259Sdim void *InsertPoint; 416249259Sdim AttributeSetNode *PA = 417249259Sdim pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint); 418249259Sdim 419249259Sdim // If we didn't find any existing attributes of the same shape then create a 420249259Sdim // new one and insert it. 421249259Sdim if (!PA) { 422263508Sdim // Coallocate entries after the AttributeSetNode itself. 423263508Sdim void *Mem = ::operator new(sizeof(AttributeSetNode) + 424263508Sdim sizeof(Attribute) * SortedAttrs.size()); 425263508Sdim PA = new (Mem) AttributeSetNode(SortedAttrs); 426249259Sdim pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint); 427249259Sdim } 428249259Sdim 429249259Sdim // Return the AttributesListNode that we found or created. 430249259Sdim return PA; 431249259Sdim} 432249259Sdim 433249259Sdimbool AttributeSetNode::hasAttribute(Attribute::AttrKind Kind) const { 434263508Sdim for (iterator I = begin(), E = end(); I != E; ++I) 435249259Sdim if (I->hasAttribute(Kind)) 436249259Sdim return true; 437249259Sdim return false; 438249259Sdim} 439249259Sdim 440249259Sdimbool AttributeSetNode::hasAttribute(StringRef Kind) const { 441263508Sdim for (iterator I = begin(), E = end(); I != E; ++I) 442249259Sdim if (I->hasAttribute(Kind)) 443249259Sdim return true; 444249259Sdim return false; 445249259Sdim} 446249259Sdim 447249259SdimAttribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const { 448263508Sdim for (iterator I = begin(), E = end(); I != E; ++I) 449249259Sdim if (I->hasAttribute(Kind)) 450249259Sdim return *I; 451249259Sdim return Attribute(); 452249259Sdim} 453249259Sdim 454249259SdimAttribute AttributeSetNode::getAttribute(StringRef Kind) const { 455263508Sdim for (iterator I = begin(), E = end(); I != E; ++I) 456249259Sdim if (I->hasAttribute(Kind)) 457249259Sdim return *I; 458249259Sdim return Attribute(); 459249259Sdim} 460249259Sdim 461249259Sdimunsigned AttributeSetNode::getAlignment() const { 462263508Sdim for (iterator I = begin(), E = end(); I != E; ++I) 463249259Sdim if (I->hasAttribute(Attribute::Alignment)) 464249259Sdim return I->getAlignment(); 465249259Sdim return 0; 466249259Sdim} 467249259Sdim 468249259Sdimunsigned AttributeSetNode::getStackAlignment() const { 469263508Sdim for (iterator I = begin(), E = end(); I != E; ++I) 470249259Sdim if (I->hasAttribute(Attribute::StackAlignment)) 471249259Sdim return I->getStackAlignment(); 472249259Sdim return 0; 473249259Sdim} 474249259Sdim 475249259Sdimstd::string AttributeSetNode::getAsString(bool InAttrGrp) const { 476251662Sdim std::string Str; 477263508Sdim for (iterator I = begin(), E = end(); I != E; ++I) { 478263508Sdim if (I != begin()) 479251662Sdim Str += ' '; 480249259Sdim Str += I->getAsString(InAttrGrp); 481249259Sdim } 482249259Sdim return Str; 483249259Sdim} 484249259Sdim 485249259Sdim//===----------------------------------------------------------------------===// 486249259Sdim// AttributeSetImpl Definition 487249259Sdim//===----------------------------------------------------------------------===// 488249259Sdim 489251662Sdimuint64_t AttributeSetImpl::Raw(unsigned Index) const { 490249259Sdim for (unsigned I = 0, E = getNumAttributes(); I != E; ++I) { 491249259Sdim if (getSlotIndex(I) != Index) continue; 492263508Sdim const AttributeSetNode *ASN = getSlotNode(I); 493249259Sdim uint64_t Mask = 0; 494249259Sdim 495263508Sdim for (AttributeSetNode::iterator II = ASN->begin(), 496249259Sdim IE = ASN->end(); II != IE; ++II) { 497249259Sdim Attribute Attr = *II; 498249259Sdim 499249259Sdim // This cannot handle string attributes. 500249259Sdim if (Attr.isStringAttribute()) continue; 501249259Sdim 502249259Sdim Attribute::AttrKind Kind = Attr.getKindAsEnum(); 503249259Sdim 504249259Sdim if (Kind == Attribute::Alignment) 505249259Sdim Mask |= (Log2_32(ASN->getAlignment()) + 1) << 16; 506249259Sdim else if (Kind == Attribute::StackAlignment) 507249259Sdim Mask |= (Log2_32(ASN->getStackAlignment()) + 1) << 26; 508249259Sdim else 509249259Sdim Mask |= AttributeImpl::getAttrMask(Kind); 510249259Sdim } 511249259Sdim 512249259Sdim return Mask; 513249259Sdim } 514249259Sdim 515249259Sdim return 0; 516249259Sdim} 517249259Sdim 518263508Sdimvoid AttributeSetImpl::dump() const { 519263508Sdim AttributeSet(const_cast<AttributeSetImpl *>(this)).dump(); 520263508Sdim} 521263508Sdim 522249259Sdim//===----------------------------------------------------------------------===// 523249259Sdim// AttributeSet Construction and Mutation Methods 524249259Sdim//===----------------------------------------------------------------------===// 525249259Sdim 526249259SdimAttributeSet 527249259SdimAttributeSet::getImpl(LLVMContext &C, 528249259Sdim ArrayRef<std::pair<unsigned, AttributeSetNode*> > Attrs) { 529249259Sdim LLVMContextImpl *pImpl = C.pImpl; 530249259Sdim FoldingSetNodeID ID; 531249259Sdim AttributeSetImpl::Profile(ID, Attrs); 532249259Sdim 533249259Sdim void *InsertPoint; 534249259Sdim AttributeSetImpl *PA = pImpl->AttrsLists.FindNodeOrInsertPos(ID, InsertPoint); 535249259Sdim 536249259Sdim // If we didn't find any existing attributes of the same shape then 537249259Sdim // create a new one and insert it. 538249259Sdim if (!PA) { 539263508Sdim // Coallocate entries after the AttributeSetImpl itself. 540263508Sdim void *Mem = ::operator new(sizeof(AttributeSetImpl) + 541263508Sdim sizeof(std::pair<unsigned, AttributeSetNode *>) * 542263508Sdim Attrs.size()); 543263508Sdim PA = new (Mem) AttributeSetImpl(C, Attrs); 544249259Sdim pImpl->AttrsLists.InsertNode(PA, InsertPoint); 545249259Sdim } 546249259Sdim 547249259Sdim // Return the AttributesList that we found or created. 548249259Sdim return AttributeSet(PA); 549249259Sdim} 550249259Sdim 551249259SdimAttributeSet AttributeSet::get(LLVMContext &C, 552249259Sdim ArrayRef<std::pair<unsigned, Attribute> > Attrs){ 553249259Sdim // If there are no attributes then return a null AttributesList pointer. 554249259Sdim if (Attrs.empty()) 555249259Sdim return AttributeSet(); 556249259Sdim 557249259Sdim#ifndef NDEBUG 558249259Sdim for (unsigned i = 0, e = Attrs.size(); i != e; ++i) { 559249259Sdim assert((!i || Attrs[i-1].first <= Attrs[i].first) && 560249259Sdim "Misordered Attributes list!"); 561249259Sdim assert(!Attrs[i].second.hasAttribute(Attribute::None) && 562249259Sdim "Pointless attribute!"); 563249259Sdim } 564249259Sdim#endif 565249259Sdim 566249259Sdim // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes 567249259Sdim // list. 568249259Sdim SmallVector<std::pair<unsigned, AttributeSetNode*>, 8> AttrPairVec; 569249259Sdim for (ArrayRef<std::pair<unsigned, Attribute> >::iterator I = Attrs.begin(), 570249259Sdim E = Attrs.end(); I != E; ) { 571249259Sdim unsigned Index = I->first; 572249259Sdim SmallVector<Attribute, 4> AttrVec; 573249259Sdim while (I != E && I->first == Index) { 574249259Sdim AttrVec.push_back(I->second); 575249259Sdim ++I; 576249259Sdim } 577249259Sdim 578249259Sdim AttrPairVec.push_back(std::make_pair(Index, 579249259Sdim AttributeSetNode::get(C, AttrVec))); 580249259Sdim } 581249259Sdim 582249259Sdim return getImpl(C, AttrPairVec); 583249259Sdim} 584249259Sdim 585249259SdimAttributeSet AttributeSet::get(LLVMContext &C, 586249259Sdim ArrayRef<std::pair<unsigned, 587249259Sdim AttributeSetNode*> > Attrs) { 588249259Sdim // If there are no attributes then return a null AttributesList pointer. 589249259Sdim if (Attrs.empty()) 590249259Sdim return AttributeSet(); 591249259Sdim 592249259Sdim return getImpl(C, Attrs); 593249259Sdim} 594249259Sdim 595251662SdimAttributeSet AttributeSet::get(LLVMContext &C, unsigned Index, AttrBuilder &B) { 596249259Sdim if (!B.hasAttributes()) 597249259Sdim return AttributeSet(); 598249259Sdim 599249259Sdim // Add target-independent attributes. 600249259Sdim SmallVector<std::pair<unsigned, Attribute>, 8> Attrs; 601249259Sdim for (Attribute::AttrKind Kind = Attribute::None; 602249259Sdim Kind != Attribute::EndAttrKinds; Kind = Attribute::AttrKind(Kind + 1)) { 603249259Sdim if (!B.contains(Kind)) 604249259Sdim continue; 605249259Sdim 606249259Sdim if (Kind == Attribute::Alignment) 607251662Sdim Attrs.push_back(std::make_pair(Index, Attribute:: 608249259Sdim getWithAlignment(C, B.getAlignment()))); 609249259Sdim else if (Kind == Attribute::StackAlignment) 610251662Sdim Attrs.push_back(std::make_pair(Index, Attribute:: 611249259Sdim getWithStackAlignment(C, B.getStackAlignment()))); 612249259Sdim else 613251662Sdim Attrs.push_back(std::make_pair(Index, Attribute::get(C, Kind))); 614249259Sdim } 615249259Sdim 616249259Sdim // Add target-dependent (string) attributes. 617249259Sdim for (AttrBuilder::td_iterator I = B.td_begin(), E = B.td_end(); 618249259Sdim I != E; ++I) 619251662Sdim Attrs.push_back(std::make_pair(Index, Attribute::get(C, I->first,I->second))); 620249259Sdim 621249259Sdim return get(C, Attrs); 622249259Sdim} 623249259Sdim 624251662SdimAttributeSet AttributeSet::get(LLVMContext &C, unsigned Index, 625249259Sdim ArrayRef<Attribute::AttrKind> Kind) { 626249259Sdim SmallVector<std::pair<unsigned, Attribute>, 8> Attrs; 627249259Sdim for (ArrayRef<Attribute::AttrKind>::iterator I = Kind.begin(), 628249259Sdim E = Kind.end(); I != E; ++I) 629251662Sdim Attrs.push_back(std::make_pair(Index, Attribute::get(C, *I))); 630249259Sdim return get(C, Attrs); 631249259Sdim} 632249259Sdim 633249259SdimAttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<AttributeSet> Attrs) { 634249259Sdim if (Attrs.empty()) return AttributeSet(); 635263508Sdim if (Attrs.size() == 1) return Attrs[0]; 636249259Sdim 637249259Sdim SmallVector<std::pair<unsigned, AttributeSetNode*>, 8> AttrNodeVec; 638263508Sdim AttributeSetImpl *A0 = Attrs[0].pImpl; 639263508Sdim if (A0) 640263508Sdim AttrNodeVec.append(A0->getNode(0), A0->getNode(A0->getNumAttributes())); 641263508Sdim // Copy all attributes from Attrs into AttrNodeVec while keeping AttrNodeVec 642263508Sdim // ordered by index. Because we know that each list in Attrs is ordered by 643263508Sdim // index we only need to merge each successive list in rather than doing a 644263508Sdim // full sort. 645263508Sdim for (unsigned I = 1, E = Attrs.size(); I != E; ++I) { 646263508Sdim AttributeSetImpl *AS = Attrs[I].pImpl; 647263508Sdim if (!AS) continue; 648263508Sdim SmallVector<std::pair<unsigned, AttributeSetNode *>, 8>::iterator 649263508Sdim ANVI = AttrNodeVec.begin(), ANVE; 650263508Sdim for (const AttributeSetImpl::IndexAttrPair 651263508Sdim *AI = AS->getNode(0), 652263508Sdim *AE = AS->getNode(AS->getNumAttributes()); 653263508Sdim AI != AE; ++AI) { 654263508Sdim ANVE = AttrNodeVec.end(); 655263508Sdim while (ANVI != ANVE && ANVI->first <= AI->first) 656263508Sdim ++ANVI; 657263508Sdim ANVI = AttrNodeVec.insert(ANVI, *AI) + 1; 658263508Sdim } 659249259Sdim } 660249259Sdim 661249259Sdim return getImpl(C, AttrNodeVec); 662249259Sdim} 663249259Sdim 664251662SdimAttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index, 665249259Sdim Attribute::AttrKind Attr) const { 666251662Sdim if (hasAttribute(Index, Attr)) return *this; 667251662Sdim return addAttributes(C, Index, AttributeSet::get(C, Index, Attr)); 668249259Sdim} 669249259Sdim 670251662SdimAttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index, 671249259Sdim StringRef Kind) const { 672249259Sdim llvm::AttrBuilder B; 673249259Sdim B.addAttribute(Kind); 674251662Sdim return addAttributes(C, Index, AttributeSet::get(C, Index, B)); 675249259Sdim} 676249259Sdim 677263508SdimAttributeSet AttributeSet::addAttribute(LLVMContext &C, unsigned Index, 678263508Sdim StringRef Kind, StringRef Value) const { 679263508Sdim llvm::AttrBuilder B; 680263508Sdim B.addAttribute(Kind, Value); 681263508Sdim return addAttributes(C, Index, AttributeSet::get(C, Index, B)); 682263508Sdim} 683263508Sdim 684251662SdimAttributeSet AttributeSet::addAttributes(LLVMContext &C, unsigned Index, 685249259Sdim AttributeSet Attrs) const { 686249259Sdim if (!pImpl) return Attrs; 687249259Sdim if (!Attrs.pImpl) return *this; 688249259Sdim 689249259Sdim#ifndef NDEBUG 690249259Sdim // FIXME it is not obvious how this should work for alignment. For now, say 691249259Sdim // we can't change a known alignment. 692251662Sdim unsigned OldAlign = getParamAlignment(Index); 693251662Sdim unsigned NewAlign = Attrs.getParamAlignment(Index); 694249259Sdim assert((!OldAlign || !NewAlign || OldAlign == NewAlign) && 695249259Sdim "Attempt to change alignment!"); 696249259Sdim#endif 697249259Sdim 698249259Sdim // Add the attribute slots before the one we're trying to add. 699249259Sdim SmallVector<AttributeSet, 4> AttrSet; 700249259Sdim uint64_t NumAttrs = pImpl->getNumAttributes(); 701249259Sdim AttributeSet AS; 702249259Sdim uint64_t LastIndex = 0; 703249259Sdim for (unsigned I = 0, E = NumAttrs; I != E; ++I) { 704251662Sdim if (getSlotIndex(I) >= Index) { 705251662Sdim if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++); 706249259Sdim break; 707249259Sdim } 708249259Sdim LastIndex = I + 1; 709249259Sdim AttrSet.push_back(getSlotAttributes(I)); 710249259Sdim } 711249259Sdim 712249259Sdim // Now add the attribute into the correct slot. There may already be an 713249259Sdim // AttributeSet there. 714251662Sdim AttrBuilder B(AS, Index); 715249259Sdim 716249259Sdim for (unsigned I = 0, E = Attrs.pImpl->getNumAttributes(); I != E; ++I) 717251662Sdim if (Attrs.getSlotIndex(I) == Index) { 718263508Sdim for (AttributeSetImpl::iterator II = Attrs.pImpl->begin(I), 719249259Sdim IE = Attrs.pImpl->end(I); II != IE; ++II) 720249259Sdim B.addAttribute(*II); 721249259Sdim break; 722249259Sdim } 723249259Sdim 724251662Sdim AttrSet.push_back(AttributeSet::get(C, Index, B)); 725249259Sdim 726249259Sdim // Add the remaining attribute slots. 727249259Sdim for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I) 728249259Sdim AttrSet.push_back(getSlotAttributes(I)); 729249259Sdim 730249259Sdim return get(C, AttrSet); 731249259Sdim} 732249259Sdim 733251662SdimAttributeSet AttributeSet::removeAttribute(LLVMContext &C, unsigned Index, 734249259Sdim Attribute::AttrKind Attr) const { 735251662Sdim if (!hasAttribute(Index, Attr)) return *this; 736251662Sdim return removeAttributes(C, Index, AttributeSet::get(C, Index, Attr)); 737249259Sdim} 738249259Sdim 739251662SdimAttributeSet AttributeSet::removeAttributes(LLVMContext &C, unsigned Index, 740249259Sdim AttributeSet Attrs) const { 741249259Sdim if (!pImpl) return AttributeSet(); 742249259Sdim if (!Attrs.pImpl) return *this; 743249259Sdim 744249259Sdim#ifndef NDEBUG 745249259Sdim // FIXME it is not obvious how this should work for alignment. 746249259Sdim // For now, say we can't pass in alignment, which no current use does. 747251662Sdim assert(!Attrs.hasAttribute(Index, Attribute::Alignment) && 748249259Sdim "Attempt to change alignment!"); 749249259Sdim#endif 750249259Sdim 751249259Sdim // Add the attribute slots before the one we're trying to add. 752249259Sdim SmallVector<AttributeSet, 4> AttrSet; 753249259Sdim uint64_t NumAttrs = pImpl->getNumAttributes(); 754249259Sdim AttributeSet AS; 755249259Sdim uint64_t LastIndex = 0; 756249259Sdim for (unsigned I = 0, E = NumAttrs; I != E; ++I) { 757251662Sdim if (getSlotIndex(I) >= Index) { 758251662Sdim if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++); 759249259Sdim break; 760249259Sdim } 761249259Sdim LastIndex = I + 1; 762249259Sdim AttrSet.push_back(getSlotAttributes(I)); 763249259Sdim } 764249259Sdim 765249259Sdim // Now remove the attribute from the correct slot. There may already be an 766249259Sdim // AttributeSet there. 767251662Sdim AttrBuilder B(AS, Index); 768249259Sdim 769249259Sdim for (unsigned I = 0, E = Attrs.pImpl->getNumAttributes(); I != E; ++I) 770251662Sdim if (Attrs.getSlotIndex(I) == Index) { 771251662Sdim B.removeAttributes(Attrs.pImpl->getSlotAttributes(I), Index); 772249259Sdim break; 773249259Sdim } 774249259Sdim 775251662Sdim AttrSet.push_back(AttributeSet::get(C, Index, B)); 776249259Sdim 777249259Sdim // Add the remaining attribute slots. 778249259Sdim for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I) 779249259Sdim AttrSet.push_back(getSlotAttributes(I)); 780249259Sdim 781249259Sdim return get(C, AttrSet); 782249259Sdim} 783249259Sdim 784249259Sdim//===----------------------------------------------------------------------===// 785249259Sdim// AttributeSet Accessor Methods 786249259Sdim//===----------------------------------------------------------------------===// 787249259Sdim 788249259SdimLLVMContext &AttributeSet::getContext() const { 789249259Sdim return pImpl->getContext(); 790249259Sdim} 791249259Sdim 792251662SdimAttributeSet AttributeSet::getParamAttributes(unsigned Index) const { 793251662Sdim return pImpl && hasAttributes(Index) ? 794249259Sdim AttributeSet::get(pImpl->getContext(), 795249259Sdim ArrayRef<std::pair<unsigned, AttributeSetNode*> >( 796251662Sdim std::make_pair(Index, getAttributes(Index)))) : 797249259Sdim AttributeSet(); 798249259Sdim} 799249259Sdim 800249259SdimAttributeSet AttributeSet::getRetAttributes() const { 801249259Sdim return pImpl && hasAttributes(ReturnIndex) ? 802249259Sdim AttributeSet::get(pImpl->getContext(), 803249259Sdim ArrayRef<std::pair<unsigned, AttributeSetNode*> >( 804249259Sdim std::make_pair(ReturnIndex, 805249259Sdim getAttributes(ReturnIndex)))) : 806249259Sdim AttributeSet(); 807249259Sdim} 808249259Sdim 809249259SdimAttributeSet AttributeSet::getFnAttributes() const { 810249259Sdim return pImpl && hasAttributes(FunctionIndex) ? 811249259Sdim AttributeSet::get(pImpl->getContext(), 812249259Sdim ArrayRef<std::pair<unsigned, AttributeSetNode*> >( 813249259Sdim std::make_pair(FunctionIndex, 814249259Sdim getAttributes(FunctionIndex)))) : 815249259Sdim AttributeSet(); 816249259Sdim} 817249259Sdim 818249259Sdimbool AttributeSet::hasAttribute(unsigned Index, Attribute::AttrKind Kind) const{ 819249259Sdim AttributeSetNode *ASN = getAttributes(Index); 820249259Sdim return ASN ? ASN->hasAttribute(Kind) : false; 821249259Sdim} 822249259Sdim 823249259Sdimbool AttributeSet::hasAttribute(unsigned Index, StringRef Kind) const { 824249259Sdim AttributeSetNode *ASN = getAttributes(Index); 825249259Sdim return ASN ? ASN->hasAttribute(Kind) : false; 826249259Sdim} 827249259Sdim 828249259Sdimbool AttributeSet::hasAttributes(unsigned Index) const { 829249259Sdim AttributeSetNode *ASN = getAttributes(Index); 830249259Sdim return ASN ? ASN->hasAttributes() : false; 831249259Sdim} 832249259Sdim 833249259Sdim/// \brief Return true if the specified attribute is set for at least one 834249259Sdim/// parameter or for the return value. 835249259Sdimbool AttributeSet::hasAttrSomewhere(Attribute::AttrKind Attr) const { 836249259Sdim if (pImpl == 0) return false; 837249259Sdim 838249259Sdim for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I) 839263508Sdim for (AttributeSetImpl::iterator II = pImpl->begin(I), 840249259Sdim IE = pImpl->end(I); II != IE; ++II) 841249259Sdim if (II->hasAttribute(Attr)) 842249259Sdim return true; 843249259Sdim 844249259Sdim return false; 845249259Sdim} 846249259Sdim 847249259SdimAttribute AttributeSet::getAttribute(unsigned Index, 848249259Sdim Attribute::AttrKind Kind) const { 849249259Sdim AttributeSetNode *ASN = getAttributes(Index); 850249259Sdim return ASN ? ASN->getAttribute(Kind) : Attribute(); 851249259Sdim} 852249259Sdim 853249259SdimAttribute AttributeSet::getAttribute(unsigned Index, 854249259Sdim StringRef Kind) const { 855249259Sdim AttributeSetNode *ASN = getAttributes(Index); 856249259Sdim return ASN ? ASN->getAttribute(Kind) : Attribute(); 857249259Sdim} 858249259Sdim 859249259Sdimunsigned AttributeSet::getParamAlignment(unsigned Index) const { 860249259Sdim AttributeSetNode *ASN = getAttributes(Index); 861249259Sdim return ASN ? ASN->getAlignment() : 0; 862249259Sdim} 863249259Sdim 864249259Sdimunsigned AttributeSet::getStackAlignment(unsigned Index) const { 865249259Sdim AttributeSetNode *ASN = getAttributes(Index); 866249259Sdim return ASN ? ASN->getStackAlignment() : 0; 867249259Sdim} 868249259Sdim 869249259Sdimstd::string AttributeSet::getAsString(unsigned Index, 870249259Sdim bool InAttrGrp) const { 871249259Sdim AttributeSetNode *ASN = getAttributes(Index); 872249259Sdim return ASN ? ASN->getAsString(InAttrGrp) : std::string(""); 873249259Sdim} 874249259Sdim 875249259Sdim/// \brief The attributes for the specified index are returned. 876251662SdimAttributeSetNode *AttributeSet::getAttributes(unsigned Index) const { 877249259Sdim if (!pImpl) return 0; 878249259Sdim 879249259Sdim // Loop through to find the attribute node we want. 880249259Sdim for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I) 881251662Sdim if (pImpl->getSlotIndex(I) == Index) 882249259Sdim return pImpl->getSlotNode(I); 883249259Sdim 884249259Sdim return 0; 885249259Sdim} 886249259Sdim 887251662SdimAttributeSet::iterator AttributeSet::begin(unsigned Slot) const { 888249259Sdim if (!pImpl) 889249259Sdim return ArrayRef<Attribute>().begin(); 890251662Sdim return pImpl->begin(Slot); 891249259Sdim} 892249259Sdim 893251662SdimAttributeSet::iterator AttributeSet::end(unsigned Slot) const { 894249259Sdim if (!pImpl) 895249259Sdim return ArrayRef<Attribute>().end(); 896251662Sdim return pImpl->end(Slot); 897249259Sdim} 898249259Sdim 899249259Sdim//===----------------------------------------------------------------------===// 900249259Sdim// AttributeSet Introspection Methods 901249259Sdim//===----------------------------------------------------------------------===// 902249259Sdim 903249259Sdim/// \brief Return the number of slots used in this attribute list. This is the 904249259Sdim/// number of arguments that have an attribute set on them (including the 905249259Sdim/// function itself). 906249259Sdimunsigned AttributeSet::getNumSlots() const { 907249259Sdim return pImpl ? pImpl->getNumAttributes() : 0; 908249259Sdim} 909249259Sdim 910251662Sdimunsigned AttributeSet::getSlotIndex(unsigned Slot) const { 911249259Sdim assert(pImpl && Slot < pImpl->getNumAttributes() && 912249259Sdim "Slot # out of range!"); 913249259Sdim return pImpl->getSlotIndex(Slot); 914249259Sdim} 915249259Sdim 916249259SdimAttributeSet AttributeSet::getSlotAttributes(unsigned Slot) const { 917249259Sdim assert(pImpl && Slot < pImpl->getNumAttributes() && 918249259Sdim "Slot # out of range!"); 919249259Sdim return pImpl->getSlotAttributes(Slot); 920249259Sdim} 921249259Sdim 922249259Sdimuint64_t AttributeSet::Raw(unsigned Index) const { 923249259Sdim // FIXME: Remove this. 924249259Sdim return pImpl ? pImpl->Raw(Index) : 0; 925249259Sdim} 926249259Sdim 927249259Sdimvoid AttributeSet::dump() const { 928249259Sdim dbgs() << "PAL[\n"; 929249259Sdim 930249259Sdim for (unsigned i = 0, e = getNumSlots(); i < e; ++i) { 931249259Sdim uint64_t Index = getSlotIndex(i); 932249259Sdim dbgs() << " { "; 933249259Sdim if (Index == ~0U) 934249259Sdim dbgs() << "~0U"; 935249259Sdim else 936249259Sdim dbgs() << Index; 937249259Sdim dbgs() << " => " << getAsString(Index) << " }\n"; 938249259Sdim } 939249259Sdim 940249259Sdim dbgs() << "]\n"; 941249259Sdim} 942249259Sdim 943249259Sdim//===----------------------------------------------------------------------===// 944249259Sdim// AttrBuilder Method Implementations 945249259Sdim//===----------------------------------------------------------------------===// 946249259Sdim 947251662SdimAttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index) 948249259Sdim : Attrs(0), Alignment(0), StackAlignment(0) { 949249259Sdim AttributeSetImpl *pImpl = AS.pImpl; 950249259Sdim if (!pImpl) return; 951249259Sdim 952249259Sdim for (unsigned I = 0, E = pImpl->getNumAttributes(); I != E; ++I) { 953251662Sdim if (pImpl->getSlotIndex(I) != Index) continue; 954249259Sdim 955263508Sdim for (AttributeSetImpl::iterator II = pImpl->begin(I), 956249259Sdim IE = pImpl->end(I); II != IE; ++II) 957249259Sdim addAttribute(*II); 958249259Sdim 959249259Sdim break; 960249259Sdim } 961249259Sdim} 962249259Sdim 963249259Sdimvoid AttrBuilder::clear() { 964249259Sdim Attrs.reset(); 965249259Sdim Alignment = StackAlignment = 0; 966249259Sdim} 967249259Sdim 968249259SdimAttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) { 969249259Sdim assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!"); 970249259Sdim assert(Val != Attribute::Alignment && Val != Attribute::StackAlignment && 971249259Sdim "Adding alignment attribute without adding alignment value!"); 972249259Sdim Attrs[Val] = true; 973249259Sdim return *this; 974249259Sdim} 975249259Sdim 976249259SdimAttrBuilder &AttrBuilder::addAttribute(Attribute Attr) { 977249259Sdim if (Attr.isStringAttribute()) { 978249259Sdim addAttribute(Attr.getKindAsString(), Attr.getValueAsString()); 979249259Sdim return *this; 980249259Sdim } 981249259Sdim 982249259Sdim Attribute::AttrKind Kind = Attr.getKindAsEnum(); 983249259Sdim Attrs[Kind] = true; 984249259Sdim 985249259Sdim if (Kind == Attribute::Alignment) 986249259Sdim Alignment = Attr.getAlignment(); 987249259Sdim else if (Kind == Attribute::StackAlignment) 988249259Sdim StackAlignment = Attr.getStackAlignment(); 989249259Sdim return *this; 990249259Sdim} 991249259Sdim 992249259SdimAttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) { 993249259Sdim TargetDepAttrs[A] = V; 994249259Sdim return *this; 995249259Sdim} 996249259Sdim 997249259SdimAttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) { 998249259Sdim assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!"); 999249259Sdim Attrs[Val] = false; 1000249259Sdim 1001249259Sdim if (Val == Attribute::Alignment) 1002249259Sdim Alignment = 0; 1003249259Sdim else if (Val == Attribute::StackAlignment) 1004249259Sdim StackAlignment = 0; 1005249259Sdim 1006249259Sdim return *this; 1007249259Sdim} 1008249259Sdim 1009249259SdimAttrBuilder &AttrBuilder::removeAttributes(AttributeSet A, uint64_t Index) { 1010251662Sdim unsigned Slot = ~0U; 1011249259Sdim for (unsigned I = 0, E = A.getNumSlots(); I != E; ++I) 1012249259Sdim if (A.getSlotIndex(I) == Index) { 1013251662Sdim Slot = I; 1014249259Sdim break; 1015249259Sdim } 1016249259Sdim 1017251662Sdim assert(Slot != ~0U && "Couldn't find index in AttributeSet!"); 1018249259Sdim 1019251662Sdim for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot); I != E; ++I) { 1020249259Sdim Attribute Attr = *I; 1021249259Sdim if (Attr.isEnumAttribute() || Attr.isAlignAttribute()) { 1022249259Sdim Attribute::AttrKind Kind = I->getKindAsEnum(); 1023249259Sdim Attrs[Kind] = false; 1024249259Sdim 1025249259Sdim if (Kind == Attribute::Alignment) 1026249259Sdim Alignment = 0; 1027249259Sdim else if (Kind == Attribute::StackAlignment) 1028249259Sdim StackAlignment = 0; 1029249259Sdim } else { 1030249259Sdim assert(Attr.isStringAttribute() && "Invalid attribute type!"); 1031249259Sdim std::map<std::string, std::string>::iterator 1032249259Sdim Iter = TargetDepAttrs.find(Attr.getKindAsString()); 1033249259Sdim if (Iter != TargetDepAttrs.end()) 1034249259Sdim TargetDepAttrs.erase(Iter); 1035249259Sdim } 1036249259Sdim } 1037249259Sdim 1038249259Sdim return *this; 1039249259Sdim} 1040249259Sdim 1041249259SdimAttrBuilder &AttrBuilder::removeAttribute(StringRef A) { 1042249259Sdim std::map<std::string, std::string>::iterator I = TargetDepAttrs.find(A); 1043249259Sdim if (I != TargetDepAttrs.end()) 1044249259Sdim TargetDepAttrs.erase(I); 1045249259Sdim return *this; 1046249259Sdim} 1047249259Sdim 1048249259SdimAttrBuilder &AttrBuilder::addAlignmentAttr(unsigned Align) { 1049249259Sdim if (Align == 0) return *this; 1050249259Sdim 1051249259Sdim assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); 1052249259Sdim assert(Align <= 0x40000000 && "Alignment too large."); 1053249259Sdim 1054249259Sdim Attrs[Attribute::Alignment] = true; 1055249259Sdim Alignment = Align; 1056249259Sdim return *this; 1057249259Sdim} 1058249259Sdim 1059249259SdimAttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align) { 1060249259Sdim // Default alignment, allow the target to define how to align it. 1061249259Sdim if (Align == 0) return *this; 1062249259Sdim 1063249259Sdim assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); 1064249259Sdim assert(Align <= 0x100 && "Alignment too large."); 1065249259Sdim 1066249259Sdim Attrs[Attribute::StackAlignment] = true; 1067249259Sdim StackAlignment = Align; 1068249259Sdim return *this; 1069249259Sdim} 1070249259Sdim 1071249259SdimAttrBuilder &AttrBuilder::merge(const AttrBuilder &B) { 1072249259Sdim // FIXME: What if both have alignments, but they don't match?! 1073249259Sdim if (!Alignment) 1074249259Sdim Alignment = B.Alignment; 1075249259Sdim 1076249259Sdim if (!StackAlignment) 1077249259Sdim StackAlignment = B.StackAlignment; 1078249259Sdim 1079249259Sdim Attrs |= B.Attrs; 1080249259Sdim 1081249259Sdim for (td_const_iterator I = B.TargetDepAttrs.begin(), 1082249259Sdim E = B.TargetDepAttrs.end(); I != E; ++I) 1083249259Sdim TargetDepAttrs[I->first] = I->second; 1084249259Sdim 1085249259Sdim return *this; 1086249259Sdim} 1087249259Sdim 1088249259Sdimbool AttrBuilder::contains(StringRef A) const { 1089249259Sdim return TargetDepAttrs.find(A) != TargetDepAttrs.end(); 1090249259Sdim} 1091249259Sdim 1092249259Sdimbool AttrBuilder::hasAttributes() const { 1093249259Sdim return !Attrs.none() || !TargetDepAttrs.empty(); 1094249259Sdim} 1095249259Sdim 1096249259Sdimbool AttrBuilder::hasAttributes(AttributeSet A, uint64_t Index) const { 1097251662Sdim unsigned Slot = ~0U; 1098249259Sdim for (unsigned I = 0, E = A.getNumSlots(); I != E; ++I) 1099249259Sdim if (A.getSlotIndex(I) == Index) { 1100251662Sdim Slot = I; 1101249259Sdim break; 1102249259Sdim } 1103249259Sdim 1104251662Sdim assert(Slot != ~0U && "Couldn't find the index!"); 1105249259Sdim 1106251662Sdim for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot); 1107249259Sdim I != E; ++I) { 1108249259Sdim Attribute Attr = *I; 1109249259Sdim if (Attr.isEnumAttribute() || Attr.isAlignAttribute()) { 1110249259Sdim if (Attrs[I->getKindAsEnum()]) 1111249259Sdim return true; 1112249259Sdim } else { 1113249259Sdim assert(Attr.isStringAttribute() && "Invalid attribute kind!"); 1114249259Sdim return TargetDepAttrs.find(Attr.getKindAsString())!=TargetDepAttrs.end(); 1115249259Sdim } 1116249259Sdim } 1117249259Sdim 1118249259Sdim return false; 1119249259Sdim} 1120249259Sdim 1121249259Sdimbool AttrBuilder::hasAlignmentAttr() const { 1122249259Sdim return Alignment != 0; 1123249259Sdim} 1124249259Sdim 1125249259Sdimbool AttrBuilder::operator==(const AttrBuilder &B) { 1126249259Sdim if (Attrs != B.Attrs) 1127249259Sdim return false; 1128249259Sdim 1129249259Sdim for (td_const_iterator I = TargetDepAttrs.begin(), 1130249259Sdim E = TargetDepAttrs.end(); I != E; ++I) 1131249259Sdim if (B.TargetDepAttrs.find(I->first) == B.TargetDepAttrs.end()) 1132249259Sdim return false; 1133249259Sdim 1134249259Sdim return Alignment == B.Alignment && StackAlignment == B.StackAlignment; 1135249259Sdim} 1136249259Sdim 1137249259SdimAttrBuilder &AttrBuilder::addRawValue(uint64_t Val) { 1138249259Sdim // FIXME: Remove this in 4.0. 1139249259Sdim if (!Val) return *this; 1140249259Sdim 1141249259Sdim for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds; 1142249259Sdim I = Attribute::AttrKind(I + 1)) { 1143249259Sdim if (uint64_t A = (Val & AttributeImpl::getAttrMask(I))) { 1144249259Sdim Attrs[I] = true; 1145249259Sdim 1146249259Sdim if (I == Attribute::Alignment) 1147249259Sdim Alignment = 1ULL << ((A >> 16) - 1); 1148249259Sdim else if (I == Attribute::StackAlignment) 1149249259Sdim StackAlignment = 1ULL << ((A >> 26)-1); 1150249259Sdim } 1151249259Sdim } 1152249259Sdim 1153249259Sdim return *this; 1154249259Sdim} 1155249259Sdim 1156249259Sdim//===----------------------------------------------------------------------===// 1157249259Sdim// AttributeFuncs Function Defintions 1158249259Sdim//===----------------------------------------------------------------------===// 1159249259Sdim 1160249259Sdim/// \brief Which attributes cannot be applied to a type. 1161249259SdimAttributeSet AttributeFuncs::typeIncompatible(Type *Ty, uint64_t Index) { 1162249259Sdim AttrBuilder Incompatible; 1163249259Sdim 1164249259Sdim if (!Ty->isIntegerTy()) 1165249259Sdim // Attribute that only apply to integers. 1166249259Sdim Incompatible.addAttribute(Attribute::SExt) 1167249259Sdim .addAttribute(Attribute::ZExt); 1168249259Sdim 1169249259Sdim if (!Ty->isPointerTy()) 1170249259Sdim // Attribute that only apply to pointers. 1171249259Sdim Incompatible.addAttribute(Attribute::ByVal) 1172249259Sdim .addAttribute(Attribute::Nest) 1173249259Sdim .addAttribute(Attribute::NoAlias) 1174249259Sdim .addAttribute(Attribute::NoCapture) 1175263508Sdim .addAttribute(Attribute::ReadNone) 1176263508Sdim .addAttribute(Attribute::ReadOnly) 1177249259Sdim .addAttribute(Attribute::StructRet); 1178249259Sdim 1179249259Sdim return AttributeSet::get(Ty->getContext(), Index, Incompatible); 1180249259Sdim} 1181