📄 class.c
字号:
treeadd_method (this_class, access_flags, name, method_sig) tree this_class; int access_flags; tree name; tree method_sig;{ tree handle_class = CLASS_TO_HANDLE_TYPE (this_class); tree function_type, fndecl; unsigned char *sig = (unsigned char*)IDENTIFIER_POINTER (method_sig); push_obstacks (&permanent_obstack, &permanent_obstack); if (sig[0] != '(') fatal ("bad method signature"); function_type = get_type_from_signature (method_sig); fndecl = add_method_1 (handle_class, access_flags, name, function_type); set_java_signature (TREE_TYPE (fndecl), method_sig); pop_obstacks (); return fndecl;}treeadd_field (class, name, field_type, flags) tree class; tree name; tree field_type; int flags;{ int is_static = (flags & ACC_STATIC) != 0; tree field; /* Push the obstack of field_type ? FIXME */ push_obstacks (&permanent_obstack, &permanent_obstack); field = build_decl (is_static ? VAR_DECL : FIELD_DECL, name, field_type); pop_obstacks (); TREE_CHAIN (field) = TYPE_FIELDS (class); TYPE_FIELDS (class) = field; DECL_CONTEXT (field) = class; if (flags & ACC_PUBLIC) FIELD_PUBLIC (field) = 1; if (flags & ACC_PROTECTED) FIELD_PROTECTED (field) = 1; if (flags & ACC_PRIVATE) FIELD_PRIVATE (field) = 1; if (flags & ACC_FINAL) FIELD_FINAL (field) = 1; if (flags & ACC_VOLATILE) FIELD_VOLATILE (field) = 1; if (flags & ACC_TRANSIENT) FIELD_TRANSIENT (field) = 1; if (is_static) { FIELD_STATIC (field) = 1; /* Always make field externally visible. This is required so that native methods can always access the field. */ TREE_PUBLIC (field) = 1; } return field;}/* Associate a constant value CONSTANT with VAR_DECL FIELD. */voidset_constant_value (field, constant) tree field, constant;{ if (field == NULL_TREE) warning ("misplaced ConstantValue attribute (not in any field)"); else if (DECL_INITIAL (field) != NULL_TREE) warning ("duplicate ConstanValue atribute for field '%s'", IDENTIFIER_POINTER (DECL_NAME (field))); else DECL_INITIAL (field) = constant;}/* Count the number of Unicode chars encoded in a given Ut8 string. */#if 0intstrLengthUtf8 (str, len) char *str; int len;{ register unsigned char* ptr = (unsigned char*) str; register unsigned char *limit = ptr + len; int str_length = 0; for (; ptr < limit; str_length++) { if (UTF8_GET (ptr, limit) < 0) return -1; } return str_length;}#endif/* Calculate a hash value for a string encoded in Utf8 format. * This returns the same hash value as specified for java.lang.String.hashCode. */static int32hashUtf8String (str, len) const char *str; int len;{ register const unsigned char* ptr = (const unsigned char*) str; register const unsigned char *limit = ptr + len; int32 hash = 0; for (; ptr < limit;) { int ch = UTF8_GET (ptr, limit); /* Updated specification from http://www.javasoft.com/docs/books/jls/clarify.html. */ hash = (31 * hash) + ch; } return hash;}tree utf8_decl_list = NULL_TREE;treebuild_utf8_ref (name) tree name;{ char* name_ptr = IDENTIFIER_POINTER(name); int name_len = IDENTIFIER_LENGTH(name); char buf[60]; char *buf_ptr; tree ctype, field = NULL_TREE, str_type, cinit, string; static int utf8_count = 0; int name_hash; tree ref = IDENTIFIER_UTF8_REF (name); tree decl; if (ref != NULL_TREE) return ref; push_obstacks (&permanent_obstack, &permanent_obstack); ctype = make_node (RECORD_TYPE); str_type = build_prim_array_type (unsigned_byte_type_node, name_len + 1); /* Allow for final '\0'. */ PUSH_FIELD (ctype, field, "hash", unsigned_short_type_node); PUSH_FIELD (ctype, field, "length", unsigned_short_type_node); PUSH_FIELD (ctype, field, "data", str_type); FINISH_RECORD (ctype); START_RECORD_CONSTRUCTOR (cinit, ctype); name_hash = hashUtf8String (name_ptr, name_len) & 0xFFFF; PUSH_FIELD_VALUE (cinit, "hash", build_int_2 (name_hash, 0)); PUSH_FIELD_VALUE (cinit, "length", build_int_2 (name_len, 0)); string = build_string (name_len, name_ptr); TREE_TYPE (string) = str_type; PUSH_FIELD_VALUE (cinit, "data", string); FINISH_RECORD_CONSTRUCTOR (cinit); TREE_CONSTANT (cinit) = 1; /* Build a unique identifier based on buf. */ sprintf(buf, "_Utf%d", ++utf8_count); buf_ptr = &buf[strlen (buf)]; if (name_len > 0 && name_ptr[0] >= '0' && name_ptr[0] <= '9') *buf_ptr++ = '_'; while (--name_len >= 0) { unsigned char c = *name_ptr++; if (c & 0x80) continue; if (!ISALPHA(c) && !ISDIGIT(c)) c = '_'; *buf_ptr++ = c; if (buf_ptr >= buf + 50) break; } *buf_ptr = '\0'; decl = build_decl (VAR_DECL, get_identifier (buf), utf8const_type); /* FIXME get some way to force this into .text, not .data. */ TREE_STATIC (decl) = 1; DECL_ARTIFICIAL (decl) = 1; DECL_IGNORED_P (decl) = 1; TREE_READONLY (decl) = 1; TREE_THIS_VOLATILE (decl) = 0; DECL_INITIAL (decl) = cinit; TREE_CHAIN (decl) = utf8_decl_list; layout_decl (decl, 0); pushdecl (decl); rest_of_decl_compilation (decl, (char*) 0, global_bindings_p (), 0); utf8_decl_list = decl; make_decl_rtl (decl, (char*) 0, 1); ref = build1 (ADDR_EXPR, utf8const_ptr_type, decl); IDENTIFIER_UTF8_REF (name) = ref; pop_obstacks (); return ref;}/* Build a reference to the class TYPE. Also handles primitive types and array types. */treebuild_class_ref (type) tree type;{ int is_compiled = is_compiled_class (type); if (is_compiled) { tree ref, decl_name, decl; if (TREE_CODE (type) == POINTER_TYPE) type = TREE_TYPE (type); if (TREE_CODE (type) == RECORD_TYPE) { if (TYPE_SIZE (type) == error_mark_node) return null_pointer_node; decl_name = identifier_subst (DECL_NAME (TYPE_NAME (type)), "", '/', '/', ".class"); decl = IDENTIFIER_GLOBAL_VALUE (decl_name); if (decl == NULL_TREE) { push_obstacks (&permanent_obstack, &permanent_obstack); decl = build_decl (VAR_DECL, decl_name, class_type_node); DECL_SIZE (decl) = TYPE_SIZE (class_type_node); TREE_STATIC (decl) = 1; TREE_PUBLIC (decl) = 1; DECL_IGNORED_P (decl) = 1; DECL_ARTIFICIAL (decl) = 1; DECL_ASSEMBLER_NAME (decl) = mangle_class_field (type); make_decl_rtl (decl, NULL, 1); pushdecl_top_level (decl); if (is_compiled == 1) DECL_EXTERNAL (decl) = 1; pop_obstacks (); } } else { char *name; char buffer[25]; if (flag_emit_class_files) { const char *prim_class_name; tree prim_class; if (type == char_type_node) prim_class_name = "java.lang.Character"; else if (type == boolean_type_node) prim_class_name = "java.lang.Boolean"; else if (type == byte_type_node) prim_class_name = "java.lang.Byte"; else if (type == short_type_node) prim_class_name = "java.lang.Short"; else if (type == int_type_node) prim_class_name = "java.lang.Integer"; else if (type == long_type_node) prim_class_name = "java.lang.Long"; else if (type == float_type_node) prim_class_name = "java.lang.Float"; else if (type == double_type_node) prim_class_name = "java.lang.Double"; else if (type == void_type_node) prim_class_name = "java.lang.Void"; else fatal ("internal error - bad type to build_class_ref"); prim_class = lookup_class (get_identifier (prim_class_name)); return build (COMPONENT_REF, NULL_TREE, prim_class, TYPE_identifier_node); } decl_name = TYPE_NAME (type); if (TREE_CODE (decl_name) == TYPE_DECL) decl_name = DECL_NAME (decl_name); name = IDENTIFIER_POINTER (decl_name); if (strncmp (name, "promoted_", 9) == 0) name += 9; sprintf (buffer, "_Jv_%sClass", name); decl_name = get_identifier (buffer); decl = IDENTIFIER_GLOBAL_VALUE (decl_name); if (decl == NULL_TREE) { push_obstacks (&permanent_obstack, &permanent_obstack); decl = build_decl (VAR_DECL, decl_name, class_type_node); TREE_STATIC (decl) = 1; TREE_PUBLIC (decl) = 1; make_decl_rtl (decl, NULL, 1); pushdecl_top_level (decl); if (is_compiled == 1) DECL_EXTERNAL (decl) = 1; pop_obstacks (); } } ref = build1 (ADDR_EXPR, class_ptr_type, decl); return ref; } else { int index; tree cl; push_obstacks (&permanent_obstack, &permanent_obstack); index = alloc_class_constant (type); cl = build_ref_from_constant_pool (index); TREE_TYPE (cl) = promote_type (class_ptr_type); pop_obstacks (); return cl; }}treebuild_static_field_ref (fdecl) tree fdecl;{ tree fclass = DECL_CONTEXT (fdecl); int is_compiled = is_compiled_class (fclass); if (is_compiled) { if (DECL_RTL (fdecl) == 0) { push_obstacks (&permanent_obstack, &permanent_obstack); make_decl_rtl (fdecl, NULL, 1); pop_obstacks (); if (is_compiled == 1) DECL_EXTERNAL (fdecl) = 1; } return fdecl; } else { /* Compile as: * *(FTYPE*)build_class_ref(FCLASS)->fields[INDEX].info.addr */ static tree fields_ident = NULL_TREE; static tree info_ident = NULL_TREE; tree ref = build_class_ref (fclass); tree fld; int field_index = 0; ref = build1 (INDIRECT_REF, class_type_node, ref); if (fields_ident == NULL_TREE) fields_ident = get_identifier ("fields"); if (info_ident == NULL_TREE) info_ident = get_identifier ("info"); ref = build (COMPONENT_REF, field_ptr_type_node, ref, lookup_field (&class_type_node, fields_ident)); for (fld = TYPE_FIELDS (fclass); ; fld = TREE_CHAIN (fld)) { if (fld == fdecl) break; if (fld == NULL_TREE) fatal ("field '%s' not found in class", IDENTIFIER_POINTER (DECL_NAME (fdecl))); if (FIELD_STATIC (fld)) field_index++; } field_index *= int_size_in_bytes (field_type_node); ref = fold (build (PLUS_EXPR, field_ptr_type_node, ref, build_int_2 (field_index, 0))); ref = build1 (INDIRECT_REF, field_type_node, ref); ref = build (COMPONENT_REF, field_info_union_node, ref, lookup_field (&field_type_node, info_ident)); ref = build (COMPONENT_REF, ptr_type_node, ref, TREE_CHAIN (TYPE_FIELDS (field_info_union_node))); return fold (build1 (INDIRECT_REF, TREE_TYPE(fdecl), ref)); }}intget_access_flags_from_decl (decl) tree decl;{ int access_flags = 0; if (TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL) { if (FIELD_STATIC (decl)) access_flags |= ACC_STATIC; if (FIELD_PUBLIC (decl)) access_flags |= ACC_PUBLIC; if (FIELD_PROTECTED (decl)) access_flags |= ACC_PROTECTED; if (FIELD_PRIVATE (decl)) access_flags |= ACC_PRIVATE; if (FIELD_FINAL (decl)) access_flags |= ACC_FINAL; if (FIELD_VOLATILE (decl)) access_flags |= ACC_VOLATILE; if (FIELD_TRANSIENT (decl)) access_flags |= ACC_TRANSIENT; return access_flags; } if (TREE_CODE (decl) == TYPE_DECL) { if (CLASS_PUBLIC (decl)) access_flags |= ACC_PUBLIC; if (CLASS_FINAL (decl)) access_flags |= ACC_FINAL; if (CLASS_SUPER (decl)) access_flags |= ACC_SUPER; if (CLASS_INTERFACE (decl)) access_flags |= ACC_INTERFACE; if (CLASS_ABSTRACT (decl)) access_flags |= ACC_ABSTRACT; return access_flags; } if (TREE_CODE (decl) == FUNCTION_DECL) { if (METHOD_PUBLIC (decl)) access_flags |= ACC_PUBLIC; if (METHOD_PRIVATE (decl)) access_flags |= ACC_PRIVATE; if (METHOD_PROTECTED (decl)) access_flags |= ACC_PROTECTED; if (METHOD_STATIC (decl)) access_flags |= ACC_STATIC; if (METHOD_FINAL (decl)) access_flags |= ACC_FINAL; if (METHOD_SYNCHRONIZED (decl)) access_flags |= ACC_SYNCHRONIZED; if (METHOD_NATIVE (decl)) access_flags |= ACC_NATIVE; if (METHOD_ABSTRACT (decl)) access_flags |= ACC_ABSTRACT; if (METHOD_TRANSIENT (decl)) access_flags |= ACC_TRANSIENT; return access_flags; } abort ();}static treemake_field_value (fdecl) tree fdecl;{ tree finit, info; int bsize, flags; tree type = TREE_TYPE (fdecl); int resolved = is_compiled_class (type); START_RECORD_CONSTRUCTOR (finit, field_type_node); PUSH_FIELD_VALUE (finit, "name", build_utf8_ref (DECL_NAME (fdecl))); if (resolved) type = build_class_ref (type); else { tree signature = build_java_signature (type); type = build_utf8_ref (unmangle_classname (IDENTIFIER_POINTER(signature), IDENTIFIER_LENGTH(signature))); } PUSH_FIELD_VALUE (finit, "type", type); flags = get_access_flags_from_decl (fdecl); if (! resolved) flags |= 0x8000 /* FIELD_UNRESOLVED_FLAG */; PUSH_FIELD_VALUE (finit, "accflags", build_int_2 (flags, 0)); bsize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (fdecl))) / BITS_PER_UNIT; PUSH_FIELD_VALUE (finit, "bsize", build_int_2 (bsize, 0)); if (FIELD_STATIC (fdecl))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -