ARM/Thumb backend and CAN_DEBUG_WITHOUT_FP

Bernd Schmidt bernds@pathia.cygnus.co.uk
Wed Dec 1 08:00:00 GMT 1999


The merged arm/thumb backend has a problem with the macro
CAN_DEBUG_WITHOUT_FP.  It defines it to TARGET_THUMB, but the value of the
macro is never used, toplev.c only tests whether it is defined or not.  We
can't change that easily, because at the point where it is tested, we
haven't parsed enough of the commandline to determine whether we're
compiling arm or thumb code.

The patch below works around this by setting a special variable
"set_flag_omit_frame_pointer" which indicates whether the user used this
compiler flag.  If not, we can later change its default value.

This isn't very pretty, but I don't really see alternatives.

Bernd

        
	* arm.c (arm_override_options): Turn on flag_omit_frame_pointer if
	compiling for thumb, optimizing, and the user did not override the
	default.
	* arm.h (CAN_DEBUG_WITHOUT_FP): Don't define.
	* flags.h (set_flag_omit_frame_pointer): Declare new variable.
	* toplev.c (set_flag_omit_frame_pointer): New variable.
	(lang_independent_options): Add field SET_FLAG.
	(f_options): Add NULL everywhere for the new field, except for
	"omit-frame-pointer".
	(decode_f_option): Store 1 in *SET_FLAG when an argument is given.

diff -c -p -r1.33 arm.c
*** arm.c	1999/11/30 02:16:35	1.33
--- arm.c	1999/12/01 15:46:23
*************** arm_override_options ()
*** 658,663 ****
--- 658,667 ----
    else if (arm_is_strong)
      max_insns_skipped = 3;
  
+   /* Fake the effect of CAN_DEBUG_WITHOUT_FP.  */
+   if (TARGET_THUMB && ! set_flag_omit_frame_pointer && optimize >= 1)
+     flag_omit_frame_pointer = 1;
+ 
    /* Register global variables with the garbage collector.  */
    arm_add_gc_roots ();
  }
diff -c -p -r1.23 arm.h
*** arm.h	1999/11/21 08:27:51	1.23
--- arm.h	1999/12/01 15:46:27
*************** extern int arm_is_6_or_7;
*** 566,572 ****
  
  /* The frame pointer register used in gcc has nothing to do with debugging;
     that is controlled by the APCS-FRAME option.  */
! #define CAN_DEBUG_WITHOUT_FP (TARGET_THUMB)
  
  #define TARGET_MEM_FUNCTIONS 1
  
--- 566,574 ----
  
  /* The frame pointer register used in gcc has nothing to do with debugging;
     that is controlled by the APCS-FRAME option.  */
! /* We can't use this, since it would be true for the Thumb, but not for the
!    ARM.  So we fake the effect in arm_override_options instead.  */
! /* #undef CAN_DEBUG_WITHOUT_FP */
  
  #define TARGET_MEM_FUNCTIONS 1
  
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/toplev.c,v
retrieving revision 1.262
diff -c -p -r1.262 toplev.c
*** toplev.c	1999/11/25 16:58:32	1.262
--- toplev.c	1999/12/01 15:52:16
*************** int flag_no_function_cse = 0;
*** 515,520 ****
--- 515,525 ----
  
  int flag_omit_frame_pointer = 0;
  
+ /* Nonzero if the user passed in -fomit-frame-pointer or
+    -fno-omit-frame-pointer.  */
+ 
+ int set_flag_omit_frame_pointer = 0;
+ 
  /* Nonzero means place each function into its own section on those platforms
     which support arbitrary section names and unlimited numbers of sections.  */
  
*************** debug_args[] =
*** 829,838 ****
  
  typedef struct
  {
!   const char * string;
!   int *  variable;
!   int    on_value;
!   const char * description;
  }
  lang_independent_options;
  
--- 834,844 ----
  
  typedef struct
  {
!   const char *string;
!   int *variable;
!   int *set_flag;
!   int on_value;
!   const char *description;
  }
  lang_independent_options;
  
*************** const char *user_label_prefix;
*** 855,1020 ****
  
  lang_independent_options f_options[] =
  {
!   {"float-store", &flag_float_store, 1,
     "Do not store floats in registers" },
!   {"volatile", &flag_volatile, 1,
     "Consider all mem refs through pointers as volatile"},
!   {"volatile-global", &flag_volatile_global, 1,
     "Consider all mem refs to global data to be volatile" },
!   {"volatile-static", &flag_volatile_static, 1,
     "Consider all mem refs to static data to be volatile" },
!   {"defer-pop", &flag_defer_pop, 1,
     "Defer popping functions args from stack until later" },
!   {"omit-frame-pointer", &flag_omit_frame_pointer, 1,
     "When possible do not generate stack frames"},
!   {"cse-follow-jumps", &flag_cse_follow_jumps, 1,
     "When running CSE, follow jumps to their targets" },
!   {"cse-skip-blocks", &flag_cse_skip_blocks, 1,
     "When running CSE, follow conditional jumps" },
!   {"expensive-optimizations", &flag_expensive_optimizations, 1,
     "Perform a number of minor, expensive optimisations" },
!   {"thread-jumps", &flag_thread_jumps, 1,
     "Perform jump threading optimisations"},
!   {"strength-reduce", &flag_strength_reduce, 1,
     "Perform strength reduction optimisations" },
!   {"unroll-loops", &flag_unroll_loops, 1,
     "Perform loop unrolling when iteration count is known" },
!   {"unroll-all-loops", &flag_unroll_all_loops, 1,
     "Perform loop unrolling for all loops" },
!   {"move-all-movables", &flag_move_all_movables, 1,
     "Force all loop invariant computations out of loops" },
!   {"reduce-all-givs", &flag_reduce_all_givs, 1,
     "Strength reduce all loop general induction variables" },
!   {"writable-strings", &flag_writable_strings, 1,
     "Store strings in writable data section" },
!   {"peephole", &flag_no_peephole, 0,
     "Enable machine specific peephole optimisations" },
!   {"force-mem", &flag_force_mem, 1,
     "Copy memory operands into registers before using" },
!   {"force-addr", &flag_force_addr, 1,
     "Copy memory address constants into regs before using" },
!   {"function-cse", &flag_no_function_cse, 0,
     "Allow function addresses to be held in registers" },
!   {"inline-functions", &flag_inline_functions, 1,
     "Integrate simple functions into their callers" },
!   {"keep-inline-functions", &flag_keep_inline_functions, 1,
     "Generate code for funcs even if they are fully inlined" },
!   {"inline", &flag_no_inline, 0,
     "Pay attention to the 'inline' keyword"},
!   {"keep-static-consts", &flag_keep_static_consts, 1,
     "Emit static const variables even if they are not used" },
!   {"syntax-only", &flag_syntax_only, 1,
     "Check for syntax errors, then stop" },
!   {"shared-data", &flag_shared_data, 1,
     "Mark data as shared rather than private" },
!   {"caller-saves", &flag_caller_saves, 1,
     "Enable saving registers around function calls" },
!   {"pcc-struct-return", &flag_pcc_struct_return, 1,
     "Return 'short' aggregates in memory, not registers" },
!   {"reg-struct-return", &flag_pcc_struct_return, 0,
     "Return 'short' aggregates in registers" },
!   {"delayed-branch", &flag_delayed_branch, 1,
     "Attempt to fill delay slots of branch instructions" },
!   {"gcse", &flag_gcse, 1,
     "Perform the global common subexpression elimination" },
!   {"rerun-cse-after-loop", &flag_rerun_cse_after_loop, 1,
     "Run CSE pass after loop optimisations"},
!   {"rerun-loop-opt", &flag_rerun_loop_opt, 1,
     "Run the loop optimiser twice"},
!   {"delete-null-pointer-checks", &flag_delete_null_pointer_checks, 1,
     "Delete useless null pointer checks" },
!   {"pretend-float", &flag_pretend_float, 1,
     "Pretend that host and target use the same FP format"},
!   {"schedule-insns", &flag_schedule_insns, 1,
     "Reschedule instructions to avoid pipeline stalls"},
!   {"schedule-insns2", &flag_schedule_insns_after_reload, 1,
    "Run two passes of the instruction scheduler"},
!   {"sched-interblock",&flag_schedule_interblock, 1,
     "Enable scheduling across basic blocks" },
!   {"sched-spec",&flag_schedule_speculative, 1,
     "Allow speculative motion of non-loads" },
!   {"sched-spec-load",&flag_schedule_speculative_load, 1,
     "Allow speculative motion of some loads" },
!   {"sched-spec-load-dangerous",&flag_schedule_speculative_load_dangerous, 1,
     "Allow speculative motion of more loads" },
!   {"branch-count-reg",&flag_branch_on_count_reg, 1,
     "Replace add,compare,branch with branch on count reg"},
!   {"pic", &flag_pic, 1,
     "Generate position independent code, if possible"},
!   {"PIC", &flag_pic, 2, ""},
!   {"exceptions", &flag_exceptions, 1,
     "Enable exception handling" },
!   {"new-exceptions", &flag_new_exceptions, 1,
     "Use the new model for exception handling" },
!   {"unwind-tables", &flag_unwind_tables, 1,
      "Just generate unwind tables for exception handling" },
!   {"sjlj-exceptions", &exceptions_via_longjmp, 1,
     "Use setjmp/longjmp to handle exceptions" },
!   {"asynchronous-exceptions", &asynchronous_exceptions, 1,
     "Support asynchronous exceptions" },
!   {"profile-arcs", &profile_arc_flag, 1,
     "Insert arc based program profiling code" },
!   {"test-coverage", &flag_test_coverage, 1,
     "Create data files needed by gcov" },
!   {"branch-probabilities", &flag_branch_probabilities, 1,
     "Use profiling information for branch probabilities" },
!   {"fast-math", &flag_fast_math, 1,
     "Improve FP speed by violating ANSI & IEEE rules" },
!   {"common", &flag_no_common, 0,
     "Do not put unitialised globals in the common section" },
!   {"inhibit-size-directive", &flag_inhibit_size_directive, 1,
     "Do not generate .size directives" },
!   {"function-sections", &flag_function_sections, 1,
     "place each function into its own section" },
!   {"data-sections", &flag_data_sections, 1,
     "place data items into their own section" },
!   {"verbose-asm", &flag_verbose_asm, 1,
     "Add extra commentry to assembler output"},
!   {"gnu-linker", &flag_gnu_linker, 1,
     "Output GNU ld formatted global initialisers"},
!   {"regmove", &flag_regmove, 1,
     "Enables a register move optimisation"},
!   {"optimize-register-move", &flag_regmove, 1,
     "Do the full regmove optimization pass"},
!   {"pack-struct", &flag_pack_struct, 1,
     "Pack structure members together without holes" },
!   {"stack-check", &flag_stack_check, 1,
     "Insert stack checking code into the program" },
!   {"argument-alias", &flag_argument_noalias, 0,
     "Specify that arguments may alias each other & globals"},
!   {"argument-noalias", &flag_argument_noalias, 1,
     "Assume arguments may alias globals but not each other"},
!   {"argument-noalias-global", &flag_argument_noalias, 2,
     "Assume arguments do not alias each other or globals" },
!   {"strict-aliasing", &flag_strict_aliasing, 1,
     "Assume strict aliasing rules apply" },
!   {"align-loops", &align_loops, 0, 
     "Align the start of loops" },
!   {"align-jumps", &align_jumps, 0, 
     "Align labels which are only reached by jumping" },
!   {"align-labels", &align_labels, 0,
     "Align all labels" },
!   {"align-functions", &align_functions, 0,
     "Align the start of functions" },
!   {"check-memory-usage", &flag_check_memory_usage, 1,
     "Generate code to check every memory access" },
!   {"prefix-function-name", &flag_prefix_function_name, 1,
     "Add a prefix to all function names" },
!   {"dump-unnumbered", &flag_dump_unnumbered, 1,
     "Suppress output of instruction numbers and line number notes in debugging dumps"},
!   {"instrument-functions", &flag_instrument_function_entry_exit, 1,
     "Instrument function entry/exit with profiling calls"},
!   {"leading-underscore", &flag_leading_underscore, 1,
     "External symbols have a leading underscore" },
!   {"ident", &flag_no_ident, 0,
     "Process #ident directives"},
!   { "peephole2", &flag_peephole2, 1,
      "Enables an rtl peephole pass run before sched2" },
!   {"math-errno", &flag_errno_math, 1,
     "Set errno after built-in math functions"},
!   {"bounded-pointers", &flag_bounded_pointers, 1,
     "Compile pointers as triples: value, base & end" },
!   {"bounds-check", &flag_bounds_check, 1,
     "Generate code to check bounds before dereferencing pointers and arrays" }
  };
  
--- 861,1026 ----
  
  lang_independent_options f_options[] =
  {
!   {"float-store", &flag_float_store, NULL, 1,
     "Do not store floats in registers" },
!   {"volatile", &flag_volatile, NULL, 1,
     "Consider all mem refs through pointers as volatile"},
!   {"volatile-global", &flag_volatile_global, NULL, 1,
     "Consider all mem refs to global data to be volatile" },
!   {"volatile-static", &flag_volatile_static, NULL, 1,
     "Consider all mem refs to static data to be volatile" },
!   {"defer-pop", &flag_defer_pop, NULL, 1,
     "Defer popping functions args from stack until later" },
!   {"omit-frame-pointer", &flag_omit_frame_pointer, NULL, 1,
     "When possible do not generate stack frames"},
!   {"cse-follow-jumps", &flag_cse_follow_jumps, NULL, 1,
     "When running CSE, follow jumps to their targets" },
!   {"cse-skip-blocks", &flag_cse_skip_blocks, NULL, 1,
     "When running CSE, follow conditional jumps" },
!   {"expensive-optimizations", &flag_expensive_optimizations, NULL, 1,
     "Perform a number of minor, expensive optimisations" },
!   {"thread-jumps", &flag_thread_jumps, NULL, 1,
     "Perform jump threading optimisations"},
!   {"strength-reduce", &flag_strength_reduce, NULL, 1,
     "Perform strength reduction optimisations" },
!   {"unroll-loops", &flag_unroll_loops, NULL, 1,
     "Perform loop unrolling when iteration count is known" },
!   {"unroll-all-loops", &flag_unroll_all_loops, NULL, 1,
     "Perform loop unrolling for all loops" },
!   {"move-all-movables", &flag_move_all_movables, NULL, 1,
     "Force all loop invariant computations out of loops" },
!   {"reduce-all-givs", &flag_reduce_all_givs, NULL, 1,
     "Strength reduce all loop general induction variables" },
!   {"writable-strings", &flag_writable_strings, NULL, 1,
     "Store strings in writable data section" },
!   {"peephole", &flag_no_peephole, NULL, 0,
     "Enable machine specific peephole optimisations" },
!   {"force-mem", &flag_force_mem, NULL, 1,
     "Copy memory operands into registers before using" },
!   {"force-addr", &flag_force_addr, NULL, 1,
     "Copy memory address constants into regs before using" },
!   {"function-cse", &flag_no_function_cse, NULL, 0,
     "Allow function addresses to be held in registers" },
!   {"inline-functions", &flag_inline_functions, NULL, 1,
     "Integrate simple functions into their callers" },
!   {"keep-inline-functions", &flag_keep_inline_functions, NULL, 1,
     "Generate code for funcs even if they are fully inlined" },
!   {"inline", &flag_no_inline, NULL, 0,
     "Pay attention to the 'inline' keyword"},
!   {"keep-static-consts", &flag_keep_static_consts, NULL, 1,
     "Emit static const variables even if they are not used" },
!   {"syntax-only", &flag_syntax_only, NULL, 1,
     "Check for syntax errors, then stop" },
!   {"shared-data", &flag_shared_data, NULL, 1,
     "Mark data as shared rather than private" },
!   {"caller-saves", &flag_caller_saves, NULL, 1,
     "Enable saving registers around function calls" },
!   {"pcc-struct-return", &flag_pcc_struct_return, NULL, 1,
     "Return 'short' aggregates in memory, not registers" },
!   {"reg-struct-return", &flag_pcc_struct_return, NULL, 0,
     "Return 'short' aggregates in registers" },
!   {"delayed-branch", &flag_delayed_branch, NULL, 1,
     "Attempt to fill delay slots of branch instructions" },
!   {"gcse", &flag_gcse, NULL, 1,
     "Perform the global common subexpression elimination" },
!   {"rerun-cse-after-loop", &flag_rerun_cse_after_loop, NULL, 1,
     "Run CSE pass after loop optimisations"},
!   {"rerun-loop-opt", &flag_rerun_loop_opt, NULL, 1,
     "Run the loop optimiser twice"},
!   {"delete-null-pointer-checks", &flag_delete_null_pointer_checks, NULL, 1,
     "Delete useless null pointer checks" },
!   {"pretend-float", &flag_pretend_float, NULL, 1,
     "Pretend that host and target use the same FP format"},
!   {"schedule-insns", &flag_schedule_insns, NULL, 1,
     "Reschedule instructions to avoid pipeline stalls"},
!   {"schedule-insns2", &flag_schedule_insns_after_reload, NULL, 1,
    "Run two passes of the instruction scheduler"},
!   {"sched-interblock",&flag_schedule_interblock, NULL, 1,
     "Enable scheduling across basic blocks" },
!   {"sched-spec",&flag_schedule_speculative, NULL, 1,
     "Allow speculative motion of non-loads" },
!   {"sched-spec-load",&flag_schedule_speculative_load, NULL, 1,
     "Allow speculative motion of some loads" },
!   {"sched-spec-load-dangerous",&flag_schedule_speculative_load_dangerous, NULL, 1,
     "Allow speculative motion of more loads" },
!   {"branch-count-reg",&flag_branch_on_count_reg, NULL, 1,
     "Replace add,compare,branch with branch on count reg"},
!   {"pic", &flag_pic, NULL, 1,
     "Generate position independent code, if possible"},
!   {"PIC", &flag_pic, NULL, 2, ""},
!   {"exceptions", &flag_exceptions, NULL, 1,
     "Enable exception handling" },
!   {"new-exceptions", &flag_new_exceptions, NULL, 1,
     "Use the new model for exception handling" },
!   {"unwind-tables", &flag_unwind_tables, NULL, 1,
      "Just generate unwind tables for exception handling" },
!   {"sjlj-exceptions", &exceptions_via_longjmp, NULL, 1,
     "Use setjmp/longjmp to handle exceptions" },
!   {"asynchronous-exceptions", &asynchronous_exceptions, NULL, 1,
     "Support asynchronous exceptions" },
!   {"profile-arcs", &profile_arc_flag, NULL, 1,
     "Insert arc based program profiling code" },
!   {"test-coverage", &flag_test_coverage, NULL, 1,
     "Create data files needed by gcov" },
!   {"branch-probabilities", &flag_branch_probabilities, NULL, 1,
     "Use profiling information for branch probabilities" },
!   {"fast-math", &flag_fast_math, NULL, 1,
     "Improve FP speed by violating ANSI & IEEE rules" },
!   {"common", &flag_no_common, NULL, 0,
     "Do not put unitialised globals in the common section" },
!   {"inhibit-size-directive", &flag_inhibit_size_directive, NULL, 1,
     "Do not generate .size directives" },
!   {"function-sections", &flag_function_sections, NULL, 1,
     "place each function into its own section" },
!   {"data-sections", &flag_data_sections, NULL, 1,
     "place data items into their own section" },
!   {"verbose-asm", &flag_verbose_asm, NULL, 1,
     "Add extra commentry to assembler output"},
!   {"gnu-linker", &flag_gnu_linker, NULL, 1,
     "Output GNU ld formatted global initialisers"},
!   {"regmove", &flag_regmove, NULL, 1,
     "Enables a register move optimisation"},
!   {"optimize-register-move", &flag_regmove, NULL, 1,
     "Do the full regmove optimization pass"},
!   {"pack-struct", &flag_pack_struct, NULL, 1,
     "Pack structure members together without holes" },
!   {"stack-check", &flag_stack_check, NULL, 1,
     "Insert stack checking code into the program" },
!   {"argument-alias", &flag_argument_noalias, NULL, 0,
     "Specify that arguments may alias each other & globals"},
!   {"argument-noalias", &flag_argument_noalias, NULL, 1,
     "Assume arguments may alias globals but not each other"},
!   {"argument-noalias-global", &flag_argument_noalias, NULL, 2,
     "Assume arguments do not alias each other or globals" },
!   {"strict-aliasing", &flag_strict_aliasing, NULL, 1,
     "Assume strict aliasing rules apply" },
!   {"align-loops", &align_loops, NULL, 0, 
     "Align the start of loops" },
!   {"align-jumps", &align_jumps, NULL, 0, 
     "Align labels which are only reached by jumping" },
!   {"align-labels", &align_labels, NULL, 0,
     "Align all labels" },
!   {"align-functions", &align_functions, NULL, 0,
     "Align the start of functions" },
!   {"check-memory-usage", &flag_check_memory_usage, NULL, 1,
     "Generate code to check every memory access" },
!   {"prefix-function-name", &flag_prefix_function_name, NULL, 1,
     "Add a prefix to all function names" },
!   {"dump-unnumbered", &flag_dump_unnumbered, NULL, 1,
     "Suppress output of instruction numbers and line number notes in debugging dumps"},
!   {"instrument-functions", &flag_instrument_function_entry_exit, NULL, 1,
     "Instrument function entry/exit with profiling calls"},
!   {"leading-underscore", &flag_leading_underscore, NULL, 1,
     "External symbols have a leading underscore" },
!   {"ident", &flag_no_ident, NULL, 0,
     "Process #ident directives"},
!   { "peephole2", &flag_peephole2, NULL, 1,
      "Enables an rtl peephole pass run before sched2" },
!   {"math-errno", &flag_errno_math, NULL, 1,
     "Set errno after built-in math functions"},
!   {"bounded-pointers", &flag_bounded_pointers, NULL, 1,
     "Compile pointers as triples: value, base & end" },
!   {"bounds-check", &flag_bounds_check, NULL, 1,
     "Generate code to check bounds before dereferencing pointers and arrays" }
  };
  
*************** decode_f_option (arg)
*** 4843,4848 ****
--- 4849,4856 ----
        if (!strcmp (arg, f_options[j].string))
  	{
  	  *f_options[j].variable = f_options[j].on_value;
+ 	  if (f_options[j].set_flag)
+ 	    *f_options[j].set_flag = 1;
  	  return 1;
  	}
      
*************** decode_f_option (arg)
*** 4850,4855 ****
--- 4858,4865 ----
  	  && ! strcmp (arg + 3, f_options[j].string))
  	{
  	  *f_options[j].variable = ! f_options[j].on_value;
+ 	  if (f_options[j].set_flag)
+ 	    *f_options[j].set_flag = 1;
  	  return 1;
  	}
      }
Index: flags.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/flags.h,v
retrieving revision 1.36
diff -c -p -r1.36 flags.h
*** flags.h	1999/11/04 07:23:58	1.36
--- flags.h	1999/12/01 15:52:17
*************** extern int flag_no_function_cse;
*** 272,277 ****
--- 272,282 ----
  
  extern int flag_omit_frame_pointer;
  
+ /* Nonzero if the user passed in -fomit-frame-pointer or
+    -fno-omit-frame-pointer.  */
+ 
+ extern int set_flag_omit_frame_pointer;
+ 
  /* Nonzero to inhibit use of define_optimization peephole opts.  */
  
  extern int flag_no_peephole;



More information about the Gcc-patches mailing list