📄 method.c
字号:
cname = TREE_OPERAND (tmp, 0); tmp = TREE_OPERAND (tmp, 1); break; default: my_friendly_abort (77); } last = tmp; tmp = TREE_OPERAND (tmp, 0); } last = groktypename (build_tree_list (TREE_TYPE (component), TREE_OPERAND (component, 0))); name = build_typename_overload (last); TREE_TYPE (name) = last; if (of && TREE_CODE (of) == TYPE_DECL) { if (cname == NULL_TREE) { cname = DECL_NAME (of); of = NULL_TREE; } else my_friendly_assert (cname == DECL_NAME (of), 256); } if (of) { tree this_this; if (current_class_decl == NULL_TREE) { cp_error ("object required for `operator %T' call", TREE_TYPE (name)); return error_mark_node; } this_this = convert_pointer_to (TREE_TYPE (of), current_class_decl); return build_component_ref (this_this, name, 0, protect); } else if (cname) return build_offset_ref (cname, name); else if (current_class_name) return build_offset_ref (current_class_name, name); cp_error ("object required for `operator %T' member reference", TREE_TYPE (name)); return error_mark_node;}#endifstatic char *thunk_printable_name (decl) tree decl;{ return "<thunk function>";}treemake_thunk (function, delta) tree function; int delta;{ char buffer[250]; tree thunk_fndecl, thunk_id; tree thunk; char *func_name; static int thunk_number = 0; tree func_decl; if (TREE_CODE (function) != ADDR_EXPR) abort (); func_decl = TREE_OPERAND (function, 0); if (TREE_CODE (func_decl) != FUNCTION_DECL) abort (); func_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (func_decl)); if (delta<=0) sprintf (buffer, "__thunk_%d_%s", -delta, func_name); else sprintf (buffer, "__thunk_n%d_%s", delta, func_name); thunk_id = get_identifier (buffer); thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id); if (thunk && TREE_CODE (thunk) != THUNK_DECL) { error_with_decl ("implementation-reserved name `%s' used"); IDENTIFIER_GLOBAL_VALUE (thunk_id) = thunk = NULL_TREE; } if (thunk == NULL_TREE) { thunk = build_decl (THUNK_DECL, thunk_id, TREE_TYPE (func_decl)); DECL_RESULT (thunk) = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (vtable_entry_type))); TREE_READONLY (thunk) = TYPE_READONLY (TREE_TYPE (vtable_entry_type)); TREE_THIS_VOLATILE (thunk) = TYPE_VOLATILE (TREE_TYPE (vtable_entry_type)); make_function_rtl (thunk); DECL_INITIAL (thunk) = function; THUNK_DELTA (thunk) = delta; /* So that finish_file can write out any thunks that need to be: */ pushdecl_top_level (thunk); } return thunk;}voidemit_thunk (thunk_fndecl) tree thunk_fndecl;{ rtx insns; char *fnname; char buffer[250]; tree argp; struct args_size stack_args_size; tree function = TREE_OPERAND (DECL_INITIAL (thunk_fndecl), 0); int delta = THUNK_DELTA (thunk_fndecl); int tem; int failure = 0; int current_call_is_indirect = 0; /* needed for HPPA FUNCTION_ARG */ /* Used to remember which regs we need to emit a USE rtx for. */ rtx need_use[FIRST_PSEUDO_REGISTER]; int need_use_count = 0; /* rtx for the 'this' parameter. */ rtx this_rtx = 0, this_reg_rtx = 0, fixed_this_rtx; char *(*save_decl_printable_name) () = decl_printable_name; /* Data on reg parms scanned so far. */ CUMULATIVE_ARGS args_so_far; if (TREE_ASM_WRITTEN (thunk_fndecl)) return; TREE_ASM_WRITTEN (thunk_fndecl) = 1; if (TREE_PUBLIC (function)) { TREE_PUBLIC (thunk_fndecl) = 1; if (DECL_EXTERNAL (function)) { DECL_EXTERNAL (thunk_fndecl) = 1; assemble_external (thunk_fndecl); return; } } decl_printable_name = thunk_printable_name; if (current_function_decl) abort (); current_function_decl = thunk_fndecl; init_function_start (thunk_fndecl, input_filename, lineno); pushlevel (0); expand_start_bindings (1); /* Start updating where the next arg would go. */ INIT_CUMULATIVE_ARGS (args_so_far, TREE_TYPE (function), NULL_RTX); stack_args_size.constant = 0; stack_args_size.var = 0; /* SETUP for possible structure return address FIXME */ /* Now look through all the parameters, make sure that we don't clobber any registers used for parameters. Also, pick up an rtx for the first "this" parameter. */ for (argp = TYPE_ARG_TYPES (TREE_TYPE (function)); argp != NULL_TREE; argp = TREE_CHAIN (argp)) { tree passed_type = TREE_VALUE (argp); register rtx entry_parm; int named = 1; /* FIXME */ struct args_size stack_offset; struct args_size arg_size; if (passed_type == void_type_node) break; if ((TREE_CODE (TYPE_SIZE (passed_type)) != INTEGER_CST && contains_placeholder_p (TYPE_SIZE (passed_type)))#ifdef FUNCTION_ARG_PASS_BY_REFERENCE || FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, TYPE_MODE (passed_type), passed_type, named)#endif ) passed_type = build_pointer_type (passed_type); entry_parm = FUNCTION_ARG (args_so_far, TYPE_MODE (passed_type), passed_type, named); if (entry_parm != 0) need_use[need_use_count++] = entry_parm; locate_and_pad_parm (TYPE_MODE (passed_type), passed_type,#ifdef STACK_PARMS_IN_REG_PARM_AREA 1,#else entry_parm != 0,#endif thunk_fndecl, &stack_args_size, &stack_offset, &arg_size);/* REGNO (entry_parm);*/ if (this_rtx == 0) { this_reg_rtx = entry_parm; if (!entry_parm) { rtx offset_rtx = ARGS_SIZE_RTX (stack_offset); rtx internal_arg_pointer, stack_parm; if ((ARG_POINTER_REGNUM == STACK_POINTER_REGNUM || ! (fixed_regs[ARG_POINTER_REGNUM] || ARG_POINTER_REGNUM == FRAME_POINTER_REGNUM))) internal_arg_pointer = copy_to_reg (virtual_incoming_args_rtx); else internal_arg_pointer = virtual_incoming_args_rtx; if (offset_rtx == const0_rtx) entry_parm = gen_rtx (MEM, TYPE_MODE (passed_type), internal_arg_pointer); else entry_parm = gen_rtx (MEM, TYPE_MODE (passed_type), gen_rtx (PLUS, Pmode, internal_arg_pointer, offset_rtx)); } this_rtx = entry_parm; } FUNCTION_ARG_ADVANCE (args_so_far, TYPE_MODE (passed_type), passed_type, named); } fixed_this_rtx = plus_constant (this_rtx, delta); if (this_rtx != fixed_this_rtx) emit_move_insn (this_rtx, fixed_this_rtx); if (this_reg_rtx) emit_insn (gen_rtx (USE, VOIDmode, this_reg_rtx)); emit_indirect_jump (XEXP (DECL_RTL (function), 0)); while (need_use_count > 0) emit_insn (gen_rtx (USE, VOIDmode, need_use[--need_use_count])); expand_end_bindings (NULL, 1, 0); poplevel (0, 0, 1); /* From now on, allocate rtl in current_obstack, not in saveable_obstack. Note that that may have been done above, in save_for_inline_copying. The call to resume_temporary_allocation near the end of this function goes back to the usual state of affairs. */ rtl_in_current_obstack (); insns = get_insns (); /* Copy any shared structure that should not be shared. */ unshare_all_rtl (insns); /* Instantiate all virtual registers. */ instantiate_virtual_regs (current_function_decl, get_insns ()); /* We are no longer anticipating cse in this function, at least. */ cse_not_expected = 1; /* Now we choose between stupid (pcc-like) register allocation (if we got the -noreg switch and not -opt) and smart register allocation. */ if (optimize > 0) /* Stupid allocation probably won't work */ obey_regdecls = 0; /* if optimizations being done. */ regclass_init (); regclass (insns, max_reg_num ()); if (obey_regdecls) { stupid_life_analysis (insns, max_reg_num (), NULL); failure = reload (insns, 0, NULL); } else { /* Do control and data flow analysis, and write some of the results to dump file. */ flow_analysis (insns, max_reg_num (), NULL); local_alloc (); failure = global_alloc (NULL); } reload_completed = 1;#ifdef LEAF_REGISTERS leaf_function = 0; if (optimize > 0 && only_leaf_regs_used () && leaf_function_p ()) leaf_function = 1;#endif /* If a machine dependent reorganization is needed, call it. */#ifdef MACHINE_DEPENDENT_REORG MACHINE_DEPENDENT_REORG (insns);#endif /* Now turn the rtl into assembler code. */ { char *fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0); assemble_start_function (thunk_fndecl, fnname); final (insns, asm_out_file, optimize, 0); assemble_end_function (thunk_fndecl, fnname); }; exit_rest_of_compilation: reload_completed = 0; /* Cancel the effect of rtl_in_current_obstack. */ resume_temporary_allocation (); decl_printable_name = save_decl_printable_name; current_function_decl = 0;}/* Code for synthesizing methods which have default semantics defined. *//* For the anonymous union in TYPE, return the member that is at least as large as the rest of the members, so we can copy it. */static treelargest_union_member (type) tree type;{ tree f, type_size = TYPE_SIZE (type); for (f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f)) if (simple_cst_equal (DECL_SIZE (f), type_size) == 1) return f; /* We should always find one. */ my_friendly_abort (323); return NULL_TREE;}/* Generate code for default X(X&) constructor. */voiddo_build_copy_constructor (fndecl) tree fndecl;{ tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); tree t; clear_last_expr (); push_momentary (); if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) parm = TREE_CHAIN (parm); parm = convert_from_reference (parm); if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)) { t = build (INIT_EXPR, void_type_node, C_C_D, parm); TREE_SIDE_EFFECTS (t) = 1; cplus_expand_expr_stmt (t); } else { tree fields = TYPE_FIELDS (current_class_type); int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type); tree binfos = TYPE_BINFO_BASETYPES (current_class_type); int i; for (t = CLASSTYPE_VBASECLASSES (current_class_type); t; t = TREE_CHAIN (t)) { tree basetype = BINFO_TYPE (t); tree p = convert_to_reference (build_reference_type (basetype), parm, CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); p = convert_from_reference (p); current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype), p, current_base_init_list); } for (i = 0; i < n_bases; ++i) { tree p, basetype = TREE_VEC_ELT (binfos, i); if (TREE_VIA_VIRTUAL (basetype)) continue; basetype = BINFO_TYPE (basetype); p = convert_to_reference (build_reference_type (basetype), parm, CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); p = convert_from_reference (p); current_base_init_list = tree_cons (TYPE_NESTED_NAME (basetype), p, current_base_init_list); } for (; fields; fields = TREE_CHAIN (fields)) { tree name, init, t; tree field = fields; if (TREE_CODE (field) != FIELD_DECL) continue; if (DECL_NAME (field)) { if (VFIELD_NAME_P (DECL_NAME (field))) continue; if (VBASE_NAME_P (DECL_NAME (field))) continue; /* True for duplicate members. */ if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field) continue; } else if ((t = TREE_TYPE (field)) != NULL_TREE && TREE_CODE (t) == UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)) && TYPE_FIELDS (t) != NULL_TREE) field = largest_union_member (t); else continue; init = build (COMPONENT_REF, TREE_TYPE (field), parm, field); init = build_tree_list (NULL_TREE, init); current_member_init_list = tree_cons (DECL_NAME (field), init, current_member_init_list); } current_member_init_list = nreverse (current_member_init_list); current_base_init_list = nreverse (current_base_init_list); setup_vtbl_ptr (); } pop_momentary ();}voiddo_build_assign_ref (fndecl) tree fndecl;{ tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); clear_last_expr (); push_momentary (); parm = convert_from_reference (parm); if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)) { tree t = build (MODIFY_EXPR, void_type_node, C_C_D, parm); TREE_SIDE_EFFECTS (t) = 1; cplus_expand_expr_stmt (t); } else { tree fields = TYPE_FIELDS (current_class_type); int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type); tree binfos = TYPE_BINFO_BASETYPES (current_class_type); int i; for (i = 0; i < n_bases; ++i) { tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i)); if (TYPE_HAS_ASSIGN_REF (basetype)) { tree p = convert_to_reference (build_reference_type (basetype), parm, CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); p = convert_from_reference (p); p = build_member_call (TYPE_NESTED_NAME (basetype), ansi_opname [MODIFY_EXPR], build_tree_list (NULL_TREE, p)); expand_expr_stmt (p); } } for (; fields; fields = TREE_CHAIN (fields)) { tree comp, init, t; tree field = fields; if (TREE_CODE (field) != FIELD_DECL) continue; if (DECL_NAME (field)) { if (VFIELD_NAME_P (DECL_NAME (field))) continue; if (VBASE_NAME_P (DECL_NAME (field))) continue; /* True for duplicate members. */ if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field) continue; } else if ((t = TREE_TYPE (field)) != NULL_TREE && TREE_CODE (t) == UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)) && TYPE_FIELDS (t) != NULL_TREE) field = largest_union_member (t); else continue; comp = build (COMPONENT_REF, TREE_TYPE (field), C_C_D, field); init = build (COMPONENT_REF, TREE_TYPE (field), parm, field); expand_expr_stmt (build_modify_expr (comp, NOP_EXPR, init)); } } c_expand_return (C_C_D); pop_momentary ();}void push_cp_function_context ();void pop_cp_function_context ();voidsynthesize_method (fndecl) tree fndecl;{ int nested = (current_function_decl != NULL_TREE); tree context = decl_function_context (fndecl); char *f = input_filename; tree base = DECL_CLASS_CONTEXT (fndecl); if (nested) push_cp_function_context (context); input_filename = DECL_SOURCE_FILE (fndecl); interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (base); interface_only = CLASSTYPE_INTERFACE_ONLY (base); start_function (NULL_TREE, fndecl, NULL_TREE, NULL_TREE, 1); store_parm_decls (); if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR]) do_build_assign_ref (fndecl); else if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) ; else { tree arg_chain = FUNCTION_ARG_CHAIN (fndecl); if (DECL_CONSTRUCTOR_FOR_VBASE_P (fndecl)) arg_chain = TREE_CHAIN (arg_chain); if (arg_chain != void_list_node) do_build_copy_constructor (fndecl); else if (TYPE_NEEDS_CONSTRUCTING (current_class_type)) setup_vtbl_ptr (); } finish_function (lineno, 0, nested); /* Do we really *want* to inline this function? */ if (DECL_INLINE (fndecl)) { /* Turn off DECL_INLINE for the moment so function_cannot_inline_p will check our size. */ DECL_INLINE (fndecl) = 0; if (function_cannot_inline_p (fndecl) == 0) DECL_INLINE (fndecl) = 1; } input_filename = f; extract_interface_info (); if (nested) pop_cp_function_context (context);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -