The way we currently expose CUMULATIVE_ARGS to the function headers
breaks modularity; in particular, one reason why function.h currently needs
to include tm.h (PR middle-end/46495) is that it defines a structure that
contains a CUMULATIVE_ARGS member. We could replace that with
cumulative_args_t, but then the underlying CUMULATIVE_ARGS has to be
allocated somehow.
In general, CUMULATIVE_ARGS can be allocated in the stack frame of the
function
that initiates the processing. (Currently we do this with automatic
variables;
we remove the tm.h dependency in the processing functions for this by using
alloca, with the size in a new target vector data member.) There is one
notable exception: crtl->info.arg . This is set by assign_parms, which lets
assign_parms_initialize_all do the initialization; the latter function is
also used from gimplify_parameters.
We must make sure that the CUMULATIVE_ARGS for the incoming arguments of
the current function remains valid till the function has finished compiling.
The options that currently come to mind are:
- Make the caller of assign_parms_initialize_all do the allocation, and pass
a pointer to the allocated memory to assign_parms_initialize_all.
- Abolish crtl->info.arg (changing its type to cumulative_args_t already
introduces churn at all use sites, so replacing it altogether doesn't make
a big difference). As a replacement, add a target hook that stores the
information in a CUMULATIVE_ARGS typed variable, for subsequent use by
the target. We can just have one definition each for hook and variable
in targhooks.c (which can become many by the magic of multiple compilations
in separate namespaces).
We could also pass the entire incoming_args struct in for a cleaner
interface, but even if we disregard the churn that would cause in
the targets, we can't to abolish crtl->args easily, since the
target-independent code needs a number of its fields.
Still, either way (passing in cumulative_args_t or struct incoming_args),
I think this option is the easiest and safest to implement.
- Have the target provide allocation to a few static areas intended for
different lifetimes, selected by an enum. This would have low overhead,
but anyone who can remember semipermanent_obstack,
resume_temporary_allocation and their ilk - and likely some who don't -
will be wary of what happens when different interpretations of what the
lifetime categories mean cause confusion and memory corruption.
- make INIT_CUMULATIVE_ARGS allocate using garbage-collected memory.
That would require that each target provides appropriately
typedefed / GTY-ed
definitions. Multi-target operation would also require an index inside
cumulative_args_t to decide during GC which target's GC functions to call.