diff options
author | geoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-06-04 07:11:05 +0000 |
---|---|---|
committer | geoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-06-04 07:11:05 +0000 |
commit | 1f3233d13f58417984cb2239d328b65e8d172744 (patch) | |
tree | 720630adca0f6b357e05c4feb8cbe33d556925ce /gcc/function.c | |
parent | 0dc11899d8781bca1da5f4421327d61890424808 (diff) | |
download | gcc-1f3233d13f58417984cb2239d328b65e8d172744.tar.gz |
Merge from pch-branch up to tag pch-commit-20020603.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@54232 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/function.c')
-rw-r--r-- | gcc/function.c | 293 |
1 files changed, 77 insertions, 216 deletions
diff --git a/gcc/function.c b/gcc/function.c index 669dd2ecf85..d1f4e89d5c2 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -55,7 +55,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "basic-block.h" #include "obstack.h" #include "toplev.h" -#include "hash.h" +#include "hashtab.h" #include "ggc.h" #include "tm_p.h" #include "integrate.h" @@ -129,12 +129,7 @@ static int profile_label_no; /* These variables hold pointers to functions to create and destroy target specific, per-function data structures. */ -void (*init_machine_status) PARAMS ((struct function *)); -void (*free_machine_status) PARAMS ((struct function *)); -/* This variable holds a pointer to a function to register any - data items in the target specific, per-function data structure - that will need garbage collection. */ -void (*mark_machine_status) PARAMS ((struct function *)); +struct machine_function * (*init_machine_status) PARAMS ((void)); /* The FUNCTION_DECL for an inline function currently being expanded. */ tree inline_function_decl; @@ -143,12 +138,12 @@ tree inline_function_decl; struct function *cfun = 0; /* These arrays record the INSN_UIDs of the prologue and epilogue insns. */ -static varray_type prologue; -static varray_type epilogue; +static GTY(()) varray_type prologue; +static GTY(()) varray_type epilogue; /* Array of INSN_UIDs to hold the INSN_UIDs for each sibcall epilogue in this function. */ -static varray_type sibcall_epilogue; +static GTY(()) varray_type sibcall_epilogue; /* In order to evaluate some expressions, such as function calls returning structures in memory, we need to temporarily allocate stack locations. @@ -168,7 +163,7 @@ static varray_type sibcall_epilogue; level where they are defined. They are marked a "kept" so that free_temp_slots will not free them. */ -struct temp_slot +struct temp_slot GTY(()) { /* Points to next temporary slot. */ struct temp_slot *next; @@ -209,7 +204,7 @@ struct temp_slot maintain this list in case two operands of an insn were required to match; in that case we must ensure we use the same replacement. */ -struct fixup_replacement +struct fixup_replacement GTY(()) { rtx old; rtx new; @@ -218,9 +213,9 @@ struct fixup_replacement struct insns_for_mem_entry { - /* The KEY in HE will be a MEM. */ - struct hash_entry he; - /* These are the INSNS which reference the MEM. */ + /* A MEM. */ + rtx key; + /* These are the INSNs which reference the MEM. */ rtx insns; }; @@ -232,18 +227,18 @@ static struct temp_slot *find_temp_slot_from_address PARAMS ((rtx)); static void put_reg_into_stack PARAMS ((struct function *, rtx, tree, enum machine_mode, enum machine_mode, int, unsigned int, int, - struct hash_table *)); + htab_t)); static void schedule_fixup_var_refs PARAMS ((struct function *, rtx, tree, enum machine_mode, - struct hash_table *)); + htab_t)); static void fixup_var_refs PARAMS ((rtx, enum machine_mode, int, rtx, - struct hash_table *)); + htab_t)); static struct fixup_replacement *find_fixup_replacement PARAMS ((struct fixup_replacement **, rtx)); static void fixup_var_refs_insns PARAMS ((rtx, rtx, enum machine_mode, int, int, rtx)); static void fixup_var_refs_insns_with_hash - PARAMS ((struct hash_table *, rtx, + PARAMS ((htab_t, rtx, enum machine_mode, int, rtx)); static void fixup_var_refs_insn PARAMS ((rtx, rtx, enum machine_mode, int, int, rtx)); @@ -283,29 +278,24 @@ static int contains PARAMS ((rtx, varray_type)); #ifdef HAVE_return static void emit_return_into_block PARAMS ((basic_block, rtx)); #endif -static void put_addressof_into_stack PARAMS ((rtx, struct hash_table *)); +static void put_addressof_into_stack PARAMS ((rtx, htab_t)); static bool purge_addressof_1 PARAMS ((rtx *, rtx, int, int, - struct hash_table *)); + htab_t)); static void purge_single_hard_subreg_set PARAMS ((rtx)); #if defined(HAVE_epilogue) && defined(INCOMING_RETURN_ADDR_RTX) static rtx keep_stack_depressed PARAMS ((rtx)); #endif static int is_addressof PARAMS ((rtx *, void *)); -static struct hash_entry *insns_for_mem_newfunc PARAMS ((struct hash_entry *, - struct hash_table *, - hash_table_key)); -static unsigned long insns_for_mem_hash PARAMS ((hash_table_key)); -static bool insns_for_mem_comp PARAMS ((hash_table_key, hash_table_key)); +static hashval_t insns_for_mem_hash PARAMS ((const void *)); +static int insns_for_mem_comp PARAMS ((const void *, const void *)); static int insns_for_mem_walk PARAMS ((rtx *, void *)); -static void compute_insns_for_mem PARAMS ((rtx, rtx, struct hash_table *)); -static void mark_function_status PARAMS ((struct function *)); -static void maybe_mark_struct_function PARAMS ((void *)); +static void compute_insns_for_mem PARAMS ((rtx, rtx, htab_t)); static void prepare_function_start PARAMS ((void)); static void do_clobber_return_reg PARAMS ((rtx, void *)); static void do_use_return_reg PARAMS ((rtx, void *)); /* Pointer to chain of `struct function' for containing functions. */ -static struct function *outer_function_chain; +static GTY(()) struct function *outer_function_chain; /* Given a function decl for a containing function, return the `struct function' for it. */ @@ -436,8 +426,8 @@ free_after_parsing (f) /* f->varasm is used by code generation. */ /* f->eh->eh_return_stub_label is used by code generation. */ - (*lang_hooks.function.free) (f); - free_stmt_status (f); + (*lang_hooks.function.final) (f); + f->stmt = NULL; } /* Clear out all parts of the state in F that can safely be discarded @@ -448,16 +438,11 @@ void free_after_compilation (f) struct function *f; { - free_eh_status (f); - free_expr_status (f); - free_emit_status (f); - free_varasm_status (f); - - if (free_machine_status) - (*free_machine_status) (f); - - if (f->x_parm_reg_stack_loc) - free (f->x_parm_reg_stack_loc); + f->eh = NULL; + f->expr = NULL; + f->emit = NULL; + f->varasm = NULL; + f->machine = NULL; f->x_temp_slots = NULL; f->arg_offset_rtx = NULL; @@ -1497,7 +1482,7 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p, int volatile_p; unsigned int original_regno; int used_p; - struct hash_table *ht; + htab_t ht; { struct function *func = function ? function : cfun; rtx new = 0; @@ -1545,7 +1530,7 @@ schedule_fixup_var_refs (function, reg, type, promoted_mode, ht) rtx reg; tree type; enum machine_mode promoted_mode; - struct hash_table *ht; + htab_t ht; { int unsigned_p = type ? TREE_UNSIGNED (type) : 0; @@ -1571,7 +1556,7 @@ fixup_var_refs (var, promoted_mode, unsignedp, may_share, ht) rtx var; enum machine_mode promoted_mode; int unsignedp; - struct hash_table *ht; + htab_t ht; rtx may_share; { tree pending; @@ -1707,17 +1692,18 @@ fixup_var_refs_insns (insn, var, promoted_mode, unsignedp, toplevel, may_share) static void fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp, may_share) - struct hash_table *ht; + htab_t ht; rtx var; enum machine_mode promoted_mode; int unsignedp; rtx may_share; { - struct insns_for_mem_entry *ime - = (struct insns_for_mem_entry *) hash_lookup (ht, var, - /*create=*/0, /*copy=*/0); + struct insns_for_mem_entry tmp; + struct insns_for_mem_entry *ime; rtx insn_list; + tmp.key = var; + ime = (struct insns_for_mem_entry *) htab_find (ht, &tmp); for (insn_list = ime->insns; insn_list != 0; insn_list = XEXP (insn_list, 1)) if (INSN_P (XEXP (insn_list, 0))) fixup_var_refs_insn (XEXP (insn_list, 0), var, promoted_mode, @@ -2979,7 +2965,7 @@ flush_addressof (decl) static void put_addressof_into_stack (r, ht) rtx r; - struct hash_table *ht; + htab_t ht; { tree decl, type; int volatile_p, used_p; @@ -3031,7 +3017,7 @@ purge_addressof_1 (loc, insn, force, store, ht) rtx *loc; rtx insn; int force, store; - struct hash_table *ht; + htab_t ht; { rtx x; RTX_CODE code; @@ -3291,50 +3277,34 @@ purge_addressof_1 (loc, insn, force, store, ht) return result; } -/* Return a new hash table entry in HT. */ - -static struct hash_entry * -insns_for_mem_newfunc (he, ht, k) - struct hash_entry *he; - struct hash_table *ht; - hash_table_key k ATTRIBUTE_UNUSED; -{ - struct insns_for_mem_entry *ifmhe; - if (he) - return he; - - ifmhe = ((struct insns_for_mem_entry *) - hash_allocate (ht, sizeof (struct insns_for_mem_entry))); - ifmhe->insns = NULL_RTX; - - return &ifmhe->he; -} - /* Return a hash value for K, a REG. */ -static unsigned long +static hashval_t insns_for_mem_hash (k) - hash_table_key k; + const void * k; { - /* K is really a RTX. Just use the address as the hash value. */ - return (unsigned long) k; + /* Use the address of the key for the hash value. */ + struct insns_for_mem_entry *m = (struct insns_for_mem_entry *) k; + return (hashval_t) m->key; } /* Return non-zero if K1 and K2 (two REGs) are the same. */ -static bool +static int insns_for_mem_comp (k1, k2) - hash_table_key k1; - hash_table_key k2; + const void * k1; + const void * k2; { - return k1 == k2; + struct insns_for_mem_entry *m1 = (struct insns_for_mem_entry *) k1; + struct insns_for_mem_entry *m2 = (struct insns_for_mem_entry *) k2; + return m1->key == m2->key; } struct insns_for_mem_walk_info { /* The hash table that we are using to record which INSNs use which MEMs. */ - struct hash_table *ht; + htab_t ht; /* The INSN we are currently processing. */ rtx insn; @@ -3356,18 +3326,26 @@ insns_for_mem_walk (r, data) { struct insns_for_mem_walk_info *ifmwi = (struct insns_for_mem_walk_info *) data; + struct insns_for_mem_entry tmp; + tmp.insns = NULL_RTX; if (ifmwi->pass == 0 && *r && GET_CODE (*r) == ADDRESSOF && GET_CODE (XEXP (*r, 0)) == REG) - hash_lookup (ifmwi->ht, XEXP (*r, 0), /*create=*/1, /*copy=*/0); + { + PTR *e; + tmp.key = XEXP (*r, 0); + e = htab_find_slot (ifmwi->ht, &tmp, INSERT); + if (*e == NULL) + { + *e = ggc_alloc (sizeof (tmp)); + memcpy (*e, &tmp, sizeof (tmp)); + } + } else if (ifmwi->pass == 1 && *r && GET_CODE (*r) == REG) { - /* Lookup this MEM in the hashtable, creating it if necessary. */ - struct insns_for_mem_entry *ifme - = (struct insns_for_mem_entry *) hash_lookup (ifmwi->ht, - *r, - /*create=*/0, - /*copy=*/0); + struct insns_for_mem_entry *ifme; + tmp.key = *r; + ifme = (struct insns_for_mem_entry *) htab_find (ifmwi->ht, &tmp); /* If we have not already recorded this INSN, do so now. Since we process the INSNs in order, we know that if we have @@ -3387,7 +3365,7 @@ static void compute_insns_for_mem (insns, last_insn, ht) rtx insns; rtx last_insn; - struct hash_table *ht; + htab_t ht; { rtx insn; struct insns_for_mem_walk_info ifmwi; @@ -3422,7 +3400,7 @@ purge_addressof (insns) rtx insns; { rtx insn; - struct hash_table ht; + htab_t ht; /* When we actually purge ADDRESSOFs, we turn REGs into MEMs. That requires a fixup pass over the instruction stream to correct @@ -3431,23 +3409,20 @@ purge_addressof (insns) mentioned in very many instructions. So, we speed up the process by pre-calculating which REGs occur in which INSNs; that allows us to perform the fixup passes much more quickly. */ - hash_table_init (&ht, - insns_for_mem_newfunc, - insns_for_mem_hash, - insns_for_mem_comp); - compute_insns_for_mem (insns, NULL_RTX, &ht); + ht = htab_create_ggc (1000, insns_for_mem_hash, insns_for_mem_comp, NULL); + compute_insns_for_mem (insns, NULL_RTX, ht); for (insn = insns; insn; insn = NEXT_INSN (insn)) if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == CALL_INSN) { if (! purge_addressof_1 (&PATTERN (insn), insn, - asm_noperands (PATTERN (insn)) > 0, 0, &ht)) + asm_noperands (PATTERN (insn)) > 0, 0, ht)) /* If we could not replace the ADDRESSOFs in the insn, something is wrong. */ abort (); - if (! purge_addressof_1 (®_NOTES (insn), NULL_RTX, 0, 0, &ht)) + if (! purge_addressof_1 (®_NOTES (insn), NULL_RTX, 0, 0, ht)) { /* If we could not replace the ADDRESSOFs in the insn's notes, we can just remove the offending notes instead. */ @@ -3468,7 +3443,6 @@ purge_addressof (insns) } /* Clean up. */ - hash_table_free (&ht); purge_bitfield_addressof_replacements = 0; purge_addressof_replacements = 0; @@ -4370,7 +4344,7 @@ assign_parms (fndecl) } max_parm_reg = LAST_VIRTUAL_REGISTER + 1; - parm_reg_stack_loc = (rtx *) xcalloc (max_parm_reg, sizeof (rtx)); + parm_reg_stack_loc = (rtx *) ggc_alloc_cleared (max_parm_reg * sizeof (rtx)); #ifdef INIT_CUMULATIVE_INCOMING_ARGS INIT_CUMULATIVE_INCOMING_ARGS (args_so_far, fntype, NULL_RTX); @@ -4934,7 +4908,7 @@ assign_parms (fndecl) but it's also rare and we need max_parm_reg to be precisely correct. */ max_parm_reg = regno + 1; - new = (rtx *) xrealloc (parm_reg_stack_loc, + new = (rtx *) ggc_realloc (parm_reg_stack_loc, max_parm_reg * sizeof (rtx)); memset ((char *) (new + old_max_parm_reg), 0, (max_parm_reg - old_max_parm_reg) * sizeof (rtx)); @@ -5936,8 +5910,6 @@ reorder_blocks () /* Remove deleted blocks from the block fragment chains. */ reorder_fix_fragments (block); - - VARRAY_FREE (block_stack); } /* Helper function for reorder_blocks. Reset TREE_ASM_WRITTEN. */ @@ -6326,7 +6298,7 @@ prepare_function_start () (*lang_hooks.function.init) (cfun); if (init_machine_status) - (*init_machine_status) (cfun); + cfun->machine = (*init_machine_status) (); } /* Initialize the rtl expansion mechanism so that we can do simple things @@ -6797,6 +6769,8 @@ use_return_register () diddle_return_value (do_use_return_reg, NULL); } +static GTY(()) rtx initial_trampoline; + /* Generate RTL for the end of the current function. FILENAME and LINE are the current position in the source file. @@ -6812,10 +6786,6 @@ expand_function_end (filename, line, end_bindings) tree link; rtx clobber_after; -#ifdef TRAMPOLINE_TEMPLATE - static rtx initial_trampoline; -#endif - finish_expr_for_function (); /* If arg_pointer_save_area was referenced only from a nested @@ -6854,8 +6824,6 @@ expand_function_end (filename, line, end_bindings) initial_trampoline = gen_rtx_MEM (BLKmode, assemble_trampoline_template ()); set_mem_align (initial_trampoline, TRAMPOLINE_ALIGNMENT); - - ggc_add_rtx_root (&initial_trampoline, 1); } #endif @@ -7955,121 +7923,14 @@ reposition_prologue_and_epilogue_notes (f) #endif /* HAVE_prologue or HAVE_epilogue */ } -/* Mark P for GC. */ - -static void -mark_function_status (p) - struct function *p; -{ - struct var_refs_queue *q; - struct temp_slot *t; - int i; - rtx *r; - - if (p == 0) - return; - - ggc_mark_rtx (p->arg_offset_rtx); - - if (p->x_parm_reg_stack_loc) - for (i = p->x_max_parm_reg, r = p->x_parm_reg_stack_loc; - i > 0; --i, ++r) - ggc_mark_rtx (*r); - - ggc_mark_rtx (p->return_rtx); - ggc_mark_rtx (p->x_cleanup_label); - ggc_mark_rtx (p->x_return_label); - ggc_mark_rtx (p->x_save_expr_regs); - ggc_mark_rtx (p->x_stack_slot_list); - ggc_mark_rtx (p->x_parm_birth_insn); - ggc_mark_rtx (p->x_tail_recursion_label); - ggc_mark_rtx (p->x_tail_recursion_reentry); - ggc_mark_rtx (p->internal_arg_pointer); - ggc_mark_rtx (p->x_arg_pointer_save_area); - ggc_mark_tree (p->x_rtl_expr_chain); - ggc_mark_rtx (p->x_last_parm_insn); - ggc_mark_tree (p->x_context_display); - ggc_mark_tree (p->x_trampoline_list); - ggc_mark_rtx (p->epilogue_delay_list); - ggc_mark_rtx (p->x_clobber_return_insn); - - for (t = p->x_temp_slots; t != 0; t = t->next) - { - ggc_mark (t); - ggc_mark_rtx (t->slot); - ggc_mark_rtx (t->address); - ggc_mark_tree (t->rtl_expr); - ggc_mark_tree (t->type); - } - - for (q = p->fixup_var_refs_queue; q != 0; q = q->next) - { - ggc_mark (q); - ggc_mark_rtx (q->modified); - } - - ggc_mark_rtx (p->x_nonlocal_goto_handler_slots); - ggc_mark_rtx (p->x_nonlocal_goto_handler_labels); - ggc_mark_rtx (p->x_nonlocal_goto_stack_level); - ggc_mark_tree (p->x_nonlocal_labels); - - mark_hard_reg_initial_vals (p); -} - -/* Mark the struct function pointed to by *ARG for GC, if it is not - NULL. This is used to mark the current function and the outer - function chain. */ - -static void -maybe_mark_struct_function (arg) - void *arg; -{ - struct function *f = *(struct function **) arg; - - if (f == 0) - return; - - ggc_mark_struct_function (f); -} - -/* Mark a struct function * for GC. This is called from ggc-common.c. */ - -void -ggc_mark_struct_function (f) - struct function *f; -{ - ggc_mark (f); - ggc_mark_tree (f->decl); - - mark_function_status (f); - mark_eh_status (f->eh); - mark_stmt_status (f->stmt); - mark_expr_status (f->expr); - mark_emit_status (f->emit); - mark_varasm_status (f->varasm); - - if (mark_machine_status) - (*mark_machine_status) (f); - (*lang_hooks.function.mark) (f); - - if (f->original_arg_vector) - ggc_mark_rtvec ((rtvec) f->original_arg_vector); - if (f->original_decl_initial) - ggc_mark_tree (f->original_decl_initial); - if (f->outer) - ggc_mark_struct_function (f->outer); -} - /* Called once, at initialization, to initialize function.c. */ void init_function_once () { - ggc_add_root (&cfun, 1, sizeof cfun, maybe_mark_struct_function); - ggc_add_root (&outer_function_chain, 1, sizeof outer_function_chain, - maybe_mark_struct_function); - VARRAY_INT_INIT (prologue, 0, "prologue"); VARRAY_INT_INIT (epilogue, 0, "epilogue"); VARRAY_INT_INIT (sibcall_epilogue, 0, "sibcall_epilogue"); } + +#include "gt-function.h" |