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