From 0670ccd1bde3fa9332e549236cbcfefc60ffd951 Mon Sep 17 00:00:00 2001 From: Kenneth Zadeck Date: Mon, 14 Jan 2008 13:50:44 +0000 Subject: 2008-01-14 Kenneth Zadeck * lto-read.c: Renamed to lto-function-in.c. (input_1_unsigned): Moved to lto-section-in.c and renamed lto_input_1_unsigned. (input_uleb128): Moved to lto-section-in.c and renamed lto_input_uleb128. (input_widest_uint_uleb128): Moved to lto-section-in.c and renamed lto_input_widest_uint_uleb128. (input_sleb128): Moved to lto-section-in.c and renamed lto_input_sleb128. (input_integer): Moved to lto-section-in.c and renamed lto_input_integer. (debug_in_fun): Moved to lto-section-in.c and renamed lto_debug_in_fun. (input_block): Moved to lto-section-in.h and renamed lto_input_block. (input_expr_operand): Fixed to allow lists with more than one element. * lto-section-in.h: New file. * lto-section-in.c: New file with changes from above. * Make-lang.in (lto-read.o): Renamed lto-function-in.c. (lto-section-in.o): New rule. 2008-01-14 Kenneth Zadeck * lto-function-out (lto_debug_context, output_stream, LTO_SET_DEBUGGING_STREAM): Moved to lto_section_out.h. (debug_out_fun): Renamed lto_debug_out_fun and moved to lto_section_out.c. (write_stream): Renamed lto_write_stream and moved to lto_section_out.c. (output_1_stream): Renamed lto_output_1_stream and moved to lto_section_out.c. (output_uleb128_stream): Renamed lto_output_uleb128 and moved to lto_section_out.c. (output_widest_uint_uleb128_stream): Renamed lto_output_widest_uint_uleb128_stream and moved to lto_section_out.c. (output_sleb128_stream): Renamed lto_output_sleb128_stream and moved to lto_section_out.c. (output_string, output_decl_index, output_record_start, output_constructor, output_expr_operand, output_local_vars, output_local_vars_index, output_ssa_names, output_bb, produce_asm, output_function, output_constructor_or_init): Renamed all calls as above. (output_integer): Guts moved to lto_output_integer_stream. (output_expr_operand, output_local_var, output_cfg, output_phi, output_bb, output_function): Added stmt_num parameter. * lto-tags.h (lto_debug_context): Added. * lto-section-out.c: New file that contains functions moved and renamed from lto-function-out. * lto-section-out.h: New file that contains declarations in lto-section-out.c. * Makefile.in (lto-section-out.o): New rule. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/lto@131526 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog.lto | 34 + gcc/Makefile.in | 10 +- gcc/lto-function-out.c | 536 ++++-------- gcc/lto-section-out.c | 265 ++++++ gcc/lto-section-out.h | 78 ++ gcc/lto-tags.h | 2 + gcc/lto/ChangeLog | 24 + gcc/lto/Make-lang.in | 15 +- gcc/lto/lto-function-in.c | 1908 ++++++++++++++++++++++++++++++++++++++++ gcc/lto/lto-read.c | 2127 --------------------------------------------- gcc/lto/lto-section-in.c | 266 ++++++ gcc/lto/lto-section-in.h | 42 + 12 files changed, 2790 insertions(+), 2517 deletions(-) create mode 100644 gcc/lto-section-out.c create mode 100644 gcc/lto-section-out.h create mode 100644 gcc/lto/lto-function-in.c delete mode 100644 gcc/lto/lto-read.c create mode 100644 gcc/lto/lto-section-in.c create mode 100644 gcc/lto/lto-section-in.h diff --git a/gcc/ChangeLog.lto b/gcc/ChangeLog.lto index ba6f87c6790..f06ecb4a5dc 100644 --- a/gcc/ChangeLog.lto +++ b/gcc/ChangeLog.lto @@ -1,3 +1,36 @@ +<<<<<<< .mine +2008-01-14 Kenneth Zadeck + * lto-function-out (lto_debug_context, output_stream, + LTO_SET_DEBUGGING_STREAM): Moved to lto_section_out.h. + (debug_out_fun): Renamed lto_debug_out_fun and moved to + lto_section_out.c. + (write_stream): Renamed lto_write_stream and moved to + lto_section_out.c. + (output_1_stream): Renamed lto_output_1_stream and moved to + lto_section_out.c. + (output_uleb128_stream): Renamed lto_output_uleb128 and moved to + lto_section_out.c. + (output_widest_uint_uleb128_stream): Renamed + lto_output_widest_uint_uleb128_stream and moved to + lto_section_out.c. + (output_sleb128_stream): Renamed lto_output_sleb128_stream and + moved to lto_section_out.c. + (output_string, output_decl_index, output_record_start, + output_constructor, output_expr_operand, output_local_vars, + output_local_vars_index, output_ssa_names, output_bb, produce_asm, + output_function, output_constructor_or_init): Renamed all calls as above. + (output_integer): Guts moved to lto_output_integer_stream. + (output_expr_operand, output_local_var, output_cfg, output_phi, + output_bb, output_function): + Added stmt_num parameter. + * lto-tags.h (lto_debug_context): Added. + * lto-section-out.c: New file that contains functions moved and + renamed from lto-function-out. + * lto-section-out.h: New file that contains declarations in + lto-section-out.c. + * Makefile.in (lto-section-out.o): New rule. + +======= 2008-01-07 Diego Novillo http://gcc.gnu.org/ml/gcc-patches/2008-01/msg00263.html @@ -5,6 +38,7 @@ * dwarf2out.c (force_decl_die): Initialize SAVED_IGNORED_FLAG. * dwarf2.h (enum dwarf_type): Remove trailing comma. +>>>>>>> .r131525 2007-12-29 Nathan Froyd * collect2.c (scan_prog_file): Read all the output when reading diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 7506756c74f..86d9fc9e916 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1087,6 +1087,7 @@ OBJS-common = \ loop-unswitch.o \ lower-subreg.o \ lto-function-out.o \ + lto-section-out.o \ lto-stream-debug.o \ mode-switching.o \ modulo-sched.o \ @@ -1966,8 +1967,13 @@ lto-function-out.o : lto-function-out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) toplev.h $(TREE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h \ $(VARRAY_H) $(HASHTAB_H) langhooks.h $(BASIC_BLOCK_H) tree-iterator.h \ tree-pass.h tree-flow.h $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H) \ - except.h debug.h $(TIMEVAR_H) $(LTO_TAGS_H) lto-tree-flags.def \ - lto-tree-tags.def output.h dwarf2asm.h dwarf2out.h + except.h debug.h $(TIMEVAR_H) $(LTO_TAGS_H) lto-tree-flags.def lto-tree-tags.def \ + lto-tags.h lto-section-out.h output.h dwarf2asm.h dwarf2out.h +lto-section-out.o : lto-section-out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ + $(TM_H) toplev.h $(TREE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h \ + $(VARRAY_H) $(HASHTAB_H) langhooks.h $(BASIC_BLOCK_H) tree-iterator.h \ + tree-pass.h tree-flow.h $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H) \ + except.h debug.h $(TIMEVAR_H) lto-section-out.h output.h dwarf2asm.h dwarf2out.h langhooks.o : langhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) toplev.h $(TREE_INLINE_H) $(RTL_H) insn-config.h $(INTEGRATE_H) \ langhooks.h $(LANGHOOKS_DEF_H) $(FLAGS_H) $(GGC_H) $(DIAGNOSTIC_H) intl.h \ diff --git a/gcc/lto-function-out.c b/gcc/lto-function-out.c index d13da808880..b99c1990eb7 100644 --- a/gcc/lto-function-out.c +++ b/gcc/lto-function-out.c @@ -51,6 +51,7 @@ Boston, MA 02110-1301, USA. */ #include "dwarf2out.h" #include "output.h" #include "lto-tags.h" +#include "lto-section-out.h" #include @@ -59,9 +60,6 @@ sbitmap lto_types_needed_for; #ifdef LTO_STREAM_DEBUGGING const char *LTO_tag_names[LTO_last_tag]; - -static struct lto_debug_context lto_debug_context; -static void debug_out_fun (struct lto_debug_context *, char); #endif @@ -187,63 +185,38 @@ eq_string_slot_node (const void *p1, const void *p2) else return 0; } - -struct char_ptr_base -{ - char *ptr; -}; - -/* An incore byte stream to buffer the various parts of the -function. The entire structure should be zeroed when created. The -record consists of a set of blocks. The first sizeof (ptr) bytes are -used as a chain, and the rest store the bytes to be written. */ - -struct output_stream -{ - /* The pointer to the first block in the stream. */ - struct char_ptr_base * first_block; - /* The pointer to the last and current block in the stream. */ - struct char_ptr_base * current_block; - /* The pointer to where the next char should be written. */ - char * current_pointer; - /* The number of characters left in the current block. */ - unsigned int left_in_block; - /* The block size of the last block allocated. */ - unsigned int block_size; - /* The total number of characters written. */ - unsigned int total_size; -}; +/* The fields written to a function or extern variable header. */ struct output_block { /* The stream that the main tree codes are written to. */ - struct output_stream *main_stream; + struct lto_output_stream *main_stream; /* The stream that contains the indexes for the local name table. */ - struct output_stream *local_decl_index_stream; + struct lto_output_stream *local_decl_index_stream; /* The stream that contains the local name table. */ - struct output_stream *local_decl_stream; + struct lto_output_stream *local_decl_stream; /* The stream that contains the names for the named_labels. */ - struct output_stream *named_label_stream; + struct lto_output_stream *named_label_stream; /* The stream that contains the string table. */ - struct output_stream *string_stream; + struct lto_output_stream *string_stream; /* The stream that contains the ssa_names table. */ - struct output_stream *ssa_names_stream; + struct lto_output_stream *ssa_names_stream; /* The stream that contains the cfg. */ - struct output_stream *cfg_stream; + struct lto_output_stream *cfg_stream; #ifdef LTO_STREAM_DEBUGGING /* The stream that contains the local decls index debugging information. */ - struct output_stream *debug_decl_index_stream; + struct lto_output_stream *debug_decl_index_stream; /* The stream that contains the local decls debugging information. */ - struct output_stream *debug_decl_stream; + struct lto_output_stream *debug_decl_stream; /* The stream that contains the labels debugging information. */ - struct output_stream *debug_label_stream; + struct lto_output_stream *debug_label_stream; /* The stream that contains the ssa_names debugging information. */ - struct output_stream *debug_ssa_names_stream; + struct lto_output_stream *debug_ssa_names_stream; /* The stream that contains the cfg debugging information. */ - struct output_stream *debug_cfg_stream; + struct lto_output_stream *debug_cfg_stream; /* The stream that contains the gimple debugging information. */ - struct output_stream *debug_main_stream; + struct lto_output_stream *debug_main_stream; #endif /* The hash table that contains the set of labels we have seen so @@ -318,24 +291,7 @@ struct output_block /* The output stream that contains the abbrev table for all of the functions in this compilation unit. */ -static void output_expr_operand (struct output_block *, tree); - - -#ifdef LTO_STREAM_DEBUGGING -#define LTO_SET_DEBUGGING_STREAM(STREAM,CONTEXT) \ -do { \ - ob-> STREAM = xcalloc (1, sizeof (struct output_stream)); \ - lto_debug_context. CONTEXT = ob-> STREAM; \ - lto_debug_context.current_data = ob-> STREAM; \ - gcc_assert (lto_debug_context.indent == 0); \ -} while (0) -#define LTO_CLEAR_DEBUGGING_STREAM(STREAM) \ - free (ob-> STREAM) -#else -#define LTO_SET_DEBUGGING_STREAM(STREAM,CONTEXT) -#define LTO_CLEAR_DEBUGGING_STREAM(STREAM) (void)0 -#endif - +static void output_expr_operand (struct output_block *, tree, unsigned int); /* Clear the line info stored in DATA_IN. */ @@ -358,18 +314,18 @@ create_output_block (bool is_function) { struct output_block *ob = xcalloc (1, sizeof (struct output_block)); - ob->main_stream = xcalloc (1, sizeof (struct output_stream)); - ob->string_stream = xcalloc (1, sizeof (struct output_stream)); + ob->main_stream = xcalloc (1, sizeof (struct lto_output_stream)); + ob->string_stream = xcalloc (1, sizeof (struct lto_output_stream)); if (is_function) { - ob->local_decl_index_stream = xcalloc (1, sizeof (struct output_stream)); - ob->local_decl_stream = xcalloc (1, sizeof (struct output_stream)); - ob->named_label_stream = xcalloc (1, sizeof (struct output_stream)); - ob->ssa_names_stream = xcalloc (1, sizeof (struct output_stream)); - ob->cfg_stream = xcalloc (1, sizeof (struct output_stream)); + ob->local_decl_index_stream = xcalloc (1, sizeof (struct lto_output_stream)); + ob->local_decl_stream = xcalloc (1, sizeof (struct lto_output_stream)); + ob->named_label_stream = xcalloc (1, sizeof (struct lto_output_stream)); + ob->ssa_names_stream = xcalloc (1, sizeof (struct lto_output_stream)); + ob->cfg_stream = xcalloc (1, sizeof (struct lto_output_stream)); } #ifdef LTO_STREAM_DEBUGGING - lto_debug_context.out = debug_out_fun; + lto_debug_context.out = lto_debug_out_fun; lto_debug_context.indent = 0; #endif @@ -459,189 +415,6 @@ destroy_output_block (struct output_block * ob, bool is_function) free (ob); } -/* Write all of the chars in OBS to the assembler. Recycle the blocks - in obs as this is being done. */ - -static void -write_stream (struct output_stream *obs) -{ - unsigned int block_size = 1024; - unsigned int num_chars; - struct char_ptr_base *block; - if (!obs->first_block) - return; - - block = obs->first_block; - while (block) - { - const char *base = ((char *)block) + sizeof (struct char_ptr_base); - struct char_ptr_base *old_block = block; - block = (struct char_ptr_base *)block->ptr; - /* If there is a next block, then this one is full, if there is - not a next block, then the left_in_block field says how many - chars there are in this block. */ - num_chars = block_size - sizeof (struct char_ptr_base); - if (!block) - num_chars = num_chars - obs->left_in_block; - - assemble_string (base, num_chars); - free (old_block); - block_size *= 2; - } -} - - -/* Write a character to the output block. */ - -static void -output_1_stream (struct output_stream *obs, char c) -{ - /* No space left. */ - if (obs->left_in_block == 0) - { - struct char_ptr_base *new_block; - - if (obs->first_block == NULL) - { - /* This is the first time the stream has been written - into. */ - obs->block_size = 1024; - new_block = (struct char_ptr_base*) xmalloc (obs->block_size); - obs->first_block = new_block; - } - else - { - struct char_ptr_base *tptr; - /* Get a new block that is twice as big as the last block - and link it into the list. */ - obs->block_size *= 2; - new_block = (struct char_ptr_base*) xmalloc (obs->block_size); - /* The first bytes of the block are reserved as a pointer to - the next block. Set the chain of the full block to the - pointer to the new block. */ - tptr = obs->current_block; - tptr->ptr = (char *)new_block; - } - - /* Set the place for the next char at the first position after the - chain to the next block. */ - obs->current_pointer - = ((char *)new_block) + sizeof (struct char_ptr_base); - obs->current_block = new_block; - /* Null out the newly allocated block's pointer to the next block. */ - new_block->ptr = NULL; - obs->left_in_block = obs->block_size - sizeof (struct char_ptr_base); - } - - /* Write the actual character. */ - *obs->current_pointer = c; - obs->current_pointer++; - obs->total_size++; - obs->left_in_block--; -} - - -/* Write a zero to the output stream. */ - -static void -output_zero (struct output_block *ob) -{ - LTO_DEBUG_WIDE ("U", 0); - output_1_stream (ob->main_stream, 0); -} - - -/* Output an unsigned LEB128 quantity to OBS. */ - -static void -output_uleb128_stream (struct output_stream *obs, unsigned HOST_WIDE_INT work) -{ - LTO_DEBUG_WIDE ("U", work); - do - { - unsigned int byte = (work & 0x7f); - work >>= 7; - if (work != 0) - /* More bytes to follow. */ - byte |= 0x80; - - output_1_stream (obs, byte); - } - while (work != 0); -} - -/* Identical to output_uleb128_stream above except using unsigned - HOST_WIDEST_INT type. For efficiency on host where unsigned HOST_WIDEST_INT - is not native, we only use this if we know that HOST_WIDE_INT is not wide - enough. */ - -static void -output_widest_uint_uleb128_stream (struct output_stream *obs, - unsigned HOST_WIDEST_INT work) -{ - LTO_DEBUG_WIDE ("U", work); - do - { - unsigned int byte = (work & 0x7f); - work >>= 7; - if (work != 0) - /* More bytes to follow. */ - byte |= 0x80; - - output_1_stream (obs, byte); - } - while (work != 0); -} - - -/* Output an unsigned LEB128 quantity to OB->main_stream. */ - -static void -output_uleb128 (struct output_block *ob, unsigned HOST_WIDE_INT work) -{ - output_uleb128_stream (ob->main_stream, work); -} - -/* HOST_WIDEST_INT version of output_uleb128. OB and WORK are as in - output_uleb128. */ - -static void -output_widest_uint_uleb128 (struct output_block *ob, - unsigned HOST_WIDEST_INT work) -{ - output_widest_uint_uleb128_stream (ob->main_stream, work); -} - -/* Output a signed LEB128 quantity. */ - -static void -output_sleb128_stream (struct output_stream *obs, HOST_WIDE_INT work) -{ - int more, byte; - LTO_DEBUG_WIDE ("S", work); - do - { - byte = (work & 0x7f); - /* arithmetic shift */ - work >>= 7; - more = !((work == 0 && (byte & 0x40) == 0) - || (work == -1 && (byte & 0x40) != 0)); - if (more) - byte |= 0x80; - - output_1_stream (obs, byte); - } - while (more); -} - - -/* Output a signed LEB128 quantity to OB->main_stream. */ - -static void -output_sleb128 (struct output_block *ob, HOST_WIDE_INT work) -{ - output_sleb128_stream (ob->main_stream, work); -} /* Output STRING of LEN to the string table in OB. Then put the index @@ -649,7 +422,7 @@ output_sleb128 (struct output_block *ob, HOST_WIDE_INT work) static void output_string (struct output_block *ob, - struct output_stream *index_stream, + struct lto_output_stream *index_stream, const char *string, unsigned int len) { @@ -661,7 +434,7 @@ output_string (struct output_block *ob, slot = htab_find_slot (ob->string_hash_table, &s_slot, INSERT); if (*slot == NULL) { - struct output_stream *string_stream = ob->string_stream; + struct lto_output_stream *string_stream = ob->string_stream; unsigned int start = string_stream->total_size; struct string_slot *new_slot = xmalloc (sizeof (struct string_slot)); @@ -670,15 +443,15 @@ output_string (struct output_block *ob, new_slot->s = string; new_slot->slot_num = start; *slot = new_slot; - output_uleb128_stream (index_stream, start); - output_uleb128_stream (string_stream, len); + lto_output_uleb128_stream (index_stream, start); + lto_output_uleb128_stream (string_stream, len); for (i=0; islot_num); + lto_output_uleb128_stream (index_stream, old_slot->slot_num); /* From the debugging protocol's point of view, the entry needs to look the same reguardless of whether this is the first @@ -705,53 +478,51 @@ output_real (struct output_block *ob, tree t) } -/* Put out a integer constant. These are stored as two HOST_WIDE_INTS - so games may have to be played to shift the data from the high to - the low value. */ +/* Write a zero to the output stream. */ static void -output_integer (struct output_block *ob, tree t) +output_zero (struct output_block *ob) { - struct output_stream *obs = ob->main_stream; - HOST_WIDE_INT low = TREE_INT_CST_LOW (t); - HOST_WIDE_INT high = TREE_INT_CST_HIGH (t); - int more, byte; - - /* Of course if the high value is just sign bits for the signed low - value, we can just punt and call output_sleb128 and be done with - it. */ - if (((high == -1) && (low < 0)) - || ((high == 0) && (low >= 0))) - { - output_sleb128_stream (obs, low); - return; - } + LTO_DEBUG_WIDE ("U", 0); + lto_output_1_stream (ob->main_stream, 0); +} - LTO_DEBUG_INTEGER ("SS", high, low); - /* This is just a copy of the output_sleb128 code with extra - operations to transfer the low 7 bits of the high value to the - top 7 bits of the low value, shift the high down by 7 and then do - a slightly more complex exit test. */ - do - { - unsigned HOST_WIDE_INT transfer = (high & 0x7f); - high = ((unsigned HOST_WIDE_INT) high) >> 7; - transfer <<= (HOST_BITS_PER_WIDE_INT - 7); +/* Output an unsigned LEB128 quantity to OB->main_stream. */ - byte = (low & 0x7f); +static void +output_uleb128 (struct output_block *ob, unsigned HOST_WIDE_INT work) +{ + lto_output_uleb128_stream (ob->main_stream, work); +} - /* Logical shift. */ - low = ((unsigned HOST_WIDE_INT) low) >> 7; - low |= transfer; - more = !((high == 0 && low == 0 && (byte & 0x40) == 0) - || (high == -1 && low == -1 && (byte & 0x40) != 0)); - if (more) - byte |= 0x80; - output_1_stream (obs, byte); - } - while (more); +/* Output a signed LEB128 quantity to OB->main_stream. */ + +static void +output_sleb128 (struct output_block *ob, HOST_WIDE_INT work) +{ + lto_output_sleb128_stream (ob->main_stream, work); +} + +/* HOST_WIDEST_INT version of output_uleb128. OB and WORK are as in + output_uleb128. */ + +static void +output_widest_uint_uleb128 (struct output_block *ob, + unsigned HOST_WIDEST_INT work) +{ + lto_output_widest_uint_uleb128_stream (ob->main_stream, work); +} + +/* Put out a integer constant. These are stored as two HOST_WIDE_INTS + so games may have to be played to shift the data from the high to + the low value. */ + +static void +output_integer (struct output_block *ob, tree t) +{ + lto_output_integer_stream (ob->main_stream, t); } @@ -763,7 +534,7 @@ output_integer (struct output_block *ob, tree t) If OBS is NULL, the only action is to add NAME to the table. */ static bool -output_decl_index (struct output_stream * obs, htab_t table, +output_decl_index (struct lto_output_stream * obs, htab_t table, unsigned int *next_index, tree name, unsigned int *this_index) { @@ -782,7 +553,7 @@ output_decl_index (struct output_stream * obs, htab_t table, *this_index = index; *slot = new_slot; if (obs) - output_uleb128_stream (obs, index); + lto_output_uleb128_stream (obs, index); return true; } else @@ -790,7 +561,7 @@ output_decl_index (struct output_stream * obs, htab_t table, struct decl_slot *old_slot = (struct decl_slot *)*slot; *this_index = old_slot->slot_num; if (obs) - output_uleb128_stream (obs, old_slot->slot_num); + lto_output_uleb128_stream (obs, old_slot->slot_num); return false; } } @@ -1055,7 +826,7 @@ static void output_record_start (struct output_block *ob, tree expr, tree value, unsigned int tag) { - output_1_stream (ob->main_stream, tag); + lto_output_1_stream (ob->main_stream, tag); LTO_DEBUG_INDENT (tag); if (expr) { @@ -1248,7 +1019,7 @@ output_constructor (struct output_block *ob, tree ctor) FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), idx, purpose, value) { if (purpose) - output_expr_operand (ob, purpose); + output_expr_operand (ob, purpose, 0); else output_zero (ob); @@ -1258,14 +1029,14 @@ output_constructor (struct output_block *ob, tree ctor) LTO_DEBUG_UNDENT (); } else - output_expr_operand (ob, value); + output_expr_operand (ob, value, 0); } } /* Output EXPR to the main stream in OB. */ static void -output_expr_operand (struct output_block *ob, tree expr) +output_expr_operand (struct output_block *ob, tree expr, unsigned int stmt_num) { enum tree_code code; enum tree_code_class class; @@ -1373,9 +1144,9 @@ output_expr_operand (struct output_block *ob, tree expr) LTO_case_label_expr0 + variant); if (CASE_LOW (expr) != NULL_TREE) - output_expr_operand (ob, CASE_LOW (expr)); + output_expr_operand (ob, CASE_LOW (expr), stmt_num); if (CASE_HIGH (expr) != NULL_TREE) - output_expr_operand (ob, CASE_HIGH (expr)); + output_expr_operand (ob, CASE_HIGH (expr), stmt_num); output_label_ref (ob, CASE_LABEL (expr)); } break; @@ -1473,14 +1244,14 @@ output_expr_operand (struct output_block *ob, tree expr) if (TREE_OPERAND (expr, 1)) { output_record_start (ob, expr, expr, LTO_cond_expr0); - output_expr_operand (ob, TREE_OPERAND (expr, 0)); - output_expr_operand (ob, TREE_OPERAND (expr, 1)); - output_expr_operand (ob, TREE_OPERAND (expr, 2)); + output_expr_operand (ob, TREE_OPERAND (expr, 0), stmt_num); + output_expr_operand (ob, TREE_OPERAND (expr, 1), stmt_num); + output_expr_operand (ob, TREE_OPERAND (expr, 2), stmt_num); } else { output_record_start (ob, expr, expr, LTO_cond_expr1); - output_expr_operand (ob, TREE_OPERAND (expr, 0)); + output_expr_operand (ob, TREE_OPERAND (expr, 0), stmt_num); } break; @@ -1490,8 +1261,8 @@ output_expr_operand (struct output_block *ob, tree expr) case COMPONENT_REF: output_record_start (ob, expr, expr, tag); - output_expr_operand (ob, TREE_OPERAND (expr, 0)); - output_expr_operand (ob, TREE_OPERAND (expr, 1)); + output_expr_operand (ob, TREE_OPERAND (expr, 0), stmt_num); + output_expr_operand (ob, TREE_OPERAND (expr, 1), stmt_num); /* Ignore 3 because it can be recomputed. */ break; @@ -1505,16 +1276,16 @@ output_expr_operand (struct output_block *ob, tree expr) { output_record_start (ob, expr, expr, LTO_call_expr1); output_uleb128 (ob, count); - output_expr_operand (ob, TREE_OPERAND (expr, 2)); + output_expr_operand (ob, TREE_OPERAND (expr, 2), stmt_num); } else { output_record_start (ob, expr, expr, LTO_call_expr0); output_uleb128 (ob, count); } - output_expr_operand (ob, TREE_OPERAND (expr, 1)); + output_expr_operand (ob, TREE_OPERAND (expr, 1), stmt_num); for (i = 3; i < count; i++) - output_expr_operand (ob, TREE_OPERAND (expr, i)); + output_expr_operand (ob, TREE_OPERAND (expr, i), stmt_num); } break; @@ -1529,15 +1300,15 @@ output_expr_operand (struct output_block *ob, tree expr) LTO_bit_field_ref1); output_uleb128 (ob, TREE_INT_CST_LOW (op1)); output_uleb128 (ob, TREE_INT_CST_LOW (op2)); - output_expr_operand (ob, TREE_OPERAND (expr, 0)); + output_expr_operand (ob, TREE_OPERAND (expr, 0), stmt_num); } else { output_record_start (ob, expr, expr, LTO_bit_field_ref0); - output_expr_operand (ob, TREE_OPERAND (expr, 0)); - output_expr_operand (ob, op1); - output_expr_operand (ob, op2); + output_expr_operand (ob, TREE_OPERAND (expr, 0), stmt_num); + output_expr_operand (ob, op1, stmt_num); + output_expr_operand (ob, op2, stmt_num); } } break; @@ -1547,8 +1318,8 @@ output_expr_operand (struct output_block *ob, tree expr) /* Ignore operands 2 and 3 for ARRAY_REF and ARRAY_RANGE REF because they can be recomputed. */ output_record_start (ob, expr, expr, tag); - output_expr_operand (ob, TREE_OPERAND (expr, 0)); - output_expr_operand (ob, TREE_OPERAND (expr, 1)); + output_expr_operand (ob, TREE_OPERAND (expr, 0), stmt_num); + output_expr_operand (ob, TREE_OPERAND (expr, 1), stmt_num); break; @@ -1560,17 +1331,17 @@ output_expr_operand (struct output_block *ob, tree expr) TREE_STRING_POINTER (string_cst), TREE_STRING_LENGTH (string_cst)); if (ASM_INPUTS (expr)) - output_expr_operand (ob, ASM_INPUTS (expr)); + output_expr_operand (ob, ASM_INPUTS (expr), stmt_num); else output_zero (ob); if (ASM_OUTPUTS (expr)) - output_expr_operand (ob, ASM_OUTPUTS (expr)); + output_expr_operand (ob, ASM_OUTPUTS (expr), stmt_num); else output_zero (ob); if (ASM_CLOBBERS (expr)) - output_expr_operand (ob, ASM_CLOBBERS (expr)); + output_expr_operand (ob, ASM_CLOBBERS (expr), stmt_num); else output_zero (ob); } @@ -1606,8 +1377,8 @@ output_expr_operand (struct output_block *ob, tree expr) /* Form return a = b; */ output_record_start (ob, expr, expr, LTO_return_expr2); - output_expr_operand (ob, TREE_OPERAND (t, 0)); - output_expr_operand (ob, TREE_OPERAND (t, 1)); + output_expr_operand (ob, TREE_OPERAND (t, 0), stmt_num); + output_expr_operand (ob, TREE_OPERAND (t, 1), stmt_num); } else { @@ -1622,15 +1393,15 @@ output_expr_operand (struct output_block *ob, tree expr) if (t == DECL_RESULT (current_function_decl)) output_zero (ob); else - output_expr_operand (ob, t); + output_expr_operand (ob, t, stmt_num); } } break; case GIMPLE_MODIFY_STMT: output_record_start (ob, expr, NULL, tag); - output_expr_operand (ob, GIMPLE_STMT_OPERAND (expr, 0)); - output_expr_operand (ob, GIMPLE_STMT_OPERAND (expr, 1)); + output_expr_operand (ob, GIMPLE_STMT_OPERAND (expr, 0), stmt_num); + output_expr_operand (ob, GIMPLE_STMT_OPERAND (expr, 1), stmt_num); break; case SWITCH_EXPR: @@ -1640,11 +1411,11 @@ output_expr_operand (struct output_block *ob, tree expr) size_t i; output_record_start (ob, expr, expr, tag); output_uleb128 (ob, len); - output_expr_operand (ob, TREE_OPERAND (expr, 0)); + output_expr_operand (ob, TREE_OPERAND (expr, 0), stmt_num); gcc_assert (TREE_OPERAND (expr, 1) == NULL); for (i = 0; i < len; ++i) - output_expr_operand (ob, TREE_VEC_ELT (label_vec, i)); + output_expr_operand (ob, TREE_VEC_ELT (label_vec, i), stmt_num); } break; @@ -1662,12 +1433,12 @@ output_expr_operand (struct output_block *ob, tree expr) for (tl = expr; tl; tl = TREE_CHAIN (tl)) { if (TREE_VALUE (tl) != NULL_TREE) - output_expr_operand (ob, TREE_VALUE (tl)); + output_expr_operand (ob, TREE_VALUE (tl), stmt_num); else output_zero (ob); if (TREE_PURPOSE (tl)) - output_expr_operand (ob, TREE_PURPOSE (tl)); + output_expr_operand (ob, TREE_PURPOSE (tl), stmt_num); else output_zero (ob); } @@ -1688,7 +1459,7 @@ output_expr_operand (struct output_block *ob, tree expr) #undef SET_NAME output_record_start (ob, expr, expr, tag); for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (expr)); i++) - output_expr_operand (ob, TREE_OPERAND (expr, i)); + output_expr_operand (ob, TREE_OPERAND (expr, i), stmt_num); break; } @@ -1772,7 +1543,7 @@ output_local_var (struct output_block *ob, int index) { LTO_DEBUG_INDENT_TOKEN ("init"); if (DECL_INITIAL (decl)) - output_expr_operand (ob, DECL_INITIAL (decl)); + output_expr_operand (ob, DECL_INITIAL (decl), 0); else output_zero (ob); /* Index in unexpanded_vars_list. */ @@ -1785,7 +1556,7 @@ output_local_var (struct output_block *ob, int index) /* The chain is only necessary for parm_decls. */ LTO_DEBUG_TOKEN ("chain"); if (TREE_CHAIN (decl)) - output_expr_operand (ob, TREE_CHAIN (decl)); + output_expr_operand (ob, TREE_CHAIN (decl), 0); else output_zero (ob); } @@ -1795,7 +1566,7 @@ output_local_var (struct output_block *ob, int index) LTO_DEBUG_TOKEN ("context"); if (DECL_CONTEXT (decl)) - output_expr_operand (ob, DECL_CONTEXT (decl)); + output_expr_operand (ob, DECL_CONTEXT (decl), 0); else output_zero (ob); @@ -1804,18 +1575,18 @@ output_local_var (struct output_block *ob, int index) /* Put out the subtrees. */ LTO_DEBUG_TOKEN ("size"); - output_expr_operand (ob, DECL_SIZE (decl)); + output_expr_operand (ob, DECL_SIZE (decl), 0); if (DECL_ATTRIBUTES (decl)!= NULL_TREE) { LTO_DEBUG_TOKEN ("attributes"); - output_expr_operand (ob, DECL_ATTRIBUTES (decl)); + output_expr_operand (ob, DECL_ATTRIBUTES (decl), 0); } if (DECL_SIZE_UNIT (decl) != NULL_TREE) - output_expr_operand (ob, DECL_SIZE_UNIT (decl)); + output_expr_operand (ob, DECL_SIZE_UNIT (decl), 0); if (needs_backing_var) - output_expr_operand (ob, DECL_DEBUG_EXPR (decl)); + output_expr_operand (ob, DECL_DEBUG_EXPR (decl), 0); if (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE) - output_expr_operand (ob, DECL_ABSTRACT_ORIGIN (decl)); + output_expr_operand (ob, DECL_ABSTRACT_ORIGIN (decl), 0); LTO_DEBUG_UNDENT(); } @@ -1829,7 +1600,7 @@ output_local_vars (struct output_block *ob, struct function *fn) unsigned int index = 0; tree t; int i = 0; - struct output_stream *tmp_stream = ob->main_stream; + struct lto_output_stream *tmp_stream = ob->main_stream; bitmap local_statics = BITMAP_ALLOC (NULL); ob->main_stream = ob->local_decl_stream; @@ -1853,7 +1624,7 @@ output_local_vars (struct output_block *ob, struct function *fn) if (!bitmap_bit_p (local_statics, DECL_UID (lv))) { bitmap_set_bit (local_statics, DECL_UID (lv)); - output_expr_operand (ob, lv); + output_expr_operand (ob, lv, 0); if (DECL_CONTEXT (lv) == fn->decl) { output_uleb128 (ob, 1); /* Restore context. */ @@ -1863,7 +1634,7 @@ output_local_vars (struct output_block *ob, struct function *fn) output_zero (ob); /* Restore context. */ } if (DECL_INITIAL (lv)) - output_expr_operand (ob, DECL_INITIAL (lv)); + output_expr_operand (ob, DECL_INITIAL (lv), 0); else output_zero (ob); /* DECL_INITIAL. */ } @@ -1905,7 +1676,7 @@ output_local_vars_index (struct output_block *ob) unsigned int index = 0; unsigned int stop; - struct output_stream *tmp_stream = ob->main_stream; + struct lto_output_stream *tmp_stream = ob->main_stream; ob->main_stream = ob->local_decl_index_stream; stop = VEC_length (int, ob->local_decls_index); @@ -1946,7 +1717,7 @@ output_ssa_names (struct output_block *ob, struct function *fn) { /* Switch streams so we can use output_expr_operand to write the SSA_NAME_VAR. */ - struct output_stream *tmp_stream = ob->main_stream; + struct lto_output_stream *tmp_stream = ob->main_stream; unsigned int i; unsigned int len = VEC_length (tree, SSANAMES (fn)); @@ -1961,7 +1732,7 @@ output_ssa_names (struct output_block *ob, struct function *fn) continue; output_uleb128 (ob, i); - output_expr_operand (ob, SSA_NAME_VAR (ptr)); + output_expr_operand (ob, SSA_NAME_VAR (ptr), 0); /* Use code 0 to force flags to be output. */ output_tree_flags (ob, 0, ptr, false); } @@ -1976,7 +1747,7 @@ output_ssa_names (struct output_block *ob, struct function *fn) static void output_cfg (struct output_block *ob, struct function *fn) { - struct output_stream *tmp_stream = ob->main_stream; + struct lto_output_stream *tmp_stream = ob->main_stream; basic_block bb; ob->main_stream = ob->cfg_stream; @@ -2025,7 +1796,7 @@ output_cfg (struct output_block *ob, struct function *fn) /* Output a phi function to the main stream in OB. */ static void -output_phi (struct output_block *ob, tree expr) +output_phi (struct output_block *ob, tree expr, unsigned int stmt_num) { int len = PHI_NUM_ARGS (expr); int i; @@ -2035,7 +1806,7 @@ output_phi (struct output_block *ob, tree expr) for (i = 0; i < len; i++) { - output_expr_operand (ob, PHI_ARG_DEF (expr, i)); + output_expr_operand (ob, PHI_ARG_DEF (expr, i), stmt_num); output_uleb128 (ob, PHI_ARG_EDGE (expr, i)->src->index); } LTO_DEBUG_UNDENT (); @@ -2044,8 +1815,9 @@ output_phi (struct output_block *ob, tree expr) /* Output a basic block BB to the main stream in OB for this FN. */ -static void -output_bb (struct output_block *ob, basic_block bb, struct function *fn) +static int +output_bb (struct output_block *ob, basic_block bb, + struct function *fn, int stmt_num) { block_stmt_iterator bsi = bsi_start (bb); @@ -2068,7 +1840,9 @@ output_bb (struct output_block *ob, basic_block bb, struct function *fn) tree stmt = bsi_stmt (bsi); LTO_DEBUG_INDENT_TOKEN ("stmt"); - output_expr_operand (ob, stmt); + output_uleb128 (ob, stmt_num); + + output_expr_operand (ob, stmt, stmt_num); /* We only need to set the region number of the tree that could throw if the region number is different from the @@ -2086,6 +1860,7 @@ output_bb (struct output_block *ob, basic_block bb, struct function *fn) last_eh_region_seen = region; } } + stmt_num++; } LTO_DEBUG_INDENT_TOKEN ("stmt"); @@ -2094,7 +1869,9 @@ output_bb (struct output_block *ob, basic_block bb, struct function *fn) for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) { LTO_DEBUG_INDENT_TOKEN ("phi"); - output_phi (ob, phi); + output_uleb128 (ob, stmt_num); + output_phi (ob, phi, stmt_num); + stmt_num++; } LTO_DEBUG_INDENT_TOKEN ("phi"); @@ -2106,6 +1883,7 @@ output_bb (struct output_block *ob, basic_block bb, struct function *fn) #ifdef LTO_STREAM_DEBUGGING gcc_assert (lto_debug_context.indent == 1); #endif + return stmt_num; } /* Write the references for the objects in V to section SEC in the @@ -2215,24 +1993,24 @@ produce_asm (struct output_block *ob, tree t, bool is_function) block of text. */ if (is_function) { - write_stream (ob->named_label_stream); - write_stream (ob->ssa_names_stream); - write_stream (ob->cfg_stream); - write_stream (ob->local_decl_index_stream); - write_stream (ob->local_decl_stream); + lto_write_stream (ob->named_label_stream); + lto_write_stream (ob->ssa_names_stream); + lto_write_stream (ob->cfg_stream); + lto_write_stream (ob->local_decl_index_stream); + lto_write_stream (ob->local_decl_stream); } - write_stream (ob->main_stream); - write_stream (ob->string_stream); + lto_write_stream (ob->main_stream); + lto_write_stream (ob->string_stream); #ifdef LTO_STREAM_DEBUGGING if (is_function) { - write_stream (ob->debug_decl_index_stream); - write_stream (ob->debug_decl_stream); - write_stream (ob->debug_label_stream); - write_stream (ob->debug_ssa_names_stream); - write_stream (ob->debug_cfg_stream); + lto_write_stream (ob->debug_decl_index_stream); + lto_write_stream (ob->debug_decl_stream); + lto_write_stream (ob->debug_label_stream); + lto_write_stream (ob->debug_ssa_names_stream); + lto_write_stream (ob->debug_cfg_stream); } - write_stream (ob->debug_main_stream); + lto_write_stream (ob->debug_main_stream); #endif } @@ -2356,6 +2134,7 @@ output_function (tree function) struct function *fn = DECL_STRUCT_FUNCTION (function); basic_block bb; struct output_block *ob = create_output_block (true); + unsigned int stmt_num = 1; LTO_SET_DEBUGGING_STREAM (debug_main_stream, main_data); clear_line_info (ob); @@ -2370,7 +2149,7 @@ output_function (tree function) generate_early_dwarf_information (function); /* Make string 0 be a NULL string. */ - output_1_stream (ob->string_stream, 0); + lto_output_1_stream (ob->string_stream, 0); last_eh_region_seen = 0; @@ -2382,19 +2161,19 @@ output_function (tree function) /* Output the head of the arguments list. */ LTO_DEBUG_INDENT_TOKEN ("decl_arguments"); if (DECL_ARGUMENTS (function)) - output_expr_operand (ob, DECL_ARGUMENTS (function)); + output_expr_operand (ob, DECL_ARGUMENTS (function), 0); else output_zero (ob); LTO_DEBUG_INDENT_TOKEN ("decl_context"); if (DECL_CONTEXT (function)) - output_expr_operand (ob, DECL_CONTEXT (function)); + output_expr_operand (ob, DECL_CONTEXT (function), 0); else output_zero (ob); /* Output the code for the function. */ FOR_ALL_BB_FN (bb, fn) - output_bb (ob, bb, fn); + stmt_num = output_bb (ob, bb, fn, stmt_num); /* The terminator for this function. */ output_zero (ob); @@ -2438,10 +2217,10 @@ output_constructor_or_init (tree var) clear_line_info (ob); /* Make string 0 be a NULL string. */ - output_1_stream (ob->string_stream, 0); + lto_output_1_stream (ob->string_stream, 0); LTO_DEBUG_INDENT_TOKEN ("init"); - output_expr_operand (ob, DECL_INITIAL (var)); + output_expr_operand (ob, DECL_INITIAL (var), 0); /* The terminator for the constructor. */ output_zero (ob); @@ -2518,17 +2297,6 @@ struct tree_opt_pass pass_ipa_lto_out = #ifdef LTO_STREAM_DEBUGGING - -/* The low level output routine to print a single character to the - debugging stream. */ - -static void -debug_out_fun (struct lto_debug_context *context, char c) -{ - struct output_stream * stream - = (struct output_stream *)context->current_data; - output_1_stream (stream, c); -} /* Print the tree flags to the debugging stream. */ void diff --git a/gcc/lto-section-out.c b/gcc/lto-section-out.c new file mode 100644 index 00000000000..33d9e2372bd --- /dev/null +++ b/gcc/lto-section-out.c @@ -0,0 +1,265 @@ +/* LTO output code. + Copyright (C) 2007, 2008 Free Software Foundation, Inc. + Contributed by Kenneth Zadeck + +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 "tm.h" +#include "toplev.h" +#include "tree.h" +#include "expr.h" +#include "flags.h" +#include "params.h" +#include "input.h" +#include "varray.h" +#include "hashtab.h" +#include "langhooks.h" +#include "basic-block.h" +#include "tree-iterator.h" +#include "tree-pass.h" +#include "tree-flow.h" +#include "cgraph.h" +#include "function.h" +#include "ggc.h" +#include "diagnostic.h" +#include "except.h" +#include "debug.h" +#include "vec.h" +#include "tree-vectorizer.h" +#include "timevar.h" +#include "dwarf2asm.h" +#include "dwarf2out.h" +#include "output.h" +#include "lto-tags.h" +#include "lto-section-out.h" +#include + +/* Write all of the chars in OBS to the assembler. Recycle the blocks + in obs as this is being done. */ + +void +lto_write_stream (struct lto_output_stream *obs) +{ + unsigned int block_size = 1024; + unsigned int num_chars; + struct lto_char_ptr_base *block; + if (!obs->first_block) + return; + + block = obs->first_block; + while (block) + { + const char *base = ((char *)block) + sizeof (struct lto_char_ptr_base); + struct lto_char_ptr_base *old_block = block; + block = (struct lto_char_ptr_base *)block->ptr; + /* If there is a next block, then this one is full, if there is + not a next block, then the left_in_block field says how many + chars there are in this block. */ + num_chars = block_size - sizeof (struct lto_char_ptr_base); + if (!block) + num_chars = num_chars - obs->left_in_block; + + assemble_string (base, num_chars); + free (old_block); + block_size *= 2; + } +} + + +/* Write a character to the output block. */ + +void +lto_output_1_stream (struct lto_output_stream *obs, char c) +{ + /* No space left. */ + if (obs->left_in_block == 0) + { + struct lto_char_ptr_base *new_block; + + if (obs->first_block == NULL) + { + /* This is the first time the stream has been written + into. */ + obs->block_size = 1024; + new_block = (struct lto_char_ptr_base*) xmalloc (obs->block_size); + obs->first_block = new_block; + } + else + { + struct lto_char_ptr_base *tptr; + /* Get a new block that is twice as big as the last block + and link it into the list. */ + obs->block_size *= 2; + new_block = (struct lto_char_ptr_base*) xmalloc (obs->block_size); + /* The first bytes of the block are reserved as a pointer to + the next block. Set the chain of the full block to the + pointer to the new block. */ + tptr = obs->current_block; + tptr->ptr = (char *)new_block; + } + + /* Set the place for the next char at the first position after the + chain to the next block. */ + obs->current_pointer + = ((char *)new_block) + sizeof (struct lto_char_ptr_base); + obs->current_block = new_block; + /* Null out the newly allocated block's pointer to the next block. */ + new_block->ptr = NULL; + obs->left_in_block = obs->block_size - sizeof (struct lto_char_ptr_base); + } + + /* Write the actual character. */ + *obs->current_pointer = c; + obs->current_pointer++; + obs->total_size++; + obs->left_in_block--; +} + + +/* Output an unsigned LEB128 quantity to OBS. */ + +void +lto_output_uleb128_stream (struct lto_output_stream *obs, unsigned HOST_WIDE_INT work) +{ + LTO_DEBUG_WIDE ("U", work); + do + { + unsigned int byte = (work & 0x7f); + work >>= 7; + if (work != 0) + /* More bytes to follow. */ + byte |= 0x80; + + lto_output_1_stream (obs, byte); + } + while (work != 0); +} + +/* Identical to output_uleb128_stream above except using unsigned + HOST_WIDEST_INT type. For efficiency on host where unsigned HOST_WIDEST_INT + is not native, we only use this if we know that HOST_WIDE_INT is not wide + enough. */ + +void +lto_output_widest_uint_uleb128_stream (struct lto_output_stream *obs, + unsigned HOST_WIDEST_INT work) +{ + LTO_DEBUG_WIDE ("U", work); + do + { + unsigned int byte = (work & 0x7f); + work >>= 7; + if (work != 0) + /* More bytes to follow. */ + byte |= 0x80; + + lto_output_1_stream (obs, byte); + } + while (work != 0); +} + + +/* Output a signed LEB128 quantity. */ + +void +lto_output_sleb128_stream (struct lto_output_stream *obs, HOST_WIDE_INT work) +{ + int more, byte; + LTO_DEBUG_WIDE ("S", work); + do + { + byte = (work & 0x7f); + /* arithmetic shift */ + work >>= 7; + more = !((work == 0 && (byte & 0x40) == 0) + || (work == -1 && (byte & 0x40) != 0)); + if (more) + byte |= 0x80; + + lto_output_1_stream (obs, byte); + } + while (more); +} + + +/* Put out a integer constant. These are stored as two HOST_WIDE_INTS + so games may have to be played to shift the data from the high to + the low value. */ + +void +lto_output_integer_stream (struct lto_output_stream *obs, tree t) +{ + HOST_WIDE_INT low = TREE_INT_CST_LOW (t); + HOST_WIDE_INT high = TREE_INT_CST_HIGH (t); + int more, byte; + + /* Of course if the high value is just sign bits for the signed low + value, we can just punt and call lto_output_sleb128 and be done with + it. */ + if (((high == -1) && (low < 0)) + || ((high == 0) && (low >= 0))) + { + lto_output_sleb128_stream (obs, low); + return; + } + + LTO_DEBUG_INTEGER ("SS", high, low); + + /* This is just a copy of the lto_output_sleb128 code with extra + operations to transfer the low 7 bits of the high value to the + top 7 bits of the low value, shift the high down by 7 and then do + a slightly more complex exit test. */ + do + { + unsigned HOST_WIDE_INT transfer = (high & 0x7f); + high = ((unsigned HOST_WIDE_INT) high) >> 7; + transfer <<= (HOST_BITS_PER_WIDE_INT - 7); + + byte = (low & 0x7f); + + /* Logical shift. */ + low = ((unsigned HOST_WIDE_INT) low) >> 7; + low |= transfer; + more = !((high == 0 && low == 0 && (byte & 0x40) == 0) + || (high == -1 && low == -1 && (byte & 0x40) != 0)); + if (more) + byte |= 0x80; + + lto_output_1_stream (obs, byte); + } + while (more); +} + +#ifdef LTO_STREAM_DEBUGGING + +struct lto_debug_context lto_debug_context; + +/* The low level output routine to print a single character to the + debugging stream. */ + +void +lto_debug_out_fun (struct lto_debug_context *context, char c) +{ + struct lto_output_stream * stream + = (struct lto_output_stream *)context->current_data; + lto_output_1_stream (stream, c); +} + +#endif diff --git a/gcc/lto-section-out.h b/gcc/lto-section-out.h new file mode 100644 index 00000000000..4bc4d814c4d --- /dev/null +++ b/gcc/lto-section-out.h @@ -0,0 +1,78 @@ +/* LTO output code. + Copyright (C) 2007, 2008 Free Software Foundation, Inc. + Contributed by Kenneth Zadeck + +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 +. */ + +#ifndef GCC_LTO_SECTION_OUT_H +#define GCC_LTO_SECTION_OUT_H + +#ifdef LTO_STREAM_DEBUGGING +void lto_debug_out_fun (struct lto_debug_context *, char); +#endif + +struct lto_char_ptr_base +{ + char *ptr; +}; + +/* An incore byte stream to buffer the various parts of the +function. The entire structure should be zeroed when created. The +record consists of a set of blocks. The first sizeof (ptr) bytes are +used as a chain, and the rest store the bytes to be written. */ + +struct lto_output_stream +{ + /* The pointer to the first block in the stream. */ + struct lto_char_ptr_base * first_block; + /* The pointer to the last and current block in the stream. */ + struct lto_char_ptr_base * current_block; + /* The pointer to where the next char should be written. */ + char * current_pointer; + /* The number of characters left in the current block. */ + unsigned int left_in_block; + /* The block size of the last block allocated. */ + unsigned int block_size; + /* The total number of characters written. */ + unsigned int total_size; +}; + +#ifdef LTO_STREAM_DEBUGGING +#define LTO_SET_DEBUGGING_STREAM(STREAM,CONTEXT) \ +do { \ + ob-> STREAM = xcalloc (1, sizeof (struct lto_output_stream)); \ + lto_debug_context. CONTEXT = ob-> STREAM; \ + lto_debug_context.current_data = ob-> STREAM; \ + gcc_assert (lto_debug_context.indent == 0); \ +} while (0) +#define LTO_CLEAR_DEBUGGING_STREAM(STREAM) \ + free (ob-> STREAM) +#else +#define LTO_SET_DEBUGGING_STREAM(STREAM,CONTEXT) +#define LTO_CLEAR_DEBUGGING_STREAM(STREAM) (void)0 +#endif + + +void lto_write_stream (struct lto_output_stream *); +void lto_output_1_stream (struct lto_output_stream *, char); +void lto_output_uleb128_stream (struct lto_output_stream *, unsigned HOST_WIDE_INT); +void lto_output_widest_uint_uleb128_stream (struct lto_output_stream *, + unsigned HOST_WIDEST_INT); +void lto_output_sleb128_stream (struct lto_output_stream *, HOST_WIDE_INT); +void lto_output_integer_stream (struct lto_output_stream *, tree); + +#endif /* GCC_LTO_SECTION_OUT_H */ diff --git a/gcc/lto-tags.h b/gcc/lto-tags.h index 36f4a1ec533..52f6c1b2a0e 100644 --- a/gcc/lto-tags.h +++ b/gcc/lto-tags.h @@ -526,6 +526,8 @@ struct lto_debug_context void * main_data; }; +extern struct lto_debug_context lto_debug_context; + /* The VAR_DECL tree code has more than 32 bits in flags. On some hosts, HOST_WIDE_INT is not wide enough. */ typedef unsigned HOST_WIDEST_INT lto_flags_type; diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 69612f0ec39..957ce09bd8e 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,27 @@ +2008-01-14 Kenneth Zadeck + + * lto-read.c: Renamed to lto-function-in.c. + (input_1_unsigned): Moved to lto-section-in.c and renamed + lto_input_1_unsigned. + (input_uleb128): Moved to lto-section-in.c and renamed + lto_input_uleb128. + (input_widest_uint_uleb128): Moved to lto-section-in.c and renamed + lto_input_widest_uint_uleb128. + (input_sleb128): Moved to lto-section-in.c and renamed + lto_input_sleb128. + (input_integer): Moved to lto-section-in.c and renamed + lto_input_integer. + (debug_in_fun): Moved to lto-section-in.c and renamed + lto_debug_in_fun. + (input_block): Moved to lto-section-in.h and renamed + lto_input_block. + (input_expr_operand): Fixed to allow lists with more than one + element. + * lto-section-in.h: New file. + * lto-section-in.c: New file with changes from above. + * Make-lang.in (lto-read.o): Renamed lto-function-in.c. + (lto-section-in.o): New rule. + 2007-12-29 Nathan Froyd * lto-read.c (input_expr_operand): Mark static and external diff --git a/gcc/lto/Make-lang.in b/gcc/lto/Make-lang.in index c062337cd63..9ecfa8cf043 100644 --- a/gcc/lto/Make-lang.in +++ b/gcc/lto/Make-lang.in @@ -26,8 +26,8 @@ # The name of the LTO compiler. LTO_EXE = lto1$(exeext) # The LTO-specific object files inclued in $(LTO_EXE). -LTO_OBJS = lto/lto-lang.o lto/lto.o lto/lto-elf.o lto/lto-read.o \ - lto/lto-symtab.o attribs.o +LTO_OBJS = lto/lto-lang.o lto/lto.o lto/lto-elf.o lto/lto-function-in.o \ + lto/lto-section-in.o lto/lto-symtab.o attribs.o LTO_H = lto/lto.h $(HASHTAB_H) $(TREE_H) ######################################################################## @@ -86,10 +86,17 @@ lto/lto-elf.o: lto/lto-elf.c $(CONFIG_H) coretypes.h $(SYSTEM_H) \ toplev.h $(LTO_H) $(LTO_TAGS_H) $(TM_H) lto/lto-symtab.o: lto/lto-symtab.c $(CONFIG_H) coretypes.h \ $(SYSTEM_H) toplev.h $(LTO_H) lto/lto-tree.h -lto/lto-read.o: lto/lto-read.c $(CONFIG_H) $(SYSTEM_H) \ +lto/lto-function-in.o: lto/lto-function-in.c $(CONFIG_H) $(SYSTEM_H) \ coretypes.h $(TM_H) toplev.h $(LTO_H) $(EXPR_H) $(FLAGS_H) \ $(PARAMS_H) input.h $(VARRAY_H) $(HASHTAB_H) langhooks.h \ $(BASIC_BLOCK_H) tree-iterator.h tree-pass.h tree-flow.h \ $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H) \ except.h debug.h $(TIMEVAR_H) $(LTO_TAGS_H) lto-tree-flags.def \ - lto-tree-tags.def output.h dwarf2asm.h dwarf2out.h + lto-tree-tags.def lto/lto-section-in.h output.h dwarf2asm.h dwarf2out.h +lto/lto-section-in.o: lto/lto-section-in.c $(CONFIG_H) $(SYSTEM_H) \ + coretypes.h $(TM_H) toplev.h $(LTO_H) $(EXPR_H) $(FLAGS_H) \ + $(PARAMS_H) input.h $(VARRAY_H) $(HASHTAB_H) langhooks.h \ + $(BASIC_BLOCK_H) tree-iterator.h tree-pass.h tree-flow.h \ + $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H) \ + except.h debug.h $(TIMEVAR_H) $(LTO_TAGS_H) lto-tree-flags.def \ + lto-tree-tags.def lto/lto-section-in.h output.h dwarf2asm.h dwarf2out.h diff --git a/gcc/lto/lto-function-in.c b/gcc/lto/lto-function-in.c new file mode 100644 index 00000000000..e7f00ded12d --- /dev/null +++ b/gcc/lto/lto-function-in.c @@ -0,0 +1,1908 @@ +/* Read the gimple representation of a function and it's local + variables from the memory mapped representation of a a .o file. + + Copyright 2006, 2007, 2008 Free Software Foundation, Inc. + Contributed by Kenneth Zadeck + +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 2, 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 COPYING. If not, write to +the Free Software Foundation, 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "toplev.h" +#include "tree.h" +#include "expr.h" +#include "flags.h" +#include "params.h" +#include "input.h" +#include "varray.h" +#include "hashtab.h" +#include "langhooks.h" +#include "basic-block.h" +#include "tree-iterator.h" +#include "tree-pass.h" +#include "tree-flow.h" +#include "cgraph.h" +#include "function.h" +#include "ggc.h" +#include "diagnostic.h" +#include "except.h" +#include "debug.h" +#include "vec.h" +#include "timevar.h" +#include "dwarf2asm.h" +#include "dwarf2out.h" +#include "output.h" +#include "lto-tags.h" +#include "lto.h" +#include "lto-section-in.h" +#include +#include "cpplib.h" + +static enum tree_code tag_to_expr[LTO_last_tag]; + +/* The number of flags that are defined for each tree code. */ +static int flags_length_for_code[NUM_TREE_CODES]; + +struct data_in +{ + tree *field_decls; /* The field decls. */ + tree *fn_decls; /* The function decls. */ + tree *var_decls; /* The global or static var_decls. */ + tree *type_decls; /* The type_decls. */ + tree *types; /* All of the types. */ + int *local_decls_index; /* The offsets to decode the local_decls. */ + int *unexpanded_indexes; /* A table to reconstruct the unexpanded_vars_list. */ +#ifdef LTO_STREAM_DEBUGGING + int *local_decls_index_d; /* The offsets to decode the local_decls debug info. */ +#endif + tree *local_decls; /* The local var_decls and the parm_decls. */ + tree *labels; /* All of the labels. */ + const char * strings; /* The string table. */ + unsigned int strings_len; /* The length of the string table. */ + /* Number of named labels. Used to find the index of unnamed labels + since they share space with the named labels. */ + unsigned int num_named_labels; + const char *current_file; + int current_line; +#ifdef USE_MAPPED_LOCATION + int current_col; +#endif +}; + + + +/* This hash table is used to hash the file names in the + source_location field. Unlike other structures here, this is a + persistent structure whose data lives for the entire + compilation. */ + +struct string_slot { + const char *s; + unsigned int slot_num; +}; + + +/* Returns a hash code for P. */ + +static hashval_t +hash_string_slot_node (const void *p) +{ + const struct string_slot *ds = (const struct string_slot *) p; + return (hashval_t) htab_hash_string (ds->s); +} + + +/* Returns nonzero if P1 and P2 are equal. */ + +static int +eq_string_slot_node (const void *p1, const void *p2) +{ + const struct string_slot *ds1 = + (const struct string_slot *) p1; + const struct string_slot *ds2 = + (const struct string_slot *) p2; + + return strcmp (ds1->s, ds2->s) == 0; +} + +/* The table to hold the file_names. */ +static htab_t file_name_hash_table; + +static tree +input_expr_operand (struct lto_input_block *, struct data_in *, struct function *, + enum LTO_tags); +static tree +input_local_var (struct lto_input_block *, struct data_in *, struct function *, unsigned int i); + + +/* Return the next character of input from IB. Abort if you + overrun. */ + +/* Read the string at LOC from the string table in DATA_IN. */ + +static const char * +input_string_internal (struct data_in *data_in, unsigned int loc, + unsigned int *rlen) +{ + struct lto_input_block str_tab + = {data_in->strings, loc, data_in->strings_len}; + unsigned int len = lto_input_uleb128 (&str_tab); + const char * result; + + *rlen = len; + gcc_assert (str_tab.p + len <= data_in->strings_len); + + result = (const char *)(data_in->strings + str_tab.p); + LTO_DEBUG_STRING (result, len); + return result; +} + + +/* Read a STRING_CST at LOC from the string table in DATA_IN. */ + +static tree +input_string (struct data_in *data_in, unsigned int loc) +{ + unsigned int len; + const char * ptr = input_string_internal (data_in, loc, &len); + return build_string (len, ptr); +} + + +/* Input a real constant of TYPE at LOC. */ + +static tree +input_real (struct lto_input_block *ib, struct data_in *data_in, tree type) +{ + unsigned int loc; + unsigned int len; + const char * str; + REAL_VALUE_TYPE value; + static char buffer[1000]; + + LTO_DEBUG_TOKEN ("real"); + loc = lto_input_uleb128 (ib); + str = input_string_internal (data_in, loc, &len); + /* Copy over to make sure real_from_string doesn't see peculiar + trailing characters in the exponent. */ + memcpy (buffer, str, len); + buffer[len] = '\0'; + real_from_string (&value, buffer); + return build_real (type, value); +} + + +/* Return the next tag in the input block IB. */ + +static enum LTO_tags +input_record_start (struct lto_input_block *ib) +{ + enum LTO_tags tag = lto_input_1_unsigned (ib); + +#ifdef LTO_STREAM_DEBUGGING + if (tag) + LTO_DEBUG_INDENT (tag); + else + LTO_DEBUG_WIDE ("U", 0); +#endif + return tag; +} + + +/* Get the label referenced by the next token in IB. */ + +static tree +get_label_decl (struct data_in *data_in, struct lto_input_block *ib) +{ + int index = lto_input_sleb128 (ib); + if (index >= 0) + return data_in->labels[index]; + else + return data_in->labels[data_in->num_named_labels - index]; +} + + +/* Get the type referenced by the next token in IB. */ + +static tree +input_type_ref (struct data_in *data_in, struct lto_input_block *ib) +{ + int index; + + LTO_DEBUG_TOKEN ("type"); + index = lto_input_uleb128 (ib); + return data_in->types[index]; +} + +/* Set all of the FLAGS for NODE. */ +#define CLEAROUT (BITS_PER_LTO_FLAGS_TYPE - 1) + + +/* Read the tree flags for CODE from IB. */ + +static lto_flags_type +input_tree_flags (struct lto_input_block *ib, enum tree_code code, bool force) +{ + lto_flags_type flags; + + if (force || TEST_BIT (lto_flags_needed_for, code)) + { + LTO_DEBUG_TOKEN ("flags"); + flags = lto_input_widest_uint_uleb128 (ib); + LTO_DEBUG_TREE_FLAGS (code, flags); + } + else + flags = 0; + return flags; +} + + +/* Set all of the flag bits inside EXPR by unpacking FLAGS. */ + +static void +process_tree_flags (tree expr, lto_flags_type flags) +{ + enum tree_code code = TREE_CODE (expr); + /* Shift the flags up so that the first flag is at the top of the + flag word. */ + flags <<= BITS_PER_LTO_FLAGS_TYPE - flags_length_for_code[code]; + +#define START_CLASS_SWITCH() \ + { \ + \ + switch (TREE_CODE_CLASS (code)) \ + { + +#define START_CLASS_CASE(class) case class: +#define ADD_CLASS_DECL_FLAG(flag_name) \ + { expr->decl_common. flag_name = flags >> CLEAROUT; flags <<= 1; } +#define ADD_CLASS_EXPR_FLAG(flag_name) \ + { expr->base. flag_name = flags >> CLEAROUT; flags <<= 1; } +#define END_CLASS_CASE(class) break; +#define END_CLASS_SWITCH() \ + default: \ + gcc_unreachable (); \ + } + + +#define START_EXPR_SWITCH() \ + switch (code) \ + { +#define START_EXPR_CASE(code) case code: +#define ADD_EXPR_FLAG(flag_name) \ + { expr->base. flag_name = (flags >> CLEAROUT); flags <<= 1; } +#define ADD_DECL_FLAG(flag_name) \ + { expr->decl_common. flag_name = flags >> CLEAROUT; flags <<= 1; } +#define ADD_VIS_FLAG(flag_name) \ + { expr->decl_with_vis. flag_name = (flags >> CLEAROUT); flags <<= 1; } +#define ADD_VIS_FLAG_SIZE(flag_name,size) \ + { expr->decl_with_vis. flag_name = (flags >> (BITS_PER_LTO_FLAGS_TYPE - size)); flags <<= size; } +#define END_EXPR_CASE(class) break; +#define END_EXPR_SWITCH() \ + default: \ + gcc_unreachable (); \ + } \ + } + +#include "lto-tree-flags.def" + +#undef START_CLASS_SWITCH +#undef START_CLASS_CASE +#undef ADD_CLASS_DECL_FLAG +#undef ADD_CLASS_EXPR_FLAG +#undef END_CLASS_CASE +#undef END_CLASS_SWITCH +#undef START_EXPR_SWITCH +#undef START_EXPR_CASE +#undef ADD_EXPR_FLAG +#undef ADD_DECL_FLAG +#undef ADD_VIS_FLAG +#undef ADD_VIS_FLAG_SIZE +#undef END_EXPR_CASE +#undef END_EXPR_SWITCH +} + + +/* Return the one true copy of STRING. */ + +static const char * +canon_file_name (const char *string) +{ + void **slot; + struct string_slot s_slot; + s_slot.s = string; + + slot = htab_find_slot (file_name_hash_table, &s_slot, INSERT); + if (*slot == NULL) + { + size_t len = strlen (string); + char * saved_string = xmalloc (len + 1); + strcpy (saved_string, string); + + struct string_slot *new_slot + = xmalloc (sizeof (struct string_slot)); + + new_slot->s = saved_string; + *slot = new_slot; + return saved_string; + } + else + { + struct string_slot *old_slot = (struct string_slot *)*slot; + return old_slot->s; + } +} + + +/* Based on the FLAGS, read in a file, a line and a col into the + fields in DATA_IN. */ + +static bool +input_line_info (struct lto_input_block *ib, struct data_in *data_in, + lto_flags_type flags) +{ +#ifdef USE_MAPPED_LOCATION + if (flags & LTO_SOURCE_FILE) + { + unsigned int len; + if (data_in->current_file) + linemap_add (line_table, LC_LEAVE, false, NULL, 0); + + LTO_DEBUG_TOKEN ("file"); + data_in->current_file + = canon_file_name (input_string_internal (data_in, lto_input_uleb128 (ib), &len)); + } + if (flags & LTO_SOURCE_LINE) + { + LTO_DEBUG_TOKEN ("line"); + data_in->current_line = lto_input_uleb128 (ib); + + if (!(flags & LTO_SOURCE_FILE)) + linemap_line_start (line_table, data_in->current_line, 80); + } + if (flags & LTO_SOURCE_FILE) + linemap_add (line_table, LC_ENTER, false, data_in->current_file, data_in->current_line); + + if (flags & LTO_SOURCE_COL) + { + LTO_DEBUG_TOKEN ("col"); + data_in->current_col = lto_input_uleb128 (ib); + } +#else + if (flags & LTO_SOURCE_FILE) + { + unsigned int len; + LTO_DEBUG_TOKEN ("file"); + data_in->current_file + = input_string_internal (data_in, lto_input_uleb128 (ib), &len); + } + if (flags & LTO_SOURCE_LINE) + { + LTO_DEBUG_TOKEN ("line"); + data_in->current_line = lto_input_uleb128 (ib); + } +#endif + return (flags & LTO_SOURCE_HAS_LOC) != 0; +} + + +/* Set the line info stored in DATA_IN for NODE. */ + +static void +set_line_info (struct data_in *data_in, tree node) +{ +#ifdef USE_MAPPED_LOCATION + if (EXPR_P (node)) + LINEMAP_POSITION_FOR_COLUMN (EXPR_CHECK (node)->exp.locus, line_table, data_in->current_col) + else if (GIMPLE_STMT_P (node)) + LINEMAP_POSITION_FOR_COLUMN (GIMPLE_STMT_LOCUS (node), line_table, data_in->current_col) + else if (DECL_P (node)) + LINEMAP_POSITION_FOR_COLUMN (DECL_SOURCE_LOCATION (node), line_table, data_in->current_col) +#else + if (EXPR_P (node) || GIMPLE_STMT_P (node)) + annotate_with_file_line (node, + canon_file_name (data_in->current_file), + data_in->current_line); + else if (DECL_P (node)) + { + DECL_SOURCE_LOCATION (node).file = canon_file_name (data_in->current_file); + DECL_SOURCE_LOCATION (node).line = data_in->current_line; + } +#endif +} + + +/* Clear the line info stored in DATA_IN. */ + +static void +clear_line_info (struct data_in *data_in) +{ +#ifdef USE_MAPPED_LOCATION + if (data_in->current_file) + linemap_add (line_table, LC_LEAVE, false, NULL, 0); + data_in->current_col = 0; +#endif + data_in->current_file = NULL; + data_in->current_line = 0; +} + + +/* Read a node in the gimple tree from IB. The TAG has already been + read. */ + +static tree +input_expr_operand (struct lto_input_block *ib, struct data_in *data_in, + struct function *fn, enum LTO_tags tag) +{ + enum tree_code code = tag_to_expr[tag]; + tree type = NULL_TREE; + lto_flags_type flags; + gcc_assert (code); + tree result = NULL_TREE; + bool needs_line_set = false; + + if (TEST_BIT (lto_types_needed_for, code)) + type = input_type_ref (data_in, ib); + + flags = input_tree_flags (ib, code, false); + + if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)) + || IS_GIMPLE_STMT_CODE_CLASS(TREE_CODE_CLASS (code))) + needs_line_set = input_line_info (ib, data_in, flags); + + switch (code) + { + case COMPLEX_CST: + { + tree elt_type = input_type_ref (data_in, ib); + + result = build0 (code, type); + if (tag == LTO_complex_cst1) + { + TREE_REALPART (result) = input_real (ib, data_in, elt_type); + TREE_IMAGPART (result) = input_real (ib, data_in, elt_type); + } + else + { + TREE_REALPART (result) = lto_input_integer (ib, elt_type); + TREE_IMAGPART (result) = lto_input_integer (ib, elt_type); + } + } + break; + + case INTEGER_CST: + result = lto_input_integer (ib, type); + break; + + case REAL_CST: + result = input_real (ib, data_in, type); + break; + + case STRING_CST: + result = input_string (data_in, lto_input_uleb128 (ib)); + TREE_TYPE (result) = type; + break; + + case IDENTIFIER_NODE: + { + unsigned int len; + const char * ptr = input_string_internal (data_in, lto_input_uleb128 (ib), &len); + result = get_identifier_with_length (ptr, len); + } + break; + + case VECTOR_CST: + { + tree chain = NULL_TREE; + int len = lto_input_uleb128 (ib); + tree elt_type = input_type_ref (data_in, ib); + + if (len && tag == LTO_vector_cst1) + { + int i; + tree last + = build_tree_list (NULL_TREE, input_real (ib, data_in, elt_type)); + chain = last; + for (i = 1; i < len; i++) + { + tree t + = build_tree_list (NULL_TREE, input_real (ib, data_in, elt_type)); + TREE_CHAIN (last) = t; + last = t; + } + } + else + { + int i; + tree last = build_tree_list (NULL_TREE, lto_input_integer (ib, elt_type)); + chain = last; + for (i = 1; i < len; i++) + { + tree t + = build_tree_list (NULL_TREE, lto_input_integer (ib, elt_type)); + TREE_CHAIN (last) = t; + last = t; + } + } + result = build_vector (type, chain); + } + break; + + case CASE_LABEL_EXPR: + { + int variant = tag - LTO_case_label_expr0; + tree op0 = NULL_TREE; + tree op1 = NULL_TREE; + + if (variant & 0x1) + op0 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + + if (variant & 0x2) + op1 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + + result = build3 (code, void_type_node, + op0, op1, get_label_decl (data_in, ib)); + } + break; + + case CONSTRUCTOR: + { + VEC(constructor_elt,gc) *vec = NULL; + unsigned int len = lto_input_uleb128 (ib); + + if (len) + { + unsigned int i = 0; + vec = VEC_alloc (constructor_elt, gc, len); + for (i = 0; i < len; i++) + { + tree purpose = NULL_TREE; + tree value; + constructor_elt *elt; + enum LTO_tags ctag = input_record_start (ib); + + if (ctag) + purpose = input_expr_operand (ib, data_in, fn, ctag); + + value = input_expr_operand (ib, data_in, fn, input_record_start (ib)); + elt = VEC_quick_push (constructor_elt, vec, NULL); + elt->index = purpose; + elt->value = value; + } + } + result = build_constructor (type, vec); + } + break; + + case SSA_NAME: + result = VEC_index (tree, SSANAMES (fn), lto_input_uleb128 (ib)); + add_referenced_var (SSA_NAME_VAR (result)); + break; + + case CONST_DECL: + /* Just ignore these, Mark will make them disappear. */ + break; + + case FIELD_DECL: + result = data_in->field_decls [lto_input_uleb128 (ib)]; + break; + + case FUNCTION_DECL: + result = data_in->fn_decls [lto_input_uleb128 (ib)]; + gcc_assert (result); + break; + + case TYPE_DECL: + result = data_in->type_decls [lto_input_uleb128 (ib)]; + gcc_assert (result); + break; + + case VAR_DECL: + case PARM_DECL: + if (tag == LTO_var_decl1) + { + /* Static or externs are here. */ + result = data_in->var_decls [lto_input_uleb128 (ib)]; + varpool_mark_needed_node (varpool_node (result)); + } + else + { + /* Locals are here. */ + int lv_index = lto_input_uleb128 (ib); + result = data_in->local_decls [lv_index]; + if (result == NULL) + { + /* Create a context to read the local variable so that + it does not disturb the position of the code that is + calling for the local variable. This allows locals + to refer to other locals. */ + struct lto_input_block lib; + +#ifdef LTO_STREAM_DEBUGGING + struct lto_input_block *current = lto_debug_context.current_data; + struct lto_input_block debug; + int current_indent = lto_debug_context.indent; + + debug.data = current->data; + debug.len = current->len; + debug.p = data_in->local_decls_index_d[lv_index]; + + lto_debug_context.indent = 0; + lto_debug_context.current_data = &debug; +#endif + lib.data = ib->data; + lib.len = ib->len; + lib.p = data_in->local_decls_index[lv_index]; + + result = input_local_var (&lib, data_in, fn, lv_index); + data_in->local_decls [lv_index] = result; + +#ifdef LTO_STREAM_DEBUGGING + lto_debug_context.indent = current_indent; + lto_debug_context.current_data = current; +#endif + + } + } + break; + + case LABEL_DECL: + result = get_label_decl (data_in, ib); + break; + + case LABEL_EXPR: + result = build1 (code, void_type_node, get_label_decl (data_in, ib)); + if (!DECL_CONTEXT (LABEL_EXPR_LABEL (result))) + DECL_CONTEXT (LABEL_EXPR_LABEL (result)) = fn->decl; + break; + + case COND_EXPR: + if (tag == LTO_cond_expr0) + { + tree op0; + tree op1; + tree op2; + op0 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + op1 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + op2 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + result = build3 (code, type, op0, op1, op2); + } + else + { + tree op0; + op0 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + result = build3 (code, type, op0, NULL, NULL); + } + break; + + + case RESULT_DECL: + result = DECL_RESULT (current_function_decl); + add_referenced_var (result); + break; + + case COMPONENT_REF: + { + tree op0; + tree op1; + op0 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + op1 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + + /* Ignore 3 because it can be recomputed. */ + result = build3 (code, type, op0, op1, NULL_TREE); + } + break; + + case CALL_EXPR: + { + unsigned int i; + unsigned int count = lto_input_uleb128 (ib); + tree op1; + tree op2 = NULL_TREE; + + /* The call chain. */ + if (tag == LTO_call_expr1) + op2 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + + /* The callee. */ + op1 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + + result = build_vl_exp (code, count); + CALL_EXPR_FN (result) = op1; + CALL_EXPR_STATIC_CHAIN (result) = op2; + for (i = 3; i < count; i++) + TREE_OPERAND (result, i) + = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + TREE_TYPE (result) = type; + } + break; + + case BIT_FIELD_REF: + { + tree op0; + tree op1; + tree op2; + if (tag == LTO_bit_field_ref1) + { + op1 = build_int_cst_wide (sizetype, lto_input_uleb128 (ib), 0); + op2 = build_int_cst_wide (bitsizetype, lto_input_uleb128 (ib), 0); + op0 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + } + else + { + op0 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + op1 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + op2 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + } + result = build3 (code, type, op0, op1, op2); + } + break; + + case ARRAY_REF: + case ARRAY_RANGE_REF: + /* Ignore operands 2 and 3 for ARRAY_REF and ARRAY_RANGE REF + because they can be recomputed. */ + { + tree op0 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + tree op1 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + result = build4 (code, type, op0, op1, NULL_TREE, NULL_TREE); + } + break; + + case ASM_EXPR: + { + tree str = input_string (data_in, lto_input_uleb128 (ib)); + tree ins = NULL_TREE; + tree outs = NULL_TREE; + tree clobbers = NULL_TREE; + tree tl; + + tag = input_record_start (ib); + if (tag) + ins = input_expr_operand (ib, data_in, fn, tag); + tag = input_record_start (ib); + if (tag) + outs = input_expr_operand (ib, data_in, fn, tag); + tag = input_record_start (ib); + if (tag) + clobbers = input_expr_operand (ib, data_in, fn, tag); + + result = build4 (code, void_type_node, str, outs, ins, clobbers); + + for (tl = ASM_OUTPUTS (result); tl; tl = TREE_CHAIN (tl)) + if (TREE_CODE (TREE_VALUE (tl)) == SSA_NAME) + SSA_NAME_DEF_STMT (TREE_VALUE (tl)) = result; + } + break; + + case RESX_EXPR: + result = build1 (code, void_type_node, lto_input_integer (ib, NULL_TREE)); + break; + + case RETURN_EXPR: + switch (tag) + { + case LTO_return_expr0: + result = build1 (code, type, NULL_TREE); + break; + + case LTO_return_expr1: + { + enum LTO_tags tag = input_record_start (ib); + tree op0; + + if (tag) + op0 = input_expr_operand (ib, data_in, fn, tag); + else + { + op0 = DECL_RESULT (current_function_decl); + add_referenced_var (op0); + } + + result = build1 (code, type, op0); + + if ((TREE_CODE (op0) == GIMPLE_MODIFY_STMT) + && (TREE_CODE (GIMPLE_STMT_OPERAND (op0, 0)) == SSA_NAME)) + SSA_NAME_DEF_STMT (GIMPLE_STMT_OPERAND (op0, 0)) = result; + } + break; + + case LTO_return_expr2: + { + tree op0 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + tree op1 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + result = build1 (code, type, + build2 (MODIFY_EXPR, NULL_TREE, op0, op1)); + } + break; + + default: + gcc_unreachable (); + } + break; + + case RANGE_EXPR: + { + tree op0 = lto_input_integer (ib, input_type_ref (data_in, ib)); + tree op1 = lto_input_integer (ib, input_type_ref (data_in, ib)); + result = build2 (RANGE_EXPR, sizetype, op0, op1); + } + break; + + case GIMPLE_MODIFY_STMT: + { + tree op0 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + tree op1 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + + result = build_gimple_modify_stmt (op0, op1); + if (TREE_CODE (op0) == SSA_NAME) + SSA_NAME_DEF_STMT (op0) = result; + } + break; + + case SWITCH_EXPR: + { + unsigned int len = lto_input_uleb128 (ib); + unsigned int i; + tree op0 = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + tree op2 = make_tree_vec (len); + + for (i = 0; i < len; ++i) + TREE_VEC_ELT (op2, i) + = input_expr_operand (ib, data_in, fn, + input_record_start (ib)); + result = build3 (code, type, op0, NULL_TREE, op2); + } + break; + + case TREE_LIST: + { + unsigned int count = lto_input_uleb128 (ib); + tree next = NULL; + + result = NULL_TREE; + while (count--) + { + tree value; + tree purpose; + tree elt; + enum LTO_tags tag = input_record_start (ib); + + if (tag) + value = input_expr_operand (ib, data_in, fn, tag); + else + value = NULL_TREE; + tag = input_record_start (ib); + if (tag) + purpose = input_expr_operand (ib, data_in, fn, tag); + else + purpose = NULL_TREE; + + elt = build_tree_list (purpose, value); + if (result) + TREE_CHAIN (next) = elt; + else + /* Save the first one. */ + result = elt; + next = elt; + } + } + break; + + /* This is the default case. All of the cases that can be done + completely mechanically are done here. */ +#define SET_NAME(a,b) +#define TREE_SINGLE_MECHANICAL_TRUE +#define MAP_EXPR_TAG(expr,tag) case expr: +#include "lto-tree-tags.def" +#undef MAP_EXPR_TAG +#undef TREE_SINGLE_MECHANICAL_TRUE +#undef SET_NAME + { + tree ops[7]; + int len = TREE_CODE_LENGTH (code); + int i; + for (i = 0; ifield_decls = xcalloc (header->num_field_decls, sizeof (tree*)); + data_in->fn_decls = xcalloc (header->num_fn_decls, sizeof (tree*)); + data_in->var_decls = xcalloc (header->num_var_decls, sizeof (tree*)); + data_in->type_decls = xcalloc (header->num_type_decls, sizeof (tree*)); + data_in->types = xcalloc (header->num_types, sizeof (tree*)); + + for (i=0; inum_field_decls; i++) + data_in->field_decls[i] + = lto_resolve_field_ref (fd, context, &in_field_decls[i]); + + for (i=0; inum_fn_decls; i++) + data_in->fn_decls[i] + = lto_resolve_fn_ref (fd, context, &in_fn_decls[i]); + + for (i=0; inum_var_decls; i++) + data_in->var_decls[i] + = lto_resolve_var_ref (fd, context, &in_var_decls[i]); + + for (i=0; inum_type_decls; i++) + data_in->type_decls[i] + = lto_resolve_typedecl_ref (fd, context, &in_type_decls[i]); + + for (i=0; inum_types; i++) + data_in->types[i] = lto_resolve_type_ref (fd, context, &in_types[i]); +} + + +/* Load NAMED_COUNT named labels and constuct UNNAMED_COUNT unnamed + labels from DATA segment SIZE bytes long using DATA_IN. */ + +static void +input_labels (struct lto_input_block *ib, struct data_in *data_in, + unsigned int named_count, unsigned int unnamed_count) +{ + unsigned int i; + + clear_line_info (data_in); + /* The named and unnamed labels share the same array. In the lto + code, the unnamed labels have a negative index. Their position + in the array can be found by subtracting that index from the + number of named labels. */ + data_in->labels = xcalloc (named_count + unnamed_count, sizeof (tree*)); + for (i = 0; i < named_count; i++) + { + unsigned int name_index = lto_input_uleb128 (ib); + unsigned int len; + const char *s = input_string_internal (data_in, name_index, &len); + tree name = get_identifier_with_length (s, len); + data_in->labels[i] = build_decl (LABEL_DECL, name, void_type_node); + } + + for (i = 0; i < unnamed_count; i++) + data_in->labels[i + named_count] + = build_decl (LABEL_DECL, NULL_TREE, void_type_node); + } + + +/* Input the local var index table. */ + + +static void +input_local_vars_index (struct lto_input_block *ib, struct data_in *data_in, + unsigned int count) +{ + unsigned int i; + data_in->local_decls_index = xcalloc (count, sizeof (unsigned int)); +#ifdef LTO_STREAM_DEBUGGING + data_in->local_decls_index_d = xcalloc (count, sizeof (unsigned int)); +#endif + + for (i = 0; i < count; i++) + { + data_in->local_decls_index[i] = lto_input_uleb128 (ib); +#ifdef LTO_STREAM_DEBUGGING + data_in->local_decls_index_d[i] = lto_input_uleb128 (ib); +#endif + } +} + + +/* Input local var I for FN from IB. */ + +static tree +input_local_var (struct lto_input_block *ib, struct data_in *data_in, + struct function *fn, unsigned int i) +{ + enum LTO_tags tag; + unsigned int variant; + bool is_var; + unsigned int name_index; + tree name; + tree type; + lto_flags_type flags; + tree result; + tree context; + + /* The line number info needs to be reset for each local var since + they are read in random order. */ + clear_line_info (data_in); + + tag = input_record_start (ib); + variant = tag & 0xF; + is_var = ((tag & 0xFFF0) == LTO_local_var_decl_body0); + + name_index = lto_input_uleb128 (ib); + if (name_index) + { + unsigned int len; + const char *s = input_string_internal (data_in, name_index, &len); + name = get_identifier_with_length (s, len); + } + else + name = NULL_TREE; + + type = input_type_ref (data_in, ib); + gcc_assert (type); + + if (is_var) + result = build_decl (VAR_DECL, name, type); + else + result = build_decl (PARM_DECL, name, type); + + data_in->local_decls[i] = result; + + if (is_var) + { + int index; + + LTO_DEBUG_INDENT_TOKEN ("init"); + tag = input_record_start (ib); + if (tag) + DECL_INITIAL (result) = input_expr_operand (ib, data_in, fn, tag); + + LTO_DEBUG_INDENT_TOKEN ("unexpanded index"); + index = lto_input_sleb128 (ib); + if (index != -1) + data_in->unexpanded_indexes[index] = i; + } + else + { + DECL_ARG_TYPE (result) = input_type_ref (data_in, ib); + LTO_DEBUG_TOKEN ("chain"); + tag = input_record_start (ib); + if (tag) + TREE_CHAIN (result) = input_expr_operand (ib, data_in, fn, tag); + else + TREE_CHAIN (result) = NULL_TREE; + } + + + flags = input_tree_flags (ib, 0, true); + if (input_line_info (ib, data_in, flags)) + set_line_info (data_in, result); + + + LTO_DEBUG_TOKEN ("context"); + context = input_expr_operand (ib, data_in, fn, input_record_start (ib)); + if (TYPE_P (context)) + DECL_CONTEXT (result) = TYPE_NAME (context); + else + DECL_CONTEXT (result) = context; + + LTO_DEBUG_TOKEN ("align"); + DECL_ALIGN (result) = lto_input_uleb128 (ib); + LTO_DEBUG_TOKEN ("size"); + DECL_SIZE (result) = input_expr_operand (ib, data_in, fn, input_record_start (ib)); + + if (variant & 0x1) + { + LTO_DEBUG_TOKEN ("attributes"); + DECL_ATTRIBUTES (result) + = input_expr_operand (ib, data_in, fn, input_record_start (ib)); + } + if (variant & 0x2) + DECL_SIZE_UNIT (result) + = input_expr_operand (ib, data_in, fn, input_record_start (ib)); + if (variant & 0x4) + SET_DECL_DEBUG_EXPR (result, + input_expr_operand (ib, data_in, fn, + input_record_start (ib))); + if (variant & 0x8) + DECL_ABSTRACT_ORIGIN (result) + = input_expr_operand (ib, data_in, fn, input_record_start (ib)); + + process_tree_flags (result, flags); + LTO_DEBUG_UNDENT(); + + return result; +} + + +/* Load COUNT local var_decls and parm_decls from a DATA segment SIZE + bytes long using DATA_IN. */ + +static void +input_local_vars (struct lto_input_block *ib, struct data_in *data_in, + struct function *fn, unsigned int count) +{ + int i; + unsigned int tag; + + data_in->unexpanded_indexes = xcalloc (count, sizeof (int)); + data_in->local_decls = xcalloc (count, sizeof (tree*)); + + memset (data_in->unexpanded_indexes, -1, count * sizeof (int)); + + /* Recreate the unexpanded_var_list. Put the statics at the end.*/ + fn->unexpanded_var_list = NULL; + LTO_DEBUG_TOKEN ("local statics"); + tag = input_record_start (ib); + + while (tag) + { + tree var = input_expr_operand (ib, data_in, fn, tag); + fn->unexpanded_var_list + = tree_cons (NULL_TREE, var, fn->unexpanded_var_list); + + if (lto_input_uleb128 (ib)) + DECL_CONTEXT (var) = fn->decl; + + /* DECL_INITIAL. */ + tag = input_record_start (ib); + if (tag) + DECL_INITIAL (var) = input_expr_operand (ib, data_in, fn, tag); + + /* Statics never have external visibility. */ + DECL_EXTERNAL (var) = 0; + + /* Next static. */ + tag = input_record_start (ib); + } + + LTO_DEBUG_TOKEN ("local vars"); + for (i = 0; i < (int)count; i++) + /* Some local decls may have already been read in if they are used + as part of a previous local_decl. */ + if (!data_in->local_decls[i]) + { +#ifdef LTO_STREAM_DEBUGGING + ((struct lto_input_block *)lto_debug_context.current_data)->p + = data_in->local_decls_index_d[i]; +#endif + ib->p = data_in->local_decls_index[i]; + input_local_var (ib, data_in, fn, i); + } + + /* Add the regular locals in the proper order. */ + for (i = count - 1; i >= 0; i--) + if (data_in->unexpanded_indexes[i] != -1) + fn->unexpanded_var_list + = tree_cons (NULL_TREE, + data_in->local_decls[data_in->unexpanded_indexes[i]], + fn->unexpanded_var_list); + + free (data_in->unexpanded_indexes); + data_in->unexpanded_indexes = NULL; +} + + +/* Read the exception table. */ + +static void +input_eh_regions (struct lto_input_block *ib, + struct function *fn ATTRIBUTE_UNUSED, + struct data_in *data_in ATTRIBUTE_UNUSED) +{ + /* Not ready to read exception records yet. */ + lto_input_uleb128 (ib); +} + + +/* Make a new basic block at INDEX in FN. */ + +static basic_block +make_new_block (struct function *fn, unsigned int index) +{ + basic_block bb = alloc_block (); + bb->index = index; + SET_BASIC_BLOCK_FOR_FUNCTION (fn, index, bb); + bb->il.tree = GGC_CNEW (struct tree_bb_info); + n_basic_blocks_for_function (fn)++; + bb->flags = 0; + set_bb_stmt_list (bb, alloc_stmt_list ()); + return bb; +} + + +/* Set up the cfg for THIS_FUN. */ + +static void +input_cfg (struct lto_input_block *ib, struct function *fn) +{ + unsigned int bb_count; + basic_block p_bb; + unsigned int i; + int index; + + init_empty_tree_cfg_for_function (fn); + init_ssa_operands (); + + LTO_DEBUG_TOKEN ("lastbb"); + bb_count = lto_input_uleb128 (ib); + + last_basic_block_for_function (fn) = bb_count; + if (bb_count > VEC_length (basic_block, + basic_block_info_for_function (fn))) + VEC_safe_grow_cleared (basic_block, gc, + basic_block_info_for_function (fn), bb_count); + if (bb_count > VEC_length (basic_block, + label_to_block_map_for_function (fn))) + VEC_safe_grow_cleared (basic_block, gc, + label_to_block_map_for_function (fn), bb_count); + + LTO_DEBUG_TOKEN ("bbindex"); + index = lto_input_sleb128 (ib); + while (index != -1) + { + basic_block bb = BASIC_BLOCK_FOR_FUNCTION (fn, index); + unsigned int edge_count; + + if (bb == NULL) + bb = make_new_block (fn, index); + + LTO_DEBUG_TOKEN ("edgecount"); + edge_count = lto_input_uleb128 (ib); + + /* Connect up the cfg. */ + for (i = 0; i < edge_count; i++) + { + unsigned int dest_index; + unsigned int edge_flags; + basic_block dest; + + LTO_DEBUG_TOKEN ("dest"); + dest_index = lto_input_uleb128 (ib); + LTO_DEBUG_TOKEN ("eflags"); + edge_flags = lto_input_uleb128 (ib); + dest = BASIC_BLOCK_FOR_FUNCTION (fn, dest_index); + + if (dest == NULL) + dest = make_new_block (fn, dest_index); + make_edge (bb, dest, edge_flags); + } + + LTO_DEBUG_TOKEN ("bbindex"); + index = lto_input_sleb128 (ib); + } + + p_bb = ENTRY_BLOCK_PTR_FOR_FUNCTION(fn); + LTO_DEBUG_TOKEN ("bbchain"); + index = lto_input_sleb128 (ib); + while (index != -1) + { + basic_block bb = BASIC_BLOCK_FOR_FUNCTION (fn, index); + bb->prev_bb = p_bb; + p_bb->next_bb = bb; + p_bb = bb; + LTO_DEBUG_TOKEN ("bbchain"); + index = lto_input_sleb128 (ib); + } +} + + +/* Input the next phi function for BB. */ + +static tree +input_phi (struct lto_input_block *ib, basic_block bb, + struct data_in *data_in, struct function *fn) +{ + lto_flags_type flags = input_tree_flags (ib, PHI_NODE, false); + + tree phi_result = VEC_index (tree, SSANAMES (fn), lto_input_uleb128 (ib)); + int len = EDGE_COUNT (bb->preds); + int i; + tree result = create_phi_node (phi_result, bb); + + SSA_NAME_DEF_STMT (phi_result) = result; + + /* We have to go thru a lookup process here because the preds in the + reconstructed graph are generally in a different order than they + were in the original program. */ + for (i = 0; i < len; i++) + { + tree def = input_expr_operand (ib, data_in, fn, input_record_start (ib)); + int src_index = lto_input_uleb128 (ib); + basic_block sbb = BASIC_BLOCK_FOR_FUNCTION (fn, src_index); + + edge e = NULL; + int j; + + for (j = 0; j < len; j++) + if (EDGE_PRED (bb, j)->src == sbb) + { + e = EDGE_PRED (bb, j); + break; + } + + add_phi_arg (result, def, e); + } + + if (flags) + process_tree_flags (result, flags); + + LTO_DEBUG_UNDENT(); + + return result; +} + + +/* Read in the ssa_names array from IB. */ + +static void +input_ssa_names (struct lto_input_block *ib, struct data_in *data_in, struct function *fn) +{ + unsigned int i; + int size = lto_input_uleb128 (ib); + + init_ssanames (fn, size); + i = lto_input_uleb128 (ib); + + while (i) + { + tree ssa_name; + tree name; + lto_flags_type flags; + + /* Skip over the elements that had been freed. */ + while (VEC_length (tree, SSANAMES (fn)) < i) + VEC_quick_push (tree, SSANAMES (fn), NULL_TREE); + + name = input_expr_operand (ib, data_in, fn, input_record_start (ib)); + ssa_name = make_ssa_name (fn, name, build_empty_stmt ()); + + flags = input_tree_flags (ib, 0, true); + process_tree_flags (ssa_name, flags); + if (SSA_NAME_IS_DEFAULT_DEF (ssa_name)) + set_default_def (SSA_NAME_VAR (ssa_name), ssa_name); + i = lto_input_uleb128 (ib); + } +} + + +/* Read in the next basic block. */ + +static void +input_bb (struct lto_input_block *ib, enum LTO_tags tag, + struct data_in *data_in, struct function *fn) +{ + unsigned int index; + basic_block bb; + block_stmt_iterator bsi; + unsigned int stmt_num; + + LTO_DEBUG_TOKEN ("bbindex"); + index = lto_input_uleb128 (ib); + bb = BASIC_BLOCK_FOR_FUNCTION (fn, index); + + /* LTO_bb1 has stmts, LTO_bb0 does not. */ + if (tag == LTO_bb0) + { + LTO_DEBUG_UNDENT(); + return; + } + + bsi = bsi_start (bb); + LTO_DEBUG_INDENT_TOKEN ("stmt"); + stmt_num = lto_input_uleb128 (ib); + while (stmt_num) + { + tree stmt; + + tag = input_record_start (ib); + stmt = input_expr_operand (ib, data_in, fn, tag); + bsi_insert_after (&bsi, stmt, BSI_NEW_STMT); + LTO_DEBUG_INDENT_TOKEN ("stmt"); + stmt_num = lto_input_uleb128 (ib); + /* FIXME, add code to handle the exception. */ + } + + LTO_DEBUG_INDENT_TOKEN ("phi"); + stmt_num = lto_input_uleb128 (ib); + while (stmt_num) + { + tag = input_record_start (ib); + input_phi (ib, bb, data_in, fn); + LTO_DEBUG_INDENT_TOKEN ("phi"); + stmt_num = lto_input_uleb128 (ib); + } + + LTO_DEBUG_UNDENT(); +} + + +/* Fill in the body of FN_DECL. */ + +static void +input_function (tree fn_decl, struct data_in *data_in, + struct lto_input_block *ib) +{ + struct function *fn = DECL_STRUCT_FUNCTION (fn_decl); + enum LTO_tags tag = input_record_start (ib); + + DECL_INITIAL (fn_decl) = DECL_SAVED_TREE (fn_decl) = make_node (BLOCK); + BLOCK_ABSTRACT_ORIGIN (DECL_SAVED_TREE (fn_decl)) = fn_decl; + clear_line_info (data_in); + + tree_register_cfg_hooks (); + gcc_assert (tag == LTO_function); + + input_eh_regions (ib, fn, data_in); + + LTO_DEBUG_INDENT_TOKEN ("decl_arguments"); + tag = input_record_start (ib); + if (tag) + DECL_ARGUMENTS (fn_decl) = input_expr_operand (ib, data_in, fn, tag); + + LTO_DEBUG_INDENT_TOKEN ("decl_context"); + tag = input_record_start (ib); + if (tag) + DECL_CONTEXT (fn_decl) = input_expr_operand (ib, data_in, fn, tag); + + tag = input_record_start (ib); + while (tag) + { + input_bb (ib, tag, data_in, fn); + tag = input_record_start (ib); + } + + LTO_DEBUG_UNDENT(); +} + + +/* Fill in the body of VAR. */ + +static void +input_constructor (tree var, struct data_in *data_in, + struct lto_input_block *ib) +{ + enum LTO_tags tag; + + clear_line_info (data_in); + LTO_DEBUG_INDENT_TOKEN ("init"); + tag = input_record_start (ib); + DECL_INITIAL (var) = input_expr_operand (ib, data_in, NULL, tag); +} + + +static bool initialized_local = false; + + +/* Static initialization for the lto reader. */ + +static void +lto_static_init_local (void) +{ + if (initialized_local) + return; + + initialized_local = true; + + /* Initialize the expression to tag mapping. */ +#define MAP_EXPR_TAG(expr,tag) tag_to_expr [tag] = expr; +#define MAP_EXPR_TAGS(expr,tag,count) \ + { \ + int i; \ + for (i=0; inum_field_decls * sizeof (lto_ref)); + int32_t vars_offset + = fns_offset + (header->num_fn_decls * sizeof (lto_ref)); + int32_t type_decls_offset + = vars_offset + (header->num_var_decls * sizeof (lto_ref)); + int32_t types_offset + = type_decls_offset + (header->num_type_decls * sizeof (lto_ref)); + int32_t named_label_offset + = types_offset + (header->num_types * sizeof (lto_ref)); + int32_t ssa_names_offset + = named_label_offset + header->named_label_size; + int32_t cfg_offset + = ssa_names_offset + header->ssa_names_size; + int32_t local_decls_index_offset = cfg_offset + header->cfg_size; + int32_t local_decls_offset = local_decls_index_offset + header->local_decls_index_size; + int32_t main_offset = local_decls_offset + header->local_decls_size; + int32_t string_offset = main_offset + header->main_size; + +#ifdef LTO_STREAM_DEBUGGING + int32_t debug_decl_index_offset = string_offset + header->string_size; + int32_t debug_decl_offset = debug_decl_index_offset + header->debug_decl_index_size; + int32_t debug_label_offset = debug_decl_offset + header->debug_decl_size; + int32_t debug_ssa_names_offset = debug_label_offset + header->debug_label_size; + int32_t debug_cfg_offset = debug_ssa_names_offset + header->debug_ssa_names_size; + int32_t debug_main_offset = debug_cfg_offset + header->debug_cfg_size; + + struct lto_input_block debug_decl_index + = {data + debug_decl_index_offset, 0, header->debug_decl_index_size}; + struct lto_input_block debug_decl + = {data + debug_decl_offset, 0, header->debug_decl_size}; + struct lto_input_block debug_label + = {data + debug_label_offset, 0, header->debug_label_size}; + struct lto_input_block debug_ssa_names + = {data + debug_ssa_names_offset, 0, header->debug_ssa_names_size}; + struct lto_input_block debug_cfg + = {data + debug_cfg_offset, 0, header->debug_cfg_size}; + struct lto_input_block debug_main + = {data + debug_main_offset, 0, header->debug_main_size}; + + lto_debug_context.out = lto_debug_in_fun; + lto_debug_context.indent = 0; +#endif + + lto_ref *in_field_decls = (lto_ref*)(data + fields_offset); + lto_ref *in_fn_decls = (lto_ref*)(data + fns_offset); + lto_ref *in_var_decls = (lto_ref*)(data + vars_offset); + lto_ref *in_type_decls = (lto_ref*)(data + type_decls_offset); + lto_ref *in_types = (lto_ref*)(data + types_offset); + + struct lto_input_block ib_named_labels + = {data + named_label_offset, 0, header->named_label_size}; + struct lto_input_block ib_ssa_names + = {data + ssa_names_offset, 0, header->ssa_names_size}; + struct lto_input_block ib_cfg + = {data + cfg_offset, 0, header->cfg_size}; + struct lto_input_block ib_local_decls_index + = {data + local_decls_index_offset, 0, header->local_decls_index_size}; + struct lto_input_block ib_local_decls + = {data + local_decls_offset, 0, header->local_decls_size}; + struct lto_input_block ib_main + = {data + main_offset, 0, header->main_size}; + + memset (&data_in, 0, sizeof (struct data_in)); + data_in.strings = data + string_offset; + data_in.strings_len = header->string_size; + + lto_static_init_local (); + + /* No upward compatibility here. */ + gcc_assert (header->major_version == LTO_major_version); + gcc_assert (header->minor_version == LTO_minor_version); + + input_globals (header, fd, context, &data_in, + in_field_decls, in_fn_decls, + in_var_decls, in_type_decls, in_types); + + if (in_function) + { + struct function *fn = DECL_STRUCT_FUNCTION (t); + push_cfun (fn); + init_tree_ssa (fn); + data_in.num_named_labels = header->num_named_labels; + +#ifdef LTO_STREAM_DEBUGGING + lto_debug_context.current_data = &debug_label; +#endif + input_labels (&ib_named_labels, &data_in, + header->num_named_labels, header->num_unnamed_labels); + +#ifdef LTO_STREAM_DEBUGGING + lto_debug_context.current_data = &debug_decl_index; +#endif + input_local_vars_index (&ib_local_decls_index, &data_in, header->num_local_decls); + +#ifdef LTO_STREAM_DEBUGGING + lto_debug_context.current_data = &debug_decl; +#endif + input_local_vars (&ib_local_decls, &data_in, fn, header->num_local_decls); + +#ifdef LTO_STREAM_DEBUGGING + lto_debug_context.current_data = &debug_ssa_names; +#endif + input_ssa_names (&ib_ssa_names, &data_in, fn); + +#ifdef LTO_STREAM_DEBUGGING + lto_debug_context.current_data = &debug_cfg; +#endif + input_cfg (&ib_cfg, fn); + + /* Ensure that all our variables have annotations attached to them + so building SSA doesn't choke. */ + { + int i; + + for (i = 0; i < header->num_var_decls; i++) + add_referenced_var (data_in.var_decls[i]); + for (i =0; i < header->num_local_decls; i++) + add_referenced_var (data_in.local_decls[i]); + } + +#ifdef LTO_STREAM_DEBUGGING + lto_debug_context.current_data = &debug_main; +#endif + /* Set up the struct function. */ + input_function (t, &data_in, &ib_main); + + /* We should now be in SSA. */ + cfun->gimple_df->in_ssa_p = true; + /* Fill in properties we know hold for the rebuilt CFG. */ + cfun->curr_properties = PROP_ssa; + + pop_cfun (); + } + else + { +#ifdef LTO_STREAM_DEBUGGING + lto_debug_context.current_data = &debug_main; +#endif + input_constructor (t, &data_in, &ib_main); + } + + clear_line_info (&data_in); + free (data_in.field_decls); + free (data_in.fn_decls); + free (data_in.var_decls); + free (data_in.type_decls); + free (data_in.types); + if (in_function) + { + free (data_in.labels); + free (data_in.local_decls_index); + free (data_in.local_decls_index_d); + } +} + + +/* Read in FN_DECL using DATA. FD and CONTEXT are magic cookies. */ + +void +lto_read_function_body (lto_info_fd *fd, + lto_context *context, + tree fn_decl, + const void *data) +{ + current_function_decl = fn_decl; + lto_read_body (fd, context, fn_decl, data, true); +} + + +/* Read in VAR_DECL using DATA. FD and CONTEXT are magic cookies. */ + +void +lto_read_var_init (lto_info_fd *fd, + lto_context *context, + tree var_decl, + const void *data) +{ + lto_read_body (fd, context, var_decl, data, false); +} + diff --git a/gcc/lto/lto-read.c b/gcc/lto/lto-read.c deleted file mode 100644 index 4b3a1ce4eb7..00000000000 --- a/gcc/lto/lto-read.c +++ /dev/null @@ -1,2127 +0,0 @@ -/* Read the gimple representation of a function and it's local - variables from the memory mapped representation of a a .o file. - - Copyright 2006 Free Software Foundation, Inc. - Contributed by Kenneth Zadeck - -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 2, 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 COPYING. If not, write to -the Free Software Foundation, 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "toplev.h" -#include "tree.h" -#include "expr.h" -#include "flags.h" -#include "params.h" -#include "input.h" -#include "varray.h" -#include "hashtab.h" -#include "langhooks.h" -#include "basic-block.h" -#include "tree-iterator.h" -#include "tree-pass.h" -#include "tree-flow.h" -#include "cgraph.h" -#include "function.h" -#include "ggc.h" -#include "diagnostic.h" -#include "except.h" -#include "debug.h" -#include "vec.h" -#include "timevar.h" -#include "dwarf2asm.h" -#include "dwarf2out.h" -#include "output.h" -#include "lto-tags.h" -#include "lto.h" -#include -#include "cpplib.h" - -static enum tree_code tag_to_expr[LTO_last_tag]; - -/* The number of flags that are defined for each tree code. */ -static int flags_length_for_code[NUM_TREE_CODES]; - -struct data_in -{ - tree *field_decls; /* The field decls. */ - tree *fn_decls; /* The function decls. */ - tree *var_decls; /* The global or static var_decls. */ - tree *type_decls; /* The type_decls. */ - tree *types; /* All of the types. */ - int *local_decls_index; /* The offsets to decode the local_decls. */ - int *unexpanded_indexes; /* A table to reconstruct the unexpanded_vars_list. */ -#ifdef LTO_STREAM_DEBUGGING - int *local_decls_index_d; /* The offsets to decode the local_decls debug info. */ -#endif - tree *local_decls; /* The local var_decls and the parm_decls. */ - tree *labels; /* All of the labels. */ - const char * strings; /* The string table. */ - unsigned int strings_len; /* The length of the string table. */ - /* Number of named labels. Used to find the index of unnamed labels - since they share space with the named labels. */ - unsigned int num_named_labels; - const char *current_file; - int current_line; -#ifdef USE_MAPPED_LOCATION - int current_col; -#endif -}; - - - -/* This hash table is used to hash the file names in the - source_location field. Unlike other structures here, this is a - persistent structure whose data lives for the entire - compilation. */ - -struct string_slot { - const char *s; - unsigned int slot_num; -}; - - -/* Returns a hash code for P. */ - -static hashval_t -hash_string_slot_node (const void *p) -{ - const struct string_slot *ds = (const struct string_slot *) p; - return (hashval_t) htab_hash_string (ds->s); -} - - -/* Returns nonzero if P1 and P2 are equal. */ - -static int -eq_string_slot_node (const void *p1, const void *p2) -{ - const struct string_slot *ds1 = - (const struct string_slot *) p1; - const struct string_slot *ds2 = - (const struct string_slot *) p2; - - return strcmp (ds1->s, ds2->s) == 0; -} - -/* The table to hold the file_names. */ -static htab_t file_name_hash_table; - -struct input_block -{ - const char *data; - unsigned int p; - unsigned int len; -}; - - -#ifdef LTO_STREAM_DEBUGGING -static struct lto_debug_context lto_debug_context; -static void debug_out_fun (struct lto_debug_context *, char); -static void dump_debug_stream (struct input_block *, char, char); -#endif - -static tree -input_expr_operand (struct input_block *, struct data_in *, struct function *, - enum LTO_tags); -static tree -input_local_var (struct input_block *, struct data_in *, struct function *, unsigned int i); - - -/* Return the next character of input from IB. Abort if you - overrun. */ - -static unsigned char -input_1_unsigned (struct input_block *ib) -{ - gcc_assert (ib->p < ib->len); - return (ib->data[ib->p++]); -} - - -/* Read an ULEB128 Number of IB. */ - -static unsigned HOST_WIDE_INT -input_uleb128 (struct input_block *ib) -{ - unsigned HOST_WIDE_INT result = 0; - int shift = 0; - unsigned HOST_WIDE_INT byte; - - while (true) - { - byte = input_1_unsigned (ib); - result |= (byte & 0x7f) << shift; - shift += 7; - if ((byte & 0x80) == 0) - { - LTO_DEBUG_WIDE ("U", result); - return result; - } - } -} - -/* HOST_WIDEST_INT version of input_uleb128. IB is as in input_uleb128. */ - -static unsigned HOST_WIDEST_INT -input_widest_uint_uleb128 (struct input_block *ib) -{ - unsigned HOST_WIDEST_INT result = 0; - int shift = 0; - unsigned HOST_WIDEST_INT byte; - - while (true) - { - byte = input_1_unsigned (ib); - result |= (byte & 0x7f) << shift; - shift += 7; - if ((byte & 0x80) == 0) - { - LTO_DEBUG_WIDE ("U", result); - return result; - } - } -} - -/* Read an SLEB128 Number of IB. */ - -static HOST_WIDE_INT -input_sleb128 (struct input_block *ib) -{ - HOST_WIDE_INT result = 0; - int shift = 0; - unsigned HOST_WIDE_INT byte; - - while (true) - { - byte = input_1_unsigned (ib); - result |= (byte & 0x7f) << shift; - shift += 7; - if ((byte & 0x80) == 0) - { - if ((shift < HOST_BITS_PER_WIDE_INT) && (byte & 0x40)) - result |= - ((HOST_WIDE_INT)1 << shift); - - LTO_DEBUG_WIDE ("S", result); - return result; - } - } -} - - -/* Read the string at LOC from the string table in DATA_IN. */ - -static const char * -input_string_internal (struct data_in *data_in, unsigned int loc, - unsigned int *rlen) -{ - struct input_block str_tab - = {data_in->strings, loc, data_in->strings_len}; - unsigned int len = input_uleb128 (&str_tab); - const char * result; - - *rlen = len; - gcc_assert (str_tab.p + len <= data_in->strings_len); - - result = (const char *)(data_in->strings + str_tab.p); - LTO_DEBUG_STRING (result, len); - return result; -} - - -/* Read a STRING_CST at LOC from the string table in DATA_IN. */ - -static tree -input_string (struct data_in *data_in, unsigned int loc) -{ - unsigned int len; - const char * ptr = input_string_internal (data_in, loc, &len); - return build_string (len, ptr); -} - - -/* Input a real constant of TYPE at LOC. */ - -static tree -input_real (struct input_block *ib, struct data_in *data_in, tree type) -{ - unsigned int loc; - unsigned int len; - const char * str; - REAL_VALUE_TYPE value; - static char buffer[1000]; - - LTO_DEBUG_TOKEN ("real"); - loc = input_uleb128 (ib); - str = input_string_internal (data_in, loc, &len); - /* Copy over to make sure real_from_string doesn't see peculiar - trailing characters in the exponent. */ - memcpy (buffer, str, len); - buffer[len] = '\0'; - real_from_string (&value, buffer); - return build_real (type, value); -} - - -/* Input the next integer constant of TYPE in IB. */ - -static tree -input_integer (struct input_block *ib, tree type) -{ - HOST_WIDE_INT low = 0; - HOST_WIDE_INT high = 0; - int shift = 0; - unsigned HOST_WIDE_INT byte; - - while (true) - { - byte = input_1_unsigned (ib); - if (shift < HOST_BITS_PER_WIDE_INT - 7) - /* Working on the low part. */ - low |= (byte & 0x7f) << shift; - else if (shift >= HOST_BITS_PER_WIDE_INT) - /* Working on the high part. */ - high |= (byte & 0x7f) << (shift - HOST_BITS_PER_WIDE_INT); - else - { - /* Working on the transition between the low and high parts. */ - low |= (byte & 0x7f) << shift; - high |= (byte & 0x7f) >> (HOST_BITS_PER_WIDE_INT - shift); - } - - shift += 7; - if ((byte & 0x80) == 0) - { - if (byte & 0x40) - { - /* The number is negative. */ - if (shift < HOST_BITS_PER_WIDE_INT) - { - low |= - ((HOST_WIDE_INT)1 << shift); - high = -1; - } - else if (shift < (2 * HOST_BITS_PER_WIDE_INT)) - high |= - ((HOST_WIDE_INT)1 << (shift - HOST_BITS_PER_WIDE_INT)); - } - -#ifdef LTO_STREAM_DEBUGGING - /* Have to match the quick out in the lto writer. */ - if (((high == -1) && (low < 0)) - || ((high == 0) && (low >= 0))) - LTO_DEBUG_WIDE ("S", low); - else - LTO_DEBUG_INTEGER ("SS", high, low); -#endif - return build_int_cst_wide (type, low, high); - } - } -} - - -/* Return the next tag in the input block IB. */ - -static enum LTO_tags -input_record_start (struct input_block *ib) -{ - enum LTO_tags tag = input_1_unsigned (ib); - -#ifdef LTO_STREAM_DEBUGGING - if (tag) - LTO_DEBUG_INDENT (tag); - else - LTO_DEBUG_WIDE ("U", 0); -#endif - return tag; -} - - -/* Get the label referenced by the next token in IB. */ - -static tree -get_label_decl (struct data_in *data_in, struct input_block *ib) -{ - int index = input_sleb128 (ib); - if (index >= 0) - return data_in->labels[index]; - else - return data_in->labels[data_in->num_named_labels - index]; -} - - -/* Get the type referenced by the next token in IB. */ - -static tree -input_type_ref (struct data_in *data_in, struct input_block *ib) -{ - int index; - - LTO_DEBUG_TOKEN ("type"); - index = input_uleb128 (ib); - return data_in->types[index]; -} - -/* Set all of the FLAGS for NODE. */ -#define CLEAROUT (BITS_PER_LTO_FLAGS_TYPE - 1) - - -/* Read the tree flags for CODE from IB. */ - -static lto_flags_type -input_tree_flags (struct input_block *ib, enum tree_code code, bool force) -{ - lto_flags_type flags; - - if (force || TEST_BIT (lto_flags_needed_for, code)) - { - LTO_DEBUG_TOKEN ("flags"); - flags = input_widest_uint_uleb128 (ib); - LTO_DEBUG_TREE_FLAGS (code, flags); - } - else - flags = 0; - return flags; -} - - -/* Set all of the flag bits inside EXPR by unpacking FLAGS. */ - -static void -process_tree_flags (tree expr, lto_flags_type flags) -{ - enum tree_code code = TREE_CODE (expr); - /* Shift the flags up so that the first flag is at the top of the - flag word. */ - flags <<= BITS_PER_LTO_FLAGS_TYPE - flags_length_for_code[code]; - -#define START_CLASS_SWITCH() \ - { \ - \ - switch (TREE_CODE_CLASS (code)) \ - { - -#define START_CLASS_CASE(class) case class: -#define ADD_CLASS_DECL_FLAG(flag_name) \ - { expr->decl_common. flag_name = flags >> CLEAROUT; flags <<= 1; } -#define ADD_CLASS_EXPR_FLAG(flag_name) \ - { expr->base. flag_name = flags >> CLEAROUT; flags <<= 1; } -#define END_CLASS_CASE(class) break; -#define END_CLASS_SWITCH() \ - default: \ - gcc_unreachable (); \ - } - - -#define START_EXPR_SWITCH() \ - switch (code) \ - { -#define START_EXPR_CASE(code) case code: -#define ADD_EXPR_FLAG(flag_name) \ - { expr->base. flag_name = (flags >> CLEAROUT); flags <<= 1; } -#define ADD_DECL_FLAG(flag_name) \ - { expr->decl_common. flag_name = flags >> CLEAROUT; flags <<= 1; } -#define ADD_VIS_FLAG(flag_name) \ - { expr->decl_with_vis. flag_name = (flags >> CLEAROUT); flags <<= 1; } -#define ADD_VIS_FLAG_SIZE(flag_name,size) \ - { expr->decl_with_vis. flag_name = (flags >> (BITS_PER_LTO_FLAGS_TYPE - size)); flags <<= size; } -#define END_EXPR_CASE(class) break; -#define END_EXPR_SWITCH() \ - default: \ - gcc_unreachable (); \ - } \ - } - -#include "lto-tree-flags.def" - -#undef START_CLASS_SWITCH -#undef START_CLASS_CASE -#undef ADD_CLASS_DECL_FLAG -#undef ADD_CLASS_EXPR_FLAG -#undef END_CLASS_CASE -#undef END_CLASS_SWITCH -#undef START_EXPR_SWITCH -#undef START_EXPR_CASE -#undef ADD_EXPR_FLAG -#undef ADD_DECL_FLAG -#undef ADD_VIS_FLAG -#undef ADD_VIS_FLAG_SIZE -#undef END_EXPR_CASE -#undef END_EXPR_SWITCH -} - - -/* Return the one true copy of STRING. */ - -static const char * -canon_file_name (const char *string) -{ - void **slot; - struct string_slot s_slot; - s_slot.s = string; - - slot = htab_find_slot (file_name_hash_table, &s_slot, INSERT); - if (*slot == NULL) - { - size_t len = strlen (string); - char * saved_string = xmalloc (len + 1); - strcpy (saved_string, string); - - struct string_slot *new_slot - = xmalloc (sizeof (struct string_slot)); - - new_slot->s = saved_string; - *slot = new_slot; - return saved_string; - } - else - { - struct string_slot *old_slot = (struct string_slot *)*slot; - return old_slot->s; - } -} - - -/* Based on the FLAGS, read in a file, a line and a col into the - fields in DATA_IN. */ - -static bool -input_line_info (struct input_block *ib, struct data_in *data_in, - lto_flags_type flags) -{ -#ifdef USE_MAPPED_LOCATION - if (flags & LTO_SOURCE_FILE) - { - unsigned int len; - if (data_in->current_file) - linemap_add (line_table, LC_LEAVE, false, NULL, 0); - - LTO_DEBUG_TOKEN ("file"); - data_in->current_file - = canon_file_name (input_string_internal (data_in, input_uleb128 (ib), &len)); - } - if (flags & LTO_SOURCE_LINE) - { - LTO_DEBUG_TOKEN ("line"); - data_in->current_line = input_uleb128 (ib); - - if (!(flags & LTO_SOURCE_FILE)) - linemap_line_start (line_table, data_in->current_line, 80); - } - if (flags & LTO_SOURCE_FILE) - linemap_add (line_table, LC_ENTER, false, data_in->current_file, data_in->current_line); - - if (flags & LTO_SOURCE_COL) - { - LTO_DEBUG_TOKEN ("col"); - data_in->current_col = input_uleb128 (ib); - } -#else - if (flags & LTO_SOURCE_FILE) - { - unsigned int len; - LTO_DEBUG_TOKEN ("file"); - data_in->current_file - = input_string_internal (data_in, input_uleb128 (ib), &len); - } - if (flags & LTO_SOURCE_LINE) - { - LTO_DEBUG_TOKEN ("line"); - data_in->current_line = input_uleb128 (ib); - } -#endif - return (flags & LTO_SOURCE_HAS_LOC) != 0; -} - - -/* Set the line info stored in DATA_IN for NODE. */ - -static void -set_line_info (struct data_in *data_in, tree node) -{ -#ifdef USE_MAPPED_LOCATION - if (EXPR_P (node)) - LINEMAP_POSITION_FOR_COLUMN (EXPR_CHECK (node)->exp.locus, line_table, data_in->current_col) - else if (GIMPLE_STMT_P (node)) - LINEMAP_POSITION_FOR_COLUMN (GIMPLE_STMT_LOCUS (node), line_table, data_in->current_col) - else if (DECL_P (node)) - LINEMAP_POSITION_FOR_COLUMN (DECL_SOURCE_LOCATION (node), line_table, data_in->current_col) -#else - if (EXPR_P (node) || GIMPLE_STMT_P (node)) - annotate_with_file_line (node, - canon_file_name (data_in->current_file), - data_in->current_line); - else if (DECL_P (node)) - { - DECL_SOURCE_LOCATION (node).file = canon_file_name (data_in->current_file); - DECL_SOURCE_LOCATION (node).line = data_in->current_line; - } -#endif -} - - -/* Clear the line info stored in DATA_IN. */ - -static void -clear_line_info (struct data_in *data_in) -{ -#ifdef USE_MAPPED_LOCATION - if (data_in->current_file) - linemap_add (line_table, LC_LEAVE, false, NULL, 0); - data_in->current_col = 0; -#endif - data_in->current_file = NULL; - data_in->current_line = 0; -} - - -/* Read a node in the gimple tree from IB. The TAG has already been - read. */ - -static tree -input_expr_operand (struct input_block *ib, struct data_in *data_in, - struct function *fn, enum LTO_tags tag) -{ - enum tree_code code = tag_to_expr[tag]; - tree type = NULL_TREE; - lto_flags_type flags; - gcc_assert (code); - tree result = NULL_TREE; - bool needs_line_set = false; - - if (TEST_BIT (lto_types_needed_for, code)) - type = input_type_ref (data_in, ib); - - flags = input_tree_flags (ib, code, false); - - if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)) - || IS_GIMPLE_STMT_CODE_CLASS(TREE_CODE_CLASS (code))) - needs_line_set = input_line_info (ib, data_in, flags); - - switch (code) - { - case COMPLEX_CST: - { - tree elt_type = input_type_ref (data_in, ib); - - result = build0 (code, type); - if (tag == LTO_complex_cst1) - { - TREE_REALPART (result) = input_real (ib, data_in, elt_type); - TREE_IMAGPART (result) = input_real (ib, data_in, elt_type); - } - else - { - TREE_REALPART (result) = input_integer (ib, elt_type); - TREE_IMAGPART (result) = input_integer (ib, elt_type); - } - } - break; - - case INTEGER_CST: - result = input_integer (ib, type); - break; - - case REAL_CST: - result = input_real (ib, data_in, type); - break; - - case STRING_CST: - result = input_string (data_in, input_uleb128 (ib)); - TREE_TYPE (result) = type; - break; - - case IDENTIFIER_NODE: - { - unsigned int len; - const char * ptr = input_string_internal (data_in, input_uleb128 (ib), &len); - result = get_identifier_with_length (ptr, len); - } - break; - - case VECTOR_CST: - { - tree chain = NULL_TREE; - int len = input_uleb128 (ib); - tree elt_type = input_type_ref (data_in, ib); - - if (len && tag == LTO_vector_cst1) - { - int i; - tree last - = build_tree_list (NULL_TREE, input_real (ib, data_in, elt_type)); - chain = last; - for (i = 1; i < len; i++) - { - tree t - = build_tree_list (NULL_TREE, input_real (ib, data_in, elt_type)); - TREE_CHAIN (last) = t; - last = t; - } - } - else - { - int i; - tree last = build_tree_list (NULL_TREE, input_integer (ib, elt_type)); - chain = last; - for (i = 1; i < len; i++) - { - tree t - = build_tree_list (NULL_TREE, input_integer (ib, elt_type)); - TREE_CHAIN (last) = t; - last = t; - } - } - result = build_vector (type, chain); - } - break; - - case CASE_LABEL_EXPR: - { - int variant = tag - LTO_case_label_expr0; - tree op0 = NULL_TREE; - tree op1 = NULL_TREE; - - if (variant & 0x1) - op0 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - - if (variant & 0x2) - op1 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - - result = build3 (code, void_type_node, - op0, op1, get_label_decl (data_in, ib)); - } - break; - - case CONSTRUCTOR: - { - VEC(constructor_elt,gc) *vec = NULL; - unsigned int len = input_uleb128 (ib); - - if (len) - { - unsigned int i = 0; - vec = VEC_alloc (constructor_elt, gc, len); - for (i = 0; i < len; i++) - { - tree purpose = NULL_TREE; - tree value; - constructor_elt *elt; - enum LTO_tags ctag = input_record_start (ib); - - if (ctag) - purpose = input_expr_operand (ib, data_in, fn, ctag); - - value = input_expr_operand (ib, data_in, fn, input_record_start (ib)); - elt = VEC_quick_push (constructor_elt, vec, NULL); - elt->index = purpose; - elt->value = value; - } - } - result = build_constructor (type, vec); - } - break; - - case SSA_NAME: - result = VEC_index (tree, SSANAMES (fn), input_uleb128 (ib)); - add_referenced_var (SSA_NAME_VAR (result)); - break; - - case CONST_DECL: - /* Just ignore these, Mark will make them disappear. */ - break; - - case FIELD_DECL: - result = data_in->field_decls [input_uleb128 (ib)]; - break; - - case FUNCTION_DECL: - result = data_in->fn_decls [input_uleb128 (ib)]; - gcc_assert (result); - break; - - case TYPE_DECL: - result = data_in->type_decls [input_uleb128 (ib)]; - gcc_assert (result); - break; - - case VAR_DECL: - case PARM_DECL: - if (tag == LTO_var_decl1) - { - /* Static or externs are here. */ - result = data_in->var_decls [input_uleb128 (ib)]; - varpool_mark_needed_node (varpool_node (result)); - } - else - { - /* Locals are here. */ - int lv_index = input_uleb128 (ib); - result = data_in->local_decls [lv_index]; - if (result == NULL) - { - /* Create a context to read the local variable so that - it does not disturb the position of the code that is - calling for the local variable. This allows locals - to refer to other locals. */ - struct input_block lib; - -#ifdef LTO_STREAM_DEBUGGING - struct input_block *current = lto_debug_context.current_data; - struct input_block debug; - int current_indent = lto_debug_context.indent; - - debug.data = current->data; - debug.len = current->len; - debug.p = data_in->local_decls_index_d[lv_index]; - - lto_debug_context.indent = 0; - lto_debug_context.current_data = &debug; -#endif - lib.data = ib->data; - lib.len = ib->len; - lib.p = data_in->local_decls_index[lv_index]; - - result = input_local_var (&lib, data_in, fn, lv_index); - data_in->local_decls [lv_index] = result; - -#ifdef LTO_STREAM_DEBUGGING - lto_debug_context.indent = current_indent; - lto_debug_context.current_data = current; -#endif - - } - } - break; - - case LABEL_DECL: - result = get_label_decl (data_in, ib); - break; - - case LABEL_EXPR: - result = build1 (code, void_type_node, get_label_decl (data_in, ib)); - if (!DECL_CONTEXT (LABEL_EXPR_LABEL (result))) - DECL_CONTEXT (LABEL_EXPR_LABEL (result)) = fn->decl; - break; - - case COND_EXPR: - if (tag == LTO_cond_expr0) - { - tree op0; - tree op1; - tree op2; - op0 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - op1 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - op2 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - result = build3 (code, type, op0, op1, op2); - } - else - { - tree op0; - op0 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - result = build3 (code, type, op0, NULL, NULL); - } - break; - - - case RESULT_DECL: - result = DECL_RESULT (current_function_decl); - add_referenced_var (result); - break; - - case COMPONENT_REF: - { - tree op0; - tree op1; - op0 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - op1 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - - /* Ignore 3 because it can be recomputed. */ - result = build3 (code, type, op0, op1, NULL_TREE); - } - break; - - case CALL_EXPR: - { - unsigned int i; - unsigned int count = input_uleb128 (ib); - tree op1; - tree op2 = NULL_TREE; - - /* The call chain. */ - if (tag == LTO_call_expr1) - op2 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - - /* The callee. */ - op1 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - - result = build_vl_exp (code, count); - CALL_EXPR_FN (result) = op1; - CALL_EXPR_STATIC_CHAIN (result) = op2; - for (i = 3; i < count; i++) - TREE_OPERAND (result, i) - = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - TREE_TYPE (result) = type; - } - break; - - case BIT_FIELD_REF: - { - tree op0; - tree op1; - tree op2; - if (tag == LTO_bit_field_ref1) - { - op1 = build_int_cst_wide (sizetype, input_uleb128 (ib), 0); - op2 = build_int_cst_wide (bitsizetype, input_uleb128 (ib), 0); - op0 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - } - else - { - op0 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - op1 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - op2 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - } - result = build3 (code, type, op0, op1, op2); - } - break; - - case ARRAY_REF: - case ARRAY_RANGE_REF: - /* Ignore operands 2 and 3 for ARRAY_REF and ARRAY_RANGE REF - because they can be recomputed. */ - { - tree op0 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - tree op1 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - result = build4 (code, type, op0, op1, NULL_TREE, NULL_TREE); - } - break; - - case ASM_EXPR: - { - tree str = input_string (data_in, input_uleb128 (ib)); - tree ins = NULL_TREE; - tree outs = NULL_TREE; - tree clobbers = NULL_TREE; - tree tl; - - tag = input_record_start (ib); - if (tag) - ins = input_expr_operand (ib, data_in, fn, tag); - tag = input_record_start (ib); - if (tag) - outs = input_expr_operand (ib, data_in, fn, tag); - tag = input_record_start (ib); - if (tag) - clobbers = input_expr_operand (ib, data_in, fn, tag); - - result = build4 (code, void_type_node, str, outs, ins, clobbers); - - for (tl = ASM_OUTPUTS (result); tl; tl = TREE_CHAIN (tl)) - if (TREE_CODE (TREE_VALUE (tl)) == SSA_NAME) - SSA_NAME_DEF_STMT (TREE_VALUE (tl)) = result; - } - break; - - case RESX_EXPR: - result = build1 (code, void_type_node, input_integer (ib, NULL_TREE)); - break; - - case RETURN_EXPR: - switch (tag) - { - case LTO_return_expr0: - result = build1 (code, type, NULL_TREE); - break; - - case LTO_return_expr1: - { - enum LTO_tags tag = input_record_start (ib); - tree op0; - - if (tag) - op0 = input_expr_operand (ib, data_in, fn, tag); - else - { - op0 = DECL_RESULT (current_function_decl); - add_referenced_var (op0); - } - - result = build1 (code, type, op0); - - if ((TREE_CODE (op0) == GIMPLE_MODIFY_STMT) - && (TREE_CODE (GIMPLE_STMT_OPERAND (op0, 0)) == SSA_NAME)) - SSA_NAME_DEF_STMT (GIMPLE_STMT_OPERAND (op0, 0)) = result; - } - break; - - case LTO_return_expr2: - { - tree op0 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - tree op1 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - result = build1 (code, type, - build2 (MODIFY_EXPR, NULL_TREE, op0, op1)); - } - break; - - default: - gcc_unreachable (); - } - break; - - case RANGE_EXPR: - { - tree op0 = input_integer (ib, input_type_ref (data_in, ib)); - tree op1 = input_integer (ib, input_type_ref (data_in, ib)); - result = build2 (RANGE_EXPR, sizetype, op0, op1); - } - break; - - case GIMPLE_MODIFY_STMT: - { - tree op0 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - tree op1 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - - result = build_gimple_modify_stmt (op0, op1); - if (TREE_CODE (op0) == SSA_NAME) - SSA_NAME_DEF_STMT (op0) = result; - } - break; - - case SWITCH_EXPR: - { - unsigned int len = input_uleb128 (ib); - unsigned int i; - tree op0 = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - tree op2 = make_tree_vec (len); - - for (i = 0; i < len; ++i) - TREE_VEC_ELT (op2, i) - = input_expr_operand (ib, data_in, fn, - input_record_start (ib)); - result = build3 (code, type, op0, NULL_TREE, op2); - } - break; - - case TREE_LIST: - { - unsigned int count = input_uleb128 (ib); - - result = NULL_TREE; - while (count--) - { - tree value; - tree purpose; - tree next = NULL; - tree elt; - enum LTO_tags tag = input_record_start (ib); - - if (tag) - value = input_expr_operand (ib, data_in, fn, tag); - else - value = NULL_TREE; - tag = input_record_start (ib); - if (tag) - purpose = input_expr_operand (ib, data_in, fn, tag); - else - purpose = NULL_TREE; - - elt = build_tree_list (purpose, value); - if (result) - TREE_CHAIN (next) = elt; - else - /* Save the first one. */ - result = elt; - next = elt; - } - } - break; - - /* This is the default case. All of the cases that can be done - completely mechanically are done here. */ -#define SET_NAME(a,b) -#define TREE_SINGLE_MECHANICAL_TRUE -#define MAP_EXPR_TAG(expr,tag) case expr: -#include "lto-tree-tags.def" -#undef MAP_EXPR_TAG -#undef TREE_SINGLE_MECHANICAL_TRUE -#undef SET_NAME - { - tree ops[7]; - int len = TREE_CODE_LENGTH (code); - int i; - for (i = 0; ifield_decls = xcalloc (header->num_field_decls, sizeof (tree*)); - data_in->fn_decls = xcalloc (header->num_fn_decls, sizeof (tree*)); - data_in->var_decls = xcalloc (header->num_var_decls, sizeof (tree*)); - data_in->type_decls = xcalloc (header->num_type_decls, sizeof (tree*)); - data_in->types = xcalloc (header->num_types, sizeof (tree*)); - - for (i=0; inum_field_decls; i++) - data_in->field_decls[i] - = lto_resolve_field_ref (fd, context, &in_field_decls[i]); - - for (i=0; inum_fn_decls; i++) - data_in->fn_decls[i] - = lto_resolve_fn_ref (fd, context, &in_fn_decls[i]); - - for (i=0; inum_var_decls; i++) - data_in->var_decls[i] - = lto_resolve_var_ref (fd, context, &in_var_decls[i]); - - for (i=0; inum_type_decls; i++) - data_in->type_decls[i] - = lto_resolve_typedecl_ref (fd, context, &in_type_decls[i]); - - for (i=0; inum_types; i++) - data_in->types[i] = lto_resolve_type_ref (fd, context, &in_types[i]); -} - - -/* Load NAMED_COUNT named labels and constuct UNNAMED_COUNT unnamed - labels from DATA segment SIZE bytes long using DATA_IN. */ - -static void -input_labels (struct input_block *ib, struct data_in *data_in, - unsigned int named_count, unsigned int unnamed_count) -{ - unsigned int i; - - clear_line_info (data_in); - /* The named and unnamed labels share the same array. In the lto - code, the unnamed labels have a negative index. Their position - in the array can be found by subtracting that index from the - number of named labels. */ - data_in->labels = xcalloc (named_count + unnamed_count, sizeof (tree*)); - for (i = 0; i < named_count; i++) - { - unsigned int name_index = input_uleb128 (ib); - unsigned int len; - const char *s = input_string_internal (data_in, name_index, &len); - tree name = get_identifier_with_length (s, len); - data_in->labels[i] = build_decl (LABEL_DECL, name, void_type_node); - } - - for (i = 0; i < unnamed_count; i++) - data_in->labels[i + named_count] - = build_decl (LABEL_DECL, NULL_TREE, void_type_node); - } - - -/* Input the local var index table. */ - - -static void -input_local_vars_index (struct input_block *ib, struct data_in *data_in, - unsigned int count) -{ - unsigned int i; - data_in->local_decls_index = xcalloc (count, sizeof (unsigned int)); -#ifdef LTO_STREAM_DEBUGGING - data_in->local_decls_index_d = xcalloc (count, sizeof (unsigned int)); -#endif - - for (i = 0; i < count; i++) - { - data_in->local_decls_index[i] = input_uleb128 (ib); -#ifdef LTO_STREAM_DEBUGGING - data_in->local_decls_index_d[i] = input_uleb128 (ib); -#endif - } -} - - -/* Input local var I for FN from IB. */ - -static tree -input_local_var (struct input_block *ib, struct data_in *data_in, - struct function *fn, unsigned int i) -{ - enum LTO_tags tag; - unsigned int variant; - bool is_var; - unsigned int name_index; - tree name; - tree type; - lto_flags_type flags; - tree result; - tree context; - - /* The line number info needs to be reset for each local var since - they are read in random order. */ - clear_line_info (data_in); - - tag = input_record_start (ib); - variant = tag & 0xF; - is_var = ((tag & 0xFFF0) == LTO_local_var_decl_body0); - - name_index = input_uleb128 (ib); - if (name_index) - { - unsigned int len; - const char *s = input_string_internal (data_in, name_index, &len); - name = get_identifier_with_length (s, len); - } - else - name = NULL_TREE; - - type = input_type_ref (data_in, ib); - gcc_assert (type); - - if (is_var) - result = build_decl (VAR_DECL, name, type); - else - result = build_decl (PARM_DECL, name, type); - - data_in->local_decls[i] = result; - - if (is_var) - { - int index; - - LTO_DEBUG_INDENT_TOKEN ("init"); - tag = input_record_start (ib); - if (tag) - DECL_INITIAL (result) = input_expr_operand (ib, data_in, fn, tag); - - LTO_DEBUG_INDENT_TOKEN ("unexpanded index"); - index = input_sleb128 (ib); - if (index != -1) - data_in->unexpanded_indexes[index] = i; - } - else - { - DECL_ARG_TYPE (result) = input_type_ref (data_in, ib); - LTO_DEBUG_TOKEN ("chain"); - tag = input_record_start (ib); - if (tag) - TREE_CHAIN (result) = input_expr_operand (ib, data_in, fn, tag); - else - TREE_CHAIN (result) = NULL_TREE; - } - - - flags = input_tree_flags (ib, 0, true); - if (input_line_info (ib, data_in, flags)) - set_line_info (data_in, result); - - - LTO_DEBUG_TOKEN ("context"); - context = input_expr_operand (ib, data_in, fn, input_record_start (ib)); - if (TYPE_P (context)) - DECL_CONTEXT (result) = TYPE_NAME (context); - else - DECL_CONTEXT (result) = context; - - LTO_DEBUG_TOKEN ("align"); - DECL_ALIGN (result) = input_uleb128 (ib); - LTO_DEBUG_TOKEN ("size"); - DECL_SIZE (result) = input_expr_operand (ib, data_in, fn, input_record_start (ib)); - - if (variant & 0x1) - { - LTO_DEBUG_TOKEN ("attributes"); - DECL_ATTRIBUTES (result) - = input_expr_operand (ib, data_in, fn, input_record_start (ib)); - } - if (variant & 0x2) - DECL_SIZE_UNIT (result) - = input_expr_operand (ib, data_in, fn, input_record_start (ib)); - if (variant & 0x4) - SET_DECL_DEBUG_EXPR (result, - input_expr_operand (ib, data_in, fn, - input_record_start (ib))); - if (variant & 0x8) - DECL_ABSTRACT_ORIGIN (result) - = input_expr_operand (ib, data_in, fn, input_record_start (ib)); - - process_tree_flags (result, flags); - LTO_DEBUG_UNDENT(); - - return result; -} - - -/* Load COUNT local var_decls and parm_decls from a DATA segment SIZE - bytes long using DATA_IN. */ - -static void -input_local_vars (struct input_block *ib, struct data_in *data_in, - struct function *fn, unsigned int count) -{ - int i; - unsigned int tag; - - data_in->unexpanded_indexes = xcalloc (count, sizeof (int)); - data_in->local_decls = xcalloc (count, sizeof (tree*)); - - memset (data_in->unexpanded_indexes, -1, count * sizeof (int)); - - /* Recreate the unexpanded_var_list. Put the statics at the end.*/ - fn->unexpanded_var_list = NULL; - LTO_DEBUG_TOKEN ("local statics"); - tag = input_record_start (ib); - - while (tag) - { - tree var = input_expr_operand (ib, data_in, fn, tag); - fn->unexpanded_var_list - = tree_cons (NULL_TREE, var, fn->unexpanded_var_list); - - if (input_uleb128 (ib)) - DECL_CONTEXT (var) = fn->decl; - - /* DECL_INITIAL. */ - tag = input_record_start (ib); - if (tag) - DECL_INITIAL (var) = input_expr_operand (ib, data_in, fn, tag); - - /* Statics never have external visibility. */ - DECL_EXTERNAL (var) = 0; - - /* Next static. */ - tag = input_record_start (ib); - } - - LTO_DEBUG_TOKEN ("local vars"); - for (i = 0; i < (int)count; i++) - /* Some local decls may have already been read in if they are used - as part of a previous local_decl. */ - if (!data_in->local_decls[i]) - { -#ifdef LTO_STREAM_DEBUGGING - ((struct input_block *)lto_debug_context.current_data)->p - = data_in->local_decls_index_d[i]; -#endif - ib->p = data_in->local_decls_index[i]; - input_local_var (ib, data_in, fn, i); - } - - /* Add the regular locals in the proper order. */ - for (i = count - 1; i >= 0; i--) - if (data_in->unexpanded_indexes[i] != -1) - fn->unexpanded_var_list - = tree_cons (NULL_TREE, - data_in->local_decls[data_in->unexpanded_indexes[i]], - fn->unexpanded_var_list); - - free (data_in->unexpanded_indexes); - data_in->unexpanded_indexes = NULL; -} - - -/* Read the exception table. */ - -static void -input_eh_regions (struct input_block *ib, - struct function *fn ATTRIBUTE_UNUSED, - struct data_in *data_in ATTRIBUTE_UNUSED) -{ - /* Not ready to read exception records yet. */ - input_uleb128 (ib); -} - - -/* Make a new basic block at INDEX in FN. */ - -static basic_block -make_new_block (struct function *fn, unsigned int index) -{ - basic_block bb = alloc_block (); - bb->index = index; - SET_BASIC_BLOCK_FOR_FUNCTION (fn, index, bb); - bb->il.tree = GGC_CNEW (struct tree_bb_info); - n_basic_blocks_for_function (fn)++; - bb->flags = 0; - set_bb_stmt_list (bb, alloc_stmt_list ()); - return bb; -} - - -/* Set up the cfg for THIS_FUN. */ - -static void -input_cfg (struct input_block *ib, struct function *fn) -{ - unsigned int bb_count; - basic_block p_bb; - unsigned int i; - int index; - - init_empty_tree_cfg_for_function (fn); - init_ssa_operands (); - - LTO_DEBUG_TOKEN ("lastbb"); - bb_count = input_uleb128 (ib); - - last_basic_block_for_function (fn) = bb_count; - if (bb_count > VEC_length (basic_block, - basic_block_info_for_function (fn))) - VEC_safe_grow_cleared (basic_block, gc, - basic_block_info_for_function (fn), bb_count); - if (bb_count > VEC_length (basic_block, - label_to_block_map_for_function (fn))) - VEC_safe_grow_cleared (basic_block, gc, - label_to_block_map_for_function (fn), bb_count); - - LTO_DEBUG_TOKEN ("bbindex"); - index = input_sleb128 (ib); - while (index != -1) - { - basic_block bb = BASIC_BLOCK_FOR_FUNCTION (fn, index); - unsigned int edge_count; - - if (bb == NULL) - bb = make_new_block (fn, index); - - LTO_DEBUG_TOKEN ("edgecount"); - edge_count = input_uleb128 (ib); - - /* Connect up the cfg. */ - for (i = 0; i < edge_count; i++) - { - unsigned int dest_index; - unsigned int edge_flags; - basic_block dest; - - LTO_DEBUG_TOKEN ("dest"); - dest_index = input_uleb128 (ib); - LTO_DEBUG_TOKEN ("eflags"); - edge_flags = input_uleb128 (ib); - dest = BASIC_BLOCK_FOR_FUNCTION (fn, dest_index); - - if (dest == NULL) - dest = make_new_block (fn, dest_index); - make_edge (bb, dest, edge_flags); - } - - LTO_DEBUG_TOKEN ("bbindex"); - index = input_sleb128 (ib); - } - - p_bb = ENTRY_BLOCK_PTR_FOR_FUNCTION(fn); - LTO_DEBUG_TOKEN ("bbchain"); - index = input_sleb128 (ib); - while (index != -1) - { - basic_block bb = BASIC_BLOCK_FOR_FUNCTION (fn, index); - bb->prev_bb = p_bb; - p_bb->next_bb = bb; - p_bb = bb; - LTO_DEBUG_TOKEN ("bbchain"); - index = input_sleb128 (ib); - } -} - - -/* Input the next phi function for BB. */ - -static tree -input_phi (struct input_block *ib, basic_block bb, - struct data_in *data_in, struct function *fn) -{ - lto_flags_type flags = input_tree_flags (ib, PHI_NODE, false); - - tree phi_result = VEC_index (tree, SSANAMES (fn), input_uleb128 (ib)); - int len = EDGE_COUNT (bb->preds); - int i; - tree result = create_phi_node (phi_result, bb); - - SSA_NAME_DEF_STMT (phi_result) = result; - - /* We have to go thru a lookup process here because the preds in the - reconstructed graph are generally in a different order than they - were in the original program. */ - for (i = 0; i < len; i++) - { - tree def = input_expr_operand (ib, data_in, fn, input_record_start (ib)); - int src_index = input_uleb128 (ib); - basic_block sbb = BASIC_BLOCK_FOR_FUNCTION (fn, src_index); - - edge e = NULL; - int j; - - for (j = 0; j < len; j++) - if (EDGE_PRED (bb, j)->src == sbb) - { - e = EDGE_PRED (bb, j); - break; - } - - add_phi_arg (result, def, e); - } - - if (flags) - process_tree_flags (result, flags); - - LTO_DEBUG_UNDENT(); - - return result; -} - - -/* Read in the ssa_names array from IB. */ - -static void -input_ssa_names (struct input_block *ib, struct data_in *data_in, struct function *fn) -{ - unsigned int i; - int size = input_uleb128 (ib); - - init_ssanames (fn, size); - i = input_uleb128 (ib); - - while (i) - { - tree ssa_name; - tree name; - lto_flags_type flags; - - /* Skip over the elements that had been freed. */ - while (VEC_length (tree, SSANAMES (fn)) < i) - VEC_quick_push (tree, SSANAMES (fn), NULL_TREE); - - name = input_expr_operand (ib, data_in, fn, input_record_start (ib)); - ssa_name = make_ssa_name (fn, name, build_empty_stmt ()); - - flags = input_tree_flags (ib, 0, true); - process_tree_flags (ssa_name, flags); - if (SSA_NAME_IS_DEFAULT_DEF (ssa_name)) - set_default_def (SSA_NAME_VAR (ssa_name), ssa_name); - i = input_uleb128 (ib); - } -} - - -/* Read in the next basic block. */ - -static void -input_bb (struct input_block *ib, enum LTO_tags tag, - struct data_in *data_in, struct function *fn) -{ - unsigned int index; - basic_block bb; - block_stmt_iterator bsi; - - LTO_DEBUG_TOKEN ("bbindex"); - index = input_uleb128 (ib); - bb = BASIC_BLOCK_FOR_FUNCTION (fn, index); - - /* LTO_bb1 has stmts, LTO_bb0 does not. */ - if (tag == LTO_bb0) - { - LTO_DEBUG_UNDENT(); - return; - } - - bsi = bsi_start (bb); - LTO_DEBUG_INDENT_TOKEN ("stmt"); - tag = input_record_start (ib); - while (tag) - { - tree stmt = input_expr_operand (ib, data_in, fn, tag); - bsi_insert_after (&bsi, stmt, BSI_NEW_STMT); - LTO_DEBUG_INDENT_TOKEN ("stmt"); - tag = input_record_start (ib); - /* FIXME, add code to handle the exception. */ - } - - LTO_DEBUG_INDENT_TOKEN ("phi"); - tag = input_record_start (ib); - while (tag) - { - input_phi (ib, bb, data_in, fn); - LTO_DEBUG_INDENT_TOKEN ("phi"); - tag = input_record_start (ib); - } - - LTO_DEBUG_UNDENT(); -} - - -/* Fill in the body of FN_DECL. */ - -static void -input_function (tree fn_decl, struct data_in *data_in, - struct input_block *ib) -{ - struct function *fn = DECL_STRUCT_FUNCTION (fn_decl); - enum LTO_tags tag = input_record_start (ib); - - DECL_INITIAL (fn_decl) = DECL_SAVED_TREE (fn_decl) = make_node (BLOCK); - BLOCK_ABSTRACT_ORIGIN (DECL_SAVED_TREE (fn_decl)) = fn_decl; - clear_line_info (data_in); - - tree_register_cfg_hooks (); - gcc_assert (tag == LTO_function); - - input_eh_regions (ib, fn, data_in); - - LTO_DEBUG_INDENT_TOKEN ("decl_arguments"); - tag = input_record_start (ib); - if (tag) - DECL_ARGUMENTS (fn_decl) = input_expr_operand (ib, data_in, fn, tag); - - LTO_DEBUG_INDENT_TOKEN ("decl_context"); - tag = input_record_start (ib); - if (tag) - DECL_CONTEXT (fn_decl) = input_expr_operand (ib, data_in, fn, tag); - - tag = input_record_start (ib); - while (tag) - { - input_bb (ib, tag, data_in, fn); - tag = input_record_start (ib); - } - - LTO_DEBUG_UNDENT(); -} - - -/* Fill in the body of VAR. */ - -static void -input_constructor (tree var, struct data_in *data_in, - struct input_block *ib) -{ - enum LTO_tags tag; - - clear_line_info (data_in); - LTO_DEBUG_INDENT_TOKEN ("init"); - tag = input_record_start (ib); - DECL_INITIAL (var) = input_expr_operand (ib, data_in, NULL, tag); -} - - -static bool initialized_local = false; - - -/* Static initialization for the lto reader. */ - -static void -lto_static_init_local (void) -{ - if (initialized_local) - return; - - initialized_local = true; - - /* Initialize the expression to tag mapping. */ -#define MAP_EXPR_TAG(expr,tag) tag_to_expr [tag] = expr; -#define MAP_EXPR_TAGS(expr,tag,count) \ - { \ - int i; \ - for (i=0; inum_field_decls * sizeof (lto_ref)); - int32_t vars_offset - = fns_offset + (header->num_fn_decls * sizeof (lto_ref)); - int32_t type_decls_offset - = vars_offset + (header->num_var_decls * sizeof (lto_ref)); - int32_t types_offset - = type_decls_offset + (header->num_type_decls * sizeof (lto_ref)); - int32_t named_label_offset - = types_offset + (header->num_types * sizeof (lto_ref)); - int32_t ssa_names_offset - = named_label_offset + header->named_label_size; - int32_t cfg_offset - = ssa_names_offset + header->ssa_names_size; - int32_t local_decls_index_offset = cfg_offset + header->cfg_size; - int32_t local_decls_offset = local_decls_index_offset + header->local_decls_index_size; - int32_t main_offset = local_decls_offset + header->local_decls_size; - int32_t string_offset = main_offset + header->main_size; - -#ifdef LTO_STREAM_DEBUGGING - int32_t debug_decl_index_offset = string_offset + header->string_size; - int32_t debug_decl_offset = debug_decl_index_offset + header->debug_decl_index_size; - int32_t debug_label_offset = debug_decl_offset + header->debug_decl_size; - int32_t debug_ssa_names_offset = debug_label_offset + header->debug_label_size; - int32_t debug_cfg_offset = debug_ssa_names_offset + header->debug_ssa_names_size; - int32_t debug_main_offset = debug_cfg_offset + header->debug_cfg_size; - - struct input_block debug_decl_index - = {data + debug_decl_index_offset, 0, header->debug_decl_index_size}; - struct input_block debug_decl - = {data + debug_decl_offset, 0, header->debug_decl_size}; - struct input_block debug_label - = {data + debug_label_offset, 0, header->debug_label_size}; - struct input_block debug_ssa_names - = {data + debug_ssa_names_offset, 0, header->debug_ssa_names_size}; - struct input_block debug_cfg - = {data + debug_cfg_offset, 0, header->debug_cfg_size}; - struct input_block debug_main - = {data + debug_main_offset, 0, header->debug_main_size}; - - lto_debug_context.out = debug_out_fun; - lto_debug_context.indent = 0; -#endif - - lto_ref *in_field_decls = (lto_ref*)(data + fields_offset); - lto_ref *in_fn_decls = (lto_ref*)(data + fns_offset); - lto_ref *in_var_decls = (lto_ref*)(data + vars_offset); - lto_ref *in_type_decls = (lto_ref*)(data + type_decls_offset); - lto_ref *in_types = (lto_ref*)(data + types_offset); - - struct input_block ib_named_labels - = {data + named_label_offset, 0, header->named_label_size}; - struct input_block ib_ssa_names - = {data + ssa_names_offset, 0, header->ssa_names_size}; - struct input_block ib_cfg - = {data + cfg_offset, 0, header->cfg_size}; - struct input_block ib_local_decls_index - = {data + local_decls_index_offset, 0, header->local_decls_index_size}; - struct input_block ib_local_decls - = {data + local_decls_offset, 0, header->local_decls_size}; - struct input_block ib_main - = {data + main_offset, 0, header->main_size}; - - memset (&data_in, 0, sizeof (struct data_in)); - data_in.strings = data + string_offset; - data_in.strings_len = header->string_size; - - lto_static_init_local (); - - /* No upward compatibility here. */ - gcc_assert (header->major_version == LTO_major_version); - gcc_assert (header->minor_version == LTO_minor_version); - - input_globals (header, fd, context, &data_in, - in_field_decls, in_fn_decls, - in_var_decls, in_type_decls, in_types); - - if (in_function) - { - struct function *fn = DECL_STRUCT_FUNCTION (t); - push_cfun (fn); - init_tree_ssa (fn); - data_in.num_named_labels = header->num_named_labels; - -#ifdef LTO_STREAM_DEBUGGING - lto_debug_context.current_data = &debug_label; -#endif - input_labels (&ib_named_labels, &data_in, - header->num_named_labels, header->num_unnamed_labels); - -#ifdef LTO_STREAM_DEBUGGING - lto_debug_context.current_data = &debug_decl_index; -#endif - input_local_vars_index (&ib_local_decls_index, &data_in, header->num_local_decls); - -#ifdef LTO_STREAM_DEBUGGING - lto_debug_context.current_data = &debug_decl; -#endif - input_local_vars (&ib_local_decls, &data_in, fn, header->num_local_decls); - -#ifdef LTO_STREAM_DEBUGGING - lto_debug_context.current_data = &debug_ssa_names; -#endif - input_ssa_names (&ib_ssa_names, &data_in, fn); - -#ifdef LTO_STREAM_DEBUGGING - lto_debug_context.current_data = &debug_cfg; -#endif - input_cfg (&ib_cfg, fn); - - /* Ensure that all our variables have annotations attached to them - so building SSA doesn't choke. */ - { - int i; - - for (i = 0; i < header->num_var_decls; i++) - add_referenced_var (data_in.var_decls[i]); - for (i =0; i < header->num_local_decls; i++) - add_referenced_var (data_in.local_decls[i]); - } - -#ifdef LTO_STREAM_DEBUGGING - lto_debug_context.current_data = &debug_main; -#endif - /* Set up the struct function. */ - input_function (t, &data_in, &ib_main); - - /* We should now be in SSA. */ - cfun->gimple_df->in_ssa_p = true; - /* Fill in properties we know hold for the rebuilt CFG. */ - cfun->curr_properties = PROP_ssa; - - pop_cfun (); - } - else - { -#ifdef LTO_STREAM_DEBUGGING - lto_debug_context.current_data = &debug_main; -#endif - input_constructor (t, &data_in, &ib_main); - } - - clear_line_info (&data_in); - free (data_in.field_decls); - free (data_in.fn_decls); - free (data_in.var_decls); - free (data_in.type_decls); - free (data_in.types); - if (in_function) - { - free (data_in.labels); - free (data_in.local_decls_index); - free (data_in.local_decls_index_d); - } -} - - -/* Read in FN_DECL using DATA. FD and CONTEXT are magic cookies. */ - -void -lto_read_function_body (lto_info_fd *fd, - lto_context *context, - tree fn_decl, - const void *data) -{ - current_function_decl = fn_decl; - lto_read_body (fd, context, fn_decl, data, true); -} - - -/* Read in VAR_DECL using DATA. FD and CONTEXT are magic cookies. */ - -void -lto_read_var_init (lto_info_fd *fd, - lto_context *context, - tree var_decl, - const void *data) -{ - lto_read_body (fd, context, var_decl, data, false); -} - -/* Dump the debug STREAM, and two characters B and C. */ - -static void -dump_debug_stream (struct input_block *stream, char b, char c) -{ - unsigned int i = 0; - bool new_line = true; - int chars = 0; - int hit_pos = -1; - fprintf (stderr, - "stream failure: looking for a '%c'[0x%x] in the debug stream.\nHowever the data translated into a '%c'[0x%x]at position%d\n\n", - c, c, b, b, stream->p); - - while (i < stream->len) - { - char x; - - if (new_line) - { - if (hit_pos >= 0) - { - int j; - fprintf (stderr, " "); - for (j=0; j>", i); - new_line = false; - chars = 0; - } - - x = stream->data[i++]; - if (x == '\n') - { - fprintf (stderr, "<<--\n"); - new_line = true; - } - else - fputc (x, stderr); - - if (i == stream->p) - hit_pos = chars; - chars++; - } -} - - -#ifdef LTO_STREAM_DEBUGGING - -/* The low level output routine to for a single character. Unlike the - version on the writing side, this does interesting processing. - - This call checks that the debugging information generated by - lto-function-out matches the debugging information generated by the - reader. Each character is checked and a call to abort is generated - when the first mismatch is found. - */ - -static void -debug_out_fun (struct lto_debug_context *context, char c) -{ - struct input_block *stream = (struct input_block *)context->current_data; - char b = input_1_unsigned (stream); - - if (b != c) - { - dump_debug_stream (stream, b, c); - gcc_unreachable (); - } -} - -#endif diff --git a/gcc/lto/lto-section-in.c b/gcc/lto/lto-section-in.c new file mode 100644 index 00000000000..e5b815e3dbd --- /dev/null +++ b/gcc/lto/lto-section-in.c @@ -0,0 +1,266 @@ +/* Input functions for reading lto sections. + + Copyright 2006, 2007, 2008 Free Software Foundation, Inc. + Contributed by Kenneth Zadeck + +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 2, 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 COPYING. If not, write to +the Free Software Foundation, 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "toplev.h" +#include "tree.h" +#include "expr.h" +#include "flags.h" +#include "params.h" +#include "input.h" +#include "varray.h" +#include "hashtab.h" +#include "langhooks.h" +#include "basic-block.h" +#include "tree-iterator.h" +#include "tree-pass.h" +#include "tree-flow.h" +#include "cgraph.h" +#include "function.h" +#include "ggc.h" +#include "diagnostic.h" +#include "except.h" +#include "debug.h" +#include "vec.h" +#include "timevar.h" +#include "dwarf2asm.h" +#include "dwarf2out.h" +#include "output.h" +#include "lto-tags.h" +#include "lto.h" +#include "lto-section-in.h" +#include +#include "cpplib.h" + +unsigned char +lto_input_1_unsigned (struct lto_input_block *ib) +{ + gcc_assert (ib->p < ib->len); + return (ib->data[ib->p++]); +} + + +/* Read an ULEB128 Number of IB. */ + +unsigned HOST_WIDE_INT +lto_input_uleb128 (struct lto_input_block *ib) +{ + unsigned HOST_WIDE_INT result = 0; + int shift = 0; + unsigned HOST_WIDE_INT byte; + + while (true) + { + byte = lto_input_1_unsigned (ib); + result |= (byte & 0x7f) << shift; + shift += 7; + if ((byte & 0x80) == 0) + { + LTO_DEBUG_WIDE ("U", result); + return result; + } + } +} + +/* HOST_WIDEST_INT version of lto_input_uleb128. IB is as in lto_input_uleb128. */ + +unsigned HOST_WIDEST_INT +lto_input_widest_uint_uleb128 (struct lto_input_block *ib) +{ + unsigned HOST_WIDEST_INT result = 0; + int shift = 0; + unsigned HOST_WIDEST_INT byte; + + while (true) + { + byte = lto_input_1_unsigned (ib); + result |= (byte & 0x7f) << shift; + shift += 7; + if ((byte & 0x80) == 0) + { + LTO_DEBUG_WIDE ("U", result); + return result; + } + } +} + +/* Read an SLEB128 Number of IB. */ + +HOST_WIDE_INT +lto_input_sleb128 (struct lto_input_block *ib) +{ + HOST_WIDE_INT result = 0; + int shift = 0; + unsigned HOST_WIDE_INT byte; + + while (true) + { + byte = lto_input_1_unsigned (ib); + result |= (byte & 0x7f) << shift; + shift += 7; + if ((byte & 0x80) == 0) + { + if ((shift < HOST_BITS_PER_WIDE_INT) && (byte & 0x40)) + result |= - ((HOST_WIDE_INT)1 << shift); + + LTO_DEBUG_WIDE ("S", result); + return result; + } + } +} + + +/* Input the next integer constant of TYPE in IB. */ + +tree +lto_input_integer (struct lto_input_block *ib, tree type) +{ + HOST_WIDE_INT low = 0; + HOST_WIDE_INT high = 0; + int shift = 0; + unsigned HOST_WIDE_INT byte; + + while (true) + { + byte = lto_input_1_unsigned (ib); + if (shift < HOST_BITS_PER_WIDE_INT - 7) + /* Working on the low part. */ + low |= (byte & 0x7f) << shift; + else if (shift >= HOST_BITS_PER_WIDE_INT) + /* Working on the high part. */ + high |= (byte & 0x7f) << (shift - HOST_BITS_PER_WIDE_INT); + else + { + /* Working on the transition between the low and high parts. */ + low |= (byte & 0x7f) << shift; + high |= (byte & 0x7f) >> (HOST_BITS_PER_WIDE_INT - shift); + } + + shift += 7; + if ((byte & 0x80) == 0) + { + if (byte & 0x40) + { + /* The number is negative. */ + if (shift < HOST_BITS_PER_WIDE_INT) + { + low |= - ((HOST_WIDE_INT)1 << shift); + high = -1; + } + else if (shift < (2 * HOST_BITS_PER_WIDE_INT)) + high |= - ((HOST_WIDE_INT)1 << (shift - HOST_BITS_PER_WIDE_INT)); + } + +#ifdef LTO_STREAM_DEBUGGING + /* Have to match the quick out in the lto writer. */ + if (((high == -1) && (low < 0)) + || ((high == 0) && (low >= 0))) + LTO_DEBUG_WIDE ("S", low); + else + LTO_DEBUG_INTEGER ("SS", high, low); +#endif + return build_int_cst_wide (type, low, high); + } + } +} + +#ifdef LTO_STREAM_DEBUGGING + +/* Dump the debug STREAM, and two characters B and C. */ + +void +dump_debug_stream (struct lto_input_block *stream, char b, char c) +{ + unsigned int i = 0; + bool new_line = true; + int chars = 0; + int hit_pos = -1; + fprintf (stderr, + "stream failure: looking for a '%c'[0x%x] in the debug stream.\nHowever the data translated into a '%c'[0x%x]at position%d\n\n", + c, c, b, b, stream->p); + + while (i < stream->len) + { + char x; + + if (new_line) + { + if (hit_pos >= 0) + { + int j; + fprintf (stderr, " "); + for (j=0; j>", i); + new_line = false; + chars = 0; + } + + x = stream->data[i++]; + if (x == '\n') + { + fprintf (stderr, "<<--\n"); + new_line = true; + } + else + fputc (x, stderr); + + if (i == stream->p) + hit_pos = chars; + chars++; + } +} + + +/* The low level output routine to for a single character. Unlike the + version on the writing side, this does interesting processing. + + This call checks that the debugging information generated by + lto-function-out matches the debugging information generated by the + reader. Each character is checked and a call to abort is generated + when the first mismatch is found. + */ + +void +lto_debug_in_fun (struct lto_debug_context *context, char c) +{ + struct lto_input_block *stream = (struct lto_input_block *)context->current_data; + char b = lto_input_1_unsigned (stream); + + if (b != c) + { + dump_debug_stream (stream, b, c); + gcc_unreachable (); + } +} + +#endif diff --git a/gcc/lto/lto-section-in.h b/gcc/lto/lto-section-in.h new file mode 100644 index 00000000000..e0b9100d25b --- /dev/null +++ b/gcc/lto/lto-section-in.h @@ -0,0 +1,42 @@ +/* LTO input code. + Copyright (C) 2007, 2008 Free Software Foundation, Inc. + Contributed by Kenneth Zadeck + +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 +. */ + +#ifndef GCC_LTO_SECTION_IN_H +#define GCC_LTO_SECTION_IN_H + +struct lto_input_block +{ + const char *data; + unsigned int p; + unsigned int len; +}; + +unsigned char lto_input_1_unsigned (struct lto_input_block *); +unsigned HOST_WIDE_INT lto_input_uleb128 (struct lto_input_block *); +unsigned HOST_WIDEST_INT lto_input_widest_uint_uleb128 (struct lto_input_block *); +HOST_WIDE_INT lto_input_sleb128 (struct lto_input_block *); +tree lto_input_integer (struct lto_input_block *, tree); + +#ifdef LTO_STREAM_DEBUGGING +void lto_debug_in_fun (struct lto_debug_context *, char); +void dump_debug_stream (struct lto_input_block *, char, char); +#endif + +#endif /* GCC_LTO_SECTION_IN_H */ -- cgit v1.2.3