// $Id: control.h,v 1.57 2004/04/04 19:45:48 ericb 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 control_INCLUDED #define control_INCLUDED #include "platform.h" #include "symbol.h" #include "tuple.h" #include "set.h" #ifdef HAVE_JIKES_NAMESPACE namespace Jikes { // Open namespace Jikes block #endif class StoragePool; class Option; class Scanner; class Parser; class Semantic; class LexStream; class AstPackageDeclaration; class AstName; class TypeDependenceChecker; // // This class represents the control information common across all compilation // units. It provides a cache for essential classes and objects, as well as // the command line options in force. // class Control : public StringConstant { public: int return_code; Option& option; SymbolTable classpath_table; SymbolTable external_table; unsigned dot_classpath_index; Tuple classpath; Tuple bad_dirnames; Tuple bad_zip_filenames; Tuple bad_input_filenames; Tuple unreadable_input_filenames; Tuple general_io_errors; Tuple general_io_warnings; SystemTable* system_table; Tuple system_directories; Semantic* system_semantic; Tuple semantic; Tuple needs_body_work; Tuple type_trash_bin; NameSymbolMap unnamed_package_types; SymbolSet input_java_file_set; SymbolSet input_class_file_set; SymbolSet expired_file_set; SymbolSet recompilation_file_set; Parser* parser; Scanner* scanner; // // Tables for hashing everything we've seen so far. // LiteralLookupTable string_table; LiteralLookupTable int_table; LiteralLookupTable long_table; LiteralLookupTable char_table; LiteralLookupTable float_table; LiteralLookupTable double_table; NameLookupTable name_table; TypeLookupTable type_table; // // This cache of name symbols is initialized in system.cpp. // NameSymbol* access_name_symbol; NameSymbol* array_name_symbol; NameSymbol* assert_name_symbol; NameSymbol* block_init_name_symbol; NameSymbol* class_name_symbol; NameSymbol* clinit_name_symbol; NameSymbol* clone_name_symbol; NameSymbol* dot_name_symbol; NameSymbol* dot_dot_name_symbol; NameSymbol* Enum_name_symbol; NameSymbol* equals_name_symbol; NameSymbol* false_name_symbol; NameSymbol* hashCode_name_symbol; NameSymbol* init_name_symbol; NameSymbol* length_name_symbol; NameSymbol* null_name_symbol; NameSymbol* Object_name_symbol; NameSymbol* package_info_name_symbol; NameSymbol* question_name_symbol; NameSymbol* serialPersistentFields_name_symbol; NameSymbol* serialVersionUID_name_symbol; NameSymbol* this_name_symbol; NameSymbol* true_name_symbol; NameSymbol* val_name_symbol; Utf8LiteralValue* ConstantValue_literal; Utf8LiteralValue* Exceptions_literal; Utf8LiteralValue* InnerClasses_literal; Utf8LiteralValue* Synthetic_literal; Utf8LiteralValue* Deprecated_literal; Utf8LiteralValue* LineNumberTable_literal; Utf8LiteralValue* LocalVariableTable_literal; Utf8LiteralValue* Code_literal; Utf8LiteralValue* SourceFile_literal; Utf8LiteralValue* EnclosingMethod_literal; // // The primitive types. // TypeSymbol* byte_type; TypeSymbol* short_type; TypeSymbol* int_type; TypeSymbol* long_type; TypeSymbol* char_type; TypeSymbol* float_type; TypeSymbol* double_type; TypeSymbol* boolean_type; TypeSymbol* void_type; TypeSymbol* null_type; TypeSymbol* no_type; // // System package accessors. // inline PackageSymbol* AnnotationPackage() { if (! annotation_package) annotation_package = ProcessPackage(US_java_SL_lang_SL_annotation); return annotation_package; } inline PackageSymbol* IoPackage() { if (! io_package) io_package = ProcessPackage(US_java_SL_io); return io_package; } inline PackageSymbol* LangPackage() { assert(lang_package); return lang_package; } inline PackageSymbol* UtilPackage() { if (! util_package) util_package = ProcessPackage(US_java_SL_util); return util_package; } inline PackageSymbol* UnnamedPackage() { assert(unnamed_package); return unnamed_package; } // // System type, method, and field accessors. Useful boilerplate macros // reduce the chance for typos, but be sure to update Control::Control to // initialize the field created by the macros to NULL. // // TYPE_ACCESSOR(classname, expression); #define TYPE_ACCESSOR(type, package) \ private: \ TypeSymbol* type ## _type; \ public: \ inline TypeSymbol* type() \ { \ if (! type ## _type) \ type ## _type = ProcessSystemType(package, #type); \ return type ## _type; \ } // METHOD_ACCESSOR(class_methodname, expression, "name", "descriptor"); #define METHOD_ACCESSOR(method, type, name, descriptor) \ private: \ MethodSymbol* method ## _method; \ public: \ inline MethodSymbol* method ## Method() \ { \ if (! method ## _method) \ method ## _method = ProcessSystemMethod(type, name, descriptor); \ return method ## _method; \ } // FIELD_ACCESSOR(classname, fieldname, "descriptor"); #define FIELD_ACCESSOR(type, name, descriptor) \ private: \ VariableSymbol* type ## _ ## name ## _field; \ public: \ inline VariableSymbol* type ## _ ## name ## _Field() \ { \ if (! type ## _ ## name ## _field) \ type ## _ ## name ## _field = \ ProcessSystemField(type (), #name, descriptor); \ return type ## _ ## name ## _field; \ } TYPE_ACCESSOR(Annotation, AnnotationPackage()); TYPE_ACCESSOR(AssertionError, lang_package); METHOD_ACCESSOR(AssertionError_Init, AssertionError(), "", "()V"); METHOD_ACCESSOR(AssertionError_InitWithChar, AssertionError(), "", "(C)V"); METHOD_ACCESSOR(AssertionError_InitWithBoolean, AssertionError(), "", "(Z)V"); METHOD_ACCESSOR(AssertionError_InitWithInt, AssertionError(), "", "(I)V"); METHOD_ACCESSOR(AssertionError_InitWithLong, AssertionError(), "", "(J)V"); METHOD_ACCESSOR(AssertionError_InitWithFloat, AssertionError(), "", "(F)V"); METHOD_ACCESSOR(AssertionError_InitWithDouble, AssertionError(), "", "(D)V"); METHOD_ACCESSOR(AssertionError_InitWithObject, AssertionError(), "", "(Ljava/lang/Object;)V"); TYPE_ACCESSOR(Boolean, lang_package); FIELD_ACCESSOR(Boolean, TYPE, "java/lang/Class"); TYPE_ACCESSOR(Byte, lang_package); FIELD_ACCESSOR(Byte, TYPE, "java/lang/Class"); TYPE_ACCESSOR(Character, lang_package); FIELD_ACCESSOR(Character, TYPE, "java/lang/Class"); TYPE_ACCESSOR(Class, lang_package); METHOD_ACCESSOR(Class_forName, Class(), "forName", "(Ljava/lang/String;)Ljava/lang/Class;"); METHOD_ACCESSOR(Class_getComponentType, Class(), "getComponentType", "()Ljava/lang/Class;"); METHOD_ACCESSOR(Class_desiredAssertionStatus, Class(), "desiredAssertionStatus", "()Z"); TYPE_ACCESSOR(ClassNotFoundException, lang_package); TYPE_ACCESSOR(Cloneable, lang_package); TYPE_ACCESSOR(Comparable, lang_package); TYPE_ACCESSOR(Double, lang_package); FIELD_ACCESSOR(Double, TYPE, "java/lang/Class"); TYPE_ACCESSOR(ElementType, AnnotationPackage()); FIELD_ACCESSOR(ElementType, TYPE, "java/lang/annotation/ElementType"); FIELD_ACCESSOR(ElementType, FIELD, "java/lang/annotation/ElementType"); FIELD_ACCESSOR(ElementType, METHOD, "java/lang/annotation/ElementType"); FIELD_ACCESSOR(ElementType, PARAMETER, "java/lang/annotation/ElementType"); FIELD_ACCESSOR(ElementType, CONSTRUCTOR, "java/lang/annotation/ElementType"); FIELD_ACCESSOR(ElementType, LOCAL_VARIABLE, "java/lang/annotation/ElementType"); FIELD_ACCESSOR(ElementType, ANNOTATION_TYPE, "java/lang/annotation/ElementType"); FIELD_ACCESSOR(ElementType, PACKAGE, "java/lang/annotation/ElementType"); TYPE_ACCESSOR(Enum, lang_package); METHOD_ACCESSOR(Enum_Init, Enum(), "", "(Ljava/lang/String;I)V"); METHOD_ACCESSOR(Enum_ordinal, Enum(), "ordinal", "()I"); METHOD_ACCESSOR(Enum_valueOf, Enum(), "valueOf", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;"); TYPE_ACCESSOR(Error, lang_package); TYPE_ACCESSOR(Exception, lang_package); TYPE_ACCESSOR(Float, lang_package); FIELD_ACCESSOR(Float, TYPE, "java/lang/Class"); TYPE_ACCESSOR(Integer, lang_package); FIELD_ACCESSOR(Integer, TYPE, "java/lang/Class"); TYPE_ACCESSOR(Iterable, lang_package); METHOD_ACCESSOR(Iterable_iterator, Iterable(), "iterator", "()Ljava/util/Iterator;"); TYPE_ACCESSOR(Iterator, UtilPackage()); METHOD_ACCESSOR(Iterator_hasNext, Iterator(), "hasNext", "()Z"); METHOD_ACCESSOR(Iterator_next, Iterator(), "next", "()Ljava/lang/Object;"); TYPE_ACCESSOR(Long, lang_package); FIELD_ACCESSOR(Long, TYPE, "java/lang/Class"); TYPE_ACCESSOR(NoClassDefFoundError, lang_package); METHOD_ACCESSOR(NoClassDefFoundError_Init, NoClassDefFoundError(), "", "()V"); METHOD_ACCESSOR(NoClassDefFoundError_InitString, NoClassDefFoundError(), "", "(Ljava/lang/String;)V"); TYPE_ACCESSOR(Object, lang_package); METHOD_ACCESSOR(Object_getClass, Object(), "getClass", "()Ljava/lang/Class;"); TYPE_ACCESSOR(Overrides, lang_package); TYPE_ACCESSOR(Retention, AnnotationPackage()); TYPE_ACCESSOR(RetentionPolicy, AnnotationPackage()); FIELD_ACCESSOR(RetentionPolicy, SOURCE, "java/lang/annotation/RetentionPolicy"); FIELD_ACCESSOR(RetentionPolicy, CLASS, "java/lang/annotation/RetentionPolicy"); FIELD_ACCESSOR(RetentionPolicy, RUNTIME, "java/lang/annotation/RetentionPolicy"); TYPE_ACCESSOR(RuntimeException, lang_package); TYPE_ACCESSOR(Serializable, IoPackage()); TYPE_ACCESSOR(Short, lang_package); FIELD_ACCESSOR(Short, TYPE, "java/lang/Class"); TYPE_ACCESSOR(String, lang_package); TYPE_ACCESSOR(StringBuffer, lang_package); METHOD_ACCESSOR(StringBuffer_Init, StringBuffer(), "", "()V"); METHOD_ACCESSOR(StringBuffer_InitWithString, StringBuffer(), "", "(Ljava/lang/String;)V"); METHOD_ACCESSOR(StringBuffer_toString, StringBuffer(), "toString", "()Ljava/lang/String;"); METHOD_ACCESSOR(StringBuffer_append_char, StringBuffer(), "append", "(C)Ljava/lang/StringBuffer;"); METHOD_ACCESSOR(StringBuffer_append_boolean, StringBuffer(), "append", "(Z)Ljava/lang/StringBuffer;"); METHOD_ACCESSOR(StringBuffer_append_int, StringBuffer(), "append", "(I)Ljava/lang/StringBuffer;"); METHOD_ACCESSOR(StringBuffer_append_long, StringBuffer(), "append", "(J)Ljava/lang/StringBuffer;"); METHOD_ACCESSOR(StringBuffer_append_float, StringBuffer(), "append", "(F)Ljava/lang/StringBuffer;"); METHOD_ACCESSOR(StringBuffer_append_double, StringBuffer(), "append", "(D)Ljava/lang/StringBuffer;"); METHOD_ACCESSOR(StringBuffer_append_string, StringBuffer(), "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"); METHOD_ACCESSOR(StringBuffer_append_object, StringBuffer(), "append", "(Ljava/lang/Object;)Ljava/lang/StringBuffer;"); TYPE_ACCESSOR(StringBuilder, lang_package); METHOD_ACCESSOR(StringBuilder_Init, StringBuilder(), "", "()V"); METHOD_ACCESSOR(StringBuilder_InitWithString, StringBuilder(), "", "(Ljava/lang/String;)V"); METHOD_ACCESSOR(StringBuilder_toString, StringBuilder(), "toString", "()Ljava/lang/String;"); METHOD_ACCESSOR(StringBuilder_append_char, StringBuilder(), "append", "(C)Ljava/lang/StringBuilder;"); METHOD_ACCESSOR(StringBuilder_append_boolean, StringBuilder(), "append", "(Z)Ljava/lang/StringBuilder;"); METHOD_ACCESSOR(StringBuilder_append_int, StringBuilder(), "append", "(I)Ljava/lang/StringBuilder;"); METHOD_ACCESSOR(StringBuilder_append_long, StringBuilder(), "append", "(J)Ljava/lang/StringBuilder;"); METHOD_ACCESSOR(StringBuilder_append_float, StringBuilder(), "append", "(F)Ljava/lang/StringBuilder;"); METHOD_ACCESSOR(StringBuilder_append_double, StringBuilder(), "append", "(D)Ljava/lang/StringBuilder;"); METHOD_ACCESSOR(StringBuilder_append_string, StringBuilder(), "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;"); METHOD_ACCESSOR(StringBuilder_append_object, StringBuilder(), "append", "(Ljava/lang/Object;)Ljava/lang/StringBuilder;"); TYPE_ACCESSOR(Target, AnnotationPackage()); TYPE_ACCESSOR(Throwable, lang_package); METHOD_ACCESSOR(Throwable_getMessage, Throwable(), "getMessage", "()Ljava/lang/String;"); METHOD_ACCESSOR(Throwable_initCause, Throwable(), "initCause", "(Ljava/lang/Throwable;)Ljava/lang/Throwable;"); TYPE_ACCESSOR(Void, lang_package); FIELD_ACCESSOR(Void, TYPE, "java/lang/Class"); #undef TYPE_ACCESSOR #undef METHOD_ACCESSOR #undef FIELD_ACCESSOR IntLiteralTable int_pool; LongLiteralTable long_pool; FloatLiteralTable float_pool; DoubleLiteralTable double_pool; Utf8LiteralTable Utf8_pool; Control(char**, Option&); ~Control(); Utf8LiteralValue* ConvertUnicodeToUtf8(const wchar_t* source) { // Should be big enough for the worst case. char* target = new char[wcslen(source) * 3 + 1]; int length = ConvertUnicodeToUtf8(source, target); Utf8LiteralValue* literal = Utf8_pool.FindOrInsert(target, length); delete [] target; return literal; } static int ConvertUtf8ToUnicode(wchar_t*, const char*, int); NameSymbol* ConvertUtf8ToUnicode(const char* source, int length) { wchar_t* name = new wchar_t[length + 1]; int name_length = ConvertUtf8ToUnicode(name, source, length); NameSymbol* name_symbol = FindOrInsertName(name, name_length); delete [] name; return name_symbol; } void FindPathsToDirectory(PackageSymbol*); DirectoryEntry* FindInputFile(FileSymbol*); void FindMoreRecentInputFiles(SymbolSet&); void RemoveTrashedTypes(SymbolSet&); void RereadDirectory(DirectorySymbol*); void RereadDirectories(); void ComputeRecompilationSet(TypeDependenceChecker&); bool IncrementalRecompilation(); // // The one and only bad value constant. // LiteralValue* BadValue() { return &bad_value; } // // Note that only names are converted here and not literals, since // no error can occur in a name. // A literal is converted during the semantic pass so that an // accurate diagnostic can be issued in case it is invalid. // NameSymbol* FindOrInsertName(const wchar_t* name, int len) { NameSymbol* name_symbol = name_table.FindOrInsertName(name, len); if (! name_symbol -> Utf8_literal) name_symbol -> Utf8_literal = ConvertUnicodeToUtf8(name_symbol -> Name()); return name_symbol; } // // Make up a parameter name of the form $(num) and return its name symbol. // NameSymbol* MakeParameter(int num) { IntToWstring value(num); wchar_t str[13]; str[0] = U_DOLLAR; // '$' wcscpy(&str[1], value.String()); return FindOrInsertName(str, value.Length() + 1); } // // // static DirectorySymbol* GetOutputDirectory(FileSymbol*); static FileSymbol* GetJavaFile(PackageSymbol*, const NameSymbol*); static FileSymbol* GetFile(Control&, PackageSymbol*, const NameSymbol*); static FileSymbol* GetFileFirst(Control&, PackageSymbol*, const NameSymbol*); static FileSymbol* GetFileBoth(Control&, PackageSymbol*, const NameSymbol*); PackageSymbol* FindOrInsertPackage(LexStream*, AstName*); void ProcessPackageDeclaration(FileSymbol*, AstPackageDeclaration*); void CleanUp(FileSymbol*); inline bool IsSimpleIntegerValueType(const TypeSymbol* type) { return type == byte_type || type == short_type || type == int_type || type == char_type; } inline bool IsIntegral(const TypeSymbol* type) { return IsSimpleIntegerValueType(type) || type == long_type; } inline bool IsFloatingPoint(const TypeSymbol* type) { return type == float_type || type == double_type; } inline bool IsNumeric(const TypeSymbol* type) { return IsIntegral(type) || IsFloatingPoint(type); } inline bool IsDoubleWordType(const TypeSymbol* type) { return type == long_type || type == double_type; } inline bool IsPrimitive(const TypeSymbol* type) { return IsNumeric(type) || type == boolean_type; } inline void ProcessBadType(TypeSymbol* type_symbol) { type_trash_bin.Next() = type_symbol; } void ProcessHeaders(FileSymbol*); #ifdef JIKES_DEBUG int input_files_processed, class_files_read, class_files_written, line_count; #endif // JIKES_DEBUG PackageSymbol* ProcessPackage(const wchar_t*); DirectorySymbol* FindSubdirectory(PathSymbol*, wchar_t*, int); DirectorySymbol* ProcessSubdirectories(wchar_t*, int, bool); private: LiteralValue bad_value; // // Cache of system packages. lang and unnamed are always valid, because of // ProcessUnnamedPackage and ProcessSystemInformation in system.cpp, the // constructor initializes the rest to NULL in control.cpp; see accessor // methods above for assignment. // PackageSymbol* annotation_package; PackageSymbol* io_package; PackageSymbol* lang_package; PackageSymbol* util_package; PackageSymbol* unnamed_package; static int ConvertUnicodeToUtf8(const wchar_t*, char*); NameSymbol* FindOrInsertSystemName(const char* name); void ProcessGlobals(); void ProcessUnnamedPackage(); void ProcessPath(); void ProcessBootClassPath(); void ProcessExtDirs(); void ProcessClassPath(); void ProcessSourcePath(); TypeSymbol* GetPrimitiveType(const char*, char); void ProcessSystemInformation(); TypeSymbol* ProcessSystemType(PackageSymbol*, const char*); MethodSymbol* ProcessSystemMethod(TypeSymbol*, const char*, const char*); VariableSymbol* ProcessSystemField(TypeSymbol*, const char*, const char*); void ProcessFile(FileSymbol*); void ProcessMembers(); void CollectTypes(TypeSymbol*, Tuple&); void ProcessBodies(TypeSymbol*); void CheckForUnusedImports(Semantic *); void ProcessNewInputFiles(SymbolSet&, char**); FileSymbol* FindOrInsertJavaInputFile(DirectorySymbol*, NameSymbol*); FileSymbol* FindOrInsertJavaInputFile(wchar_t*, int); }; #ifdef HAVE_JIKES_NAMESPACE } // Close namespace Jikes block #endif #endif // control_INCLUDED