Hi!

Any time somebody adds or removes an option in some *.opt file (which e.g.
on the 10 branch after branching off 11 happened 5 times already), many
offsets in global_options variable change.  It is true we don't guarantee
ABI stability for plugins, but we change the most often used data structures
on the release branches only very rarely and so the options changes are the
most problematic for ABI stability of plugins.

Annobin uses a way to remap accesses to some of the global_options.x_* by
looking them up in the cl_options array where we have
offsetof (struct gcc_options, x_flag_lto)
etc. remembered, but sadly doesn't do it for all options (e.g. some flag_*
etc. option accesses may be hidden in various macros like POINTER_SIZE),
and more importantly some struct gcc_options offsets are not covered at all.
E.g. there is no offsetof (struct gcc_options, x_optimize),
offsetof (struct gcc_options, x_flag_sanitize) etc.  Those are usually:
Variable
int optimize
in the *.opt files.

So, couldn't our opt*.awk scripts generate another array that would either
cover just the offsets not covered in struct cl_options that a plugin could
use to remap struct global_options offsets at runtime, which would include
e.g. the offsetof value and the name of the variable and perhaps sizeof for
verification purposes?
Or couldn't we in plugin/include/ install a modified version of options.h
that instead of all the:
#define flag_opts_finished global_options.x_flag_opts_finished
will do:
#define flag_opts_finished gcc_lookup_option (flag_opts_finished)
where lookup_option would be a macro that does something like:
__attribute__((__pure__))
void *gcc_lookup_option_2 (unsigned short, const char *, unsigned short);
template <typename T>
T &gcc_lookup_option_1 (unsigned short offset, const char *name)
{
  T *ptr = static_cast <T *> (gcc_lookup_option_2 (offset, name, sizeof (T)));
  return *ptr;
}
#define lookup_option(var) \
  gcc_lookup_option_1 <decltype (global_options.x_##var)> \
    (offsetof (struct gcc_options, x_##var), #var, \
     sizeof (global_options.x_##var))
where the gcc_lookup_option_2 function would lookup the variable in an
opt*.awk generated table, containing entries like:
  "ix86_stack_protector_guard_offset", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  "ix86_stack_protector_guard_reg", "", NULL, NULL,
  "recip_mask", NULL, NULL, NULL,
...
As struct gcc_options is around 5KB now, that table would need 5K entries,
NULL and "" stand for no variable starts here, and "" additionally says that
padding starts here.
So, if no options have changed since the plugin has been built, it would be
very cheap, it would just verify that at the given offset the table contains
the corresponding string (i.e. non-NULL and strcmp == 0 and that the size
matches (that size - 1 following entries are NULL and then there is
non-NULL)). If not, it would keep looking around (one loop that looks in
both directions in the table, so first it would check offsets -1 and +1 from
the original, then -2 and +2, etc.
And would gcc_unreachable () if it can't find it in the table, or can find
it, but the size has changed.

If that is unacceptable, at least having a table with variables not covered
in struct cl_options offsets would allow the plugin to do it itself
(basically by constructing a remapping table, original offsetof (struct 
gcc_options, XXX)
remaps to offset ABC (and have some value like (unsigned short) -1 to signal
it is gone and there should be assertion failure.

Thoughts on this?

        Jakub

Reply via email to