1212795Sdim//===--- AttributeList.cpp --------------------------------------*- C++ -*-===// 2212795Sdim// 3212795Sdim// The LLVM Compiler Infrastructure 4212795Sdim// 5212795Sdim// This file is distributed under the University of Illinois Open Source 6212795Sdim// License. See LICENSE.TXT for details. 7212795Sdim// 8212795Sdim//===----------------------------------------------------------------------===// 9212795Sdim// 10212795Sdim// This file defines the AttributeList class implementation 11212795Sdim// 12212795Sdim//===----------------------------------------------------------------------===// 13212795Sdim 14212795Sdim#include "clang/Sema/AttributeList.h" 15239462Sdim#include "clang/AST/ASTContext.h" 16221345Sdim#include "clang/AST/Expr.h" 17212795Sdim#include "clang/Basic/IdentifierTable.h" 18249423Sdim#include "llvm/ADT/SmallString.h" 19212795Sdim#include "llvm/ADT/StringSwitch.h" 20212795Sdimusing namespace clang; 21212795Sdim 22263508SdimIdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc, 23263508Sdim IdentifierInfo *Ident) { 24263508Sdim IdentifierLoc *Result = new (Ctx) IdentifierLoc; 25263508Sdim Result->Loc = Loc; 26263508Sdim Result->Ident = Ident; 27263508Sdim return Result; 28263508Sdim} 29263508Sdim 30221345Sdimsize_t AttributeList::allocated_size() const { 31221345Sdim if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; 32239462Sdim else if (IsTypeTagForDatatype) 33239462Sdim return AttributeFactory::TypeTagForDatatypeAllocSize; 34251662Sdim else if (IsProperty) 35251662Sdim return AttributeFactory::PropertyAllocSize; 36263508Sdim return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion)); 37221345Sdim} 38212795Sdim 39221345SdimAttributeFactory::AttributeFactory() { 40221345Sdim // Go ahead and configure all the inline capacity. This is just a memset. 41221345Sdim FreeLists.resize(InlineFreeListsCapacity); 42221345Sdim} 43221345SdimAttributeFactory::~AttributeFactory() {} 44221345Sdim 45221345Sdimstatic size_t getFreeListIndexForSize(size_t size) { 46221345Sdim assert(size >= sizeof(AttributeList)); 47221345Sdim assert((size % sizeof(void*)) == 0); 48221345Sdim return ((size - sizeof(AttributeList)) / sizeof(void*)); 49221345Sdim} 50221345Sdim 51221345Sdimvoid *AttributeFactory::allocate(size_t size) { 52221345Sdim // Check for a previously reclaimed attribute. 53221345Sdim size_t index = getFreeListIndexForSize(size); 54221345Sdim if (index < FreeLists.size()) { 55221345Sdim if (AttributeList *attr = FreeLists[index]) { 56221345Sdim FreeLists[index] = attr->NextInPool; 57221345Sdim return attr; 58221345Sdim } 59212795Sdim } 60221345Sdim 61221345Sdim // Otherwise, allocate something new. 62221345Sdim return Alloc.Allocate(size, llvm::AlignOf<AttributeFactory>::Alignment); 63212795Sdim} 64212795Sdim 65221345Sdimvoid AttributeFactory::reclaimPool(AttributeList *cur) { 66221345Sdim assert(cur && "reclaiming empty pool!"); 67221345Sdim do { 68221345Sdim // Read this here, because we're going to overwrite NextInPool 69221345Sdim // when we toss 'cur' into the appropriate queue. 70221345Sdim AttributeList *next = cur->NextInPool; 71221345Sdim 72221345Sdim size_t size = cur->allocated_size(); 73221345Sdim size_t freeListIndex = getFreeListIndexForSize(size); 74221345Sdim 75221345Sdim // Expand FreeLists to the appropriate size, if required. 76221345Sdim if (freeListIndex >= FreeLists.size()) 77221345Sdim FreeLists.resize(freeListIndex+1); 78221345Sdim 79221345Sdim // Add 'cur' to the appropriate free-list. 80221345Sdim cur->NextInPool = FreeLists[freeListIndex]; 81221345Sdim FreeLists[freeListIndex] = cur; 82221345Sdim 83221345Sdim cur = next; 84221345Sdim } while (cur); 85221345Sdim} 86221345Sdim 87221345Sdimvoid AttributePool::takePool(AttributeList *pool) { 88221345Sdim assert(pool); 89221345Sdim 90221345Sdim // Fast path: this pool is empty. 91221345Sdim if (!Head) { 92221345Sdim Head = pool; 93221345Sdim return; 94221345Sdim } 95221345Sdim 96221345Sdim // Reverse the pool onto the current head. This optimizes for the 97221345Sdim // pattern of pulling a lot of pools into a single pool. 98221345Sdim do { 99221345Sdim AttributeList *next = pool->NextInPool; 100221345Sdim pool->NextInPool = Head; 101221345Sdim Head = pool; 102221345Sdim pool = next; 103221345Sdim } while (pool); 104221345Sdim} 105221345Sdim 106221345SdimAttributeList * 107221345SdimAttributePool::createIntegerAttribute(ASTContext &C, IdentifierInfo *Name, 108221345Sdim SourceLocation TokLoc, int Arg) { 109263508Sdim ArgsUnion IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg), 110221345Sdim C.IntTy, TokLoc); 111263508Sdim return create(Name, TokLoc, 0, TokLoc, &IArg, 1, AttributeList::AS_GNU); 112221345Sdim} 113221345Sdim 114239462Sdim#include "clang/Sema/AttrParsedAttrKinds.inc" 115239462Sdim 116239462SdimAttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name, 117239462Sdim const IdentifierInfo *ScopeName, 118239462Sdim Syntax SyntaxUsed) { 119226633Sdim StringRef AttrName = Name->getName(); 120212795Sdim 121212795Sdim // Normalize the attribute name, __foo__ becomes foo. 122234353Sdim if (AttrName.startswith("__") && AttrName.endswith("__") && 123234353Sdim AttrName.size() >= 4) 124212795Sdim AttrName = AttrName.substr(2, AttrName.size() - 4); 125212795Sdim 126239462Sdim SmallString<64> Buf; 127239462Sdim if (ScopeName) 128239462Sdim Buf += ScopeName->getName(); 129239462Sdim // Ensure that in the case of C++11 attributes, we look for '::foo' if it is 130239462Sdim // unscoped. 131239462Sdim if (ScopeName || SyntaxUsed == AS_CXX11) 132239462Sdim Buf += "::"; 133239462Sdim Buf += AttrName; 134239462Sdim 135239462Sdim return ::getAttrKind(Buf); 136212795Sdim} 137249423Sdim 138249423Sdimunsigned AttributeList::getAttributeSpellingListIndex() const { 139249423Sdim // Both variables will be used in tablegen generated 140249423Sdim // attribute spell list index matching code. 141249423Sdim StringRef Name = AttrName->getName(); 142249423Sdim StringRef Scope = ScopeName ? ScopeName->getName() : ""; 143249423Sdim 144249423Sdim#include "clang/Sema/AttrSpellingListIndex.inc" 145249423Sdim 146249423Sdim} 147249423Sdim 148263508Sdimstruct ParsedAttrInfo { 149263508Sdim unsigned NumArgs : 4; 150263508Sdim unsigned OptArgs : 4; 151263508Sdim unsigned HasCustomParsing : 1; 152263508Sdim}; 153263508Sdim 154263508Sdimnamespace { 155263508Sdim #include "clang/Sema/AttrParsedAttrImpl.inc" 156263508Sdim} 157263508Sdim 158263508Sdimstatic const ParsedAttrInfo &getInfo(const AttributeList &A) { 159263508Sdim return AttrInfoMap[A.getKind()]; 160263508Sdim} 161263508Sdim 162263508Sdimunsigned AttributeList::getMinArgs() const { 163263508Sdim return getInfo(*this).NumArgs; 164263508Sdim} 165263508Sdim 166263508Sdimunsigned AttributeList::getMaxArgs() const { 167263508Sdim return getMinArgs() + getInfo(*this).OptArgs; 168263508Sdim} 169263508Sdim 170263508Sdimbool AttributeList::hasCustomParsing() const { 171263508Sdim return getInfo(*this).HasCustomParsing; 172263508Sdim} 173