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-2020 Free Software Foundation, Inc. 5 Contributed by Diego Novillo <dnovillo@google.com> 6 7This file is part of GCC. 8 9GCC is free software; you can redistribute it and/or modify it under 10the terms of the GNU General Public License as published by the Free 11Software Foundation; either version 3, or (at your option) any later 12version. 13 14GCC is distributed in the hope that it will be useful, but WITHOUT ANY 15WARRANTY; without even the implied warranty of MERCHANTABILITY or 16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17for more details. 18 19You should have received a copy of the GNU General Public License 20along 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 "backend.h" 27#include "tree.h" 28#include "gimple.h" 29#include "cgraph.h" 30#include "data-streamer.h" 31 32/* Read a string from the string table in DATA_IN using input block 33 IB. Write the length to RLEN. */ 34 35static const char * 36string_for_index (class data_in *data_in, unsigned int loc, unsigned int *rlen) 37{ 38 unsigned int len; 39 const char *result; 40 41 if (!loc) 42 { 43 *rlen = 0; 44 return NULL; 45 } 46 47 /* Get the string stored at location LOC in DATA_IN->STRINGS. */ 48 lto_input_block str_tab (data_in->strings, loc - 1, data_in->strings_len, NULL); 49 len = streamer_read_uhwi (&str_tab); 50 *rlen = len; 51 52 if (str_tab.p + len > data_in->strings_len) 53 internal_error ("bytecode stream: string too long for the string table"); 54 55 result = (const char *)(data_in->strings + str_tab.p); 56 57 return result; 58} 59 60 61/* Read a string from the string table in DATA_IN using input block 62 IB. Write the length to RLEN. */ 63 64const char * 65streamer_read_indexed_string (class data_in *data_in, 66 class lto_input_block *ib, unsigned int *rlen) 67{ 68 return string_for_index (data_in, streamer_read_uhwi (ib), rlen); 69} 70 71 72/* Read a NULL terminated string from the string table in DATA_IN. */ 73 74const char * 75streamer_read_string (class data_in *data_in, class lto_input_block *ib) 76{ 77 unsigned int len; 78 const char *ptr; 79 80 ptr = streamer_read_indexed_string (data_in, ib, &len); 81 if (!ptr) 82 return NULL; 83 if (ptr[len - 1] != '\0') 84 internal_error ("bytecode stream: found non-null terminated string"); 85 86 return ptr; 87} 88 89 90/* Read a string from the string table in DATA_IN using the bitpack BP. 91 Write the length to RLEN. */ 92 93const char * 94bp_unpack_indexed_string (class data_in *data_in, 95 struct bitpack_d *bp, unsigned int *rlen) 96{ 97 return string_for_index (data_in, bp_unpack_var_len_unsigned (bp), rlen); 98} 99 100 101/* Read a NULL terminated string from the string table in DATA_IN. */ 102 103const char * 104bp_unpack_string (class data_in *data_in, struct bitpack_d *bp) 105{ 106 unsigned int len; 107 const char *ptr; 108 109 ptr = bp_unpack_indexed_string (data_in, bp, &len); 110 if (!ptr) 111 return NULL; 112 if (ptr[len - 1] != '\0') 113 internal_error ("bytecode stream: found non-null terminated string"); 114 115 return ptr; 116} 117 118 119/* Read an unsigned HOST_WIDE_INT number from IB. */ 120 121unsigned HOST_WIDE_INT 122streamer_read_uhwi (class lto_input_block *ib) 123{ 124 unsigned HOST_WIDE_INT result; 125 int shift; 126 unsigned HOST_WIDE_INT byte; 127 unsigned int p = ib->p; 128 unsigned int len = ib->len; 129 130 const char *data = ib->data; 131 result = data[p++]; 132 if ((result & 0x80) != 0) 133 { 134 result &= 0x7f; 135 shift = 7; 136 do 137 { 138 byte = data[p++]; 139 result |= (byte & 0x7f) << shift; 140 shift += 7; 141 } 142 while ((byte & 0x80) != 0); 143 } 144 145 /* We check for section overrun after the fact for performance reason. */ 146 if (p > len) 147 lto_section_overrun (ib); 148 149 ib->p = p; 150 return result; 151} 152 153 154/* Read a HOST_WIDE_INT number from IB. */ 155 156HOST_WIDE_INT 157streamer_read_hwi (class lto_input_block *ib) 158{ 159 HOST_WIDE_INT result = 0; 160 int shift = 0; 161 unsigned HOST_WIDE_INT byte; 162 163 while (true) 164 { 165 byte = streamer_read_uchar (ib); 166 result |= (byte & 0x7f) << shift; 167 shift += 7; 168 if ((byte & 0x80) == 0) 169 { 170 if ((shift < HOST_BITS_PER_WIDE_INT) && (byte & 0x40)) 171 result |= - (HOST_WIDE_INT_1U << shift); 172 173 return result; 174 } 175 } 176} 177 178/* Read a poly_uint64 from IB. */ 179 180poly_uint64 181streamer_read_poly_uint64 (class lto_input_block *ib) 182{ 183 poly_uint64 res; 184 for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i) 185 res.coeffs[i] = streamer_read_uhwi (ib); 186 return res; 187} 188 189/* Read gcov_type value from IB. */ 190 191gcov_type 192streamer_read_gcov_count (class lto_input_block *ib) 193{ 194 gcov_type ret = streamer_read_hwi (ib); 195 return ret; 196} 197 198/* Read the physical representation of a wide_int val from 199 input block IB. */ 200 201wide_int 202streamer_read_wide_int (class lto_input_block *ib) 203{ 204 HOST_WIDE_INT a[WIDE_INT_MAX_ELTS]; 205 int i; 206 int prec = streamer_read_uhwi (ib); 207 int len = streamer_read_uhwi (ib); 208 for (i = 0; i < len; i++) 209 a[i] = streamer_read_hwi (ib); 210 return wide_int::from_array (a, len, prec); 211} 212 213/* Read the physical representation of a widest_int val from 214 input block IB. */ 215 216widest_int 217streamer_read_widest_int (class lto_input_block *ib) 218{ 219 HOST_WIDE_INT a[WIDE_INT_MAX_ELTS]; 220 int i; 221 int prec ATTRIBUTE_UNUSED = streamer_read_uhwi (ib); 222 int len = streamer_read_uhwi (ib); 223 for (i = 0; i < len; i++) 224 a[i] = streamer_read_hwi (ib); 225 return widest_int::from_array (a, len); 226} 227 228