📄 class.c
字号:
/* Functions related to building classes and their related objects. Copyright (C) 1996, 97-98, 1999 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.Java and all Java-based marks are trademarks or registered trademarksof Sun Microsystems, Inc. in the United States and other countries.The Free Software Foundation is independent of Sun Microsystems, Inc. *//* Written by Per Bothner <bothner@cygnus.com> */#include "config.h"#include "system.h"#include "tree.h"#include "rtl.h"#include "flags.h"#include "java-tree.h"#include "jcf.h"#include "obstack.h"#include "toplev.h"#include "output.h"#include "parse.h"static tree mangle_class_field PROTO ((tree class));static tree make_method_value PROTO ((tree));static tree build_java_method_type PROTO ((tree, tree, int));static int32 hashUtf8String PROTO ((const char *, int));static tree make_field_value PROTO ((tree));static tree get_dispatch_vector PROTO ((tree));static tree get_dispatch_table PROTO ((tree, tree));static void append_gpp_mangled_type PROTO ((struct obstack *, tree));static tree mangle_static_field PROTO ((tree));static rtx registerClass_libfunc;extern struct obstack permanent_obstack;extern struct obstack temporary_obstack;/* Return an IDENTIFIER_NODE the same as (OLD_NAME, OLD_LENGTH). except that characters matching OLD_CHAR are substituted by NEW_CHAR. Also, PREFIX is prepended, and SUFFIX is appended. */treeident_subst (old_name, old_length, prefix, old_char, new_char, suffix) const char* old_name; int old_length; const char *prefix; int old_char; int new_char; const char *suffix;{ int prefix_len = strlen (prefix); int suffix_len = strlen (suffix); int i = prefix_len + old_length + suffix_len + 1;#ifdef __GNUC__ char buffer[i];#else char *buffer = (char *)alloca (i);#endif strcpy (buffer, prefix); for (i = 0; i < old_length; i++) { char ch = old_name[i]; if (ch == old_char) ch = new_char; buffer[prefix_len + i] = ch; } strcpy (buffer + prefix_len + old_length, suffix); return get_identifier (buffer);}/* Return an IDENTIFIER_NODE the same as OLD_ID, except that characters matching OLD_CHAR are substituted by NEW_CHAR. Also, PREFIX is prepended, and SUFFIX is appended. */treeidentifier_subst (old_id, prefix, old_char, new_char, suffix) const tree old_id; const char *prefix; int old_char; int new_char; const char *suffix;{ return ident_subst (IDENTIFIER_POINTER (old_id), IDENTIFIER_LENGTH (old_id), prefix, old_char, new_char, suffix);}/* Generate a valid C identifier from the name of the class TYPE, prefixed by PREFIX. */treemangled_classname (prefix, type) const char *prefix; tree type;{ tree ident = TYPE_NAME (type); if (TREE_CODE (ident) != IDENTIFIER_NODE) ident = DECL_NAME (ident); return identifier_subst (ident, prefix, '.', '_', "");}treemake_class (){ tree type; push_obstacks (&permanent_obstack, &permanent_obstack); type = make_node (RECORD_TYPE);#ifdef JAVA_USE_HANDLES tree field1 = build_decl (FIELD_DECL, get_identifier ("obj"), build_pointer_type (type)); tree field2 = build_decl (FIELD_DECL, get_identifier ("methods"), methodtable_ptr_type); tree handle_type = make_node (RECORD_TYPE); TREE_CHAIN (field1) = field2; TYPE_FIELDS (handle_type) = field1; TYPE_BINFO (type) = make_tree_vec (7); TYPE_BINFO (handle_type) = make_tree_vec (7); BINFO_HANDLE (TYPE_BINFO (handle_type)) = type; BINFO_HANDLE (TYPE_BINFO (type)) = handle_type;#else TYPE_BINFO (type) = make_tree_vec (6);#endif pop_obstacks (); return type;}/* Given a fully-qualified classname in NAME (whose length is NAME_LENGTH), and where each of the constituents is separated by '/', return a corresponding IDENTIFIER_NODE, except using '.' as separator. */treeunmangle_classname (name, name_length) const char *name; int name_length;{ tree to_return = ident_subst (name, name_length, "", '/', '.', ""); /* It's not sufficient to compare to_return and get_identifier (name) to determine whether to_return is qualified. There are cases in signature analysis where name will be stripped of a trailing ';'. */ name = IDENTIFIER_POINTER (to_return); while (*name) if (*name++ == '.') { QUALIFIED_P (to_return) = 1; break; } return to_return;}treepush_class (class_type, class_name) tree class_type, class_name;{ tree decl, signature; char *save_input_filename = input_filename; int save_lineno = lineno; tree source_name = identifier_subst (class_name, "", '.', '/', ".java"); push_obstacks (&permanent_obstack, &permanent_obstack); CLASS_P (class_type) = 1; input_filename = IDENTIFIER_POINTER (source_name); lineno = 0; decl = build_decl (TYPE_DECL, class_name, class_type); input_filename = save_input_filename; lineno = save_lineno; signature = identifier_subst (class_name, "L", '.', '/', ";"); IDENTIFIER_SIGNATURE_TYPE (signature) = build_pointer_type (class_type); /* Setting DECL_ARTIFICAL forces dbxout.c to specific the type is both a typedef and in the struct name-space. We may want to re-visit this later, but for now it reduces the changes needed for gdb. */ DECL_ARTIFICIAL (decl) = 1; pushdecl_top_level (decl);#ifdef JAVA_USE_HANDLES { tree handle_name = identifier_subst (class_name, "Handle$", '.', '.', ""); tree handle_decl = build_decl (TYPE_DECL, handle_name, CLASS_TO_HANDLE_TYPE (class_type)); pushdecl (handle_decl); }#endif pop_obstacks (); return decl;}/* Finds the (global) class named NAME. Creates the class if not found. Also creates associated TYPE_DECL. Does not check if the class actually exists, load the class, fill in field or methods, or do layout_type. */treelookup_class (name) tree name;{ tree decl = IDENTIFIER_CLASS_VALUE (name); if (decl == NULL_TREE) decl = push_class (make_class (), name); return TREE_TYPE (decl);}voidset_super_info (access_flags, this_class, super_class, interfaces_count) int access_flags; tree this_class; tree super_class; int interfaces_count;{ int total_supers = interfaces_count; tree class_decl = TYPE_NAME (this_class); if (super_class) total_supers++; push_obstacks (&permanent_obstack, &permanent_obstack); TYPE_BINFO_BASETYPES (this_class) = make_tree_vec (total_supers); if (super_class) { tree super_binfo = make_tree_vec (6); BINFO_TYPE (super_binfo) = super_class; BINFO_OFFSET (super_binfo) = integer_zero_node; TREE_VIA_PUBLIC (super_binfo) = 1; TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (this_class)), 0) = super_binfo; CLASS_HAS_SUPER (this_class) = 1; } pop_obstacks (); if (access_flags & ACC_PUBLIC) CLASS_PUBLIC (class_decl) = 1; if (access_flags & ACC_FINAL) CLASS_FINAL (class_decl) = 1; if (access_flags & ACC_SUPER) CLASS_SUPER (class_decl) = 1; if (access_flags & ACC_INTERFACE) CLASS_INTERFACE (class_decl) = 1; if (access_flags & ACC_ABSTRACT) CLASS_ABSTRACT (class_decl) = 1;}/* Return length of inheritance chain of CLAS, where java.lang.Object is 0, direct sub-classes of Object are 1, and so on. */intclass_depth (clas) tree clas;{ int depth = 0; if (! CLASS_LOADED_P (clas)) load_class (clas, 1); while (clas != object_type_node) { depth++; clas = TYPE_BINFO_BASETYPE (clas, 0); } return depth;}/* Return true iff TYPE2 is an interface that extends interface TYPE1 */intinterface_of_p (type1, type2) tree type1, type2;{ int n, i; tree basetype_vec; if (!(basetype_vec = TYPE_BINFO_BASETYPES (type2))) return 0; n = TREE_VEC_LENGTH (basetype_vec); for (i = 0; i < n; i++) { tree vec_elt = TREE_VEC_ELT (basetype_vec, i); if (vec_elt && BINFO_TYPE (vec_elt) == type1) return 1; } for (i = 0; i < n; i++) { tree vec_elt = TREE_VEC_ELT (basetype_vec, i); if (vec_elt && BINFO_TYPE (vec_elt) && interface_of_p (type1, BINFO_TYPE (vec_elt))) return 1; } return 0;}/* Return true iff TYPE1 inherits from TYPE2. */intinherits_from_p (type1, type2) tree type1, type2;{ while (type1 != NULL_TREE && TREE_CODE (type1) == RECORD_TYPE) { if (type1 == type2) return 1; type1 = CLASSTYPE_SUPER (type1); } return 0;}static voidadd_interface_do (basetype_vec, interface_class, i) tree basetype_vec, interface_class; int i;{ tree interface_binfo = make_tree_vec (6); BINFO_TYPE (interface_binfo) = interface_class; BINFO_OFFSET (interface_binfo) = integer_zero_node; TREE_VIA_VIRTUAL (interface_binfo) = 1; TREE_VIA_PUBLIC (interface_binfo) = 1; TREE_VEC_ELT (basetype_vec, i) = interface_binfo;}/* Add INTERFACE_CLASS to THIS_CLASS iff INTERFACE_CLASS can't be found in THIS_CLASS. Returns NULL_TREE upon success, INTERFACE_CLASS if attempt is made to add it twice. */treemaybe_add_interface (this_class, interface_class) tree this_class, interface_class;{ tree basetype_vec = TYPE_BINFO_BASETYPES (this_class); int i; int n = TREE_VEC_LENGTH (basetype_vec); for (i = 0; ; i++) { if (i >= n) { error ("internal error - too many interface type"); return NULL_TREE; } else if (TREE_VEC_ELT (basetype_vec, i) == NULL_TREE) break; else if (BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i)) == interface_class) return interface_class; } add_interface_do (basetype_vec, interface_class, i); return NULL_TREE;}/* Add the INTERFACE_CLASS as one of the interfaces of THIS_CLASS. */voidadd_interface (this_class, interface_class) tree this_class, interface_class;{ tree basetype_vec = TYPE_BINFO_BASETYPES (this_class); int i; int n = TREE_VEC_LENGTH (basetype_vec); for (i = 0; ; i++) { if (i >= n) { error ("internal error - too many interface type"); return; } else if (TREE_VEC_ELT (basetype_vec, i) == NULL_TREE) break; } add_interface_do (basetype_vec, interface_class, i);}#if 0/* Return the address of a pointer to the first FUNCTION_DECL in the list (*LIST) whose DECL_NAME is NAME. */static tree *find_named_method (list, name) tree *list; tree name;{ while (*list && DECL_NAME (*list) != name) list = &TREE_CHAIN (*list); return list;}#endifstatic treebuild_java_method_type (fntype, this_class, access_flags) tree fntype; tree this_class; int access_flags;{ if (access_flags & ACC_STATIC) return fntype; return build_method_type (CLASS_TO_HANDLE_TYPE (this_class), fntype);}treeadd_method_1 (handle_class, access_flags, name, function_type) tree handle_class; int access_flags; tree name; tree function_type;{ tree method_type, fndecl; push_obstacks (&permanent_obstack, &permanent_obstack); method_type = build_java_method_type (function_type, handle_class, access_flags); fndecl = build_decl (FUNCTION_DECL, name, method_type); DECL_CONTEXT (fndecl) = handle_class; DECL_LANG_SPECIFIC (fndecl) = (struct lang_decl *) permalloc (sizeof (struct lang_decl)); bzero ((PTR) DECL_LANG_SPECIFIC (fndecl), sizeof (struct lang_decl)); TREE_CHAIN (fndecl) = TYPE_METHODS (handle_class); TYPE_METHODS (handle_class) = fndecl; pop_obstacks (); if (access_flags & ACC_PUBLIC) METHOD_PUBLIC (fndecl) = 1; if (access_flags & ACC_PROTECTED) METHOD_PROTECTED (fndecl) = 1; if (access_flags & ACC_PRIVATE) METHOD_PRIVATE (fndecl) = 1; if (access_flags & ACC_NATIVE) METHOD_NATIVE (fndecl) = 1; if (access_flags & ACC_STATIC) METHOD_STATIC (fndecl) = 1; if (access_flags & ACC_FINAL) METHOD_FINAL (fndecl) = 1; if (access_flags & ACC_SYNCHRONIZED) METHOD_SYNCHRONIZED (fndecl) = 1; if (access_flags & ACC_ABSTRACT) METHOD_ABSTRACT (fndecl) = 1; if (access_flags & ACC_TRANSIENT) METHOD_TRANSIENT (fndecl) = 1; return fndecl;}/* Add a method to THIS_CLASS. The method's name is NAME. Its signature (mangled type) is METHOD_SIG (an IDENTIFIER_NODE). */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -