diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 43cce51e977..2bc9180eb08 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2011-05-27 Jan Hubicka + + * lto-streamer-out.c (lto_string_index): break out from...; offset by 1 + so 0 means NULL string. + (lto_output_string_with_length): ... here. + (lto_output_string, output_string_cst, output_identifier): Update handling + of NULL strings. + (lto_output_location_bitpack): New function. + (lto_output_location): Use it. + (lto_output_tree_ref): Use output_record_start. + (pack_ts_type_common_value_fields): Pack aliagn & alias set in var len values. + * lto-streamer-in.c (string_for_index): Break out from ...; offset values by 1. + (input_string_internal): ... here; + (input_string_cst, input_identifier, lto_input_string): Update handling of + NULL strings. + (lto_input_location_bitpack): New function + (lto_input_location): Use it. + (unpack_ts_type_common_value_fields): Pack align & alias in var len values. + * lto-streamer.h (bp_pack_val_len_unsigned, bp_pack_val_len_int, + bp_unpack_val_len_unsigned, bp_unpack_val_len_int): Declare. + (bp_pack_value): Sanity check the value range. + * lto-section-in.c (bp_unpack_val_len_unsigned, bp_unpack_val_len_int): + New functions. + * lto-section-out.h (bp_pack_val_len_unsigned, bp_pack_val_len_int): + New functions. + 2011-05-27 Hariharan Sandanagobalane * config/picochip/picochip.c (reorder_var_tracking_notes): Drop diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c index b6277a35532..0c2c4c0f1c0 100644 --- a/gcc/lto-section-in.c +++ b/gcc/lto-section-in.c @@ -127,6 +127,51 @@ lto_input_sleb128 (struct lto_input_block *ib) } +/* Unpack VAL from BP in a variant of uleb format. */ + +unsigned HOST_WIDE_INT +bp_unpack_var_len_unsigned (struct bitpack_d *bp) +{ + unsigned HOST_WIDE_INT result = 0; + int shift = 0; + unsigned HOST_WIDE_INT half_byte; + + while (true) + { + half_byte = bp_unpack_value (bp, 4); + result |= (half_byte & 0x7) << shift; + shift += 3; + if ((half_byte & 0x8) == 0) + return result; + } +} + + +/* Unpack VAL from BP in a variant of sleb format. */ + +HOST_WIDE_INT +bp_unpack_var_len_int (struct bitpack_d *bp) +{ + HOST_WIDE_INT result = 0; + int shift = 0; + unsigned HOST_WIDE_INT half_byte; + + while (true) + { + half_byte = bp_unpack_value (bp, 4); + result |= (half_byte & 0x7) << shift; + shift += 3; + if ((half_byte & 0x8) == 0) + { + if ((shift < HOST_BITS_PER_WIDE_INT) && (half_byte & 0x4)) + result |= - ((HOST_WIDE_INT)1 << shift); + + return result; + } + } +} + + /* Hooks so that the ipa passes can call into the lto front end to get sections. */ diff --git a/gcc/lto-section-out.c b/gcc/lto-section-out.c index 234d63eaabd..55c9d8d165f 100644 --- a/gcc/lto-section-out.c +++ b/gcc/lto-section-out.c @@ -330,6 +330,48 @@ lto_output_sleb128_stream (struct lto_output_stream *obs, HOST_WIDE_INT work) } +/* Pack WORK into BP in a variant of uleb format. */ + +void +bp_pack_var_len_unsigned (struct bitpack_d *bp, unsigned HOST_WIDE_INT work) +{ + do + { + unsigned int half_byte = (work & 0x7); + work >>= 3; + if (work != 0) + /* More half_bytes to follow. */ + half_byte |= 0x8; + + bp_pack_value (bp, half_byte, 4); + } + while (work != 0); +} + + +/* Pack WORK into BP in a variant of sleb format. */ + +void +bp_pack_var_len_int (struct bitpack_d *bp, HOST_WIDE_INT work) +{ + int more, half_byte; + + do + { + half_byte = (work & 0x7); + /* arithmetic shift */ + work >>= 3; + more = !((work == 0 && (half_byte & 0x4) == 0) + || (work == -1 && (half_byte & 0x4) != 0)); + if (more) + half_byte |= 0x8; + + bp_pack_value (bp, half_byte, 4); + } + while (more); +} + + /* Lookup NAME in ENCODER. If NAME is not found, create a new entry in ENCODER for NAME with the next available index of ENCODER, then print the index to OBS. True is returned if NAME was added to diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index dd14c0cedf9..d2e4ed3ec20 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -132,19 +132,22 @@ eq_string_slot_node (const void *p1, const void *p2) IB. Write the length to RLEN. */ static const char * -input_string_internal (struct data_in *data_in, struct lto_input_block *ib, - unsigned int *rlen) +string_for_index (struct data_in *data_in, + unsigned int loc, + unsigned int *rlen) { struct lto_input_block str_tab; unsigned int len; - unsigned int loc; const char *result; - /* Read the location of the string from IB. */ - loc = lto_input_uleb128 (ib); + if (!loc) + { + *rlen = 0; + return NULL; + } /* Get the string stored at location LOC in DATA_IN->STRINGS. */ - LTO_INIT_INPUT_BLOCK (str_tab, data_in->strings, loc, data_in->strings_len); + LTO_INIT_INPUT_BLOCK (str_tab, data_in->strings, loc - 1, data_in->strings_len); len = lto_input_uleb128 (&str_tab); *rlen = len; @@ -157,6 +160,17 @@ input_string_internal (struct data_in *data_in, struct lto_input_block *ib, } +/* Read a string from the string table in DATA_IN using input block + IB. Write the length to RLEN. */ + +static const char * +input_string_internal (struct data_in *data_in, struct lto_input_block *ib, + unsigned int *rlen) +{ + return string_for_index (data_in, lto_input_uleb128 (ib), rlen); +} + + /* Read a STRING_CST from the string table in DATA_IN using input block IB. */ @@ -165,13 +179,10 @@ input_string_cst (struct data_in *data_in, struct lto_input_block *ib) { unsigned int len; const char * ptr; - unsigned int is_null; - - is_null = lto_input_uleb128 (ib); - if (is_null) - return NULL; ptr = input_string_internal (data_in, ib, &len); + if (!ptr) + return NULL; return build_string (len, ptr); } @@ -184,13 +195,10 @@ input_identifier (struct data_in *data_in, struct lto_input_block *ib) { unsigned int len; const char *ptr; - unsigned int is_null; - - is_null = lto_input_uleb128 (ib); - if (is_null) - return NULL; ptr = input_string_internal (data_in, ib, &len); + if (!ptr) + return NULL; return get_identifier_with_length (ptr, len); } @@ -215,13 +223,10 @@ lto_input_string (struct data_in *data_in, struct lto_input_block *ib) { unsigned int len; const char *ptr; - unsigned int is_null; - - is_null = lto_input_uleb128 (ib); - if (is_null) - return NULL; ptr = input_string_internal (data_in, ib, &len); + if (!ptr) + return NULL; if (ptr[len - 1] != '\0') internal_error ("bytecode stream: found non-null terminated string"); @@ -284,37 +289,57 @@ clear_line_info (struct data_in *data_in) } +/* Read a location bitpack from input block IB. */ + +static location_t +lto_input_location_bitpack (struct data_in *data_in, struct bitpack_d *bp) +{ + bool file_change, line_change, column_change; + unsigned len; + bool prev_file = data_in->current_file != NULL; + + if (bp_unpack_value (bp, 1)) + return UNKNOWN_LOCATION; + + file_change = bp_unpack_value (bp, 1); + if (file_change) + data_in->current_file = canon_file_name + (string_for_index (data_in, + bp_unpack_var_len_unsigned (bp), + &len)); + + line_change = bp_unpack_value (bp, 1); + if (line_change) + data_in->current_line = bp_unpack_var_len_unsigned (bp); + + column_change = bp_unpack_value (bp, 1); + if (column_change) + data_in->current_col = bp_unpack_var_len_unsigned (bp); + + if (file_change) + { + if (prev_file) + linemap_add (line_table, LC_LEAVE, false, NULL, 0); + + linemap_add (line_table, LC_ENTER, false, data_in->current_file, + data_in->current_line); + } + else if (line_change) + linemap_line_start (line_table, data_in->current_line, data_in->current_col); + + return linemap_position_for_column (line_table, data_in->current_col); +} + + /* Read a location from input block IB. */ static location_t lto_input_location (struct lto_input_block *ib, struct data_in *data_in) { - expanded_location xloc; + struct bitpack_d bp; - xloc.file = lto_input_string (data_in, ib); - if (xloc.file == NULL) - return UNKNOWN_LOCATION; - - xloc.file = canon_file_name (xloc.file); - xloc.line = lto_input_sleb128 (ib); - xloc.column = lto_input_sleb128 (ib); - xloc.sysp = lto_input_sleb128 (ib); - - if (data_in->current_file != xloc.file) - { - if (data_in->current_file) - linemap_add (line_table, LC_LEAVE, false, NULL, 0); - - linemap_add (line_table, LC_ENTER, xloc.sysp, xloc.file, xloc.line); - } - else if (data_in->current_line != xloc.line) - linemap_line_start (line_table, xloc.line, xloc.column); - - data_in->current_file = xloc.file; - data_in->current_line = xloc.line; - data_in->current_col = xloc.column; - - return linemap_position_for_column (line_table, xloc.column); + bp = lto_input_bitpack (ib); + return lto_input_location_bitpack (data_in, &bp); } @@ -1766,8 +1791,8 @@ unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr) = (unsigned) bp_unpack_value (bp, 2); TYPE_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1); TYPE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1); - TYPE_ALIGN (expr) = (unsigned) bp_unpack_value (bp, HOST_BITS_PER_INT); - TYPE_ALIAS_SET (expr) = bp_unpack_value (bp, HOST_BITS_PER_INT); + TYPE_ALIGN (expr) = bp_unpack_var_len_unsigned (bp); + TYPE_ALIAS_SET (expr) = bp_unpack_var_len_int (bp); } diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index 0cfe25a5d26..b9ac6d03245 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -143,16 +143,14 @@ destroy_output_block (struct output_block *ob) free (ob); } - -/* Output STRING of LEN characters to the string - table in OB. The string might or might not include a trailing '\0'. +/* Return index used to reference STRING of LEN characters in the string table + in OB. The string might or might not include a trailing '\0'. Then put the index onto the INDEX_STREAM. */ -void -lto_output_string_with_length (struct output_block *ob, - struct lto_output_stream *index_stream, - const char *s, - unsigned int len) +static unsigned +lto_string_index (struct output_block *ob, + const char *s, + unsigned int len) { struct string_slot **slot; struct string_slot s_slot; @@ -164,9 +162,6 @@ lto_output_string_with_length (struct output_block *ob, s_slot.len = len; s_slot.slot_num = 0; - /* Indicate that this is not a NULL string. */ - lto_output_uleb128_stream (index_stream, 0); - slot = (struct string_slot **) htab_find_slot (ob->string_hash_table, &s_slot, INSERT); if (*slot == NULL) @@ -180,18 +175,33 @@ lto_output_string_with_length (struct output_block *ob, new_slot->len = len; new_slot->slot_num = start; *slot = new_slot; - lto_output_uleb128_stream (index_stream, start); lto_output_uleb128_stream (string_stream, len); lto_output_data_stream (string_stream, string, len); + return start + 1; } else { struct string_slot *old_slot = *slot; - lto_output_uleb128_stream (index_stream, old_slot->slot_num); free (string); + return old_slot->slot_num + 1; } } + +/* Output STRING of LEN characters to the string + table in OB. The string might or might not include a trailing '\0'. + Then put the index onto the INDEX_STREAM. */ + +void +lto_output_string_with_length (struct output_block *ob, + struct lto_output_stream *index_stream, + const char *s, + unsigned int len) +{ + lto_output_uleb128_stream (index_stream, + lto_string_index (ob, s, len)); +} + /* Output the '\0' terminated STRING to the string table in OB. Then put the index onto the INDEX_STREAM. */ @@ -204,7 +214,7 @@ lto_output_string (struct output_block *ob, lto_output_string_with_length (ob, index_stream, string, strlen (string) + 1); else - lto_output_uleb128_stream (index_stream, 1); + lto_output_1_stream (index_stream, 0); } @@ -221,7 +231,7 @@ output_string_cst (struct output_block *ob, TREE_STRING_POINTER (string), TREE_STRING_LENGTH (string )); else - lto_output_uleb128_stream (index_stream, 1); + lto_output_1_stream (index_stream, 0); } @@ -238,9 +248,10 @@ output_identifier (struct output_block *ob, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id)); else - lto_output_uleb128_stream (index_stream, 1); + lto_output_1_stream (index_stream, 0); } + /* Write a zero to the output stream. */ static void @@ -504,8 +515,8 @@ pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr) bp_pack_value (bp, TYPE_CONTAINS_PLACEHOLDER_INTERNAL (expr), 2); bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1); bp_pack_value (bp, TYPE_READONLY (expr), 1); - bp_pack_value (bp, TYPE_ALIGN (expr), HOST_BITS_PER_INT); - bp_pack_value (bp, TYPE_ALIAS_SET (expr) == 0 ? 0 : -1, HOST_BITS_PER_INT); + bp_pack_var_len_unsigned (bp, TYPE_ALIGN (expr)); + bp_pack_var_len_int (bp, TYPE_ALIAS_SET (expr) == 0 ? 0 : -1); } @@ -587,29 +598,52 @@ pack_value_fields (struct bitpack_d *bp, tree expr) } -/* Emit location LOC to output block OB. */ +/* Output info about new location into bitpack BP. + After outputting bitpack, lto_output_location_data has + to be done to output actual data. */ + +static inline void +lto_output_location_bitpack (struct bitpack_d *bp, + struct output_block *ob, + location_t loc) +{ + expanded_location xloc; + + bp_pack_value (bp, loc == UNKNOWN_LOCATION, 1); + if (loc == UNKNOWN_LOCATION) + return; + + xloc = expand_location (loc); + + bp_pack_value (bp, ob->current_file != xloc.file, 1); + if (ob->current_file != xloc.file) + bp_pack_var_len_unsigned (bp, lto_string_index (ob, + xloc.file, + strlen (xloc.file) + 1)); + ob->current_file = xloc.file; + + bp_pack_value (bp, ob->current_line != xloc.line, 1); + if (ob->current_line != xloc.line) + bp_pack_var_len_unsigned (bp, xloc.line); + ob->current_line = xloc.line; + + bp_pack_value (bp, ob->current_col != xloc.column, 1); + if (ob->current_col != xloc.column) + bp_pack_var_len_unsigned (bp, xloc.column); + ob->current_col = xloc.column; +} + + +/* Emit location LOC to output block OB. + When bitpack is handy, it is more space effecient to call + lto_output_location_bitpack with existing bitpack. */ static void lto_output_location (struct output_block *ob, location_t loc) { - expanded_location xloc; - - if (loc == UNKNOWN_LOCATION) - { - lto_output_string (ob, ob->main_stream, NULL); - return; - } - - xloc = expand_location (loc); - - lto_output_string (ob, ob->main_stream, xloc.file); - output_sleb128 (ob, xloc.line); - output_sleb128 (ob, xloc.column); - output_sleb128 (ob, xloc.sysp); - - ob->current_file = xloc.file; - ob->current_line = xloc.line; - ob->current_col = xloc.column; + struct bitpack_d bp = bitpack_create (ob->main_stream); + lto_output_location_bitpack (&bp, ob, loc); + lto_output_bitpack (&bp); } @@ -642,7 +676,7 @@ lto_output_tree_ref (struct output_block *ob, tree expr) if (expr == NULL_TREE) { - output_zero (ob); + output_record_start (ob, LTO_null); return; } diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index 3389b564374..4508818a4a6 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -774,6 +774,10 @@ extern void lto_section_overrun (struct lto_input_block *) ATTRIBUTE_NORETURN; extern void lto_value_range_error (const char *, HOST_WIDE_INT, HOST_WIDE_INT, HOST_WIDE_INT) ATTRIBUTE_NORETURN; +extern void bp_pack_var_len_unsigned (struct bitpack_d *, unsigned HOST_WIDE_INT); +extern void bp_pack_var_len_int (struct bitpack_d *, HOST_WIDE_INT); +extern unsigned HOST_WIDE_INT bp_unpack_var_len_unsigned (struct bitpack_d *); +extern HOST_WIDE_INT bp_unpack_var_len_int (struct bitpack_d *); /* In lto-section-out.c */ extern hashval_t lto_hash_decl_slot_node (const void *); @@ -1110,6 +1114,11 @@ bp_pack_value (struct bitpack_d *bp, bitpack_word_t val, unsigned nbits) { bitpack_word_t word = bp->word; int pos = bp->pos; + + /* Verify that VAL fits in the NBITS. */ + gcc_checking_assert (nbits == BITS_PER_BITPACK_WORD + || !(val & ~(((bitpack_word_t)1< BITS_PER_BITPACK_WORD)