Attributes.cpp revision 1ed86d74a87baca2e42b90873345c63811647b1d
1//===-- Attributes.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 AttributesList class and Attribute utilities. 11// 12//===----------------------------------------------------------------------===// 13 14#include "llvm/Attributes.h" 15#include "llvm/Type.h" 16#include "llvm/ADT/StringExtras.h" 17#include "llvm/ADT/FoldingSet.h" 18#include "llvm/Support/Streams.h" 19#include "llvm/Support/ManagedStatic.h" 20using namespace llvm; 21 22//===----------------------------------------------------------------------===// 23// Attribute Function Definitions 24//===----------------------------------------------------------------------===// 25 26std::string Attribute::getAsString(Attributes Attrs) { 27 std::string Result; 28 if (Attrs & Attribute::ZExt) 29 Result += "zeroext "; 30 if (Attrs & Attribute::SExt) 31 Result += "signext "; 32 if (Attrs & Attribute::NoReturn) 33 Result += "noreturn "; 34 if (Attrs & Attribute::NoUnwind) 35 Result += "nounwind "; 36 if (Attrs & Attribute::InReg) 37 Result += "inreg "; 38 if (Attrs & Attribute::NoAlias) 39 Result += "noalias "; 40 if (Attrs & Attribute::NoCapture) 41 Result += "nocapture "; 42 if (Attrs & Attribute::StructRet) 43 Result += "sret "; 44 if (Attrs & Attribute::ByVal) 45 Result += "byval "; 46 if (Attrs & Attribute::Nest) 47 Result += "nest "; 48 if (Attrs & Attribute::ReadNone) 49 Result += "readnone "; 50 if (Attrs & Attribute::ReadOnly) 51 Result += "readonly "; 52 if (Attrs & Attribute::OptimizeForSize) 53 Result += "optsize "; 54 if (Attrs & Attribute::NoInline) 55 Result += "noinline "; 56 if (Attrs & Attribute::AlwaysInline) 57 Result += "alwaysinline "; 58 if (Attrs & Attribute::StackProtect) 59 Result += "ssp "; 60 if (Attrs & Attribute::StackProtectReq) 61 Result += "sspreq "; 62 if (Attrs & Attribute::Alignment) { 63 Result += "align "; 64 Result += utostr(Attribute::getAlignmentFromAttrs(Attrs)); 65 Result += " "; 66 } 67 // Trim the trailing space. 68 assert(!Result.empty() && "Unknown attribute!"); 69 Result.erase(Result.end()-1); 70 return Result; 71} 72 73Attributes Attribute::typeIncompatible(const Type *Ty) { 74 Attributes Incompatible = None; 75 76 if (!Ty->isInteger()) 77 // Attributes that only apply to integers. 78 Incompatible |= SExt | ZExt; 79 80 if (!isa<PointerType>(Ty)) 81 // Attributes that only apply to pointers. 82 Incompatible |= ByVal | Nest | NoAlias | StructRet | NoCapture; 83 84 return Incompatible; 85} 86 87//===----------------------------------------------------------------------===// 88// AttributeListImpl Definition 89//===----------------------------------------------------------------------===// 90 91namespace llvm { 92class AttributeListImpl : public FoldingSetNode { 93 unsigned RefCount; 94 95 // AttributesList is uniqued, these should not be publicly available. 96 void operator=(const AttributeListImpl &); // Do not implement 97 AttributeListImpl(const AttributeListImpl &); // Do not implement 98 ~AttributeListImpl(); // Private implementation 99public: 100 SmallVector<AttributeWithIndex, 4> Attrs; 101 102 AttributeListImpl(const AttributeWithIndex *Attr, unsigned NumAttrs) 103 : Attrs(Attr, Attr+NumAttrs) { 104 RefCount = 0; 105 } 106 107 void AddRef() { ++RefCount; } 108 void DropRef() { if (--RefCount == 0) delete this; } 109 110 void Profile(FoldingSetNodeID &ID) const { 111 Profile(ID, &Attrs[0], Attrs.size()); 112 } 113 static void Profile(FoldingSetNodeID &ID, const AttributeWithIndex *Attr, 114 unsigned NumAttrs) { 115 for (unsigned i = 0; i != NumAttrs; ++i) 116 ID.AddInteger(uint64_t(Attr[i].Attrs) << 32 | unsigned(Attr[i].Index)); 117 } 118}; 119} 120 121static ManagedStatic<FoldingSet<AttributeListImpl> > AttributesLists; 122 123AttributeListImpl::~AttributeListImpl() { 124 AttributesLists->RemoveNode(this); 125} 126 127 128AttrListPtr AttrListPtr::get(const AttributeWithIndex *Attrs, unsigned NumAttrs) { 129 // If there are no attributes then return a null AttributesList pointer. 130 if (NumAttrs == 0) 131 return AttrListPtr(); 132 133#ifndef NDEBUG 134 for (unsigned i = 0; i != NumAttrs; ++i) { 135 assert(Attrs[i].Attrs != Attribute::None && 136 "Pointless attribute!"); 137 assert((!i || Attrs[i-1].Index < Attrs[i].Index) && 138 "Misordered AttributesList!"); 139 } 140#endif 141 142 // Otherwise, build a key to look up the existing attributes. 143 FoldingSetNodeID ID; 144 AttributeListImpl::Profile(ID, Attrs, NumAttrs); 145 void *InsertPos; 146 AttributeListImpl *PAL = 147 AttributesLists->FindNodeOrInsertPos(ID, InsertPos); 148 149 // If we didn't find any existing attributes of the same shape then 150 // create a new one and insert it. 151 if (!PAL) { 152 PAL = new AttributeListImpl(Attrs, NumAttrs); 153 AttributesLists->InsertNode(PAL, InsertPos); 154 } 155 156 // Return the AttributesList that we found or created. 157 return AttrListPtr(PAL); 158} 159 160 161//===----------------------------------------------------------------------===// 162// AttrListPtr Method Implementations 163//===----------------------------------------------------------------------===// 164 165AttrListPtr::AttrListPtr(AttributeListImpl *LI) : AttrList(LI) { 166 if (LI) LI->AddRef(); 167} 168 169AttrListPtr::AttrListPtr(const AttrListPtr &P) : AttrList(P.AttrList) { 170 if (AttrList) AttrList->AddRef(); 171} 172 173const AttrListPtr &AttrListPtr::operator=(const AttrListPtr &RHS) { 174 if (AttrList == RHS.AttrList) return *this; 175 if (AttrList) AttrList->DropRef(); 176 AttrList = RHS.AttrList; 177 if (AttrList) AttrList->AddRef(); 178 return *this; 179} 180 181AttrListPtr::~AttrListPtr() { 182 if (AttrList) AttrList->DropRef(); 183} 184 185/// getNumSlots - Return the number of slots used in this attribute list. 186/// This is the number of arguments that have an attribute set on them 187/// (including the function itself). 188unsigned AttrListPtr::getNumSlots() const { 189 return AttrList ? AttrList->Attrs.size() : 0; 190} 191 192/// getSlot - Return the AttributeWithIndex at the specified slot. This 193/// holds a number plus a set of attributes. 194const AttributeWithIndex &AttrListPtr::getSlot(unsigned Slot) const { 195 assert(AttrList && Slot < AttrList->Attrs.size() && "Slot # out of range!"); 196 return AttrList->Attrs[Slot]; 197} 198 199 200/// getAttributes - The attributes for the specified index are 201/// returned. Attributes for the result are denoted with Idx = 0. 202/// Function notes are denoted with idx = ~0. 203Attributes AttrListPtr::getAttributes(unsigned Idx) const { 204 if (AttrList == 0) return Attribute::None; 205 206 const SmallVector<AttributeWithIndex, 4> &Attrs = AttrList->Attrs; 207 for (unsigned i = 0, e = Attrs.size(); i != e && Attrs[i].Index <= Idx; ++i) 208 if (Attrs[i].Index == Idx) 209 return Attrs[i].Attrs; 210 return Attribute::None; 211} 212 213/// hasAttrSomewhere - Return true if the specified attribute is set for at 214/// least one parameter or for the return value. 215bool AttrListPtr::hasAttrSomewhere(Attributes Attr) const { 216 if (AttrList == 0) return false; 217 218 const SmallVector<AttributeWithIndex, 4> &Attrs = AttrList->Attrs; 219 for (unsigned i = 0, e = Attrs.size(); i != e; ++i) 220 if (Attrs[i].Attrs & Attr) 221 return true; 222 return false; 223} 224 225 226AttrListPtr AttrListPtr::addAttr(unsigned Idx, Attributes Attrs) const { 227 Attributes OldAttrs = getAttributes(Idx); 228#ifndef NDEBUG 229 // FIXME it is not obvious how this should work for alignment. 230 // For now, say we can't change a known alignment. 231 Attributes OldAlign = OldAttrs & Attribute::Alignment; 232 Attributes NewAlign = Attrs & Attribute::Alignment; 233 assert((!OldAlign || !NewAlign || OldAlign == NewAlign) && 234 "Attempt to change alignment!"); 235#endif 236 237 Attributes NewAttrs = OldAttrs | Attrs; 238 if (NewAttrs == OldAttrs) 239 return *this; 240 241 SmallVector<AttributeWithIndex, 8> NewAttrList; 242 if (AttrList == 0) 243 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs)); 244 else { 245 const SmallVector<AttributeWithIndex, 4> &OldAttrList = AttrList->Attrs; 246 unsigned i = 0, e = OldAttrList.size(); 247 // Copy attributes for arguments before this one. 248 for (; i != e && OldAttrList[i].Index < Idx; ++i) 249 NewAttrList.push_back(OldAttrList[i]); 250 251 // If there are attributes already at this index, merge them in. 252 if (i != e && OldAttrList[i].Index == Idx) { 253 Attrs |= OldAttrList[i].Attrs; 254 ++i; 255 } 256 257 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs)); 258 259 // Copy attributes for arguments after this one. 260 NewAttrList.insert(NewAttrList.end(), 261 OldAttrList.begin()+i, OldAttrList.end()); 262 } 263 264 return get(&NewAttrList[0], NewAttrList.size()); 265} 266 267AttrListPtr AttrListPtr::removeAttr(unsigned Idx, Attributes Attrs) const { 268#ifndef NDEBUG 269 // FIXME it is not obvious how this should work for alignment. 270 // For now, say we can't pass in alignment, which no current use does. 271 assert(!(Attrs & Attribute::Alignment) && "Attempt to exclude alignment!"); 272#endif 273 if (AttrList == 0) return AttrListPtr(); 274 275 Attributes OldAttrs = getAttributes(Idx); 276 Attributes NewAttrs = OldAttrs & ~Attrs; 277 if (NewAttrs == OldAttrs) 278 return *this; 279 280 SmallVector<AttributeWithIndex, 8> NewAttrList; 281 const SmallVector<AttributeWithIndex, 4> &OldAttrList = AttrList->Attrs; 282 unsigned i = 0, e = OldAttrList.size(); 283 284 // Copy attributes for arguments before this one. 285 for (; i != e && OldAttrList[i].Index < Idx; ++i) 286 NewAttrList.push_back(OldAttrList[i]); 287 288 // If there are attributes already at this index, merge them in. 289 assert(OldAttrList[i].Index == Idx && "Attribute isn't set?"); 290 Attrs = OldAttrList[i].Attrs & ~Attrs; 291 ++i; 292 if (Attrs) // If any attributes left for this parameter, add them. 293 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs)); 294 295 // Copy attributes for arguments after this one. 296 NewAttrList.insert(NewAttrList.end(), 297 OldAttrList.begin()+i, OldAttrList.end()); 298 299 return get(&NewAttrList[0], NewAttrList.size()); 300} 301 302void AttrListPtr::dump() const { 303 cerr << "PAL[ "; 304 for (unsigned i = 0; i < getNumSlots(); ++i) { 305 const AttributeWithIndex &PAWI = getSlot(i); 306 cerr << "{" << PAWI.Index << "," << PAWI.Attrs << "} "; 307 } 308 309 cerr << "]\n"; 310} 311