LLVM API Documentation
00001 //===-- Attributes.cpp - Implement AttributesList -------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the AttributesList class and Attribute utilities. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "llvm/Attributes.h" 00015 #include "llvm/Type.h" 00016 #include "llvm/ADT/StringExtras.h" 00017 #include "llvm/ADT/FoldingSet.h" 00018 #include "llvm/Support/Streams.h" 00019 #include "llvm/Support/ManagedStatic.h" 00020 using namespace llvm; 00021 00022 //===----------------------------------------------------------------------===// 00023 // Attribute Function Definitions 00024 //===----------------------------------------------------------------------===// 00025 00026 std::string Attribute::getAsString(Attributes Attrs) { 00027 std::string Result; 00028 if (Attrs & Attribute::ZExt) 00029 Result += "zeroext "; 00030 if (Attrs & Attribute::SExt) 00031 Result += "signext "; 00032 if (Attrs & Attribute::NoReturn) 00033 Result += "noreturn "; 00034 if (Attrs & Attribute::NoUnwind) 00035 Result += "nounwind "; 00036 if (Attrs & Attribute::InReg) 00037 Result += "inreg "; 00038 if (Attrs & Attribute::NoAlias) 00039 Result += "noalias "; 00040 if (Attrs & Attribute::NoCapture) 00041 Result += "nocapture "; 00042 if (Attrs & Attribute::StructRet) 00043 Result += "sret "; 00044 if (Attrs & Attribute::ByVal) 00045 Result += "byval "; 00046 if (Attrs & Attribute::Nest) 00047 Result += "nest "; 00048 if (Attrs & Attribute::ReadNone) 00049 Result += "readnone "; 00050 if (Attrs & Attribute::ReadOnly) 00051 Result += "readonly "; 00052 if (Attrs & Attribute::OptimizeForSize) 00053 Result += "optsize "; 00054 if (Attrs & Attribute::NoInline) 00055 Result += "noinline "; 00056 if (Attrs & Attribute::AlwaysInline) 00057 Result += "alwaysinline "; 00058 if (Attrs & Attribute::StackProtect) 00059 Result += "ssp "; 00060 if (Attrs & Attribute::StackProtectReq) 00061 Result += "sspreq "; 00062 if (Attrs & Attribute::Alignment) { 00063 Result += "align "; 00064 Result += utostr(Attribute::getAlignmentFromAttrs(Attrs)); 00065 Result += " "; 00066 } 00067 // Trim the trailing space. 00068 assert(!Result.empty() && "Unknown attribute!"); 00069 Result.erase(Result.end()-1); 00070 return Result; 00071 } 00072 00073 Attributes Attribute::typeIncompatible(const Type *Ty) { 00074 Attributes Incompatible = None; 00075 00076 if (!Ty->isInteger()) 00077 // Attributes that only apply to integers. 00078 Incompatible |= SExt | ZExt; 00079 00080 if (!isa<PointerType>(Ty)) 00081 // Attributes that only apply to pointers. 00082 Incompatible |= ByVal | Nest | NoAlias | StructRet | NoCapture; 00083 00084 return Incompatible; 00085 } 00086 00087 //===----------------------------------------------------------------------===// 00088 // AttributeListImpl Definition 00089 //===----------------------------------------------------------------------===// 00090 00091 namespace llvm { 00092 class AttributeListImpl : public FoldingSetNode { 00093 unsigned RefCount; 00094 00095 // AttributesList is uniqued, these should not be publicly available. 00096 void operator=(const AttributeListImpl &); // Do not implement 00097 AttributeListImpl(const AttributeListImpl &); // Do not implement 00098 ~AttributeListImpl(); // Private implementation 00099 public: 00100 SmallVector<AttributeWithIndex, 4> Attrs; 00101 00102 AttributeListImpl(const AttributeWithIndex *Attr, unsigned NumAttrs) 00103 : Attrs(Attr, Attr+NumAttrs) { 00104 RefCount = 0; 00105 } 00106 00107 void AddRef() { ++RefCount; } 00108 void DropRef() { if (--RefCount == 0) delete this; } 00109 00110 void Profile(FoldingSetNodeID &ID) const { 00111 Profile(ID, &Attrs[0], Attrs.size()); 00112 } 00113 static void Profile(FoldingSetNodeID &ID, const AttributeWithIndex *Attr, 00114 unsigned NumAttrs) { 00115 for (unsigned i = 0; i != NumAttrs; ++i) 00116 ID.AddInteger(uint64_t(Attr[i].Attrs) << 32 | unsigned(Attr[i].Index)); 00117 } 00118 }; 00119 } 00120 00121 static ManagedStatic<FoldingSet<AttributeListImpl> > AttributesLists; 00122 00123 AttributeListImpl::~AttributeListImpl() { 00124 AttributesLists->RemoveNode(this); 00125 } 00126 00127 00128 AttrListPtr AttrListPtr::get(const AttributeWithIndex *Attrs, unsigned NumAttrs) { 00129 // If there are no attributes then return a null AttributesList pointer. 00130 if (NumAttrs == 0) 00131 return AttrListPtr(); 00132 00133 #ifndef NDEBUG 00134 for (unsigned i = 0; i != NumAttrs; ++i) { 00135 assert(Attrs[i].Attrs != Attribute::None && 00136 "Pointless attribute!"); 00137 assert((!i || Attrs[i-1].Index < Attrs[i].Index) && 00138 "Misordered AttributesList!"); 00139 } 00140 #endif 00141 00142 // Otherwise, build a key to look up the existing attributes. 00143 FoldingSetNodeID ID; 00144 AttributeListImpl::Profile(ID, Attrs, NumAttrs); 00145 void *InsertPos; 00146 AttributeListImpl *PAL = 00147 AttributesLists->FindNodeOrInsertPos(ID, InsertPos); 00148 00149 // If we didn't find any existing attributes of the same shape then 00150 // create a new one and insert it. 00151 if (!PAL) { 00152 PAL = new AttributeListImpl(Attrs, NumAttrs); 00153 AttributesLists->InsertNode(PAL, InsertPos); 00154 } 00155 00156 // Return the AttributesList that we found or created. 00157 return AttrListPtr(PAL); 00158 } 00159 00160 00161 //===----------------------------------------------------------------------===// 00162 // AttrListPtr Method Implementations 00163 //===----------------------------------------------------------------------===// 00164 00165 AttrListPtr::AttrListPtr(AttributeListImpl *LI) : AttrList(LI) { 00166 if (LI) LI->AddRef(); 00167 } 00168 00169 AttrListPtr::AttrListPtr(const AttrListPtr &P) : AttrList(P.AttrList) { 00170 if (AttrList) AttrList->AddRef(); 00171 } 00172 00173 const AttrListPtr &AttrListPtr::operator=(const AttrListPtr &RHS) { 00174 if (AttrList == RHS.AttrList) return *this; 00175 if (AttrList) AttrList->DropRef(); 00176 AttrList = RHS.AttrList; 00177 if (AttrList) AttrList->AddRef(); 00178 return *this; 00179 } 00180 00181 AttrListPtr::~AttrListPtr() { 00182 if (AttrList) AttrList->DropRef(); 00183 } 00184 00185 /// getNumSlots - Return the number of slots used in this attribute list. 00186 /// This is the number of arguments that have an attribute set on them 00187 /// (including the function itself). 00188 unsigned AttrListPtr::getNumSlots() const { 00189 return AttrList ? AttrList->Attrs.size() : 0; 00190 } 00191 00192 /// getSlot - Return the AttributeWithIndex at the specified slot. This 00193 /// holds a number plus a set of attributes. 00194 const AttributeWithIndex &AttrListPtr::getSlot(unsigned Slot) const { 00195 assert(AttrList && Slot < AttrList->Attrs.size() && "Slot # out of range!"); 00196 return AttrList->Attrs[Slot]; 00197 } 00198 00199 00200 /// getAttributes - The attributes for the specified index are 00201 /// returned. Attributes for the result are denoted with Idx = 0. 00202 /// Function notes are denoted with idx = ~0. 00203 Attributes AttrListPtr::getAttributes(unsigned Idx) const { 00204 if (AttrList == 0) return Attribute::None; 00205 00206 const SmallVector<AttributeWithIndex, 4> &Attrs = AttrList->Attrs; 00207 for (unsigned i = 0, e = Attrs.size(); i != e && Attrs[i].Index <= Idx; ++i) 00208 if (Attrs[i].Index == Idx) 00209 return Attrs[i].Attrs; 00210 return Attribute::None; 00211 } 00212 00213 /// hasAttrSomewhere - Return true if the specified attribute is set for at 00214 /// least one parameter or for the return value. 00215 bool AttrListPtr::hasAttrSomewhere(Attributes Attr) const { 00216 if (AttrList == 0) return false; 00217 00218 const SmallVector<AttributeWithIndex, 4> &Attrs = AttrList->Attrs; 00219 for (unsigned i = 0, e = Attrs.size(); i != e; ++i) 00220 if (Attrs[i].Attrs & Attr) 00221 return true; 00222 return false; 00223 } 00224 00225 00226 AttrListPtr AttrListPtr::addAttr(unsigned Idx, Attributes Attrs) const { 00227 Attributes OldAttrs = getAttributes(Idx); 00228 #ifndef NDEBUG 00229 // FIXME it is not obvious how this should work for alignment. 00230 // For now, say we can't change a known alignment. 00231 Attributes OldAlign = OldAttrs & Attribute::Alignment; 00232 Attributes NewAlign = Attrs & Attribute::Alignment; 00233 assert((!OldAlign || !NewAlign || OldAlign == NewAlign) && 00234 "Attempt to change alignment!"); 00235 #endif 00236 00237 Attributes NewAttrs = OldAttrs | Attrs; 00238 if (NewAttrs == OldAttrs) 00239 return *this; 00240 00241 SmallVector<AttributeWithIndex, 8> NewAttrList; 00242 if (AttrList == 0) 00243 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs)); 00244 else { 00245 const SmallVector<AttributeWithIndex, 4> &OldAttrList = AttrList->Attrs; 00246 unsigned i = 0, e = OldAttrList.size(); 00247 // Copy attributes for arguments before this one. 00248 for (; i != e && OldAttrList[i].Index < Idx; ++i) 00249 NewAttrList.push_back(OldAttrList[i]); 00250 00251 // If there are attributes already at this index, merge them in. 00252 if (i != e && OldAttrList[i].Index == Idx) { 00253 Attrs |= OldAttrList[i].Attrs; 00254 ++i; 00255 } 00256 00257 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs)); 00258 00259 // Copy attributes for arguments after this one. 00260 NewAttrList.insert(NewAttrList.end(), 00261 OldAttrList.begin()+i, OldAttrList.end()); 00262 } 00263 00264 return get(&NewAttrList[0], NewAttrList.size()); 00265 } 00266 00267 AttrListPtr AttrListPtr::removeAttr(unsigned Idx, Attributes Attrs) const { 00268 #ifndef NDEBUG 00269 // FIXME it is not obvious how this should work for alignment. 00270 // For now, say we can't pass in alignment, which no current use does. 00271 assert(!(Attrs & Attribute::Alignment) && "Attempt to exclude alignment!"); 00272 #endif 00273 if (AttrList == 0) return AttrListPtr(); 00274 00275 Attributes OldAttrs = getAttributes(Idx); 00276 Attributes NewAttrs = OldAttrs & ~Attrs; 00277 if (NewAttrs == OldAttrs) 00278 return *this; 00279 00280 SmallVector<AttributeWithIndex, 8> NewAttrList; 00281 const SmallVector<AttributeWithIndex, 4> &OldAttrList = AttrList->Attrs; 00282 unsigned i = 0, e = OldAttrList.size(); 00283 00284 // Copy attributes for arguments before this one. 00285 for (; i != e && OldAttrList[i].Index < Idx; ++i) 00286 NewAttrList.push_back(OldAttrList[i]); 00287 00288 // If there are attributes already at this index, merge them in. 00289 assert(OldAttrList[i].Index == Idx && "Attribute isn't set?"); 00290 Attrs = OldAttrList[i].Attrs & ~Attrs; 00291 ++i; 00292 if (Attrs) // If any attributes left for this parameter, add them. 00293 NewAttrList.push_back(AttributeWithIndex::get(Idx, Attrs)); 00294 00295 // Copy attributes for arguments after this one. 00296 NewAttrList.insert(NewAttrList.end(), 00297 OldAttrList.begin()+i, OldAttrList.end()); 00298 00299 return get(&NewAttrList[0], NewAttrList.size()); 00300 } 00301 00302 void AttrListPtr::dump() const { 00303 cerr << "PAL[ "; 00304 for (unsigned i = 0; i < getNumSlots(); ++i) { 00305 const AttributeWithIndex &PAWI = getSlot(i); 00306 cerr << "{" << PAWI.Index << "," << PAWI.Attrs << "} "; 00307 } 00308 00309 cerr << "]\n"; 00310 }