[PATCH] Per-function flag setting
Zdenek Dvorak
rakdver@atrey.karlin.mff.cuni.cz
Tue Jun 3 09:00:00 GMT 2003
Hello,
this patch enables you to change optimization flags on per-function
basis, by attaching
__attribute__ ((options ("whatever", "flags", "you", "want")))
to it. It is quite simple and does no sanity checking at all, but I
think it might be quite useful for debugging (locating which function
is misscompiled).
Zdenek
* c-common.c (handle_options_attribute): New static function.
(c_common_attribute_table): Add options attribute.
* toplev.c (save_flag_values, restore_flag_values,
process_local_options): New static functions.
(rest_of_compilation): Set per-function flags from options attribute.
(parse_options_and_default_flags): Split parts into ...
(set_optimization_level_defaults, decode_flags): ... new functions.
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.417
diff -c -3 -p -r1.417 c-common.c
*** c-common.c 19 May 2003 19:19:42 -0000 1.417
--- c-common.c 2 Jun 2003 15:17:48 -0000
*************** static tree handle_vector_size_attribute
*** 790,795 ****
--- 790,797 ----
bool *));
static tree handle_nonnull_attribute PARAMS ((tree *, tree, tree, int,
bool *));
+ static tree handle_options_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
static tree handle_nothrow_attribute PARAMS ((tree *, tree, tree, int,
bool *));
static tree vector_size_helper PARAMS ((tree, tree));
*************** const struct attribute_spec c_common_att
*** 865,870 ****
--- 867,874 ----
handle_tls_model_attribute },
{ "nonnull", 0, -1, false, true, true,
handle_nonnull_attribute },
+ { "options", 1, -1, true, false, false,
+ handle_options_attribute },
{ "nothrow", 0, 0, true, false, false,
handle_nothrow_attribute },
{ "may_alias", 0, 0, false, true, false, NULL },
*************** handle_nonnull_attribute (node, name, ar
*** 5964,5969 ****
--- 5968,6007 ----
return NULL_TREE;
}
}
+ }
+
+ return NULL_TREE;
+ }
+
+ /* Handle the "options" attribute. */
+ static tree
+ handle_options_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name ATTRIBUTE_UNUSED;
+ tree args;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs ATTRIBUTE_UNUSED;
+ {
+ tree decl = *node;
+
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ {
+ error_with_decl (decl,
+ "options attribute can only be specified for functions");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ while (args)
+ {
+ if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
+ {
+ error_with_decl (decl,
+ "argument to options attribute must be a string");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ args = TREE_CHAIN (args);
}
return NULL_TREE;
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.762
diff -c -3 -p -r1.762 toplev.c
*** toplev.c 2 Jun 2003 05:05:33 -0000 1.762
--- toplev.c 2 Jun 2003 15:17:48 -0000
*************** extern void reg_alloc (void);
*** 105,110 ****
--- 105,115 ----
static void general_init (char *);
static void parse_options_and_default_flags (int, char **);
static void do_compile (void);
+ static int *save_flag_values (void);
+ static void restore_flag_values (int *);
+ static void process_local_options (tree);
+ static void set_optimization_level_defaults (int, char **);
+ static void decode_flags (int, char **);
static void process_options (void);
static void backend_init (void);
static int lang_dependent_init (const char *);
*************** rest_of_compilation (tree decl)
*** 3465,3472 ****
--- 3470,3487 ----
{
rtx insns;
int rebuild_label_notes_after_reload;
+ int *global_flags;
+ tree local_flags;
timevar_push (TV_REST_OF_COMPILATION);
+ local_flags = lookup_attribute ("options", DECL_ATTRIBUTES (decl));
+ if (local_flags)
+ {
+ global_flags = save_flag_values ();
+ process_local_options (local_flags);
+ }
+ else
+ global_flags = NULL;
/* Now that we're out of the frontend, we shouldn't have any more
CONCATs anywhere. */
*************** rest_of_compilation (tree decl)
*** 4002,4007 ****
--- 4017,4027 ----
ggc_collect ();
+ if (global_flags)
+ {
+ restore_flag_values (global_flags);
+ free (global_flags);
+ }
timevar_pop (TV_REST_OF_COMPILATION);
}
*************** general_init (char *argv0)
*** 5118,5152 ****
init_ttree ();
}
! /* Parse command line options and set default flag values, called
! after language-independent option-independent initialization. Do
! minimal options processing. Outputting diagnostics is OK, but GC
! and identifier hashtables etc. are not initialized yet.
!
! Return nonzero to suppress compiler back end initialization. */
static void
! parse_options_and_default_flags (int argc, char **argv)
{
int i;
- /* Save in case md file wants to emit args as a comment. */
- save_argc = argc;
- save_argv = argv;
-
- /* Initialize register usage now so switches may override. */
- init_reg_sets ();
-
- /* Register the language-independent parameters. */
- add_params (lang_independent_params, LAST_PARAM);
-
- /* This must be done after add_params but before argument processing. */
- init_ggc_heuristics();
-
- /* Perform language-specific options initialization. */
- (*lang_hooks.init_options) ();
-
- /* Scan to see what optimization level has been specified. That will
- determine the default value of many flags. */
for (i = 1; i < argc; i++)
{
if (!strcmp (argv[i], "-O"))
--- 5138,5150 ----
init_ttree ();
}
! /* Scan command line options for optimization level and set default values
! of flags accordingly. */
static void
! set_optimization_level_defaults (int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++)
{
if (!strcmp (argv[i], "-O"))
*************** parse_options_and_default_flags (int arg
*** 5272,5279 ****
/* Allow default optimizations to be specified on a per-machine basis. */
OPTIMIZATION_OPTIONS (optimize, optimize_size);
#endif
- /* Perform normal command line switch decoding. */
for (i = 1; i < argc;)
{
int lang_processed;
--- 5270,5283 ----
/* Allow default optimizations to be specified on a per-machine basis. */
OPTIMIZATION_OPTIONS (optimize, optimize_size);
#endif
+ }
+
+ /* Scan command line options and set the values of flags accordingly. */
+ static void
+ decode_flags (int argc, char **argv)
+ {
+ int i;
for (i = 1; i < argc;)
{
int lang_processed;
*************** parse_options_and_default_flags (int arg
*** 5366,5371 ****
--- 5370,5408 ----
flag_really_no_inline = flag_no_inline;
}
+ /* Parse command line options and set default flag values, called
+ after language-independent option-independent initialization. Do
+ minimal options processing. Outputting diagnostics is OK, but GC
+ and identifier hashtables etc. are not initialized yet.
+
+ Return nonzero to suppress compiler back end initialization. */
+ static void
+ parse_options_and_default_flags (int argc, char **argv)
+ {
+ /* Save in case md file wants to emit args as a comment. */
+ save_argc = argc;
+ save_argv = argv;
+
+ /* Initialize register usage now so switches may override. */
+ init_reg_sets ();
+
+ /* Register the language-independent parameters. */
+ add_params (lang_independent_params, LAST_PARAM);
+
+ /* This must be done after add_params but before argument processing. */
+ init_ggc_heuristics();
+
+ /* Perform language-specific options initialization. */
+ (*lang_hooks.init_options) ();
+
+ /* Scan to see what optimization level has been specified and set
+ the default value of flags. */
+ set_optimization_level_defaults (argc, argv);
+
+ /* Perform normal command line switch decoding. */
+ decode_flags (argc, argv);
+ }
+
/* Process the options that have been parsed. */
static void
process_options (void)
*************** process_options (void)
*** 5575,5580 ****
--- 5612,5677 ----
/* The presence of IEEE signaling NaNs, implies all math can trap. */
if (flag_signaling_nans)
flag_trapping_math = 1;
+ }
+
+ /* Save the values of flags. */
+ static int *
+ save_flag_values ()
+ {
+ int *storage = xmalloc (sizeof (int) * (LAST_PARAM
+ + ARRAY_SIZE (f_options)
+ + ARRAY_SIZE (W_options)));
+ unsigned i, b;
+
+ for (i = 0, b = 0; i < LAST_PARAM; i++, b++)
+ storage[b] = compiler_params[i].value;
+
+ for (i = 0; i < ARRAY_SIZE (f_options); i++, b++)
+ storage[b] = *f_options[i].variable;
+
+ for (i = 0; i < ARRAY_SIZE (W_options); i++, b++)
+ storage[b] = *W_options[i].variable;
+
+ return storage;
+ }
+
+ /* Restore the values of flags. */
+ static void
+ restore_flag_values (storage)
+ int *storage;
+ {
+ unsigned i, b;
+
+ for (i = 0, b = 0; i < LAST_PARAM; i++, b++)
+ compiler_params[i].value = storage[b];
+
+ for (i = 0; i < ARRAY_SIZE (f_options); i++, b++)
+ *f_options[i].variable = storage[b];
+
+ for (i = 0; i < ARRAY_SIZE (W_options); i++, b++)
+ *W_options[i].variable = storage[b];
+ }
+
+ /* Process OPTIONS passed through "options" attribute. */
+ static void
+ process_local_options (options)
+ tree options;
+ {
+ char **argv;
+ int argc, i;
+
+ options = TREE_VALUE (options);
+ argc = list_length (options) + 1;
+ argv = xmalloc (sizeof (char *) * argc);
+
+ argv[0] = NULL;
+ for (i = 1; i < argc; i++)
+ {
+ argv[i] = (char *) TREE_STRING_POINTER (TREE_VALUE (options));
+ options = TREE_CHAIN (options);
+ }
+ decode_flags (argc, argv);
+ free (argv);
}
/* Initialize the compiler back end. */
More information about the Gcc-patches
mailing list