//===--- 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"

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);
#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 (IdentifierInfo *II = getAsIdentifierInfo()) {
    if (getNumArgs() == 0)
      return II->getName();
    
    std::string Res = II->getName();
    Res += ":";
    return Res;
  }
  
  // We have a multiple keyword selector (no embedded flags).
  return reinterpret_cast<MultiKeywordSelector *>(InfoPtr)->getName();
}


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

  void *InsertPos = 0;
  if (MultiKeywordSelector *SI = SelTab->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.
  MultiKeywordSelector *SI = 
    (MultiKeywordSelector*)malloc(sizeof(MultiKeywordSelector) + 
                                  nKeys*sizeof(IdentifierInfo *));
  new (SI) MultiKeywordSelector(nKeys, IIV);
  SelTab->InsertNode(SI, InsertPos);
  return Selector(SI);
}

SelectorTable::SelectorTable() {
  Impl = new llvm::FoldingSet<MultiKeywordSelector>;
}

SelectorTable::~SelectorTable() {
  delete static_cast<llvm::FoldingSet<MultiKeywordSelector> *>(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.RegisterRef(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;
}
