diff options
author | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-08-30 20:04:49 +0000 |
---|---|---|
committer | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-08-30 20:04:49 +0000 |
commit | 990495a75cd770ac6234fdd765cda3a70221644d (patch) | |
tree | ca99479811fedf830873973cdd6050ed0d345e29 /gcc/toplev.c | |
parent | d16175cce35b50e4b97a0253b51546c0581ac6e4 (diff) | |
download | gcc-990495a75cd770ac6234fdd765cda3a70221644d.tar.gz |
Stack usage support
* common.opt (-fstack-usage): New option.
* doc/invoke.texi (Debugging options): Document it.
* builtins.c (expand_builtin_apply): Pass TRUE as 4th argument to
allocate_dynamic_stack_space.
(expand_builtin_alloca): Add 4th bool parameter CANNOT_ACCUMULATE
and propagate it to allocate_dynamic_stack_space.
(expand_builtin) <BUILT_IN_ALLOCA>: Adjust for above change.
* calls.c (initialize_argument_information): Pass TRUE as 4th
argument to allocate_dynamic_stack_space.
(expand_call): Set current_function_has_unbounded_dynamic_stack_size
to 1 when pushing a variable-sized argument onto the stack. Pass
TRUE as 4th argument to allocate_dynamic_stack_space.
Update current_function_pushed_stack_size.
(emit_library_call_value_1): Likewise.
* explow.c (allocate_dynamic_stack_space): Add 4th bool parameter
CANNOT_ACCUMULATE. If flag_stack_usage, look into the size and
attempt to find an upper bound. Remove redundant code for the
SETJMP_VIA_SAVE_AREA case.
* expr.h (allocate_dynamic_stack_space): Add 4th bool parameter.
* function.h (struct stack_usage): New structure.
(current_function_static_stack_size): New macro.
(current_function_dynamic_stack_size): Likewise.
(current_function_pushed_stack_size): Likewise.
(current_function_dynamic_alloc_count): Likewise.
(current_function_has_unbounded_dynamic_stack_size): Likewise.
(current_function_allocates_dynamic_stack_space): Likewise.
(struct function): Add new field 'su'.
* function.c (instantiate_virtual_regs): If SETJMP_VIA_SAVE_AREA,
add the value of the dynamic offset to the dynamic stack usage.
(gimplify_parameters): Set ALLOCA_FOR_VAR_P on call to BUILT_IN_ALLOCA
for variable-sized objects.
(prepare_function_start): Allocate cfun->su if flag_stack_usage.
(rest_of_handle_thread_prologue_and_epilogue): Call output_stack_usage.
* gimplify.c (gimplify_decl_expr): Set ALLOCA_FOR_VAR_P on call to
BUILT_IN_ALLOCA for variable-sized objects.
* output.h (output_stack_usage): Declare.
* toplev.c (stack_usage_file): New file pointer.
(output_stack_usage): New function.
(open_auxiliary_file): Likewise.
(lang_dependent_init): Open file if flag_stack_usage is set.
(finalize): Close file if stack_usage_file is not null.
* tree.h (ALLOCA_FOR_VAR_P): New macro.
* config/alpha/alpha.c (compute_frame_size): New function.
(alpha_expand_prologue): Use it.
(alpha_start_function): Likewise.
(alpha_expand_epilogue): Likewise. Set stack usage info.
* config/i386/i386.c (ix86_expand_prologue): Likewise.
* config/ia64/ia64.c (ia64_expand_prologue): Likewise.
* config/mips/mips.c (mips_expand_prologue): Likewise.
* config/pa/pa.c (hppa_expand_prologue): Likewise.
* config/rs6000/rs6000.c (rs6000_emit_prologue): Likewise.
* config/sparc/sparc.c (sparc_expand_prologue): Likewise.
testsuite/
* lib/gcc-dg.exp (cleanup-stack-usage): New procedure.
* lib/scanasm.exp (scan-stack-usage): Likewise.
(scan-stack-usage-not): Likewise.
* gcc.dg/stack-usage-1.c: New test.
* gcc.target/i386/stack-usage-realign.c: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@163660 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/toplev.c')
-rw-r--r-- | gcc/toplev.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/gcc/toplev.c b/gcc/toplev.c index ff824662a22..8aa18229e94 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -350,6 +350,7 @@ static const param_info lang_independent_params[] = { FILE *asm_out_file; FILE *aux_info_file; +FILE *stack_usage_file = NULL; FILE *dump_file = NULL; const char *dump_file_name; @@ -1584,6 +1585,88 @@ alloc_for_identifier_to_locale (size_t len) return ggc_alloc_atomic (len); } +/* Output stack usage information. */ +void +output_stack_usage (void) +{ + static bool warning_issued = false; + enum stack_usage_kind_type { STATIC = 0, DYNAMIC, DYNAMIC_BOUNDED }; + const char *stack_usage_kind_str[] = { + "static", + "dynamic", + "dynamic,bounded" + }; + HOST_WIDE_INT stack_usage = current_function_static_stack_size; + enum stack_usage_kind_type stack_usage_kind; + expanded_location loc; + const char *raw_id, *id; + + if (stack_usage < 0) + { + if (!warning_issued) + { + warning (0, "-fstack-usage not supported for this target"); + warning_issued = true; + } + return; + } + + stack_usage_kind = STATIC; + + /* Add the maximum amount of space pushed onto the stack. */ + if (current_function_pushed_stack_size > 0) + { + stack_usage += current_function_pushed_stack_size; + stack_usage_kind = DYNAMIC_BOUNDED; + } + + /* Now on to the tricky part: dynamic stack allocation. */ + if (current_function_allocates_dynamic_stack_space) + { + if (current_function_has_unbounded_dynamic_stack_size) + stack_usage_kind = DYNAMIC; + else + stack_usage_kind = DYNAMIC_BOUNDED; + + /* Add the size even in the unbounded case, this can't hurt. */ + stack_usage += current_function_dynamic_stack_size; + } + + loc = expand_location (DECL_SOURCE_LOCATION (current_function_decl)); + + /* Strip the scope prefix if any. */ + raw_id = lang_hooks.decl_printable_name (current_function_decl, 2); + id = strrchr (raw_id, '.'); + if (id) + id++; + else + id = raw_id; + + fprintf (stack_usage_file, + "%s:%d:%d:%s\t"HOST_WIDE_INT_PRINT_DEC"\t%s\n", + basename (loc.file), + loc.line, + loc.column, + id, + stack_usage, + stack_usage_kind_str[stack_usage_kind]); +} + +/* Open an auxiliary output file. */ +static FILE * +open_auxiliary_file (const char *ext) +{ + char *filename; + FILE *file; + + filename = concat (aux_base_name, ".", ext, NULL); + file = fopen (filename, "w"); + if (!file) + fatal_error ("can't open %s for writing: %m", filename); + free (filename); + return file; +} + /* Initialization of the front end environment, before command line options are parsed. Signal handlers, internationalization etc. ARGV0 is main's argv[0]. */ @@ -2199,6 +2282,10 @@ lang_dependent_init (const char *name) init_asm_output (name); + /* If stack usage information is desired, open the output file. */ + if (flag_stack_usage) + stack_usage_file = open_auxiliary_file ("su"); + /* This creates various _DECL nodes, so needs to be called after the front end is initialized. */ init_eh (); @@ -2280,6 +2367,9 @@ finalize (void) unlink_if_ordinary (asm_file_name); } + if (stack_usage_file) + fclose (stack_usage_file); + statistics_fini (); finish_optimization_passes (); |