summaryrefslogtreecommitdiff
path: root/gcc/toplev.c
diff options
context:
space:
mode:
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2010-08-30 20:04:49 +0000
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2010-08-30 20:04:49 +0000
commit990495a75cd770ac6234fdd765cda3a70221644d (patch)
treeca99479811fedf830873973cdd6050ed0d345e29 /gcc/toplev.c
parentd16175cce35b50e4b97a0253b51546c0581ac6e4 (diff)
downloadgcc-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.c90
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 ();