IdentifierTable.h revision 8e748ab52395328f2905855b295a22e33dc800b2
15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===--- IdentifierTable.h - Hash table for identifier lookup ---*- 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//
10c7229c338c21ef26b01ef3ecf9eec4fd373fa9ecChris Lattner// This file defines the IdentifierInfo, IdentifierTable, and Selector
11c7229c338c21ef26b01ef3ecf9eec4fd373fa9ecChris Lattner// interfaces.
125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
15c7229c338c21ef26b01ef3ecf9eec4fd373fa9ecChris Lattner#ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
16c7229c338c21ef26b01ef3ecf9eec4fd373fa9ecChris Lattner#define LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Basic/TokenKinds.h"
195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "llvm/ADT/StringMap.h"
2068d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff#include "llvm/ADT/SmallString.h"
2193a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek#include "llvm/Bitcode/SerializationFwd.h"
225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <string>
239dc62f044a6ba21f503bd56607d94b32704e7945Chris Lattner#include <cassert>
245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2585994260c41a54cab061a434ed378fc448333a4eChris Lattnernamespace llvm {
2685994260c41a54cab061a434ed378fc448333a4eChris Lattner  template <typename T> struct DenseMapInfo;
2785994260c41a54cab061a434ed378fc448333a4eChris Lattner}
2829238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff
295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencernamespace clang {
30b8128140956c6f8f0ab143818775a81f4b4aa477Chris Lattner  struct LangOptions;
3185994260c41a54cab061a434ed378fc448333a4eChris Lattner  class MultiKeywordSelector; // a private class used by Selector.
325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// IdentifierInfo - One of these records is kept for each identifier that
345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// is lexed.  This contains information about whether the token was #define'd,
355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// is a language keyword, or if it is a front-end token of some sort (e.g. a
365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// variable or function name).  The preprocessor keeps this information in a
375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// set, and all tok::identifier tokens have a pointer to one of these.
385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerclass IdentifierInfo {
398e748ab52395328f2905855b295a22e33dc800b2Ted Kremenek  // Note: DON'T make TokenID a 'tok::TokenKind'; MSVC will treat it as a
408e748ab52395328f2905855b295a22e33dc800b2Ted Kremenek  //       signed char and TokenKinds > 127 won't be handled correctly.
418e748ab52395328f2905855b295a22e33dc800b2Ted Kremenek  unsigned TokenID            : 8; // Front-end token ID or tok::identifier.
424365a7e46822700357a272d839ee2656d9603d5aChris Lattner  unsigned BuiltinID          : 9; // ID if this is a builtin (__builtin_inf).
435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  tok::ObjCKeywordKind ObjCID : 5; // ID for objc @ keyword like @'protocol'.
444365a7e46822700357a272d839ee2656d9603d5aChris Lattner  bool HasMacro               : 1; // True if there is a #define for this.
455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool IsExtension            : 1; // True if identifier is a lang extension.
465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool IsPoisoned             : 1; // True if identifier is poisoned.
475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool IsOtherTargetMacro     : 1; // True if ident is macro on another target.
485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool IsCPPOperatorKeyword   : 1; // True if ident is a C++ operator keyword.
495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool IsNonPortableBuiltin   : 1; // True if builtin varies across targets.
502d29581d2b7ad5ec5df6ff3947fb0711339361a4Chris Lattner  // 4 bits left in 32-bit word.
515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void *FETokenInfo;               // Managed by the language front-end.
525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  IdentifierInfo(const IdentifierInfo&);  // NONCOPYABLE.
534365a7e46822700357a272d839ee2656d9603d5aChris Lattner  void operator=(const IdentifierInfo&);  // NONASSIGNABLE.
545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerpublic:
555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  IdentifierInfo();
565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
573f128ad2691d299b96663da85a9e069c4081ea7cSteve Naroff  /// getName - Return the actual string for this identifier.  The returned
583f128ad2691d299b96663da85a9e069c4081ea7cSteve Naroff  /// string is properly null terminated.
595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ///
605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  const char *getName() const {
611f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner    // We know that this is embedded into a StringMapEntry, and it knows how to
621f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner    // efficiently find the string.
631f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner    return llvm::StringMapEntry<IdentifierInfo>::
641f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner                  GetStringMapEntryFromValue(*this).getKeyData();
651f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner  }
661f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner
671f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner  /// getLength - Efficiently return the length of this identifier info.
681f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner  ///
691f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner  unsigned getLength() const {
701f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner    return llvm::StringMapEntry<IdentifierInfo>::
711f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner                    GetStringMapEntryFromValue(*this).getKeyLength();
725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
749c46de446d18f4a28446cb798d4131bd05515699Chris Lattner  /// hasMacroDefinition - Return true if this identifier is #defined to some
759c46de446d18f4a28446cb798d4131bd05515699Chris Lattner  /// other value.
769c46de446d18f4a28446cb798d4131bd05515699Chris Lattner  bool hasMacroDefinition() const {
779c46de446d18f4a28446cb798d4131bd05515699Chris Lattner    return HasMacro;
789c46de446d18f4a28446cb798d4131bd05515699Chris Lattner  }
79cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattner  void setHasMacroDefinition(bool Val) { HasMacro = Val; }
805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// get/setTokenID - If this is a source-language token (e.g. 'for'), this API
825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// can be used to cause the lexer to map identifiers to source-language
835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// tokens.
848e748ab52395328f2905855b295a22e33dc800b2Ted Kremenek  tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; }
855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void setTokenID(tok::TokenKind ID) { TokenID = ID; }
865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// getPPKeywordID - Return the preprocessor keyword ID for this identifier.
886d9a3e648d6bf6b347174152f191bd1377528f8cChris Lattner  /// For example, "define" will return tok::pp_define.
89387b98d37e08f7aa9ddf23e067e1d27e39ce16f3Chris Lattner  tok::PPKeywordKind getPPKeywordID() const;
905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// getObjCKeywordID - Return the Objective-C keyword ID for the this
925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// identifier.  For example, 'class' will return tok::objc_class if ObjC is
935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// enabled.
945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  tok::ObjCKeywordKind getObjCKeywordID() const { return ObjCID; }
955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCID = ID; }
965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// getBuiltinID - Return a value indicating whether this is a builtin
985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// function.  0 is not-built-in.  1 is builtin-for-some-nonprimary-target.
995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// 2+ are specific builtin functions.
1005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  unsigned getBuiltinID() const { return BuiltinID; }
1015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void setBuiltinID(unsigned ID) {
1025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    BuiltinID = ID;
103adb83b41cb00acac7a9c035996318d88ecf2e6c8Chris Lattner    assert(BuiltinID == ID && "ID too large for field!");
1045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
1055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// isNonPortableBuiltin - Return true if this identifier corresponds to a
1075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// builtin on some other target, but isn't one on this target, or if it is on
1085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// the target but not on another, or if it is on both but it differs somehow
1095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// in behavior.
1105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool isNonPortableBuiltin() const { return IsNonPortableBuiltin; }
1115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void setNonPortableBuiltin(bool Val) { IsNonPortableBuiltin = Val; }
1125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// get/setExtension - Initialize information about whether or not this
1145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// language token is an extension.  This controls extension warnings, and is
1155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// only valid if a custom token ID is set.
1165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool isExtensionToken() const { return IsExtension; }
1175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void setIsExtensionToken(bool Val) { IsExtension = Val; }
1185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// setIsPoisoned - Mark this identifier as poisoned.  After poisoning, the
1205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// Preprocessor will emit an error every time this token is used.
1215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void setIsPoisoned(bool Value = true) { IsPoisoned = Value; }
1225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// isPoisoned - Return true if this token has been poisoned.
1245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool isPoisoned() const { return IsPoisoned; }
1255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// setIsOtherTargetMacro/isOtherTargetMacro control whether this identifier
1275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// is seen as being a macro on some other target.
1285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void setIsOtherTargetMacro(bool Val = true) { IsOtherTargetMacro = Val; }
1295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool isOtherTargetMacro() const { return IsOtherTargetMacro; }
1305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// isCPlusPlusOperatorKeyword/setIsCPlusPlusOperatorKeyword controls whether
1325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// this identifier is a C++ alternate representation of an operator.
133c637e6b7afeebc6b4f751e4373715b6a8ea77272Ted Kremenek  void setIsCPlusPlusOperatorKeyword(bool Val = true)
1345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    { IsCPPOperatorKeyword = Val; }
1355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; }
1365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// getFETokenInfo/setFETokenInfo - The language front-end is allowed to
1385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// associate arbitrary metadata with this token.
1395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  template<typename T>
1405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  T *getFETokenInfo() const { return static_cast<T*>(FETokenInfo); }
1415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void setFETokenInfo(void *T) { FETokenInfo = T; }
14293a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek
14393a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  /// Emit - Serialize this IdentifierInfo to a bitstream.
14493a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  void Emit(llvm::Serializer& S) const;
14593a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek
14693a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  /// Read - Deserialize an IdentifierInfo object from a bitstream.
14793a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  void Read(llvm::Deserializer& D);
1485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer};
1495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// IdentifierTable - This table implements an efficient mapping from strings to
1515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// IdentifierInfo nodes.  It has no other purpose, but this is an
1525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// extremely performance-critical piece of the code, as each occurrance of
1535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// every identifier goes through here when lexed.
1545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerclass IdentifierTable {
1555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Shark shows that using MallocAllocator is *much* slower than using this
1565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // BumpPtrAllocator!
1575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  typedef llvm::StringMap<IdentifierInfo, llvm::BumpPtrAllocator> HashTableTy;
1585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  HashTableTy HashTable;
1595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerpublic:
1605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// IdentifierTable ctor - Create the identifier table, populating it with
1615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// info about the language keywords for the language specified by LangOpts.
1625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  IdentifierTable(const LangOptions &LangOpts);
1635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// get - Return the identifier token info for the specified named identifier.
1655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ///
1665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  IdentifierInfo &get(const char *NameStart, const char *NameEnd) {
1675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return HashTable.GetOrCreateValue(NameStart, NameEnd).getValue();
1685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
1695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  IdentifierInfo &get(const char *Name) {
1715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return get(Name, Name+strlen(Name));
1725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
1735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  IdentifierInfo &get(const std::string &Name) {
1745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // Don't use c_str() here: no need to be null terminated.
1755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    const char *NameBytes = &Name[0];
1765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return get(NameBytes, NameBytes+Name.size());
1775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
1785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  typedef HashTableTy::const_iterator iterator;
1805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  typedef HashTableTy::const_iterator const_iterator;
1815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  iterator begin() const { return HashTable.begin(); }
1835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  iterator end() const   { return HashTable.end(); }
1845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
185c637e6b7afeebc6b4f751e4373715b6a8ea77272Ted Kremenek  unsigned size() const { return HashTable.size(); }
186c637e6b7afeebc6b4f751e4373715b6a8ea77272Ted Kremenek
1875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// PrintStats - Print some statistics to stderr that indicate how well the
1885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// hashing is doing.
1895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void PrintStats() const;
190bfa82c4c23ce96fdcf357a8f7ef70a9b71b69144Ted Kremenek
1915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void AddKeywords(const LangOptions &LangOpts);
192c637e6b7afeebc6b4f751e4373715b6a8ea77272Ted Kremenek
19393a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  /// Emit - Serialize this IdentifierTable to a bitstream.  This should
19493a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  ///  be called AFTER objects that externally reference the identifiers in the
19593a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  ///  table have been serialized.  This is because only the identifiers that
19693a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  ///  are actually referenced are serialized.
19793a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  void Emit(llvm::Serializer& S) const;
19893a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek
1990f84c0059cec39fd1c73ac05bc2864dca664e7f4Ted Kremenek  /// Create - Deserialize an IdentifierTable from a bitstream.
200bdbb285aed1bb1e20090a16929f4c1da33d2d5c5Ted Kremenek  static IdentifierTable* CreateAndRegister(llvm::Deserializer& D);
20193a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek
202c637e6b7afeebc6b4f751e4373715b6a8ea77272Ted Kremenekprivate:
203c637e6b7afeebc6b4f751e4373715b6a8ea77272Ted Kremenek  /// This ctor is not intended to be used by anyone except for object
204c637e6b7afeebc6b4f751e4373715b6a8ea77272Ted Kremenek  /// serialization.
20593a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  IdentifierTable();
2065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer};
2075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
20829238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff/// Selector - This smart pointer class efficiently represents Objective-C
20929238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff/// method names. This class will either point to an IdentifierInfo or a
21029238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff/// MultiKeywordSelector (which is private). This enables us to optimize
21129238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff/// selectors that no arguments and selectors that take 1 argument, which
21229238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff/// accounts for 78% of all selectors in Cocoa.h.
213bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroffclass Selector {
214bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  enum IdentifierInfoFlag {
2150e2dfd3963465d238e791eb8996e4d49fa47b615Chris Lattner    // MultiKeywordSelector = 0.
216bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    ZeroArg  = 0x1,
217bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    OneArg   = 0x2,
218bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    ArgFlags = ZeroArg|OneArg
219bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  };
220bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  uintptr_t InfoPtr; // a pointer to the MultiKeywordSelector or IdentifierInfo.
221bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff
222bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  Selector(IdentifierInfo *II, unsigned nArgs) {
223bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    InfoPtr = reinterpret_cast<uintptr_t>(II);
2240e2dfd3963465d238e791eb8996e4d49fa47b615Chris Lattner    assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo");
2250e2dfd3963465d238e791eb8996e4d49fa47b615Chris Lattner    assert(nArgs < 2 && "nArgs not equal to 0/1");
2260e2dfd3963465d238e791eb8996e4d49fa47b615Chris Lattner    InfoPtr |= nArgs+1;
227bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
228bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  Selector(MultiKeywordSelector *SI) {
229bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    InfoPtr = reinterpret_cast<uintptr_t>(SI);
2300e2dfd3963465d238e791eb8996e4d49fa47b615Chris Lattner    assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo");
231bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
232bdbb285aed1bb1e20090a16929f4c1da33d2d5c5Ted Kremenek  Selector(uintptr_t V) : InfoPtr(V) {}
23329238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroffpublic:
23429238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff  friend class SelectorTable; // only the SelectorTable can create these.
235bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff
236bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  IdentifierInfo *getAsIdentifierInfo() const {
2370e2dfd3963465d238e791eb8996e4d49fa47b615Chris Lattner    if (getIdentifierInfoFlag())
238bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff      return reinterpret_cast<IdentifierInfo *>(InfoPtr & ~ArgFlags);
239bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    return 0;
240bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
241bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  unsigned getIdentifierInfoFlag() const {
242bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    return InfoPtr & ArgFlags;
243bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
244bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  /// operator==/!= - Indicate whether the specified selectors are identical.
245bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  bool operator==(const Selector &RHS) const {
246bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    return InfoPtr == RHS.InfoPtr;
247bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
248bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  bool operator!=(const Selector &RHS) const {
249bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    return InfoPtr != RHS.InfoPtr;
250bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
251bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  void *getAsOpaquePtr() const {
252bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    return reinterpret_cast<void*>(InfoPtr);
253bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
254bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  // Predicates to identify the selector type.
255bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  bool isKeywordSelector() const {
256bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    return getIdentifierInfoFlag() != ZeroArg;
257bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
258bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  bool isUnarySelector() const {
259bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    return getIdentifierInfoFlag() == ZeroArg;
260bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
2615b6b72f53ad164497cf62484b60cdbb4361f1978Steve Naroff  unsigned getNumArgs() const;
262f836e3fea2c77fdbb18170fb313ee0d45551320bChris Lattner  IdentifierInfo *getIdentifierInfoForSlot(unsigned argIndex) const;
2635b6b72f53ad164497cf62484b60cdbb4361f1978Steve Naroff
264f836e3fea2c77fdbb18170fb313ee0d45551320bChris Lattner  /// getName - Derive the full selector name (e.g. "foo:bar:") and return it.
265f836e3fea2c77fdbb18170fb313ee0d45551320bChris Lattner  ///
266f836e3fea2c77fdbb18170fb313ee0d45551320bChris Lattner  std::string getName() const;
26785994260c41a54cab061a434ed378fc448333a4eChris Lattner
26885994260c41a54cab061a434ed378fc448333a4eChris Lattner  static Selector getEmptyMarker() {
26985994260c41a54cab061a434ed378fc448333a4eChris Lattner    return Selector(uintptr_t(-1));
27085994260c41a54cab061a434ed378fc448333a4eChris Lattner  }
27185994260c41a54cab061a434ed378fc448333a4eChris Lattner  static Selector getTombstoneMarker() {
27285994260c41a54cab061a434ed378fc448333a4eChris Lattner    return Selector(uintptr_t(-2));
27385994260c41a54cab061a434ed378fc448333a4eChris Lattner  }
274bdbb285aed1bb1e20090a16929f4c1da33d2d5c5Ted Kremenek
275bdbb285aed1bb1e20090a16929f4c1da33d2d5c5Ted Kremenek  // Emit - Emit a selector to bitcode.
276bdbb285aed1bb1e20090a16929f4c1da33d2d5c5Ted Kremenek  void Emit(llvm::Serializer& S) const;
277bdbb285aed1bb1e20090a16929f4c1da33d2d5c5Ted Kremenek
278bdbb285aed1bb1e20090a16929f4c1da33d2d5c5Ted Kremenek  // ReadVal - Read a selector from bitcode.
279bdbb285aed1bb1e20090a16929f4c1da33d2d5c5Ted Kremenek  static Selector ReadVal(llvm::Deserializer& D);
280bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff};
281bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff
28229238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff/// SelectorTable - This table allows us to fully hide how we implement
28329238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff/// multi-keyword caching.
28429238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroffclass SelectorTable {
28529238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff  void *Impl;  // Actually a FoldingSet<MultiKeywordSelector>*
28629238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff  SelectorTable(const SelectorTable&); // DISABLED: DO NOT IMPLEMENT
28729238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff  void operator=(const SelectorTable&); // DISABLED: DO NOT IMPLEMENT
28829238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroffpublic:
28929238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff  SelectorTable();
29029238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff  ~SelectorTable();
29129238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff
292ff38491c18b060526d754765b952f4a497a89416Chris Lattner  /// getSelector - This can create any sort of selector.  NumArgs indicates
293ff38491c18b060526d754765b952f4a497a89416Chris Lattner  /// whether this is a no argument selector "foo", a single argument selector
294ff38491c18b060526d754765b952f4a497a89416Chris Lattner  /// "foo:" or multi-argument "foo:bar:".
295ff38491c18b060526d754765b952f4a497a89416Chris Lattner  Selector getSelector(unsigned NumArgs, IdentifierInfo **IIV);
296ff38491c18b060526d754765b952f4a497a89416Chris Lattner
297ff38491c18b060526d754765b952f4a497a89416Chris Lattner  Selector getUnarySelector(IdentifierInfo *ID) {
298ff38491c18b060526d754765b952f4a497a89416Chris Lattner    return Selector(ID, 1);
299ff38491c18b060526d754765b952f4a497a89416Chris Lattner  }
300ff38491c18b060526d754765b952f4a497a89416Chris Lattner  Selector getNullarySelector(IdentifierInfo *ID) {
301ff38491c18b060526d754765b952f4a497a89416Chris Lattner    return Selector(ID, 0);
302ff38491c18b060526d754765b952f4a497a89416Chris Lattner  }
303bdbb285aed1bb1e20090a16929f4c1da33d2d5c5Ted Kremenek
304bdbb285aed1bb1e20090a16929f4c1da33d2d5c5Ted Kremenek  // Emit - Emit a SelectorTable to bitcode.
305bdbb285aed1bb1e20090a16929f4c1da33d2d5c5Ted Kremenek  void Emit(llvm::Serializer& S) const;
306bdbb285aed1bb1e20090a16929f4c1da33d2d5c5Ted Kremenek
307bdbb285aed1bb1e20090a16929f4c1da33d2d5c5Ted Kremenek  // Create - Reconstitute a SelectorTable from bitcode.
308bdbb285aed1bb1e20090a16929f4c1da33d2d5c5Ted Kremenek  static SelectorTable* CreateAndRegister(llvm::Deserializer& D);
30929238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff};
31029238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff
3115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}  // end namespace clang
3125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3134365a7e46822700357a272d839ee2656d9603d5aChris Lattner
3144365a7e46822700357a272d839ee2656d9603d5aChris Lattner/// Define DenseMapInfo so that Selectors can be used as keys in DenseMap and
3154365a7e46822700357a272d839ee2656d9603d5aChris Lattner/// DenseSets.
31685994260c41a54cab061a434ed378fc448333a4eChris Lattnernamespace llvm {
31785994260c41a54cab061a434ed378fc448333a4eChris Lattnertemplate <>
31885994260c41a54cab061a434ed378fc448333a4eChris Lattnerstruct DenseMapInfo<clang::Selector> {
31985994260c41a54cab061a434ed378fc448333a4eChris Lattner  static inline clang::Selector getEmptyKey() {
32085994260c41a54cab061a434ed378fc448333a4eChris Lattner    return clang::Selector::getEmptyMarker();
32185994260c41a54cab061a434ed378fc448333a4eChris Lattner  }
32285994260c41a54cab061a434ed378fc448333a4eChris Lattner  static inline clang::Selector getTombstoneKey() {
32385994260c41a54cab061a434ed378fc448333a4eChris Lattner    return clang::Selector::getTombstoneMarker();
32485994260c41a54cab061a434ed378fc448333a4eChris Lattner  }
32585994260c41a54cab061a434ed378fc448333a4eChris Lattner
32685994260c41a54cab061a434ed378fc448333a4eChris Lattner  static unsigned getHashValue(clang::Selector S);
32785994260c41a54cab061a434ed378fc448333a4eChris Lattner
32885994260c41a54cab061a434ed378fc448333a4eChris Lattner  static bool isEqual(clang::Selector LHS, clang::Selector RHS) {
32985994260c41a54cab061a434ed378fc448333a4eChris Lattner    return LHS == RHS;
33085994260c41a54cab061a434ed378fc448333a4eChris Lattner  }
33185994260c41a54cab061a434ed378fc448333a4eChris Lattner
33285994260c41a54cab061a434ed378fc448333a4eChris Lattner  static bool isPod() { return true; }
33385994260c41a54cab061a434ed378fc448333a4eChris Lattner};
33485994260c41a54cab061a434ed378fc448333a4eChris Lattner}  // end namespace llvm
33585994260c41a54cab061a434ed378fc448333a4eChris Lattner
3365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#endif
337