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