📄 class.c
字号:
{ tree cfield = TREE_CHAIN (TYPE_FIELDS(field_info_union_node)); tree faddr = build_address_of (build_static_field_ref (fdecl)); info = build (CONSTRUCTOR, field_info_union_node, NULL_TREE, build_tree_list (cfield, faddr)); } else { int boffset = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (fdecl)) / BITS_PER_UNIT; info = build (CONSTRUCTOR, field_info_union_node, NULL_TREE, build_tree_list (TYPE_FIELDS(field_info_union_node), build_int_2 (boffset, 0))); } PUSH_FIELD_VALUE (finit, "info", info); FINISH_RECORD_CONSTRUCTOR (finit); return finit;}static treemake_method_value (mdecl) tree mdecl;{ tree minit; tree code;#define ACC_TRANSLATED 0x4000 int accflags = get_access_flags_from_decl (mdecl) | ACC_TRANSLATED; code = null_pointer_node; if (DECL_RTL (mdecl)) code = build1 (ADDR_EXPR, nativecode_ptr_type_node, mdecl); START_RECORD_CONSTRUCTOR (minit, method_type_node); PUSH_FIELD_VALUE (minit, "name", build_utf8_ref (DECL_CONSTRUCTOR_P (mdecl) ? init_identifier_node : DECL_NAME (mdecl))); { tree signature = build_java_signature (TREE_TYPE (mdecl)); PUSH_FIELD_VALUE (minit, "signature", (build_utf8_ref (unmangle_classname (IDENTIFIER_POINTER(signature), IDENTIFIER_LENGTH(signature))))); } PUSH_FIELD_VALUE (minit, "accflags", build_int_2 (accflags, 0)); PUSH_FIELD_VALUE (minit, "ncode", code); FINISH_RECORD_CONSTRUCTOR (minit); return minit;}static treeget_dispatch_vector (type) tree type;{ tree vtable = TYPE_VTABLE (type); if (vtable == NULL) { int i; tree method; tree super = CLASSTYPE_SUPER (type); int nvirtuals = TREE_INT_CST_LOW (TYPE_NVIRTUALS (type)); vtable = make_tree_vec (nvirtuals); TYPE_VTABLE (type) = vtable; if (super != NULL_TREE) { tree super_vtable = get_dispatch_vector (super); for ( i = TREE_INT_CST_LOW (TYPE_NVIRTUALS (super)); --i >= 0; ) TREE_VEC_ELT (vtable, i) = TREE_VEC_ELT (super_vtable, i); } for (method = TYPE_METHODS (type); method != NULL_TREE; method = TREE_CHAIN (method)) { if (DECL_VINDEX (method) != NULL_TREE && TREE_CODE (DECL_VINDEX (method)) == INTEGER_CST) { TREE_VEC_ELT (vtable, TREE_INT_CST_LOW (DECL_VINDEX (method))) = method; } } } return vtable;}static treeget_dispatch_table (type, this_class_addr) tree type, this_class_addr;{ tree vtable = get_dispatch_vector (type); int i; tree list = NULL_TREE; int nvirtuals = TREE_VEC_LENGTH (vtable); for (i = nvirtuals; --i >= 0; ) { tree method = TREE_VEC_ELT (vtable, i); if (METHOD_ABSTRACT (method)) warning_with_decl (method, "abstract method in non-abstract class"); if (DECL_RTL (method) == 0) make_decl_rtl (method, NULL, 1); list = tree_cons (NULL_TREE /*DECL_VINDEX (method) + 2*/, build1 (ADDR_EXPR, nativecode_ptr_type_node, method), list); } /* Dummy entry for compatibility with G++ -fvtable-thunks. */ list = tree_cons (integer_zero_node, null_pointer_node, list); list = tree_cons (integer_zero_node, this_class_addr, list); return build (CONSTRUCTOR, build_prim_array_type (nativecode_ptr_type_node, nvirtuals + 2), NULL_TREE, list);}voidmake_class_data (type) tree type;{ tree decl, cons, temp; tree field, fields_decl; tree static_fields = NULL_TREE; tree instance_fields = NULL_TREE; HOST_WIDE_INT static_field_count = 0; HOST_WIDE_INT instance_field_count = 0; HOST_WIDE_INT field_count; tree field_array_type; tree method; tree methods = NULL_TREE; tree dtable_decl = NULL_TREE; HOST_WIDE_INT method_count = 0; tree method_array_type; tree methods_decl; tree super; tree this_class_addr; tree constant_pool_constructor; tree interfaces = null_pointer_node; int interface_len = 0; tree type_decl = TYPE_NAME (type); this_class_addr = build_class_ref (type); decl = TREE_OPERAND (this_class_addr, 0); /* Build Field array. */ field = TYPE_FIELDS (type); if (DECL_NAME (field) == NULL_TREE) field = TREE_CHAIN (field); /* Skip dummy field for inherited data. */ for ( ; field != NULL_TREE; field = TREE_CHAIN (field)) { if (! DECL_ARTIFICIAL (field)) { tree init = make_field_value (field); if (FIELD_STATIC (field)) { tree initial = DECL_INITIAL (field); static_field_count++; static_fields = tree_cons (NULL_TREE, init, static_fields); /* If the initial value is a string constant, prevent output_constant from trying to assemble the value. */ if (initial != NULL_TREE && TREE_TYPE (initial) == string_ptr_type_node) DECL_INITIAL (field) = NULL_TREE; rest_of_decl_compilation (field, (char*) 0, 1, 1); DECL_INITIAL (field) = initial; } else { instance_field_count++; instance_fields = tree_cons (NULL_TREE, init, instance_fields); } } } field_count = static_field_count + instance_field_count; if (field_count > 0) { static_fields = nreverse (static_fields); instance_fields = nreverse (instance_fields); static_fields = chainon (static_fields, instance_fields); field_array_type = build_prim_array_type (field_type_node, field_count); fields_decl = build_decl (VAR_DECL, mangled_classname ("_FL_", type), field_array_type); DECL_INITIAL (fields_decl) = build (CONSTRUCTOR, field_array_type, NULL_TREE, static_fields); TREE_STATIC (fields_decl) = 1; DECL_ARTIFICIAL (fields_decl) = 1; DECL_IGNORED_P (fields_decl) = 1; rest_of_decl_compilation (fields_decl, (char*) 0, 1, 0); } else fields_decl = NULL_TREE; /* Build Method array. */ for (method = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (type)); method != NULL_TREE; method = TREE_CHAIN (method)) { tree init; if (METHOD_PRIVATE (method) && (flag_inline_functions || optimize)) continue; init = make_method_value (method); method_count++; methods = tree_cons (NULL_TREE, init, methods); } method_array_type = build_prim_array_type (method_type_node, method_count); methods_decl = build_decl (VAR_DECL, mangled_classname ("_MT_", type), method_array_type); DECL_INITIAL (methods_decl) = build (CONSTRUCTOR, method_array_type, NULL_TREE, nreverse (methods)); TREE_STATIC (methods_decl) = 1; DECL_ARTIFICIAL (methods_decl) = 1; DECL_IGNORED_P (methods_decl) = 1; rest_of_decl_compilation (methods_decl, (char*) 0, 1, 0); if (flag_assume_compiled && ! CLASS_ABSTRACT (type_decl) && ! CLASS_INTERFACE (type_decl)) { tree dtable = get_dispatch_table (type, this_class_addr); dtable_decl = build_dtable_decl (type); DECL_INITIAL (dtable_decl) = dtable; TREE_STATIC (dtable_decl) = 1; DECL_ARTIFICIAL (dtable_decl) = 1; DECL_IGNORED_P (dtable_decl) = 1; TREE_PUBLIC (dtable_decl) = 1; rest_of_decl_compilation (dtable_decl, (char*) 0, 1, 0); } super = CLASSTYPE_SUPER (type); if (super == NULL_TREE) super = null_pointer_node; else if (flag_assume_compiled) super = build_class_ref (super); else { int super_index = alloc_class_constant (super); super = build_int_2 (super_index, 0); TREE_TYPE (super) = ptr_type_node; } /* Build and emit the array of implemented interfaces. */ if (type != object_type_node) interface_len = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type)) - 1; if (interface_len > 0) { tree init = NULL_TREE; int i; tree interface_array_type, idecl; interface_array_type = build_prim_array_type (class_ptr_type, interface_len); idecl = build_decl (VAR_DECL, mangled_classname ("_IF_", type), interface_array_type); for (i = interface_len; i > 0; i--) { tree child = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), i); tree iclass = BINFO_TYPE (child); tree index; if (flag_assume_compiled) index = build_class_ref (iclass); else { int int_index = alloc_class_constant (iclass); index = build_int_2 (int_index, 0); TREE_TYPE (index) = ptr_type_node; } init = tree_cons (NULL_TREE, index, init); } DECL_INITIAL (idecl) = build (CONSTRUCTOR, interface_array_type, NULL_TREE, init); TREE_STATIC (idecl) = 1; DECL_ARTIFICIAL (idecl) = 1; DECL_IGNORED_P (idecl) = 1; interfaces = build1 (ADDR_EXPR, ptr_type_node, idecl); rest_of_decl_compilation (idecl, (char*) 0, 1, 0); } constant_pool_constructor = build_constants_constructor (); START_RECORD_CONSTRUCTOR (temp, object_type_node);#if 0 PUSH_FIELD_VALUE (temp, "vtable", NULL_TREE);#else PUSH_FIELD_VALUE (temp, "vtable", build1 (ADDR_EXPR, dtable_ptr_type, class_dtable_decl));#endif PUSH_FIELD_VALUE (temp, "sync_info", null_pointer_node); FINISH_RECORD_CONSTRUCTOR (temp); START_RECORD_CONSTRUCTOR (cons, class_type_node); PUSH_SUPER_VALUE (cons, temp); PUSH_FIELD_VALUE (cons, "next", null_pointer_node); PUSH_FIELD_VALUE (cons, "name", build_utf8_ref (DECL_NAME (type_decl))); PUSH_FIELD_VALUE (cons, "accflags", build_int_2 (get_access_flags_from_decl (type_decl), 0)); PUSH_FIELD_VALUE (cons, "superclass", CLASS_INTERFACE (type_decl) ? null_pointer_node : super); PUSH_FIELD_VALUE (cons, "constants", constant_pool_constructor); PUSH_FIELD_VALUE (cons, "methods", build1 (ADDR_EXPR, method_ptr_type_node, methods_decl)); PUSH_FIELD_VALUE (cons, "method_count", build_int_2 (method_count, 0)); PUSH_FIELD_VALUE (cons, "vtable_method_count", TYPE_NVIRTUALS (type)); PUSH_FIELD_VALUE (cons, "fields", fields_decl == NULL_TREE ? null_pointer_node : build1 (ADDR_EXPR, field_ptr_type_node, fields_decl)); PUSH_FIELD_VALUE (cons, "size_in_bytes", size_in_bytes (type)); PUSH_FIELD_VALUE (cons, "field_count", build_int_2 (field_count, 0)); PUSH_FIELD_VALUE (cons, "static_field_count", build_int_2 (static_field_count, 0)); PUSH_FIELD_VALUE (cons, "vtable", dtable_decl == NULL_TREE ? null_pointer_node : build1 (ADDR_EXPR, dtable_ptr_type, dtable_decl)); PUSH_FIELD_VALUE (cons, "interfaces", interfaces); PUSH_FIELD_VALUE (cons, "loader", null_pointer_node); PUSH_FIELD_VALUE (cons, "interface_count", build_int_2 (interface_len, 0)); PUSH_FIELD_VALUE (cons, "state", integer_zero_node); PUSH_FIELD_VALUE (cons, "thread", null_pointer_node); FINISH_RECORD_CONSTRUCTOR (cons); DECL_INITIAL (decl) = cons; rest_of_decl_compilation (decl, (char*) 0, 1, 0);}voidfinish_class (cl) tree cl;{ tree method; /* Emit deferred inline methods. */ for ( method = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (current_class)); method != NULL_TREE; method = TREE_CHAIN (method)) { if (! TREE_ASM_WRITTEN (method) && DECL_SAVED_INSNS (method) != 0) { /* It's a deferred inline method. Decide if we need to emit it. */ if (flag_keep_inline_functions || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (method)) || ! METHOD_PRIVATE (method)) { temporary_allocation (); output_inline_function (method); permanent_allocation (1); } } } make_class_data (current_class); register_class (); rest_of_decl_compilation (TYPE_NAME (current_class), (char*) 0, 1, 0);}/* Return 2 if CLASS is compiled by this compilation job; return 1 if CLASS can otherwise be assumed to be compiled; return 0 if we cannot assume that CLASS is compiled. Returns 1 for primitive and 0 for array types. */intis_compiled_class (class) tree class;{ int seen_in_zip; if (TREE_CODE (class) == POINTER_TYPE) class = TREE_TYPE (class); if (TREE_CODE (class) != RECORD_TYPE) /* Primitive types are static. */ return 1; if (TYPE_ARRAY_P (class)) return 0; if (class == current_class) return 2; seen_in_zip = (TYPE_LANG_SPECIFIC (class) && TYPE_LANG_SPECIFIC (class)->jcf && TYPE_LANG_SPECIFIC (class)->jcf->seen_in_zip); if (CLASS_FROM_CURRENTLY_COMPILED_SOURCE_P (class) || seen_in_zip) { /* The class was seen in the current ZIP file and will be available as a compiled class in the future but may not have been loaded already. Load it if necessary. This prevent build_class_ref () from crashing. */ if (seen_in_zip && !CLASS_LOADED_P (class)) load_class (class, 1); /* We return 2 for class seen in ZIP and class from files belonging to the same compilation unit */ return 2; } if (flag_assume_compiled) { if (!CLASS_LOADED_P (class)) { if (CLASS_FROM_SOURCE_P (class)) safe_layout_class (class); else load_class (class, 1); } return 1; } return 0;}/* Append the mangled name of TYPE onto OBSTACK. */static voidappend_gpp_mangled_type (obstack, type) struct obstack *obstack; tree type;{ switch (TREE_CODE (type)) { char code; case BOOLEAN_TYPE: code = 'b'; goto primitive; case CHAR_TYPE: code = 'w'; goto primitive; case VOID_TYPE: code = 'v'; goto primitive; case INTEGER_TYPE: /* Get the original type instead of the arguments promoted type. Avoid symbol name clashes. Should call a function to do that. FIXME. */ if (type == promoted_short_type_node) type = short_type_node; if (type == promoted_byte_type_node) type = byte_type_node; switch (TYPE_PRECISION (type)) { case 8: code = 'c'; goto primitive; case 16: code = 's'; goto primitive; case 32: code = 'i'; goto primitive; case 64: code = 'x'; goto primitive; default: goto bad_type; } primitive: obstack_1grow (obstack, code); break; case REAL_TYPE: switch (TYPE_PRECISION (type)) { case 32: code = 'f'; goto primitive; case 64: code = 'd'; goto primitive; default: goto bad_type; } case POINTER_TYPE: type = TREE_TYPE (type); obstack_1grow (obstack, 'P'); case RECORD_TYPE: if (TYPE_ARRAY_P (type))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -