From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- gcc/lto-opts.c | 428 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 428 insertions(+) create mode 100644 gcc/lto-opts.c (limited to 'gcc/lto-opts.c') diff --git a/gcc/lto-opts.c b/gcc/lto-opts.c new file mode 100644 index 000000000..71a7067ce --- /dev/null +++ b/gcc/lto-opts.c @@ -0,0 +1,428 @@ +/* LTO IL options. + + Copyright 2009, 2010 Free Software Foundation, Inc. + Contributed by Simon Baldwin + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "hashtab.h" +#include "ggc.h" +#include "vec.h" +#include "bitmap.h" +#include "flags.h" +#include "opts.h" +#include "options.h" +#include "target.h" +#include "diagnostic.h" +#include "lto-streamer.h" + +/* 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 -flto -c f1.c -o f1.o + $ gcc -flto -c f2.c -o f2.o + ... + $ gcc -flto -c fN.c -o fN.o + + And the final link may or may not include the same used + to generate the initial object files: + + $ gcc -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 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)); +} + +/* Read LENGTH bytes from STREAM to ADDR. */ + +static void +input_data_block (struct lto_input_block *ib, void *addr, size_t length) +{ + size_t i; + unsigned char *const buffer = (unsigned char *const) addr; + + for (i = 0; i < length; i++) + buffer[i] = lto_input_1_unsigned (ib); +} + +/* 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; + + input_data_block (ib, &flag, sizeof (flag)); + if (flag) + { + size_t length; + char *string; + + input_data_block (ib, &length, sizeof (length)); + string = (char *) xcalloc (1, length + 1); + 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, 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, 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); +} + +/* Write currently held options to an LTO IL section. */ + +void +lto_write_options (void) +{ + char *const section_name = lto_get_section_name (LTO_section_opts, NULL, NULL); + struct lto_output_stream stream; + struct lto_simple_header header; + struct lto_output_stream *header_stream; + + /* Targets and languages can provide defaults for -fexceptions but + we only process user options from the command-line. Until we + serialize out a white list of options from the new global state + explicitly append important options as user options here. */ + if (flag_exceptions) + lto_register_user_option (OPT_fexceptions, NULL, 1, CL_COMMON); + + lto_begin_section (section_name, !flag_wpa); + free (section_name); + + memset (&stream, 0, sizeof (stream)); + output_options (&stream); + + memset (&header, 0, sizeof (header)); + header.lto_header.major_version = LTO_major_version; + header.lto_header.minor_version = LTO_minor_version; + header.lto_header.section_type = LTO_section_opts; + + header.compressed_size = 0; + header.main_size = stream.total_size; + + header_stream = ((struct lto_output_stream *) + xcalloc (1, sizeof (*header_stream))); + lto_output_data_stream (header_stream, &header, sizeof (header)); + lto_write_stream (header_stream); + free (header_stream); + + lto_write_stream (&stream); + lto_end_section (); +} + +/* Unserialize an options vector from IB, and append to file_options. */ + +static void +input_options (struct lto_input_block *ib) +{ + size_t length, i; + + input_data_block (ib, &length, sizeof (length)); + + for (i = 0; i < length; i++) + { + opt_t o; + + input_data_block (ib, &o.type, sizeof (o.type)); + input_data_block (ib, &o.code, sizeof (o.code)); + o.arg = input_string_block (ib); + input_data_block (ib, &o.value, sizeof (o.value)); + VEC_safe_push (opt_t, heap, file_options, &o); + } +} + +/* Read options from an LTO IL section. */ + +void +lto_read_file_options (struct lto_file_decl_data *file_data) +{ + size_t len, l, skip; + const char *data, *p; + const struct lto_simple_header *header; + int opts_offset; + struct lto_input_block ib; + + data = lto_get_section_data (file_data, LTO_section_opts, NULL, &len); + if (!data) + return; + + /* Option could be multiple sections merged (through ld -r) + Keep reading all options. This is ok right now because + the options just get mashed together anyways. + This will have to be done differently once lto-opts knows + how to associate options with different files. */ + l = len; + p = data; + do + { + header = (const struct lto_simple_header *) p; + opts_offset = sizeof (*header); + + lto_check_version (header->lto_header.major_version, + header->lto_header.minor_version); + + LTO_INIT_INPUT_BLOCK (ib, p + opts_offset, 0, header->main_size); + input_options (&ib); + + skip = header->main_size + opts_offset; + l -= skip; + p += skip; + } + while (l > 0); + + lto_free_section_data (file_data, LTO_section_opts, 0, data, len); +} + +/* Concatenate the user options and any file options read from an LTO IL + file, and reissue them as if all had just been read in from the command + line. As with serialization, file options precede user options. */ + +void +lto_reissue_options (void) +{ + VEC(opt_t, heap) *opts = concatenate_options (file_options, user_options); + int i; + opt_t *o; + + FOR_EACH_VEC_ELT (opt_t, opts, i, o) + { + void *flag_var = option_flag_var (o->code, &global_options); + + if (flag_var) + set_option (&global_options, &global_options_set, + o->code, o->value, o->arg, + DK_UNSPECIFIED, UNKNOWN_LOCATION, global_dc); + + if (o->type == CL_TARGET) + targetm.handle_option (o->code, o->arg, o->value); + else if (o->type == CL_COMMON) + gcc_assert (flag_var); + else + gcc_unreachable (); + } + + /* Flag_shlib is usually set by finish_options, but we are issuing flag_pic + too late. */ + if (flag_pic && !flag_pie) + flag_shlib = 1; + VEC_free (opt_t, heap, opts); +} -- cgit v1.2.3