1 /* Routines for restoring various data types from a file stream. This deals 2 with various data types like strings, integers, enums, etc. 3 4 Copyright (C) 2011-2013 Free Software Foundation, Inc. 5 Contributed by Diego Novillo <dnovillo@google.com> 6 7 This file is part of GCC. 8 9 GCC is free software; you can redistribute it and/or modify it under 10 the terms of the GNU General Public License as published by the Free 11 Software Foundation; either version 3, or (at your option) any later 12 version. 13 14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 15 WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17 for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with GCC; see the file COPYING3. If not see 21 <http://www.gnu.org/licenses/>. */ 22 23 #include "config.h" 24 #include "system.h" 25 #include "coretypes.h" 26 #include "diagnostic.h" 27 #include "data-streamer.h" 28 29 /* Read a string from the string table in DATA_IN using input block 30 IB. Write the length to RLEN. */ 31 32 const char * 33 string_for_index (struct data_in *data_in, unsigned int loc, unsigned int *rlen) 34 { 35 struct lto_input_block str_tab; 36 unsigned int len; 37 const char *result; 38 39 if (!loc) 40 { 41 *rlen = 0; 42 return NULL; 43 } 44 45 /* Get the string stored at location LOC in DATA_IN->STRINGS. */ 46 LTO_INIT_INPUT_BLOCK (str_tab, data_in->strings, loc - 1, 47 data_in->strings_len); 48 len = streamer_read_uhwi (&str_tab); 49 *rlen = len; 50 51 if (str_tab.p + len > data_in->strings_len) 52 internal_error ("bytecode stream: string too long for the string table"); 53 54 result = (const char *)(data_in->strings + str_tab.p); 55 56 return result; 57 } 58 59 60 /* Read a string from the string table in DATA_IN using input block 61 IB. Write the length to RLEN. */ 62 63 const char * 64 streamer_read_indexed_string (struct data_in *data_in, 65 struct lto_input_block *ib, unsigned int *rlen) 66 { 67 return string_for_index (data_in, streamer_read_uhwi (ib), rlen); 68 } 69 70 71 /* Read a NULL terminated string from the string table in DATA_IN. */ 72 73 const char * 74 streamer_read_string (struct data_in *data_in, struct lto_input_block *ib) 75 { 76 unsigned int len; 77 const char *ptr; 78 79 ptr = streamer_read_indexed_string (data_in, ib, &len); 80 if (!ptr) 81 return NULL; 82 if (ptr[len - 1] != '\0') 83 internal_error ("bytecode stream: found non-null terminated string"); 84 85 return ptr; 86 } 87 88 89 /* Read a string from the string table in DATA_IN using the bitpack BP. 90 Write the length to RLEN. */ 91 92 const char * 93 bp_unpack_indexed_string (struct data_in *data_in, 94 struct bitpack_d *bp, unsigned int *rlen) 95 { 96 return string_for_index (data_in, bp_unpack_var_len_unsigned (bp), rlen); 97 } 98 99 100 /* Read a NULL terminated string from the string table in DATA_IN. */ 101 102 const char * 103 bp_unpack_string (struct data_in *data_in, struct bitpack_d *bp) 104 { 105 unsigned int len; 106 const char *ptr; 107 108 ptr = bp_unpack_indexed_string (data_in, bp, &len); 109 if (!ptr) 110 return NULL; 111 if (ptr[len - 1] != '\0') 112 internal_error ("bytecode stream: found non-null terminated string"); 113 114 return ptr; 115 } 116 117 118 /* Read an unsigned HOST_WIDE_INT number from IB. */ 119 120 unsigned HOST_WIDE_INT 121 streamer_read_uhwi (struct lto_input_block *ib) 122 { 123 unsigned HOST_WIDE_INT result = 0; 124 int shift = 0; 125 unsigned HOST_WIDE_INT byte; 126 127 while (true) 128 { 129 byte = streamer_read_uchar (ib); 130 result |= (byte & 0x7f) << shift; 131 shift += 7; 132 if ((byte & 0x80) == 0) 133 return result; 134 } 135 } 136 137 138 /* Read a HOST_WIDE_INT number from IB. */ 139 140 HOST_WIDE_INT 141 streamer_read_hwi (struct lto_input_block *ib) 142 { 143 HOST_WIDE_INT result = 0; 144 int shift = 0; 145 unsigned HOST_WIDE_INT byte; 146 147 while (true) 148 { 149 byte = streamer_read_uchar (ib); 150 result |= (byte & 0x7f) << shift; 151 shift += 7; 152 if ((byte & 0x80) == 0) 153 { 154 if ((shift < HOST_BITS_PER_WIDE_INT) && (byte & 0x40)) 155 result |= - ((HOST_WIDE_INT)1 << shift); 156 157 return result; 158 } 159 } 160 } 161