-
-/* When a file is initially compiled, the options used when generating
- the IL are not necessarily the same as those used when linking the
- objects into the final executable. In general, most build systems
- will proceed with something along the lines of:
-
- $ gcc <cc-flags> -flto -c f1.c -o f1.o
- $ gcc <cc-flags> -flto -c f2.c -o f2.o
- ...
- $ gcc <cc-flags> -flto -c fN.c -o fN.o
-
- And the final link may or may not include the same <cc-flags> used
- to generate the initial object files:
-
- $ gcc <ld-flags> -flto -o prog f1.o ... fN.o
-
- Since we will be generating final code during the link step, some
- of the flags used during the compile step need to be re-applied
- during the link step. For instance, flags in the -m family.
-
- The idea is to save a selected set of <cc-flags> in a special
- section of the initial object files. This section is then read
- during linking and the options re-applied.
-
- FIXME lto. Currently the scheme is limited in that only the
- options saved on the first object file (f1.o) are read back during
- the link step. This means that the options used to compile f1.o
- will be applied to ALL the object files in the final link step.
- More work needs to be done to implement a merging and validation
- mechanism, as this will not be enough for all cases. */
-
-/* Saved options hold the type of the option (currently CL_TARGET or
- CL_COMMON), and the code, argument, and value. */
-
-typedef struct GTY(()) opt_d
-{
- unsigned int type;
- size_t code;
- char *arg;
- int value;
-} opt_t;
-
-DEF_VEC_O (opt_t);
-DEF_VEC_ALLOC_O (opt_t, heap);
-
-
-/* Options are held in two vectors, one for those registered by
- command line handling code, and the other for those read in from
- any LTO IL input. */
-static VEC(opt_t, heap) *user_options = NULL;
-static VEC(opt_t, heap) *file_options = NULL;
-
-/* Iterate FROM in reverse, writing option codes not yet in CODES into *TO.
- Mark each new option code encountered in CODES. */
-
-static void
-reverse_iterate_options (VEC(opt_t, heap) *from, VEC(opt_t, heap) **to,
- bitmap codes)
-{
- int i;
-
- for (i = VEC_length (opt_t, from); i > 0; i--)
- {
- const opt_t *const o = VEC_index (opt_t, from, i - 1);
-
- if (bitmap_set_bit (codes, o->code))
- VEC_safe_push (opt_t, heap, *to, o);
- }
-}
-
-/* Concatenate options vectors FIRST and SECOND, rationalize so that only the
- final of any given option remains, and return the result. */
-
-static VEC(opt_t, heap) *
-concatenate_options (VEC(opt_t, heap) *first, VEC(opt_t, heap) *second)
-{
- VEC(opt_t, heap) *results = NULL;
- bitmap codes = lto_bitmap_alloc ();
-
- reverse_iterate_options (second, &results, codes);
- reverse_iterate_options (first, &results, codes);
-
- lto_bitmap_free (codes);
- return results;
-}
-
-/* Clear the options vector in *OPTS_P and set it to NULL. */
-
-static void
-clear_options (VEC(opt_t, heap) **opts_p)
-{
- int i;
- opt_t *o;
-
- FOR_EACH_VEC_ELT (opt_t, *opts_p, i, o)
- free (o->arg);
-
- VEC_free (opt_t, heap, *opts_p);
-}
-
-/* Write LENGTH bytes from ADDR to STREAM. */
-
-static void
-output_data_stream (struct lto_output_stream *stream,
- const void *addr, size_t length)
-{
- lto_output_data_stream (stream, addr, length);
-}
-
-/* Write string STRING to STREAM. */
-
-static void
-output_string_stream (struct lto_output_stream *stream, const char *string)
-{
- bool flag = false;
-
- if (string != NULL)
- {
- const size_t length = strlen (string);
-
- flag = true;
- output_data_stream (stream, &flag, sizeof (flag));
- output_data_stream (stream, &length, sizeof (length));
- output_data_stream (stream, string, length);
- }
- else
- output_data_stream (stream, &flag, sizeof (flag));
-}
-
-/* Return a string from IB. The string is allocated, and the caller is
- responsible for freeing it. */
-
-static char *
-input_string_block (struct lto_input_block *ib)
-{
- bool flag;
-
- lto_input_data_block (ib, &flag, sizeof (flag));
- if (flag)
- {
- size_t length;
- char *string;
-
- lto_input_data_block (ib, &length, sizeof (length));
- string = (char *) xcalloc (1, length + 1);
- lto_input_data_block (ib, string, length);
-
- return string;
- }
- else
- return NULL;
-}
-
-/* Return true if this option is one we need to save in LTO output files.
- At present, we pass along all target options, and common options that
- involve position independent code.
-
- TODO This list of options requires expansion and rationalization.
- Among others, optimization options may well be appropriate here. */
-
-static bool
-register_user_option_p (size_t code, unsigned int type)
-{
- if (type == CL_TARGET)
- return true;
- else if (type == CL_COMMON)
- {
- return (code == OPT_fPIC
- || code == OPT_fpic
- || code == OPT_fPIE
- || code == OPT_fpie
- || code == OPT_fcommon
- || code == OPT_fexceptions);
- }
-
- return false;
-}
-
-/* Note command line option with the given TYPE and CODE, ARG, and VALUE.
- If relevant to LTO, save it in the user options vector. */
-
-void
-lto_register_user_option (size_t code, const char *arg, int value,
- unsigned int type)
-{
- if (register_user_option_p (code, type))
- {
- opt_t o;
-
- o.type = type;
- o.code = code;
- if (arg != NULL)
- {
- o.arg = (char *) xmalloc (strlen (arg) + 1);
- strcpy (o.arg, arg);
- }
- else
- o.arg = NULL;
- o.value = value;
- VEC_safe_push (opt_t, heap, user_options, &o);
- }
-}
-
-/* Empty the saved user options vector. */
-
-void
-lto_clear_user_options (void)
-{
- clear_options (&user_options);
-}
-
-/* Empty the saved file options vector. */
-
-void
-lto_clear_file_options (void)
-{
- clear_options (&file_options);
-}
-
-/* Concatenate the user options and any file options read from an LTO IL
- file, and serialize them to STREAM. File options precede user options
- so that the latter override the former when reissued. */
-
-static void
-output_options (struct lto_output_stream *stream)
-{
- VEC(opt_t, heap) *opts = concatenate_options (file_options, user_options);
- const size_t length = VEC_length (opt_t, opts);
- int i;
- opt_t *o;
-
- output_data_stream (stream, &length, sizeof (length));
-
- FOR_EACH_VEC_ELT (opt_t, opts, i, o)
- {
- output_data_stream (stream, &o->type, sizeof (o->type));
- output_data_stream (stream, &o->code, sizeof (o->code));
- output_string_stream (stream, o->arg);
- output_data_stream (stream, &o->value, sizeof (o->value));
- }
-
- VEC_free (opt_t, heap, opts);
-}