15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===--- AttributeList.cpp --------------------------------------*- C++ -*-===//
25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//                     The LLVM Compiler Infrastructure
45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source
60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details.
75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// This file defines the AttributeList class implementation
115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1419510856727e0e14a3696b2a72c35163bff2a71fJohn McCall#include "clang/Sema/AttributeList.h"
15478851c3ed6bd784e7377dffd8e57b200c1b9ba9Benjamin Kramer#include "clang/AST/ASTContext.h"
160b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall#include "clang/AST/Expr.h"
178f823d2d3c557326d22699d66e5d367d0f0e44efChris Lattner#include "clang/Basic/IdentifierTable.h"
18d6268ffe94e5159ef41c61fe7f750c22546d3ef3Douglas Gregor#include "llvm/ADT/StringSwitch.h"
19e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith#include "llvm/ADT/SmallString.h"
205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang;
215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
220b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCallsize_t AttributeList::allocated_size() const {
230b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
240d5a069f66df09b3308ccfdce84a88170034c657Dmitri Gribenko  else if (IsTypeTagForDatatype)
250d5a069f66df09b3308ccfdce84a88170034c657Dmitri Gribenko    return AttributeFactory::TypeTagForDatatypeAllocSize;
260b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  return (sizeof(AttributeList) + NumArgs * sizeof(Expr*));
270b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall}
280b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
290b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCallAttributeFactory::AttributeFactory() {
300b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  // Go ahead and configure all the inline capacity.  This is just a memset.
310b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  FreeLists.resize(InlineFreeListsCapacity);
320b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall}
330b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCallAttributeFactory::~AttributeFactory() {}
340b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
350b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCallstatic size_t getFreeListIndexForSize(size_t size) {
360b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  assert(size >= sizeof(AttributeList));
370b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  assert((size % sizeof(void*)) == 0);
380b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  return ((size - sizeof(AttributeList)) / sizeof(void*));
390b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall}
400b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
410b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCallvoid *AttributeFactory::allocate(size_t size) {
420b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  // Check for a previously reclaimed attribute.
430b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  size_t index = getFreeListIndexForSize(size);
440b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  if (index < FreeLists.size()) {
450b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    if (AttributeList *attr = FreeLists[index]) {
460b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall      FreeLists[index] = attr->NextInPool;
470b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall      return attr;
480b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    }
49005b235fbc8449142befa81ec30e8e4c654182c5Chris Lattner  }
500b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
510b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  // Otherwise, allocate something new.
520b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  return Alloc.Allocate(size, llvm::AlignOf<AttributeFactory>::Alignment);
530b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall}
540b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
550b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCallvoid AttributeFactory::reclaimPool(AttributeList *cur) {
560b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  assert(cur && "reclaiming empty pool!");
570b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  do {
580b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    // Read this here, because we're going to overwrite NextInPool
590b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    // when we toss 'cur' into the appropriate queue.
600b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    AttributeList *next = cur->NextInPool;
610b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
620b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    size_t size = cur->allocated_size();
630b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    size_t freeListIndex = getFreeListIndexForSize(size);
640b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
650b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    // Expand FreeLists to the appropriate size, if required.
660b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    if (freeListIndex >= FreeLists.size())
670b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall      FreeLists.resize(freeListIndex+1);
680b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
690b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    // Add 'cur' to the appropriate free-list.
700b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    cur->NextInPool = FreeLists[freeListIndex];
710b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    FreeLists[freeListIndex] = cur;
720b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
730b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    cur = next;
740b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  } while (cur);
750b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall}
760b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
770b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCallvoid AttributePool::takePool(AttributeList *pool) {
780b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  assert(pool);
790b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
800b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  // Fast path:  this pool is empty.
810b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  if (!Head) {
820b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    Head = pool;
830b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    return;
840b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  }
850b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
860b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  // Reverse the pool onto the current head.  This optimizes for the
870b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  // pattern of pulling a lot of pools into a single pool.
880b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  do {
890b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    AttributeList *next = pool->NextInPool;
900b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    pool->NextInPool = Head;
910b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    Head = pool;
920b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    pool = next;
930b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  } while (pool);
945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
952335191341a58fa3f8abea3c9b391c5bb03d67b3Chris Lattner
960b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCallAttributeList *
970b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCallAttributePool::createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
980b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall                                      SourceLocation TokLoc, int Arg) {
990b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  Expr *IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg),
1000b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall                                      C.IntTy, TokLoc);
10193f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt  return create(Name, TokLoc, 0, TokLoc, 0, TokLoc, &IArg, 1,
10293f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt                AttributeList::AS_GNU);
1030a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor}
1040a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor
1050c19b3c38e356058aeb2424d175eae232bf014d9Douglas Gregor#include "clang/Sema/AttrParsedAttrKinds.inc"
1060c19b3c38e356058aeb2424d175eae232bf014d9Douglas Gregor
107e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard SmithAttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
10893f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt                                           const IdentifierInfo *ScopeName,
10993f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt                                           Syntax SyntaxUsed) {
1105f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  StringRef AttrName = Name->getName();
1112335191341a58fa3f8abea3c9b391c5bb03d67b3Chris Lattner
1122335191341a58fa3f8abea3c9b391c5bb03d67b3Chris Lattner  // Normalize the attribute name, __foo__ becomes foo.
1135297d71e8c85f9b04dc31c690e91c6a2f7eddb90Richard Smith  if (AttrName.startswith("__") && AttrName.endswith("__") &&
1145297d71e8c85f9b04dc31c690e91c6a2f7eddb90Richard Smith      AttrName.size() >= 4)
1154f90d8d2b087450a84c331365017b2f53a60e09cDaniel Dunbar    AttrName = AttrName.substr(2, AttrName.size() - 4);
1161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
117e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith  SmallString<64> Buf;
118e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith  if (ScopeName)
11993f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt    Buf += ScopeName->getName();
12093f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt  // Ensure that in the case of C++11 attributes, we look for '::foo' if it is
12193f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt  // unscoped.
12293f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt  if (ScopeName || SyntaxUsed == AS_CXX11)
12393f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt    Buf += "::";
12493f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt  Buf += AttrName;
12593f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt
12693f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt  return ::getAttrKind(Buf);
1272335191341a58fa3f8abea3c9b391c5bb03d67b3Chris Lattner}
128