//===--- IdentifierTable.cpp - Hash table for identifier lookup -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the IdentifierInfo, IdentifierVisitor, and
// IdentifierTable interfaces.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Bitcode/Serialize.h"
#include "llvm/Bitcode/Deserialize.h"
#include <cstdio>

using namespace clang;

//===----------------------------------------------------------------------===//
// IdentifierInfo Implementation
//===----------------------------------------------------------------------===//

IdentifierInfo::IdentifierInfo() {
  TokenID = tok::identifier;
  ObjCOrBuiltinID = 0;
  HasMacro = false;
  IsExtension = false;
  IsPoisoned = false;
  IsCPPOperatorKeyword = false;
  NeedsHandleIdentifier = false;
  FETokenInfo = 0;
  Entry = 0;
}

//===----------------------------------------------------------------------===//
// IdentifierTable Implementation
//===----------------------------------------------------------------------===//

IdentifierInfoLookup::~IdentifierInfoLookup() {}

IdentifierTable::IdentifierTable(const LangOptions &LangOpts,
                                 IdentifierInfoLookup* externalLookup)
  : HashTable(8192), // Start with space for 8K identifiers.
    ExternalLookup(externalLookup) {

  // Populate the identifier table with info about keywords for the current
  // language.
  AddKeywords(LangOpts);
}

// This cstor is intended to be used only for serialization.
IdentifierTable::IdentifierTable() 
  : HashTable(8192), ExternalLookup(0) { }

//===----------------------------------------------------------------------===//
// Language Keyword Implementation
//===----------------------------------------------------------------------===//

/// AddKeyword - This method is used to associate a token ID with specific
/// identifiers because they are language keywords.  This causes the lexer to
/// automatically map matching identifiers to specialized token codes.
///
/// The C90/C99/CPP/CPP0x flags are set to 0 if the token should be
/// enabled in the specified langauge, set to 1 if it is an extension
/// in the specified language, and set to 2 if disabled in the
/// specified language.
static void AddKeyword(const char *Keyword, unsigned KWLen,
                       tok::TokenKind TokenCode,
                       int C90, int C99, int CXX, int CXX0x, int BoolSupport,
                       const LangOptions &LangOpts, IdentifierTable &Table) {
  int Flags = 0;
  if (BoolSupport != 0) {
    Flags = LangOpts.CPlusPlus? 0 : LangOpts.Boolean ? BoolSupport : 2;
  } else if (LangOpts.CPlusPlus) {
    Flags = LangOpts.CPlusPlus0x ? CXX0x : CXX;
  } else if (LangOpts.C99) {
    Flags = C99;
  } else {
    Flags = C90;
  }
  
  // Don't add this keyword if disabled in this language or if an extension
  // and extensions are disabled.
  if (Flags + LangOpts.NoExtensions >= 2) return;
  
  IdentifierInfo &Info = Table.get(Keyword, Keyword+KWLen);
  Info.setTokenID(TokenCode);
  Info.setIsExtensionToken(Flags == 1);
}

static void AddAlias(const char *Keyword, unsigned KWLen,
                     tok::TokenKind AliaseeID,
                     const char *AliaseeKeyword, unsigned AliaseeKWLen,
                     const LangOptions &LangOpts, IdentifierTable &Table) {
  IdentifierInfo &AliasInfo = Table.get(Keyword, Keyword+KWLen);
  IdentifierInfo &AliaseeInfo = Table.get(AliaseeKeyword,
                                          AliaseeKeyword+AliaseeKWLen);
  AliasInfo.setTokenID(AliaseeID);
  AliasInfo.setIsExtensionToken(AliaseeInfo.isExtensionToken());
}  

/// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
/// representations.
static void AddCXXOperatorKeyword(const char *Keyword, unsigned KWLen,
                                  tok::TokenKind TokenCode,
                                  IdentifierTable &Table) {
  IdentifierInfo &Info = Table.get(Keyword, Keyword + KWLen);
  Info.setTokenID(TokenCode);
  Info.setIsCPlusPlusOperatorKeyword();
}

/// AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or 
/// "property".
static void AddObjCKeyword(tok::ObjCKeywordKind ObjCID, 
                           const char *Name, unsigned NameLen,
                           IdentifierTable &Table) {
  Table.get(Name, Name+NameLen).setObjCKeywordID(ObjCID);
}

/// AddKeywords - Add all keywords to the symbol table.
///
void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
  enum {
    C90Shift = 0,
    EXTC90   = 1 << C90Shift,
    NOTC90   = 2 << C90Shift,
    C99Shift = 2,
    EXTC99   = 1 << C99Shift,
    NOTC99   = 2 << C99Shift,
    CPPShift = 4,
    EXTCPP   = 1 << CPPShift,
    NOTCPP   = 2 << CPPShift,
    CPP0xShift = 6,
    EXTCPP0x   = 1 << CPP0xShift,
    NOTCPP0x   = 2 << CPP0xShift,
    BoolShift = 8,
    BOOLSUPPORT = 1 << BoolShift,
    Mask     = 3
  };
  
  // Add keywords and tokens for the current language.
#define KEYWORD(NAME, FLAGS) \
  AddKeyword(#NAME, strlen(#NAME), tok::kw_ ## NAME,  \
             ((FLAGS) >> C90Shift) & Mask, \
             ((FLAGS) >> C99Shift) & Mask, \
             ((FLAGS) >> CPPShift) & Mask, \
             ((FLAGS) >> CPP0xShift) & Mask, \
             ((FLAGS) >> BoolShift) & Mask, LangOpts, *this);
#define ALIAS(NAME, TOK) \
  AddAlias(NAME, strlen(NAME), tok::kw_ ## TOK, #TOK, strlen(#TOK),  \
           LangOpts, *this);
#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
  if (LangOpts.CXXOperatorNames)          \
    AddCXXOperatorKeyword(#NAME, strlen(#NAME), tok::ALIAS, *this);
#define OBJC1_AT_KEYWORD(NAME) \
  if (LangOpts.ObjC1)          \
    AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
#define OBJC2_AT_KEYWORD(NAME) \
  if (LangOpts.ObjC2)          \
    AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
#include "clang/Basic/TokenKinds.def"
}

tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
  // We use a perfect hash function here involving the length of the keyword,
  // the first and third character.  For preprocessor ID's there are no
  // collisions (if there were, the switch below would complain about duplicate
  // case values).  Note that this depends on 'if' being null terminated.
  
#define HASH(LEN, FIRST, THIRD) \
  (LEN << 5) + (((FIRST-'a') + (THIRD-'a')) & 31)
#define CASE(LEN, FIRST, THIRD, NAME) \
  case HASH(LEN, FIRST, THIRD): \
    return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
    
  unsigned Len = getLength();
  if (Len < 2) return tok::pp_not_keyword;
  const char *Name = getName();
  switch (HASH(Len, Name[0], Name[2])) {
  default: return tok::pp_not_keyword;
  CASE( 2, 'i', '\0', if);
  CASE( 4, 'e', 'i', elif);
  CASE( 4, 'e', 's', else);
  CASE( 4, 'l', 'n', line);
  CASE( 4, 's', 'c', sccs);
  CASE( 5, 'e', 'd', endif);
  CASE( 5, 'e', 'r', error);
  CASE( 5, 'i', 'e', ident);
  CASE( 5, 'i', 'd', ifdef);
  CASE( 5, 'u', 'd', undef);

  CASE( 6, 'a', 's', assert);
  CASE( 6, 'd', 'f', define);
  CASE( 6, 'i', 'n', ifndef);
  CASE( 6, 'i', 'p', import);
  CASE( 6, 'p', 'a', pragma);

  CASE( 7, 'd', 'f', defined);
  CASE( 7, 'i', 'c', include);
  CASE( 7, 'w', 'r', warning);

  CASE( 8, 'u', 'a', unassert);
  CASE(12, 'i', 'c', include_next);
      
  CASE(16, '_', 'i', __include_macros);
#undef CASE
#undef HASH
  }
}

//===----------------------------------------------------------------------===//
// Stats Implementation
//===----------------------------------------------------------------------===//

/// PrintStats - Print statistics about how well the identifier table is doing
/// at hashing identifiers.
void IdentifierTable::PrintStats() const {
  unsigned NumBuckets = HashTable.getNumBuckets();
  unsigned NumIdentifiers = HashTable.getNumItems();
  unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
  unsigned AverageIdentifierSize = 0;
  unsigned MaxIdentifierLength = 0;
  
  // TODO: Figure out maximum times an identifier had to probe for -stats.
  for (llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator>::const_iterator
       I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
    unsigned IdLen = I->getKeyLength();
    AverageIdentifierSize += IdLen;
    if (MaxIdentifierLength < IdLen)
      MaxIdentifierLength = IdLen;
  }
  
  fprintf(stderr, "\n*** Identifier Table Stats:\n");
  fprintf(stderr, "# Identifiers:   %d\n", NumIdentifiers);
  fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets);
  fprintf(stderr, "Hash density (#identifiers per bucket): %f\n",
          NumIdentifiers/(double)NumBuckets);
  fprintf(stderr, "Ave identifier length: %f\n",
          (AverageIdentifierSize/(double)NumIdentifiers));
  fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength);
  
  // Compute statistics about the memory allocated for identifiers.
  HashTable.getAllocator().PrintStats();
}

//===----------------------------------------------------------------------===//
// SelectorTable Implementation
//===----------------------------------------------------------------------===//

unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) {
  return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());
}

namespace clang {
/// MultiKeywordSelector - One of these variable length records is kept for each
/// selector containing more than one keyword. We use a folding set
/// to unique aggregate names (keyword selectors in ObjC parlance). Access to 
/// this class is provided strictly through Selector.
class MultiKeywordSelector 
  : public DeclarationNameExtra, public llvm::FoldingSetNode {
  friend SelectorTable* SelectorTable::CreateAndRegister(llvm::Deserializer&);
  MultiKeywordSelector(unsigned nKeys) {
    ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys;
  }
public:  
  // Constructor for keyword selectors.
  MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV) {
    assert((nKeys > 1) && "not a multi-keyword selector");
    ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys;
    
    // Fill in the trailing keyword array.
    IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(this+1);
    for (unsigned i = 0; i != nKeys; ++i)
      KeyInfo[i] = IIV[i];
  }  
  
  // getName - Derive the full selector name and return it.
  std::string getName() const;
    
  unsigned getNumArgs() const { return ExtraKindOrNumArgs - NUM_EXTRA_KINDS; }
  
  typedef IdentifierInfo *const *keyword_iterator;
  keyword_iterator keyword_begin() const {
    return reinterpret_cast<keyword_iterator>(this+1);
  }
  keyword_iterator keyword_end() const { 
    return keyword_begin()+getNumArgs(); 
  }
  IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const {
    assert(i < getNumArgs() && "getIdentifierInfoForSlot(): illegal index");
    return keyword_begin()[i];
  }
  static void Profile(llvm::FoldingSetNodeID &ID, 
                      keyword_iterator ArgTys, unsigned NumArgs) {
    ID.AddInteger(NumArgs);
    for (unsigned i = 0; i != NumArgs; ++i)
      ID.AddPointer(ArgTys[i]);
  }
  void Profile(llvm::FoldingSetNodeID &ID) {
    Profile(ID, keyword_begin(), getNumArgs());
  }
};
} // end namespace clang.

unsigned Selector::getNumArgs() const {
  unsigned IIF = getIdentifierInfoFlag();
  if (IIF == ZeroArg)
    return 0;
  if (IIF == OneArg)
    return 1;
  // We point to a MultiKeywordSelector (pointer doesn't contain any flags).
  MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
  return SI->getNumArgs(); 
}

IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
  if (IdentifierInfo *II = getAsIdentifierInfo()) {
    assert(argIndex == 0 && "illegal keyword index");
    return II;
  }
  // We point to a MultiKeywordSelector (pointer doesn't contain any flags).
  MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
  return SI->getIdentifierInfoForSlot(argIndex);
}

std::string MultiKeywordSelector::getName() const {
  std::string Result;
  unsigned Length = 0;
  for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
    if (*I)
      Length += (*I)->getLength();
    ++Length;  // :
  }
  
  Result.reserve(Length);
  
  for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
    if (*I)
      Result.insert(Result.end(), (*I)->getName(),
                    (*I)->getName()+(*I)->getLength());
    Result.push_back(':');
  }
  
  return Result;
}

std::string Selector::getAsString() const {
  if (InfoPtr & ArgFlags) {
    IdentifierInfo *II = getAsIdentifierInfo();
    
    // If the number of arguments is 0 then II is guaranteed to not be null.
    if (getNumArgs() == 0)
      return II->getName();

    std::string Res = II ? II->getName() : "";
    Res += ":";
    return Res;
  }
  
  // We have a multiple keyword selector (no embedded flags).
  return reinterpret_cast<MultiKeywordSelector *>(InfoPtr)->getName();
}


namespace {
  struct SelectorTableImpl {
    llvm::FoldingSet<MultiKeywordSelector> Table;
    llvm::BumpPtrAllocator Allocator;
  };
} // end anonymous namespace.

static SelectorTableImpl &getSelectorTableImpl(void *P) {
  return *static_cast<SelectorTableImpl*>(P);
}


Selector SelectorTable::getSelector(unsigned nKeys, IdentifierInfo **IIV) {
  if (nKeys < 2)
    return Selector(IIV[0], nKeys);
  
  SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
    
  // Unique selector, to guarantee there is one per name.
  llvm::FoldingSetNodeID ID;
  MultiKeywordSelector::Profile(ID, IIV, nKeys);

  void *InsertPos = 0;
  if (MultiKeywordSelector *SI =
        SelTabImpl.Table.FindNodeOrInsertPos(ID, InsertPos))
    return Selector(SI);
  
  // MultiKeywordSelector objects are not allocated with new because they have a
  // variable size array (for parameter types) at the end of them.
  unsigned Size = sizeof(MultiKeywordSelector) + nKeys*sizeof(IdentifierInfo *);
  MultiKeywordSelector *SI =
    (MultiKeywordSelector*)SelTabImpl.Allocator.Allocate(Size, 
                                         llvm::alignof<MultiKeywordSelector>());
  new (SI) MultiKeywordSelector(nKeys, IIV);
  SelTabImpl.Table.InsertNode(SI, InsertPos);
  return Selector(SI);
}

SelectorTable::SelectorTable() {
  Impl = new SelectorTableImpl();
}

SelectorTable::~SelectorTable() {
  delete &getSelectorTableImpl(Impl);
}

//===----------------------------------------------------------------------===//
// Serialization for IdentifierInfo and IdentifierTable.
//===----------------------------------------------------------------------===//

void IdentifierInfo::Emit(llvm::Serializer& S) const {
  S.EmitInt(getTokenID());
  S.EmitInt(getBuiltinID());
  S.EmitInt(getObjCKeywordID());  
  S.EmitBool(hasMacroDefinition());
  S.EmitBool(isExtensionToken());
  S.EmitBool(isPoisoned());
  S.EmitBool(isCPlusPlusOperatorKeyword());
  // FIXME: FETokenInfo
}

void IdentifierInfo::Read(llvm::Deserializer& D) {
  setTokenID((tok::TokenKind) D.ReadInt());
  setBuiltinID(D.ReadInt());  
  setObjCKeywordID((tok::ObjCKeywordKind) D.ReadInt());  
  setHasMacroDefinition(D.ReadBool());
  setIsExtensionToken(D.ReadBool());
  setIsPoisoned(D.ReadBool());
  setIsCPlusPlusOperatorKeyword(D.ReadBool());
  // FIXME: FETokenInfo
}

void IdentifierTable::Emit(llvm::Serializer& S) const {
  S.EnterBlock();
  
  S.EmitPtr(this);
  
  for (iterator I=begin(), E=end(); I != E; ++I) {
    const char* Key = I->getKeyData();
    const IdentifierInfo* Info = I->getValue();
    
    bool KeyRegistered = S.isRegistered(Key);
    bool InfoRegistered = S.isRegistered(Info);
    
    if (KeyRegistered || InfoRegistered) {
      // These acrobatics are so that we don't incur the cost of registering
      // a pointer with the backpatcher during deserialization if nobody
      // references the object.
      S.EmitPtr(InfoRegistered ? Info : NULL);
      S.EmitPtr(KeyRegistered ? Key : NULL);
      S.EmitCStr(Key);
      S.Emit(*Info);
    }
  }
  
  S.ExitBlock();
}

IdentifierTable* IdentifierTable::CreateAndRegister(llvm::Deserializer& D) {
  llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();

  std::vector<char> buff;
  buff.reserve(200);

  IdentifierTable* t = new IdentifierTable();
  D.RegisterPtr(t);  
  
  while (!D.FinishedBlock(BLoc)) {
    llvm::SerializedPtrID InfoPtrID = D.ReadPtrID();
    llvm::SerializedPtrID KeyPtrID = D.ReadPtrID();
    
    D.ReadCStr(buff);
    IdentifierInfo *II = &t->get(&buff[0], &buff[0] + buff.size());
    II->Read(D);
    
    if (InfoPtrID) D.RegisterPtr(InfoPtrID, II);
    if (KeyPtrID)  D.RegisterPtr(KeyPtrID, II->getName());
  }
  
  return t;
}

//===----------------------------------------------------------------------===//
// Serialization for Selector and SelectorTable.
//===----------------------------------------------------------------------===//

void Selector::Emit(llvm::Serializer& S) const {
  S.EmitInt(getIdentifierInfoFlag());
  S.EmitPtr(reinterpret_cast<void*>(InfoPtr & ~ArgFlags));
}

Selector Selector::ReadVal(llvm::Deserializer& D) {
  unsigned flag = D.ReadInt();
  
  uintptr_t ptr;  
  D.ReadUIntPtr(ptr,false); // No backpatching.
  
  return Selector(ptr | flag);
}

void SelectorTable::Emit(llvm::Serializer& S) const {
  typedef llvm::FoldingSet<MultiKeywordSelector>::iterator iterator;
  llvm::FoldingSet<MultiKeywordSelector> *SelTab;
  SelTab = static_cast<llvm::FoldingSet<MultiKeywordSelector> *>(Impl);
  
  S.EnterBlock();
  
  S.EmitPtr(this);
  
  for (iterator I=SelTab->begin(), E=SelTab->end(); I != E; ++I) {
    if (!S.isRegistered(&*I))
      continue;
    
    S.FlushRecord(); // Start a new record.

    S.EmitPtr(&*I);
    S.EmitInt(I->getNumArgs());

    for (MultiKeywordSelector::keyword_iterator KI = I->keyword_begin(),
         KE = I->keyword_end(); KI != KE; ++KI)
      S.EmitPtr(*KI);
  }
  
  S.ExitBlock();
}

SelectorTable* SelectorTable::CreateAndRegister(llvm::Deserializer& D) {
  llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();
  
  SelectorTable* t = new SelectorTable();
  D.RegisterPtr(t);
  
  llvm::FoldingSet<MultiKeywordSelector>& SelTab =
    *static_cast<llvm::FoldingSet<MultiKeywordSelector>*>(t->Impl);

  while (!D.FinishedBlock(BLoc)) {

    llvm::SerializedPtrID PtrID = D.ReadPtrID();
    unsigned nKeys = D.ReadInt();
    
    MultiKeywordSelector *SI = 
      (MultiKeywordSelector*)malloc(sizeof(MultiKeywordSelector) + 
                                    nKeys*sizeof(IdentifierInfo *));

    new (SI) MultiKeywordSelector(nKeys);
    
    D.RegisterPtr(PtrID,SI);

    IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(SI+1);

    for (unsigned i = 0; i != nKeys; ++i)
      D.ReadPtr(KeyInfo[i],false);
    
    SelTab.GetOrInsertNode(SI);
  }
  
  return t;
}
