// $Id: lookup.h,v 1.37 2004/01/26 06:07:16 cabbey Exp $ -*- c++ -*- // // This software is subject to the terms of the IBM Jikes Compiler // License Agreement available at the following URL: // http://ibm.com/developerworks/opensource/jikes. // Copyright (C) 1996, 2004 IBM Corporation and others. All Rights Reserved. // You must accept the terms of that agreement to use this software. // #ifndef lookup_INCLUDED #define lookup_INCLUDED #include "platform.h" #include "tuple.h" #include "long.h" #include "double.h" #ifdef HAVE_JIKES_NAMESPACE namespace Jikes { // Open namespace Jikes block #endif class Control; class Symbol; class PackageSymbol; class TypeSymbol; class MethodSymbol; class MethodShadowSymbol; class BlockSymbol; class VariableSymbol; class VariableShadowSymbol; class LabelSymbol; class LiteralSymbol; class NameSymbol; class PathSymbol; class DirectorySymbol; class FileSymbol; class ShadowSymbol; class LiteralValue; class IntLiteralValue; class LongLiteralValue; class FloatLiteralValue; class DoubleLiteralValue; class Utf8LiteralValue; class Utf8LiteralTable; class NameLookupTable; class TypeLookupTable; class LiteralLookupTable; class AstBinaryExpression; class AstExpression; class Hash { public: // // HASH takes as argument a pointer to a character string // and its length which it hashes it into a location in the name // hash table. // inline static unsigned Function(const wchar_t* head, int len) { unsigned hash_value = 0; while (--len >= 0) hash_value = (hash_value << 5) - hash_value + *head++; return hash_value; } // // Same as above function for a regular "char" string. // inline static unsigned Function(const char* head, int len) { unsigned hash_value = 0; while (--len >= 0) hash_value = (hash_value << 5) - hash_value + *head++; return hash_value; } inline static unsigned Function(LongInt value) { return value.hashCode(); } inline static unsigned Function(IEEEfloat value) { return value.hashCode(); } inline static unsigned Function(IEEEdouble value) { return value.hashCode(); } }; class DirectoryEntry { public: DirectoryEntry* next; char* name; int length; DirectoryEntry() : next(NULL), name(NULL), length(0), directory(NULL), mtime_(0) { image = this; } virtual ~DirectoryEntry() { delete [] name; } inline void Initialize(DirectorySymbol* directory_, char* name_, int length_) { directory = directory_; length = length_; name = new char[length + 1]; memcpy(name, name_, length * sizeof(char)); name[length] = U_NULL; } inline void Initialize(DirectoryEntry* entry, char* name_, int length_) { Initialize(entry -> directory, name_, length_); } time_t Mtime(); bool IsDummy() { return this != image; } // // See FoldedDirectoryEntry for an explanation of the use of this function // virtual DirectoryEntry* Image() { return this; } protected: DirectorySymbol* directory; DirectoryEntry* image; time_t mtime_; }; #ifdef WIN32_FILE_SYSTEM // // This object is needed only for systems such as Windows NT/95/98 that // treat filenames in a case-insensitive fashion. // class FoldedDirectoryEntry : public DirectoryEntry { public: FoldedDirectoryEntry(DirectoryEntry* image_) { DirectoryEntry::image = image_; } virtual ~FoldedDirectoryEntry() {} virtual DirectoryEntry* Image() { return image; } }; #endif // WIN32_FILE_SYSTEM class SystemTable { enum { DEFAULT_HASH_SIZE = 13, MAX_HASH_SIZE = 1021 }; public: SystemTable(unsigned = DEFAULT_HASH_SIZE); virtual ~SystemTable(); DirectorySymbol* FindDirectorySymbol(dev_t, ino_t); void InsertDirectorySymbol(dev_t, ino_t, DirectorySymbol*); private: class Element { public: Element(dev_t device_, ino_t inode_, DirectorySymbol* directory_symbol_) : device(device_), inode(inode_), directory_symbol(directory_symbol_) {} Element* next; dev_t device; ino_t inode; DirectorySymbol* directory_symbol; }; Tuple directories; Element** base; unsigned hash_size; static unsigned primes[]; int prime_index; unsigned hash(dev_t device, ino_t inode) { return (device + inode) % hash_size; } void Rehash(); }; class DirectoryTable { public: Tuple entry_pool; DirectoryTable(int estimate = 1024); ~DirectoryTable(); DirectoryEntry* FindEntry(char*, int); DirectoryEntry* InsertEntry(DirectorySymbol*, char*, int); #ifdef WIN32_FILE_SYSTEM // // See FoldedDirectoryEntry for an explanation of the use of this function // DirectoryEntry* FindCaseInsensitiveEntry(char*, int); void InsertCaseInsensitiveEntry(DirectoryEntry*); #endif private: enum { DEFAULT_HASH_SIZE = 1021, MAX_HASH_SIZE = 8191 }; DirectoryEntry** base; unsigned hash_size; static unsigned primes[]; int prime_index; inline static unsigned Hash(const char* head, int len) { return Hash::Function(head, len); } void Rehash(); }; class Symbol { public: Symbol* next; enum SymbolKind { NONE, NAME, PACKAGE, TYPE, // class or interface METHOD, BLOCK, VARIABLE, LABEL, LITERAL, PATH, _DIRECTORY, _FILE, _num_kinds }; SymbolKind Kind() const { return _kind; } virtual const wchar_t* Name() const { return NULL; } virtual unsigned NameLength() const { return 0; } virtual const NameSymbol* Identity() const { return NULL; } inline unsigned HashCode() const; // // These cannot be inline without including symbol.h, because they // would cast to incomplete types. // PackageSymbol* PackageCast(); const PackageSymbol* PackageCast() const; TypeSymbol* TypeCast(); const TypeSymbol* TypeCast() const; MethodSymbol* MethodCast(); const MethodSymbol* MethodCast() const; BlockSymbol* BlockCast(); const BlockSymbol* BlockCast() const; VariableSymbol* VariableCast(); const VariableSymbol* VariableCast() const; LabelSymbol* LabelCast(); const LabelSymbol* LabelCast() const; LiteralSymbol* LiteralCast(); const LiteralSymbol* LiteralCast() const; NameSymbol* NameCast(); const NameSymbol* NameCast() const; PathSymbol* PathCast(); const PathSymbol* PathCast() const; DirectorySymbol* DirectoryCast(); const DirectorySymbol* DirectoryCast() const; FileSymbol* FileCast(); const FileSymbol* FileCast() const; virtual ~Symbol() {} protected: SymbolKind _kind; }; class LiteralValue { public: LiteralValue* next; int index; virtual ~LiteralValue() {} }; class IntLiteralValue : public LiteralValue { public: i4 value; virtual ~IntLiteralValue() {} void Initialize(int value_, int index_) { value = value_; index = index_; } }; class LongLiteralValue : public LiteralValue { public: LongInt value; virtual ~LongLiteralValue() {} void Initialize(LongInt value_, int index_) { value = value_; index = index_; } }; class FloatLiteralValue : public LiteralValue { public: IEEEfloat value; virtual ~FloatLiteralValue() {} void Initialize(IEEEfloat value_, int index_) { value = value_; index = index_; } }; class DoubleLiteralValue : public LiteralValue { public: IEEEdouble value; virtual ~DoubleLiteralValue() {} void Initialize(IEEEdouble value_, int index_) { value = value_; index = index_; } }; class Utf8LiteralValue : public LiteralValue { public: char* value; int length; Utf8LiteralValue() : value(NULL) {} virtual ~Utf8LiteralValue() { delete [] value; } void Initialize(const char* value_, int length_, unsigned hash_address_, int index_) { length = length_; value = new char[length + 1]; memcpy(value, value_, length * sizeof(char)); value[length] = U_NULL; hash_address = hash_address_; index = index_; } private: friend class Utf8LiteralTable; unsigned hash_address; }; class NameSymbol : public Symbol { public: int index; Utf8LiteralValue* Utf8_literal; virtual const wchar_t* Name() const { return name_; } virtual unsigned NameLength() const { return length; } virtual const NameSymbol* Identity() const { return this; } const char* Utf8Name() const { return Utf8_literal ? Utf8_literal -> value : (char*) NULL; } unsigned Utf8NameLength() const { return Utf8_literal ? Utf8_literal -> length : 0; } bool IsBadStyleForClass() const; bool IsBadStyleForConstantField() const; bool IsBadStyleForField() const; bool IsBadStyleForMethod() const; bool IsBadStyleForVariable() const; NameSymbol() : name_(NULL) {} virtual ~NameSymbol() { delete [] name_; } inline void Initialize(const wchar_t* str, unsigned length_, unsigned hash_address_, int index_) { Symbol::_kind = NAME; hash_address = hash_address_; index = index_; length = length_; name_ = new wchar_t[length + 1]; memcpy(name_, str, length * sizeof(wchar_t)); name_[length] = U_NULL; Utf8_literal = NULL; } private: bool Contains(wchar_t character) const; friend class NameLookupTable; wchar_t* name_; unsigned length; unsigned hash_address; }; class NameLookupTable { public: Tuple symbol_pool; NameLookupTable(int estimate = 16384); ~NameLookupTable(); NameSymbol* FindOrInsertName(const wchar_t*, unsigned); private: enum { DEFAULT_HASH_SIZE = 4093, MAX_HASH_SIZE = 32771 }; NameSymbol** base; unsigned hash_size; static unsigned primes[]; int prime_index; inline static unsigned Hash(const wchar_t* head, int len) { return Hash::Function(head, len); } void Rehash(); }; class TypeLookupTable { public: TypeLookupTable(int estimate = 16384); ~TypeLookupTable(); TypeSymbol* FindType(const char*, int); void InsertType(TypeSymbol*); void SetEmpty(); private: Tuple symbol_pool; enum { DEFAULT_HASH_SIZE = 4093, MAX_HASH_SIZE = 32771 }; TypeSymbol** base; unsigned hash_size; static unsigned primes[]; int prime_index; inline static unsigned Hash(const char* head, int len) { return Hash::Function(head, len); } void Rehash(); }; class LiteralSymbol : public Symbol { public: LiteralValue* value; virtual const wchar_t* Name() const { return name_; } virtual unsigned NameLength() const { return length; } virtual const NameSymbol* Identity() const { return NULL; } LiteralSymbol() : name_(NULL) {} virtual ~LiteralSymbol() { delete [] name_; } void Initialize(const wchar_t* str, unsigned hash_address_, int length_) { Symbol::_kind = LITERAL; hash_address = hash_address_; length = length_; name_ = new wchar_t[length + 1]; memcpy(name_, str, length * sizeof(wchar_t)); name_[length] = U_NULL; value = NULL; } private: friend class LiteralLookupTable; wchar_t* name_; int length; unsigned hash_address; }; class LiteralLookupTable { public: Tuple symbol_pool; LiteralLookupTable(); ~LiteralLookupTable(); LiteralSymbol* FindOrInsertLiteral(const wchar_t*, unsigned); private: enum { DEFAULT_HASH_SIZE = 1021, MAX_HASH_SIZE = 8191 }; LiteralSymbol** base; unsigned hash_size; static unsigned primes[]; int prime_index; inline static unsigned Hash(const wchar_t* head, int len) { return Hash::Function(head, len); } void Rehash(); }; class IntLiteralTable { public: Tuple symbol_pool; IntLiteralTable(LiteralValue*); ~IntLiteralTable(); LiteralValue* FindOrInsertNull() { return FindOrInsert(0); } LiteralValue* FindOrInsertChar(LiteralSymbol*); LiteralValue* FindOrInsertInt(LiteralSymbol*); LiteralValue* FindOrInsertHexInt(LiteralSymbol*); LiteralValue* FindOrInsertOctalInt(LiteralSymbol*); LiteralValue* FindOrInsertNegativeInt(LiteralSymbol*); IntLiteralValue* FindOrInsert(i4); IntLiteralValue* Find(i4); // Forwarding methods, if needed, so that Find(0) works. #ifndef TYPE_I4_IS_INT inline IntLiteralValue* FindOrInsert(int i) { return FindOrInsert((i4) i); } inline IntLiteralValue* Find(int i) { return Find((i4) i); } #endif // TYPE_I4_IS_INT #ifdef JIKES_DEBUG // // To prevent arithmetic conversion to allow illegal calls inadvertently. // Since the return type is wrong, compilation will fail ! // void FindOrInsert(LongInt) {} void FindOrInsert(float) {} void FindOrInsert(double) {} #endif private: enum { DEFAULT_HASH_SIZE = 4093, MAX_HASH_SIZE = 32771 }; IntLiteralValue** base; unsigned hash_size; static unsigned primes[]; int prime_index; static int int32_limit; LiteralValue* bad_value; void Rehash(); }; class LongLiteralTable { public: Tuple symbol_pool; LongLiteralTable(LiteralValue*); ~LongLiteralTable(); LiteralValue* FindOrInsertLong(LiteralSymbol*); LiteralValue* FindOrInsertHexLong(LiteralSymbol*); LiteralValue* FindOrInsertOctalLong(LiteralSymbol*); LiteralValue* FindOrInsertNegativeLong(LiteralSymbol*); LongLiteralValue* FindOrInsert(LongInt); #ifdef JIKES_DEBUG // // To prevent arithmetic conversion to allow illegal calls inadvertently. // void FindOrInsert(int) {} void FindOrInsert(float) {} void FindOrInsert(double) {} #endif private: enum { DEFAULT_HASH_SIZE = 1021, MAX_HASH_SIZE = 8191 }; LongLiteralValue** base; unsigned hash_size; static unsigned primes[]; int prime_index; static LongInt int64_limit; LiteralValue* bad_value; inline static unsigned Hash(LongInt value) { return Hash::Function(value); } void Rehash(); }; class FloatLiteralTable { public: Tuple symbol_pool; FloatLiteralTable(LiteralValue*); ~FloatLiteralTable(); LiteralValue* FindOrInsertFloat(LiteralSymbol*); FloatLiteralValue* FindOrInsert(IEEEfloat); #ifdef JIKES_DEBUG // // To prevent arithmetic conversion to allow illegal calls inadvertently. // void FindOrInsert(int) {} void FindOrInsert(LongInt) {} void FindOrInsert(double) {} #endif private: enum { DEFAULT_HASH_SIZE = 1021, MAX_HASH_SIZE = 8191 }; FloatLiteralValue** base; unsigned hash_size; static unsigned primes[]; int prime_index; LiteralValue* bad_value; inline static unsigned Hash(IEEEfloat value) { return Hash::Function(value); } void Rehash(); }; class DoubleLiteralTable { public: Tuple symbol_pool; DoubleLiteralTable(LiteralValue*); ~DoubleLiteralTable(); LiteralValue* FindOrInsertDouble(LiteralSymbol*); DoubleLiteralValue* FindOrInsert(IEEEdouble); #ifdef JIKES_DEBUG // // To prevent arithmetic conversion to allow illegal calls inadvertently. // void FindOrInsert(int) {} void FindOrInsert(LongInt) {} void FindOrInsert(float) {} #endif private: enum { DEFAULT_HASH_SIZE = 1021, MAX_HASH_SIZE = 8191 }; DoubleLiteralValue** base; unsigned hash_size; static unsigned primes[]; int prime_index; LiteralValue* bad_value; inline static unsigned Hash(IEEEdouble value) { return Hash::Function(value); } void Rehash(); }; class Utf8LiteralTable { public: Tuple symbol_pool; Utf8LiteralTable(LiteralValue*); ~Utf8LiteralTable(); LiteralValue* FindOrInsertString(LiteralSymbol*); Utf8LiteralValue* FindOrInsert(const char*, int); Utf8LiteralValue* FindOrInsert(wchar_t); void CheckStringConstant(AstExpression* expr); private: Tuple* utf8_literals; AstExpression* leftmost_constant_expr; void CollectStrings(); bool EndsInKnownString(AstExpression*); enum { DEFAULT_HASH_SIZE = 4093, MAX_HASH_SIZE = 32771 }; Utf8LiteralValue** base; unsigned hash_size; static unsigned primes[]; int prime_index; LiteralValue* bad_value; inline static unsigned Hash(const char* head, int len) { return Hash::Function(head, len); } void Rehash(); }; inline unsigned Symbol::HashCode() const { return (unsigned) Identity() -> index; } #ifdef HAVE_JIKES_NAMESPACE } // Close namespace Jikes block #endif #endif // lookup_INCLUDED