Branch data Line data Source code
1 : : // import.cc -- Go frontend import declarations.
2 : :
3 : : // Copyright 2009 The Go Authors. All rights reserved.
4 : : // Use of this source code is governed by a BSD-style
5 : : // license that can be found in the LICENSE file.
6 : :
7 : : #include "go-system.h"
8 : :
9 : : #include "filenames.h"
10 : :
11 : : #include "go-c.h"
12 : : #include "go-diagnostics.h"
13 : : #include "gogo.h"
14 : : #include "lex.h"
15 : : #include "types.h"
16 : : #include "export.h"
17 : : #include "import.h"
18 : :
19 : : #ifndef O_BINARY
20 : : #define O_BINARY 0
21 : : #endif
22 : :
23 : : // The list of paths we search for import files.
24 : :
25 : : static std::vector<std::string> search_path;
26 : :
27 : : // Add a directory to the search path. This is called from the option
28 : : // handling language hook.
29 : :
30 : : GO_EXTERN_C
31 : : void
32 : 38826 : go_add_search_path(const char* path)
33 : : {
34 : 38826 : search_path.push_back(std::string(path));
35 : 38826 : }
36 : :
37 : : // Read an importcfg file.
38 : :
39 : : void
40 : 379 : Gogo::read_importcfg(const char* filename)
41 : : {
42 : 379 : std::string data;
43 : 379 : if (!Gogo::read_file(filename, Linemap::unknown_location(), &data))
44 : : return;
45 : 379 : const char* p = data.data();
46 : 379 : const char* pend = p + data.length();
47 : 379 : int lineno = 0;
48 : 379 : const char *pnext = NULL;
49 : 1481 : for (; p < pend; p = pnext)
50 : : {
51 : : // Line numbers start at 1.
52 : 1102 : lineno++;
53 : :
54 : : // Find end of line.
55 : 1102 : const char* pnl = static_cast<const char*>(memchr(p, '\n', pend - p));
56 : 1102 : if (pnl != NULL)
57 : 1102 : pnext = pnl + 1;
58 : : else
59 : : {
60 : 1102 : pnl = pend;
61 : 1102 : pnext = pnl;
62 : : }
63 : :
64 : : // Trim leading spaces.
65 : 1102 : while (p < pnl)
66 : : {
67 : 1102 : unsigned int rune;
68 : 1102 : int rune_len = Lex::fetch_char(p, &rune);
69 : 1102 : if (rune_len == 0)
70 : : {
71 : 0 : go_error_at(Linemap::unknown_location(),
72 : : "%s:%d: invalid character in importcfg file",
73 : : filename, lineno);
74 : 0 : return;
75 : : }
76 : 1102 : if (!Lex::is_unicode_space(rune))
77 : : break;
78 : 0 : p += rune_len;
79 : : }
80 : :
81 : : // Trim trailing spaces.
82 : 1102 : while (pnl > p)
83 : : {
84 : 1102 : size_t start = pnl - p - 1;
85 : 1102 : unsigned int rune = (unsigned char)p[start];
86 : 1102 : int rune_len = 1;
87 : 1102 : if (rune > 0x7f)
88 : : {
89 : 0 : for (start--; start > 0; start--)
90 : : {
91 : 0 : unsigned char c = p[start];
92 : 0 : if ((c & 0xc0) != 0x80)
93 : : break;
94 : : }
95 : 0 : rune_len = Lex::fetch_char(p + start, &rune);
96 : 0 : if (static_cast<size_t>(rune_len) != (pnl - p) - start)
97 : : {
98 : 0 : go_error_at(Linemap::unknown_location(),
99 : : "%s:%d: invalid character in importcfg file",
100 : : filename, lineno);
101 : 0 : return;
102 : : }
103 : : }
104 : 1102 : if (!Lex::is_unicode_space(rune))
105 : : break;
106 : 0 : pnl -= rune_len;
107 : : }
108 : :
109 : : // Skip empty lines and comment lines.
110 : 1102 : if (p == pnl || *p == '#')
111 : 379 : continue;
112 : :
113 : 723 : size_t verb_len;
114 : 723 : const char* psp = static_cast<const char*>(memchr(p, ' ', pnl - p));
115 : 723 : if (psp == NULL)
116 : : verb_len = pnl - p;
117 : : else
118 : 723 : verb_len = psp - p;
119 : :
120 : 723 : bool importmap = false;
121 : 723 : bool packagefile = false;
122 : 723 : if (strncmp(p, "importmap", verb_len) == 0)
123 : : importmap = true;
124 : 703 : else if (strncmp(p, "packagefile", verb_len) == 0)
125 : : packagefile = true;
126 : : else
127 : : {
128 : 0 : go_error_at(Linemap::unknown_location(),
129 : : "%s:%d: unknown directive in importcfg file",
130 : : filename, lineno);
131 : 0 : return;
132 : : }
133 : :
134 : 723 : const char* peq;
135 : 723 : if (psp == NULL)
136 : : peq = NULL;
137 : : else
138 : : {
139 : 723 : psp++;
140 : 723 : peq = static_cast<const char*>(memchr(psp, '=', pnl - psp));
141 : : }
142 : 723 : if (peq == NULL || peq + 1 == pnl)
143 : : {
144 : 0 : go_error_at(Linemap::unknown_location(),
145 : : "%s:%d: invalid syntax in importcfg file",
146 : : filename, lineno);
147 : 0 : return;
148 : : }
149 : :
150 : 723 : std::string first(psp, peq - psp);
151 : 723 : std::string second(peq + 1, pnl - (peq + 1));
152 : 723 : if (importmap)
153 : 20 : this->import_map_[first] = second;
154 : 703 : else if (packagefile)
155 : 703 : this->package_file_[first] = second;
156 : : else
157 : 0 : go_unreachable();
158 : 723 : }
159 : 379 : }
160 : :
161 : : // Find import data. This searches the file system for FILENAME and
162 : : // returns a pointer to a Stream object to read the data that it
163 : : // exports. If the file is not found, it returns NULL.
164 : :
165 : : // When FILENAME is not an absolute path and does not start with ./ or
166 : : // ../, we use the search path provided by -I and -L options.
167 : :
168 : : // When FILENAME does start with ./ or ../, we use
169 : : // RELATIVE_IMPORT_PATH as a prefix.
170 : :
171 : : // When FILENAME does not exist, we try modifying FILENAME to find the
172 : : // file. We use the first of these which exists:
173 : : // * We append ".gox".
174 : : // * We turn the base of FILENAME into libFILENAME.so.
175 : : // * We turn the base of FILENAME into libFILENAME.a.
176 : : // * We append ".o".
177 : :
178 : : // When using a search path, we apply each of these transformations at
179 : : // each entry on the search path before moving on to the next entry.
180 : : // If the file exists, but does not contain any Go export data, we
181 : : // stop; we do not keep looking for another file with the same name
182 : : // later in the search path.
183 : :
184 : : Import::Stream*
185 : 21818 : Import::open_package(const std::string& filename, Location location,
186 : : const std::string& relative_import_path)
187 : : {
188 : 21818 : bool is_local;
189 : 21818 : if (IS_ABSOLUTE_PATH(filename))
190 : : is_local = true;
191 : 21116 : else if (filename[0] == '.'
192 : 21116 : && (filename[1] == '\0' || IS_DIR_SEPARATOR(filename[1])))
193 : : is_local = true;
194 : 20475 : else if (filename[0] == '.'
195 : 0 : && filename[1] == '.'
196 : 20475 : && (filename[2] == '\0' || IS_DIR_SEPARATOR(filename[2])))
197 : : is_local = true;
198 : : else
199 : : is_local = false;
200 : :
201 : 21818 : std::string fn = filename;
202 : 21818 : if (is_local && !IS_ABSOLUTE_PATH(filename) && !relative_import_path.empty())
203 : : {
204 : 0 : if (fn == ".")
205 : : {
206 : : // A special case.
207 : 0 : fn = relative_import_path;
208 : : }
209 : 0 : else if (fn[0] == '.' && fn[1] == '.'
210 : 0 : && (fn[2] == '\0' || IS_DIR_SEPARATOR(fn[2])))
211 : : {
212 : : // We are going to join relative_import_path and fn, and it
213 : : // will look like DIR/../PATH. But DIR does not necessarily
214 : : // exist in this case, and if it doesn't the use of .. will
215 : : // fail although it shouldn't. The gc compiler uses
216 : : // path.Join here, which cleans up the .., so we need to do
217 : : // the same.
218 : 0 : size_t index;
219 : 0 : for (index = relative_import_path.length() - 1;
220 : 0 : index > 0 && !IS_DIR_SEPARATOR(relative_import_path[index]);
221 : : index--)
222 : : ;
223 : 0 : if (index > 0)
224 : 0 : fn = relative_import_path.substr(0, index) + fn.substr(2);
225 : : else
226 : 0 : fn = relative_import_path + '/' + fn;
227 : : }
228 : : else
229 : 0 : fn = relative_import_path + '/' + fn;
230 : : is_local = false;
231 : : }
232 : :
233 : 21818 : if (!is_local)
234 : : {
235 : 20475 : for (std::vector<std::string>::const_iterator p = search_path.begin();
236 : 27204 : p != search_path.end();
237 : 6729 : ++p)
238 : : {
239 : 27190 : std::string indir = *p;
240 : 27190 : if (!indir.empty() && indir[indir.size() - 1] != '/')
241 : 27190 : indir += '/';
242 : 27190 : indir += fn;
243 : 27190 : Stream* s = Import::try_package_in_directory(indir, location);
244 : 27190 : if (s != NULL)
245 : 20461 : return s;
246 : 27190 : }
247 : : }
248 : :
249 : 1357 : Stream* s = Import::try_package_in_directory(fn, location);
250 : 1357 : if (s != NULL)
251 : : return s;
252 : :
253 : : return NULL;
254 : 21818 : }
255 : :
256 : : // Try to find the export data for FILENAME.
257 : :
258 : : Import::Stream*
259 : 28547 : Import::try_package_in_directory(const std::string& filename,
260 : : Location location)
261 : : {
262 : 28547 : std::string found_filename = filename;
263 : 28547 : int fd = open(found_filename.c_str(), O_RDONLY | O_BINARY);
264 : :
265 : 28547 : if (fd >= 0)
266 : : {
267 : 11156 : struct stat s;
268 : 11156 : if (fstat(fd, &s) >= 0 && S_ISDIR(s.st_mode))
269 : : {
270 : 10454 : close(fd);
271 : 10454 : fd = -1;
272 : 10454 : errno = EISDIR;
273 : : }
274 : : }
275 : :
276 : 11156 : if (fd < 0)
277 : : {
278 : 27845 : if (errno != ENOENT && errno != EISDIR)
279 : 0 : go_warning_at(location, 0, "%s: %m", filename.c_str());
280 : :
281 : 27845 : fd = Import::try_suffixes(&found_filename);
282 : 27845 : if (fd < 0)
283 : : return NULL;
284 : : }
285 : :
286 : : // The export data may not be in this file.
287 : 21808 : Stream* s = Import::find_export_data(found_filename, fd, location);
288 : 21808 : if (s != NULL)
289 : : return s;
290 : :
291 : 0 : close(fd);
292 : :
293 : 0 : go_error_at(location, "%s exists but does not contain any Go export data",
294 : : found_filename.c_str());
295 : :
296 : 0 : return NULL;
297 : 28547 : }
298 : :
299 : : // Given import "*PFILENAME", where *PFILENAME does not exist, try
300 : : // various suffixes. If we find one, set *PFILENAME to the one we
301 : : // found. Return the open file descriptor.
302 : :
303 : : int
304 : 27845 : Import::try_suffixes(std::string* pfilename)
305 : : {
306 : 27845 : std::string filename = *pfilename + ".gox";
307 : 27845 : int fd = open(filename.c_str(), O_RDONLY | O_BINARY);
308 : 27845 : if (fd >= 0)
309 : : {
310 : 20189 : *pfilename = filename;
311 : 20189 : return fd;
312 : : }
313 : :
314 : 7656 : const char* basename = lbasename(pfilename->c_str());
315 : 7656 : size_t basename_pos = basename - pfilename->c_str();
316 : 30624 : filename = pfilename->substr(0, basename_pos) + "lib" + basename + ".so";
317 : 7656 : fd = open(filename.c_str(), O_RDONLY | O_BINARY);
318 : 7656 : if (fd >= 0)
319 : : {
320 : 0 : *pfilename = filename;
321 : 0 : return fd;
322 : : }
323 : :
324 : 30624 : filename = pfilename->substr(0, basename_pos) + "lib" + basename + ".a";
325 : 7656 : fd = open(filename.c_str(), O_RDONLY | O_BINARY);
326 : 7656 : if (fd >= 0)
327 : : {
328 : 198 : *pfilename = filename;
329 : 198 : return fd;
330 : : }
331 : :
332 : 7458 : filename = *pfilename + ".o";
333 : 7458 : fd = open(filename.c_str(), O_RDONLY | O_BINARY);
334 : 7458 : if (fd >= 0)
335 : : {
336 : 719 : *pfilename = filename;
337 : 719 : return fd;
338 : : }
339 : :
340 : : return -1;
341 : 27845 : }
342 : :
343 : : // Look for export data in the file descriptor FD.
344 : :
345 : : Import::Stream*
346 : 21808 : Import::find_export_data(const std::string& filename, int fd, Location location)
347 : : {
348 : : // See if we can read this as an object file.
349 : 21808 : Import::Stream* stream = Import::find_object_export_data(filename, fd, 0,
350 : : location);
351 : 21808 : if (stream != NULL)
352 : : return stream;
353 : :
354 : 702 : const int len = MAX(Export::magic_len, Import::archive_magic_len);
355 : :
356 : 702 : if (lseek(fd, 0, SEEK_SET) < 0)
357 : : {
358 : 0 : go_error_at(location, "lseek %s failed: %m", filename.c_str());
359 : 0 : return NULL;
360 : : }
361 : :
362 : 702 : char buf[len];
363 : 702 : ssize_t c = ::read(fd, buf, len);
364 : 702 : if (c < len)
365 : : return NULL;
366 : :
367 : : // Check for a file containing nothing but Go export data.
368 : 702 : if (memcmp(buf, Export::cur_magic, Export::magic_len) == 0
369 : 702 : || memcmp(buf, Export::v1_magic, Export::magic_len) == 0
370 : 702 : || memcmp(buf, Export::v2_magic, Export::magic_len) == 0)
371 : 0 : return new Stream_from_file(fd);
372 : :
373 : : // See if we can read this as an archive.
374 : 702 : if (Import::is_archive_magic(buf))
375 : 702 : return Import::find_archive_export_data(filename, fd, location);
376 : :
377 : : return NULL;
378 : : }
379 : :
380 : : // Look for export data in an object file.
381 : :
382 : : Import::Stream*
383 : 23332 : Import::find_object_export_data(const std::string& filename,
384 : : int fd,
385 : : off_t offset,
386 : : Location location)
387 : : {
388 : 23332 : char *buf;
389 : 23332 : size_t len;
390 : 23332 : int err;
391 : 23332 : const char *errmsg = go_read_export_data(fd, offset, &buf, &len, &err);
392 : 23332 : if (errmsg != NULL)
393 : : {
394 : 0 : if (err == 0)
395 : 0 : go_error_at(location, "%s: %s", filename.c_str(), errmsg);
396 : : else
397 : 0 : go_error_at(location, "%s: %s: %s", filename.c_str(), errmsg,
398 : : xstrerror(err));
399 : 0 : return NULL;
400 : : }
401 : :
402 : 23332 : if (buf == NULL)
403 : : return NULL;
404 : :
405 : 21808 : return new Stream_from_buffer(buf, len);
406 : : }
407 : :
408 : : // Class Import.
409 : :
410 : : // Construct an Import object. We make the builtin_types_ vector
411 : : // large enough to hold all the builtin types.
412 : :
413 : 21808 : Import::Import(Stream* stream, Location location)
414 : 21808 : : gogo_(NULL), stream_(stream), location_(location), package_(NULL),
415 : 21808 : add_to_globals_(false), packages_(), type_data_(), type_pos_(0),
416 : 21808 : type_offsets_(), builtin_types_((- SMALLEST_BUILTIN_CODE) + 1),
417 : 21808 : types_(), version_(EXPORT_FORMAT_UNKNOWN)
418 : : {
419 : 21808 : }
420 : :
421 : : // Import the data in the associated stream.
422 : :
423 : : Package*
424 : 21808 : Import::import(Gogo* gogo, const std::string& local_name,
425 : : bool is_local_name_exported)
426 : : {
427 : : // Hold on to the Gogo structure. Otherwise we need to pass it
428 : : // through all the import functions, because we need it when reading
429 : : // a type.
430 : 21808 : this->gogo_ = gogo;
431 : :
432 : : // A stream of export data can include data from more than one input
433 : : // file. Here we loop over each input file.
434 : 21808 : Stream* stream = this->stream_;
435 : 43616 : while (!stream->at_eof() && !stream->saw_error())
436 : : {
437 : : // The vector of types is package specific.
438 : 21808 : this->types_.clear();
439 : :
440 : : // Check magic string / version number.
441 : 21808 : if (stream->match_bytes(Export::cur_magic, Export::magic_len))
442 : : {
443 : 21808 : stream->require_bytes(this->location_, Export::cur_magic,
444 : : Export::magic_len);
445 : 21808 : this->version_ = EXPORT_FORMAT_CURRENT;
446 : : }
447 : 0 : else if (stream->match_bytes(Export::v1_magic, Export::magic_len))
448 : : {
449 : 0 : stream->require_bytes(this->location_, Export::v1_magic,
450 : : Export::magic_len);
451 : 0 : this->version_ = EXPORT_FORMAT_V1;
452 : : }
453 : 0 : else if (stream->match_bytes(Export::v2_magic, Export::magic_len))
454 : : {
455 : 0 : stream->require_bytes(this->location_, Export::v2_magic,
456 : : Export::magic_len);
457 : 0 : this->version_ = EXPORT_FORMAT_V2;
458 : : }
459 : : else
460 : : {
461 : 0 : go_error_at(this->location_,
462 : : ("error in import data at %d: invalid magic string"),
463 : : stream->pos());
464 : 0 : return NULL;
465 : : }
466 : :
467 : 21808 : this->require_c_string("package ");
468 : 21808 : std::string package_name = this->read_identifier();
469 : 21808 : this->require_semicolon_if_old_version();
470 : 21808 : this->require_c_string("\n");
471 : :
472 : 21808 : std::string pkgpath;
473 : 21808 : std::string pkgpath_symbol;
474 : 21808 : if (this->match_c_string("prefix "))
475 : : {
476 : 175 : this->advance(7);
477 : 175 : std::string unique_prefix = this->read_identifier();
478 : 175 : this->require_semicolon_if_old_version();
479 : 175 : this->require_c_string("\n");
480 : 175 : pkgpath = unique_prefix + '.' + package_name;
481 : 350 : pkgpath_symbol = (Gogo::pkgpath_for_symbol(unique_prefix) + '.'
482 : 525 : + Gogo::pkgpath_for_symbol(package_name));
483 : 175 : }
484 : : else
485 : : {
486 : 21633 : this->require_c_string("pkgpath ");
487 : 21633 : pkgpath = this->read_identifier();
488 : 21633 : this->require_semicolon_if_old_version();
489 : 21633 : this->require_c_string("\n");
490 : 21633 : pkgpath_symbol = Gogo::pkgpath_for_symbol(pkgpath);
491 : : }
492 : :
493 : 21808 : if (stream->saw_error())
494 : : return NULL;
495 : :
496 : 21808 : this->package_ = gogo->add_imported_package(package_name, local_name,
497 : : is_local_name_exported,
498 : : pkgpath, pkgpath_symbol,
499 : : this->location_,
500 : : &this->add_to_globals_);
501 : 21808 : if (this->package_ == NULL)
502 : : {
503 : 0 : stream->set_saw_error();
504 : 0 : return NULL;
505 : : }
506 : :
507 : : // Read and discard priority if older V1 export data format.
508 : 21808 : if (version() == EXPORT_FORMAT_V1)
509 : : {
510 : 0 : this->require_c_string("priority ");
511 : 0 : std::string priority_string = this->read_identifier();
512 : 0 : int prio;
513 : 0 : if (!this->string_to_int(priority_string, false, &prio))
514 : 0 : return NULL;
515 : 0 : this->require_c_string(";\n");
516 : 0 : }
517 : :
518 : 22015 : while (stream->match_c_string("package"))
519 : 207 : this->read_one_package();
520 : :
521 : 211683 : while (stream->match_c_string("import"))
522 : 189875 : this->read_one_import();
523 : :
524 : 46024 : while (stream->match_c_string("indirectimport"))
525 : 24216 : this->read_one_indirect_import();
526 : :
527 : 21808 : if (stream->match_c_string("init"))
528 : 21808 : this->read_import_init_fns(gogo);
529 : :
530 : 21808 : if (stream->match_c_string("types "))
531 : : {
532 : 21808 : if (!this->read_types())
533 : : return NULL;
534 : : }
535 : :
536 : : // Loop over all the input data for this package.
537 : 2456902 : while (!stream->saw_error())
538 : : {
539 : 2456902 : if (stream->match_c_string("const "))
540 : 837398 : this->import_const();
541 : 1619504 : else if (stream->match_c_string("type "))
542 : 0 : this->import_type();
543 : 1619504 : else if (stream->match_c_string("var "))
544 : 326311 : this->import_var();
545 : 1293193 : else if (stream->match_c_string("func "))
546 : 1271385 : this->import_func(this->package_);
547 : 21808 : else if (stream->match_c_string("checksum "))
548 : : break;
549 : : else
550 : : {
551 : 0 : go_error_at(this->location_,
552 : : ("error in import data at %d: "
553 : : "expected %<const%>, %<type%>, %<var%>, "
554 : : "%<func%>, or %<checksum%>"),
555 : : stream->pos());
556 : 0 : stream->set_saw_error();
557 : 0 : return NULL;
558 : : }
559 : : }
560 : :
561 : : // We currently ignore the checksum. In the future we could
562 : : // store the checksum somewhere in the generated object and then
563 : : // verify that the checksum matches at link time or at dynamic
564 : : // load time.
565 : 21808 : this->require_c_string("checksum ");
566 : 21808 : stream->advance(Export::checksum_len * 2);
567 : 21808 : this->require_semicolon_if_old_version();
568 : 21808 : this->require_c_string("\n");
569 : 21808 : }
570 : :
571 : : // Finalize methods for any imported types. This call is made late in the
572 : : // import process so as to A) avoid finalization of a type whose methods
573 : : // refer to types that are only partially read in, and B) capture both the
574 : : // types imported by read_types() directly, and those imported indirectly
575 : : // because they are referenced by an imported function or variable.
576 : : // See issues #33013 and #33219 for more on why this is needed.
577 : 21808 : this->finalize_methods();
578 : :
579 : 21808 : return this->package_;
580 : : }
581 : :
582 : : // Read a package line. This let us reliably determine the pkgpath
583 : : // symbol, even if the package was compiled with a -fgo-prefix option.
584 : :
585 : : void
586 : 207 : Import::read_one_package()
587 : : {
588 : 207 : this->require_c_string("package ");
589 : 207 : std::string package_name = this->read_identifier();
590 : 207 : this->require_c_string(" ");
591 : 207 : std::string pkgpath = this->read_identifier();
592 : 207 : this->require_c_string(" ");
593 : 207 : std::string pkgpath_symbol = this->read_identifier();
594 : 207 : this->require_semicolon_if_old_version();
595 : 207 : this->require_c_string("\n");
596 : :
597 : 207 : Package* p = this->gogo_->register_package(pkgpath, pkgpath_symbol,
598 : : Linemap::unknown_location());
599 : 207 : p->set_package_name(package_name, this->location());
600 : 207 : }
601 : :
602 : : // Read an import line.
603 : :
604 : : void
605 : 189875 : Import::read_one_import()
606 : : {
607 : 189875 : this->require_c_string("import ");
608 : 189875 : std::string package_name = this->read_identifier();
609 : 189875 : this->require_c_string(" ");
610 : 189875 : std::string pkgpath = this->read_identifier();
611 : 189875 : this->require_c_string(" \"");
612 : 189875 : Stream* stream = this->stream_;
613 : 1989745 : while (stream->peek_char() != '"')
614 : 1799870 : stream->advance(1);
615 : 189875 : this->require_c_string("\"");
616 : 189875 : this->require_semicolon_if_old_version();
617 : 189875 : this->require_c_string("\n");
618 : :
619 : 189875 : Package* p = this->gogo_->register_package(pkgpath, "",
620 : 189875 : Linemap::unknown_location());
621 : 189875 : p->set_package_name(package_name, this->location());
622 : :
623 : 189875 : this->packages_.push_back(p);
624 : :
625 : 189875 : if (pkgpath == "unsafe")
626 : 7306 : this->gogo_->add_unsafe_bindings(p);
627 : 189875 : }
628 : :
629 : : // Read an indirectimport line.
630 : :
631 : : void
632 : 24216 : Import::read_one_indirect_import()
633 : : {
634 : 24216 : this->require_c_string("indirectimport ");
635 : 24216 : std::string package_name = this->read_identifier();
636 : 24216 : this->require_c_string(" ");
637 : 24216 : std::string pkgpath = this->read_identifier();
638 : 24216 : this->require_c_string("\n");
639 : :
640 : 24216 : Package* p = this->gogo_->register_package(pkgpath, "",
641 : 24216 : Linemap::unknown_location());
642 : 24216 : p->set_package_name(package_name, this->location());
643 : :
644 : 24216 : this->packages_.push_back(p);
645 : :
646 : 24216 : if (pkgpath == "unsafe")
647 : 3655 : this->gogo_->add_unsafe_bindings(p);
648 : 24216 : }
649 : :
650 : : // Read the list of import control functions and/or init graph.
651 : :
652 : : void
653 : 21808 : Import::read_import_init_fns(Gogo* gogo)
654 : : {
655 : 21808 : this->require_c_string("init");
656 : :
657 : : // Maps init function to index in the "init" clause; needed
658 : : // to read the init_graph section.
659 : 21808 : std::map<std::string, unsigned> init_idx;
660 : :
661 : 682010 : while (!this->match_c_string("\n") && !this->match_c_string(";"))
662 : : {
663 : 660202 : int priority = -1;
664 : :
665 : 660202 : this->require_c_string(" ");
666 : 660202 : std::string package_name = this->read_identifier();
667 : 660202 : this->require_c_string(" ");
668 : 660202 : std::string init_name = this->read_identifier();
669 : 660202 : if (this->version_ == EXPORT_FORMAT_V1)
670 : : {
671 : : // Older version 1 init fcn export data format is:
672 : : //
673 : : // <packname> <fcn> <priority>
674 : 0 : this->require_c_string(" ");
675 : 0 : std::string prio_string = this->read_identifier();
676 : 0 : if (!this->string_to_int(prio_string, false, &priority))
677 : 0 : return;
678 : 0 : }
679 : 660202 : gogo->add_import_init_fn(package_name, init_name, priority);
680 : :
681 : : // Record the index of this init fcn so that we can look it
682 : : // up by index in the subsequent init_graph section.
683 : 660202 : unsigned idx = init_idx.size();
684 : 660202 : init_idx[init_name] = idx;
685 : 660202 : }
686 : 21808 : this->require_semicolon_if_old_version();
687 : 21808 : this->require_c_string("\n");
688 : :
689 : 21808 : if (this->match_c_string("init_graph"))
690 : : {
691 : 20261 : this->require_c_string("init_graph");
692 : :
693 : : // Build a vector mapping init fcn slot to Import_init pointer.
694 : 20261 : go_assert(init_idx.size() > 0);
695 : 20261 : std::vector<Import_init*> import_initvec;
696 : 20261 : import_initvec.resize(init_idx.size());
697 : 678916 : for (std::map<std::string, unsigned>::const_iterator it =
698 : 20261 : init_idx.begin();
699 : 678916 : it != init_idx.end(); ++it)
700 : : {
701 : 658655 : const std::string& init_name = it->first;
702 : 658655 : Import_init* ii = gogo->lookup_init(init_name);
703 : 658655 : import_initvec[it->second] = ii;
704 : : }
705 : :
706 : : // Init graph format is:
707 : : //
708 : : // init_graph <src1> <sink1> <src2> <sink2> ... ;
709 : : //
710 : : // where src + sink are init functions indices.
711 : :
712 : 3322940 : while (!this->match_c_string("\n") && !this->match_c_string(";"))
713 : : {
714 : 3302679 : this->require_c_string(" ");
715 : 3302679 : std::string src_string = this->read_identifier();
716 : 3302679 : unsigned src;
717 : 3302679 : if (!this->string_to_unsigned(src_string, &src)) return;
718 : :
719 : 3302679 : this->require_c_string(" ");
720 : 3302679 : std::string sink_string = this->read_identifier();
721 : 3302679 : unsigned sink;
722 : 3302679 : if (!this->string_to_unsigned(sink_string, &sink)) return;
723 : :
724 : 3302679 : go_assert(src < import_initvec.size());
725 : 3302679 : Import_init* ii_src = import_initvec[src];
726 : 3302679 : go_assert(sink < import_initvec.size());
727 : 3302679 : Import_init* ii_sink = import_initvec[sink];
728 : :
729 : 3302679 : ii_src->record_precursor_fcn(ii_sink->init_name());
730 : 3302679 : }
731 : 20261 : this->require_semicolon_if_old_version();
732 : 20261 : this->require_c_string("\n");
733 : 20261 : }
734 : 21808 : }
735 : :
736 : : // Import the types. Starting in export format version 3 all the
737 : : // types are listed first.
738 : :
739 : : bool
740 : 21808 : Import::read_types()
741 : : {
742 : 21808 : this->require_c_string("types ");
743 : 21808 : std::string str = this->read_identifier();
744 : 21808 : int maxp1;
745 : 21808 : if (!this->string_to_int(str, false, &maxp1))
746 : : return false;
747 : :
748 : 21808 : this->require_c_string(" ");
749 : 21808 : str = this->read_identifier();
750 : 21808 : int exportedp1;
751 : 21808 : if (!this->string_to_int(str, false, &exportedp1))
752 : : return false;
753 : :
754 : 21808 : this->type_offsets_.resize(maxp1, std::make_pair<size_t, size_t>(0, 0));
755 : 21808 : size_t total_type_size = 0;
756 : : // Start at 1 because type index 0 not used.
757 : 3218999 : for (int i = 1; i < maxp1; i++)
758 : : {
759 : 3197191 : this->require_c_string(" ");
760 : 3197191 : str = this->read_identifier();
761 : 3197191 : int v;
762 : 3197191 : if (!this->string_to_int(str, false, &v))
763 : 0 : return false;
764 : 3197191 : size_t vs = static_cast<size_t>(v);
765 : 3197191 : this->type_offsets_[i] = std::make_pair(total_type_size, vs);
766 : 3197191 : total_type_size += vs;
767 : : }
768 : :
769 : 21808 : this->require_c_string("\n");
770 : :
771 : : // Types can refer to each other in an unpredictable order. Read
772 : : // all the type data into type_data_. The type_offsets_ vector we
773 : : // just initialized provides indexes into type_data_.
774 : :
775 : 21808 : this->type_pos_ = this->stream_->pos();
776 : 21808 : const char* type_data;
777 : 21808 : if (!this->stream_->peek(total_type_size, &type_data))
778 : : return false;
779 : 21808 : this->type_data_ = std::string(type_data, total_type_size);
780 : 21808 : this->advance(total_type_size);
781 : :
782 : 21808 : this->types_.resize(maxp1, NULL);
783 : :
784 : : // Parse all the exported types now, so that the names are properly
785 : : // bound and visible to the parser. Parse unexported types lazily.
786 : :
787 : : // Start at 1 because there is no type 0.
788 : 195846 : for (int i = 1; i < exportedp1; i++)
789 : : {
790 : : // We may have already parsed this type when we parsed an
791 : : // earlier type.
792 : 174038 : Type* type = this->types_[i];
793 : 174038 : if (type == NULL)
794 : : {
795 : 137360 : if (!this->parse_type(i))
796 : : return false;
797 : 137360 : type = this->types_[i];
798 : 137360 : go_assert(type != NULL);
799 : : }
800 : 174038 : Named_type* nt = type->named_type();
801 : 174038 : if (nt == NULL)
802 : : {
803 : 0 : go_error_at(this->location_,
804 : : "error in import data: exported unnamed type %d",
805 : : i);
806 : 0 : return false;
807 : : }
808 : 174038 : nt->set_is_visible();
809 : 174038 : if (this->add_to_globals_)
810 : 33 : this->gogo_->add_named_type(nt);
811 : : }
812 : :
813 : : return true;
814 : 21808 : }
815 : :
816 : : void
817 : 21808 : Import::finalize_methods()
818 : : {
819 : 21808 : Finalize_methods finalizer(this->gogo_);
820 : 21808 : Unordered_set(Type*) real_for_named;
821 : 3218999 : for (size_t i = 1; i < this->types_.size(); i++)
822 : : {
823 : 3197191 : Type* type = this->types_[i];
824 : 3197191 : if (type != NULL && type->named_type() != NULL)
825 : : {
826 : 663173 : finalizer.type(type);
827 : :
828 : : // If the real type is a struct type, we don't want to
829 : : // finalize its methods. For a named type defined as a
830 : : // struct type, we only want to finalize the methods of the
831 : : // named type. This is like Finalize_methods::type.
832 : 663173 : Type* real_type = type->named_type()->real_type();
833 : 1326346 : if (real_type->struct_type() != NULL)
834 : 422259 : real_for_named.insert(real_type);
835 : : }
836 : : }
837 : 3218999 : for (size_t i = 1; i < this->types_.size(); i++)
838 : : {
839 : 3197191 : Type* type = this->types_[i];
840 : 3197191 : if (type != NULL
841 : 1870210 : && type->named_type() == NULL
842 : 4404228 : && real_for_named.find(type) == real_for_named.end())
843 : 840815 : finalizer.type(type);
844 : : }
845 : 21808 : }
846 : :
847 : : // Import a constant.
848 : :
849 : : void
850 : 837398 : Import::import_const()
851 : : {
852 : 837398 : std::string name;
853 : 837398 : Type* type;
854 : 837398 : Expression* expr;
855 : 837398 : Named_constant::import_const(this, &name, &type, &expr);
856 : 837398 : Typed_identifier tid(name, type, this->location_);
857 : 837398 : Named_object* no = this->package_->add_constant(tid, expr);
858 : 837398 : if (this->add_to_globals_)
859 : 6 : this->gogo_->add_dot_import_object(no);
860 : 837398 : }
861 : :
862 : : // Import a type.
863 : :
864 : : void
865 : 0 : Import::import_type()
866 : : {
867 : 0 : if (this->version_ >= EXPORT_FORMAT_V3)
868 : : {
869 : 0 : if (!this->stream_->saw_error())
870 : : {
871 : 0 : go_error_at(this->location_,
872 : : "error in import data at %d: old type syntax",
873 : 0 : this->stream_->pos());
874 : 0 : this->stream_->set_saw_error();
875 : : }
876 : 0 : return;
877 : : }
878 : :
879 : 0 : Named_type* type;
880 : 0 : Named_type::import_named_type(this, &type);
881 : :
882 : : // The named type has been added to the package by the type import
883 : : // process. Here we need to make it visible to the parser, and it
884 : : // to the global bindings if necessary.
885 : 0 : type->set_is_visible();
886 : :
887 : 0 : if (this->add_to_globals_)
888 : 0 : this->gogo_->add_named_type(type);
889 : : }
890 : :
891 : : // Import a variable.
892 : :
893 : : void
894 : 326311 : Import::import_var()
895 : : {
896 : 326311 : std::string name;
897 : 326311 : Package* vpkg;
898 : 326311 : bool is_exported;
899 : 326311 : Type* type;
900 : 326311 : if (!Variable::import_var(this, &name, &vpkg, &is_exported, &type))
901 : 0 : return;
902 : 326311 : if (vpkg == NULL)
903 : 292670 : vpkg = this->package_;
904 : 326311 : if (!is_exported)
905 : 193687 : name = '.' + vpkg->pkgpath() + '.' + name;
906 : 326311 : Variable* var = new Variable(type, NULL, true, false, false,
907 : 326311 : this->location_);
908 : 326311 : Named_object* no;
909 : 326311 : no = vpkg->add_variable(name, var);
910 : 326311 : if (this->add_to_globals_ && vpkg == this->package_)
911 : 24 : this->gogo_->add_dot_import_object(no);
912 : 326311 : }
913 : :
914 : : // Import a function into PACKAGE. PACKAGE is normally
915 : : // THIS->PACKAGE_, but it will be different for a method associated
916 : : // with a type defined in a different package.
917 : :
918 : : void
919 : 3055849 : Import::import_func(Package* package)
920 : : {
921 : 3055849 : std::string name;
922 : 3055849 : Package* fpkg;
923 : 3055849 : bool is_exported;
924 : 3055849 : Typed_identifier* receiver;
925 : 3055849 : Typed_identifier_list* parameters;
926 : 3055849 : Typed_identifier_list* results;
927 : 3055849 : bool is_varargs;
928 : 3055849 : bool nointerface;
929 : 3055849 : std::string asm_name;
930 : 3055849 : std::string body;
931 : 3055849 : if (!Function::import_func(this, &name, &fpkg, &is_exported, &receiver,
932 : : ¶meters, &results, &is_varargs, &nointerface,
933 : : &asm_name, &body))
934 : : return;
935 : 3055849 : if (fpkg == NULL)
936 : 2846750 : fpkg = package;
937 : 3055849 : if (!is_exported)
938 : 1448859 : name = '.' + fpkg->pkgpath() + '.' + name;
939 : 3055849 : Function_type *fntype = Type::make_function_type(receiver, parameters,
940 : : results, this->location_);
941 : 3055849 : if (is_varargs)
942 : 52697 : fntype->set_is_varargs();
943 : :
944 : 3055849 : Location loc = this->location_;
945 : 3055849 : Named_object* no;
946 : 3055849 : if (fntype->is_method())
947 : : {
948 : 1784464 : Type* rtype = receiver->type();
949 : :
950 : : // We may still be reading the definition of RTYPE, so we have
951 : : // to be careful to avoid calling base or convert. If RTYPE is
952 : : // a named type or a forward declaration, then we know that it
953 : : // is not a pointer, because we are reading a method on RTYPE
954 : : // and named pointers can't have methods.
955 : :
956 : 1784464 : if (rtype->classification() == Type::TYPE_POINTER)
957 : 1351586 : rtype = rtype->points_to();
958 : :
959 : 1784464 : if (rtype->is_error_type())
960 : : return;
961 : 1784464 : else if (rtype->named_type() != NULL)
962 : 1784464 : no = rtype->named_type()->add_method_declaration(name, fpkg, fntype,
963 : : loc);
964 : 0 : else if (rtype->forward_declaration_type() != NULL)
965 : 0 : no = rtype->forward_declaration_type()->add_method_declaration(name,
966 : : fpkg,
967 : : fntype,
968 : : loc);
969 : : else
970 : 0 : go_unreachable();
971 : : }
972 : : else
973 : : {
974 : 1271385 : no = fpkg->add_function_declaration(name, fntype, loc);
975 : 1271385 : if (this->add_to_globals_ && fpkg == package)
976 : 105 : this->gogo_->add_dot_import_object(no);
977 : : }
978 : :
979 : 3055849 : if (nointerface)
980 : 2 : no->func_declaration_value()->set_nointerface();
981 : 3055849 : if (!asm_name.empty())
982 : 112194 : no->func_declaration_value()->set_asm_name(asm_name);
983 : 3055849 : if (!body.empty() && !no->func_declaration_value()->has_imported_body())
984 : 492072 : no->func_declaration_value()->set_imported_body(this, body);
985 : 3055849 : }
986 : :
987 : : // Read a type definition and initialize the entry in this->types_.
988 : : // This parses the type definition saved by read_types earlier. This
989 : : // returns true on success, false on failure.
990 : :
991 : : bool
992 : 1975892 : Import::parse_type(int i)
993 : : {
994 : 1975892 : go_assert(i >= 0 && static_cast<size_t>(i) < this->types_.size());
995 : 1975892 : go_assert(this->types_[i] == NULL);
996 : 1975892 : size_t offset = this->type_offsets_[i].first;
997 : 1975892 : size_t len = this->type_offsets_[i].second;
998 : :
999 : 1975892 : Stream* orig_stream = this->stream_;
1000 : :
1001 : 1975892 : Stream_from_string_ref stream(this->type_data_, offset, len);
1002 : 1975892 : stream.set_pos(this->type_pos_ + offset);
1003 : 1975892 : this->stream_ = &stream;
1004 : :
1005 : 1975892 : this->require_c_string("type ");
1006 : 1975892 : std::string str = this->read_identifier();
1007 : 1975892 : int id;
1008 : 1975892 : if (!this->string_to_int(str, false, &id))
1009 : : {
1010 : 0 : this->stream_ = orig_stream;
1011 : 0 : return false;
1012 : : }
1013 : 1975892 : if (i != id)
1014 : : {
1015 : 0 : go_error_at(this->location_,
1016 : : ("error in import data at %d: "
1017 : : "type ID mismatch: got %d, want %d"),
1018 : : stream.pos(), id, i);
1019 : 0 : this->stream_ = orig_stream;
1020 : 0 : return false;
1021 : : }
1022 : :
1023 : 1975892 : this->require_c_string(" ");
1024 : 1975892 : if (stream.peek_char() == '"')
1025 : : {
1026 : 663506 : stream.advance(1);
1027 : 663506 : Type* type = this->read_named_type(i);
1028 : 663506 : if (type->is_error_type())
1029 : : {
1030 : 0 : this->stream_ = orig_stream;
1031 : 0 : return false;
1032 : : }
1033 : : }
1034 : : else
1035 : : {
1036 : 1312386 : Type* type = Type::import_type(this);
1037 : 1312386 : if (type->is_error_type())
1038 : : {
1039 : 0 : this->stream_ = orig_stream;
1040 : 0 : return false;
1041 : : }
1042 : 1312386 : this->types_[i] = type;
1043 : :
1044 : 1312386 : this->require_c_string("\n");
1045 : : }
1046 : :
1047 : 1975892 : this->stream_ = orig_stream;
1048 : 1975892 : return true;
1049 : 1975892 : }
1050 : :
1051 : : // Read a type in the import stream. This records the type by the
1052 : : // type index. If the type is named (which can only happen with older
1053 : : // export formats), it registers the name, but marks it as invisible.
1054 : :
1055 : : Type*
1056 : 12323552 : Import::read_type()
1057 : : {
1058 : 12323552 : Stream* stream = this->stream_;
1059 : 12323552 : this->require_c_string("<type ");
1060 : :
1061 : 12323552 : std::string number;
1062 : 44572701 : int c;
1063 : 32249149 : while (true)
1064 : : {
1065 : 44572701 : c = stream->get_char();
1066 : 44572701 : if (c != '-' && (c < '0' || c > '9'))
1067 : : break;
1068 : 32249149 : number += c;
1069 : : }
1070 : :
1071 : 12323552 : int index;
1072 : 12323552 : if (!this->string_to_int(number, true, &index))
1073 : 0 : return Type::make_error_type();
1074 : :
1075 : 12323552 : if (c == '>')
1076 : : {
1077 : : // A reference to a type defined earlier.
1078 : 12323552 : bool parsed;
1079 : 12323552 : return this->type_for_index(index, "import data", stream->pos(),
1080 : : &parsed);
1081 : : }
1082 : :
1083 : 0 : if (this->version_ >= EXPORT_FORMAT_V3)
1084 : : {
1085 : 0 : if (!stream->saw_error())
1086 : 0 : go_error_at(this->location_,
1087 : : "error in import data at %d: expected %<>%>",
1088 : : stream->pos());
1089 : 0 : stream->set_saw_error();
1090 : 0 : return Type::make_error_type();
1091 : : }
1092 : :
1093 : 0 : if (c != ' ')
1094 : : {
1095 : 0 : if (!stream->saw_error())
1096 : 0 : go_error_at(this->location_,
1097 : : "error in import data at %d: expected %< %> or %<>%>",
1098 : : stream->pos());
1099 : 0 : stream->set_saw_error();
1100 : 0 : stream->advance(1);
1101 : 0 : return Type::make_error_type();
1102 : : }
1103 : :
1104 : 0 : if (index <= 0
1105 : 0 : || (static_cast<size_t>(index) < this->types_.size()
1106 : 0 : && this->types_[index] != NULL))
1107 : : {
1108 : 0 : go_error_at(this->location_,
1109 : : "error in import data at %d: type index already defined",
1110 : : stream->pos());
1111 : 0 : stream->set_saw_error();
1112 : 0 : return Type::make_error_type();
1113 : : }
1114 : :
1115 : 0 : if (static_cast<size_t>(index) >= this->types_.size())
1116 : : {
1117 : 0 : int newsize = std::max(static_cast<size_t>(index) + 1,
1118 : 0 : this->types_.size() * 2);
1119 : 0 : this->types_.resize(newsize, NULL);
1120 : : }
1121 : :
1122 : 0 : if (stream->peek_char() != '"')
1123 : : {
1124 : 0 : Type* type = Type::import_type(this);
1125 : 0 : this->require_c_string(">");
1126 : 0 : this->types_[index] = type;
1127 : 0 : return type;
1128 : : }
1129 : :
1130 : 0 : stream->advance(1);
1131 : :
1132 : 0 : Type* type = this->read_named_type(index);
1133 : :
1134 : 0 : this->require_c_string(">");
1135 : :
1136 : 0 : return type;
1137 : 12323552 : }
1138 : :
1139 : : // Read a named type from the import stream and store it in
1140 : : // this->types_[index]. The stream should be positioned immediately
1141 : : // after the '"' that starts the name.
1142 : :
1143 : : Type*
1144 : 663506 : Import::read_named_type(int index)
1145 : : {
1146 : 663506 : Stream* stream = this->stream_;
1147 : 663506 : std::string type_name;
1148 : 663506 : int c;
1149 : 10433420 : while ((c = stream->get_char()) != '"')
1150 : 9769914 : type_name += c;
1151 : :
1152 : : // If this type is in the package we are currently importing, the
1153 : : // name will be .PKGPATH.NAME or simply NAME with no dots.
1154 : : // Otherwise, a non-hidden symbol will be PKGPATH.NAME and a hidden
1155 : : // symbol will be .PKGPATH.NAME.
1156 : 663506 : std::string pkgpath;
1157 : 663506 : if (type_name.find('.') != std::string::npos)
1158 : : {
1159 : 489468 : size_t start = 0;
1160 : 489468 : if (type_name[0] == '.')
1161 : 294678 : start = 1;
1162 : 489468 : size_t dot = type_name.rfind('.');
1163 : 489468 : pkgpath = type_name.substr(start, dot - start);
1164 : 489468 : if (type_name[0] != '.')
1165 : 194790 : type_name.erase(0, dot + 1);
1166 : : }
1167 : :
1168 : 663506 : this->require_c_string(" ");
1169 : :
1170 : : // The package name may follow. This is the name of the package in
1171 : : // the package clause of that package. The type name will include
1172 : : // the pkgpath, which may be different.
1173 : 663506 : std::string package_name;
1174 : 663506 : if (stream->peek_char() == '"')
1175 : : {
1176 : 0 : stream->advance(1);
1177 : 0 : while ((c = stream->get_char()) != '"')
1178 : 0 : package_name += c;
1179 : 0 : this->require_c_string(" ");
1180 : : }
1181 : :
1182 : 663506 : bool in_heap = true;
1183 : 663506 : if (this->match_c_string("notinheap"))
1184 : : {
1185 : 23369 : this->require_c_string("notinheap ");
1186 : 23369 : in_heap = false;
1187 : : }
1188 : :
1189 : 663506 : bool is_alias = false;
1190 : 663506 : if (this->match_c_string("= "))
1191 : : {
1192 : 14776 : stream->advance(2);
1193 : 14776 : is_alias = true;
1194 : : }
1195 : :
1196 : : // Declare the type in the appropriate package. If we haven't seen
1197 : : // it before, mark it as invisible. We declare it before we read
1198 : : // the actual definition of the type, since the definition may refer
1199 : : // to the type itself.
1200 : 663506 : Package* package;
1201 : 663506 : if (pkgpath.empty() || pkgpath == this->gogo_->pkgpath())
1202 : 174038 : package = this->package_;
1203 : : else
1204 : : {
1205 : 489468 : package = this->gogo_->register_package(pkgpath, "",
1206 : : Linemap::unknown_location());
1207 : 489468 : if (!package_name.empty())
1208 : 0 : package->set_package_name(package_name, this->location());
1209 : : }
1210 : :
1211 : 663506 : Named_object* no = package->bindings()->lookup(type_name);
1212 : 663506 : if (no == NULL)
1213 : 586329 : no = package->add_type_declaration(type_name, this->location_);
1214 : 77177 : else if (!no->is_type_declaration() && !no->is_type())
1215 : : {
1216 : 0 : go_error_at(this->location_, "imported %<%s.%s%> both type and non-type",
1217 : 0 : pkgpath.c_str(), Gogo::message_name(type_name).c_str());
1218 : 0 : stream->set_saw_error();
1219 : 0 : return Type::make_error_type();
1220 : : }
1221 : : else
1222 : 77177 : go_assert(no->package() == package);
1223 : :
1224 : 663506 : if (this->types_[index] == NULL)
1225 : : {
1226 : 663506 : if (no->is_type_declaration())
1227 : : {
1228 : : // FIXME: It's silly to make a forward declaration every time.
1229 : 586329 : this->types_[index] = Type::make_forward_declaration(no);
1230 : : }
1231 : : else
1232 : : {
1233 : 77177 : go_assert(no->is_type());
1234 : 77177 : this->types_[index] = no->type_value();
1235 : : }
1236 : : }
1237 : :
1238 : : // If there is no type definition, then this is just a forward
1239 : : // declaration of a type defined in some other file.
1240 : 663506 : Type* type;
1241 : 663506 : if (this->match_c_string(">") || this->match_c_string("\n"))
1242 : : {
1243 : 0 : type = this->types_[index];
1244 : 0 : if (!in_heap)
1245 : 0 : go_error_at(this->location_,
1246 : : ("import error at %d for type index %d: "
1247 : : "forward declaration marked notinheap"),
1248 : : this->pos(), index);
1249 : : }
1250 : : else
1251 : : {
1252 : 663506 : if (no->is_type_declaration())
1253 : : {
1254 : : // We can define the type now.
1255 : :
1256 : 586329 : type = this->read_type();
1257 : :
1258 : 586329 : no = package->add_type(type_name, type, this->location_);
1259 : 586329 : Named_type* ntype = no->type_value();
1260 : :
1261 : : // This type has not yet been imported.
1262 : 586329 : ntype->clear_is_visible();
1263 : :
1264 : 586329 : if (!in_heap)
1265 : 23278 : ntype->set_not_in_heap();
1266 : 586329 : if (is_alias)
1267 : 13186 : ntype->set_is_alias();
1268 : :
1269 : 586329 : if (!type->is_undefined() && type->interface_type() != NULL)
1270 : 136970 : this->gogo_->record_interface_type(type->interface_type());
1271 : :
1272 : : type = ntype;
1273 : : }
1274 : 77177 : else if (no->is_type())
1275 : : {
1276 : : // We have seen this type before.
1277 : 77177 : type = no->type_value();
1278 : :
1279 : : // Don't change the visibility of the existing type.
1280 : :
1281 : : // For older export versions, we need to skip the type
1282 : : // definition in the stream.
1283 : 77177 : if (this->version_ < EXPORT_FORMAT_V3)
1284 : 0 : this->read_type();
1285 : : }
1286 : : else
1287 : 0 : go_unreachable();
1288 : :
1289 : 663506 : this->types_[index] = type;
1290 : :
1291 : : // Read the type methods.
1292 : 663506 : if (this->match_c_string("\n"))
1293 : : {
1294 : 586329 : this->advance(1);
1295 : 2957122 : while (this->match_c_string(" func"))
1296 : : {
1297 : 1784464 : this->advance(1);
1298 : 1784464 : this->import_func(package);
1299 : : }
1300 : : }
1301 : : }
1302 : :
1303 : : return type;
1304 : 663506 : }
1305 : :
1306 : : // Return the type given an index. Set *PARSED if we parsed it here.
1307 : :
1308 : : Type*
1309 : 12347551 : Import::type_for_index(int index, const std::string& input_name,
1310 : : size_t input_offset, bool* parsed)
1311 : : {
1312 : 12347551 : *parsed = false;
1313 : 12347551 : if (index >= 0 && !this->type_data_.empty())
1314 : : {
1315 : 6514116 : if (static_cast<size_t>(index) >= this->type_offsets_.size())
1316 : : {
1317 : 0 : go_error_at(this->location_,
1318 : : "error in %s at %lu: bad type index %d, max %d",
1319 : : input_name.c_str(),
1320 : : static_cast<unsigned long>(input_offset),
1321 : 0 : index, static_cast<int>(this->type_offsets_.size()));
1322 : 0 : return Type::make_error_type();
1323 : : }
1324 : :
1325 : 6514116 : if (this->types_[index] == NULL)
1326 : : {
1327 : 1838532 : if (!this->parse_type(index))
1328 : 0 : return Type::make_error_type();
1329 : 1838532 : *parsed = true;
1330 : : }
1331 : : }
1332 : :
1333 : 12347551 : if (index < 0
1334 : 12347551 : ? (static_cast<size_t>(- index) >= this->builtin_types_.size()
1335 : 5833435 : || this->builtin_types_[- index] == NULL)
1336 : 6514116 : : (static_cast<size_t>(index) >= this->types_.size()
1337 : 6514116 : || this->types_[index] == NULL))
1338 : : {
1339 : 0 : go_error_at(this->location_,
1340 : : "error in %s at %lu: bad type index %d",
1341 : : input_name.c_str(),
1342 : : static_cast<unsigned long>(input_offset), index);
1343 : 0 : return Type::make_error_type();
1344 : : }
1345 : :
1346 : 12347551 : return index < 0 ? this->builtin_types_[- index] : this->types_[index];
1347 : : }
1348 : :
1349 : : // Read an escape note.
1350 : :
1351 : : std::string
1352 : 6290244 : Import::read_escape()
1353 : : {
1354 : 6290244 : if (this->match_c_string(" <esc:"))
1355 : : {
1356 : 2196059 : Stream* stream = this->stream_;
1357 : 2196059 : this->require_c_string(" <esc:");
1358 : :
1359 : 2196059 : std::string escape = "esc:";
1360 : 9145292 : int c;
1361 : 6949233 : while (true)
1362 : : {
1363 : 9145292 : c = stream->get_char();
1364 : 9145292 : if (c != 'x' && !ISXDIGIT(c))
1365 : : break;
1366 : 6949233 : escape += c;
1367 : : }
1368 : :
1369 : 2196059 : if (c != '>')
1370 : : {
1371 : 0 : go_error_at(this->location(),
1372 : : ("error in import data at %d: "
1373 : : "expect %< %> or %<>%>, got %c"),
1374 : : stream->pos(), c);
1375 : 0 : stream->set_saw_error();
1376 : 0 : stream->advance(1);
1377 : 0 : escape = Escape_note::make_tag(Node::ESCAPE_UNKNOWN);
1378 : : }
1379 : : return escape;
1380 : : }
1381 : : else
1382 : 4094185 : return Escape_note::make_tag(Node::ESCAPE_UNKNOWN);
1383 : : }
1384 : :
1385 : :
1386 : : // Register the builtin types.
1387 : :
1388 : : void
1389 : 21808 : Import::register_builtin_types(Gogo* gogo)
1390 : : {
1391 : 21808 : this->register_builtin_type(gogo, "int8", BUILTIN_INT8);
1392 : 21808 : this->register_builtin_type(gogo, "int16", BUILTIN_INT16);
1393 : 21808 : this->register_builtin_type(gogo, "int32", BUILTIN_INT32);
1394 : 21808 : this->register_builtin_type(gogo, "int64", BUILTIN_INT64);
1395 : 21808 : this->register_builtin_type(gogo, "uint8", BUILTIN_UINT8);
1396 : 21808 : this->register_builtin_type(gogo, "uint16", BUILTIN_UINT16);
1397 : 21808 : this->register_builtin_type(gogo, "uint32", BUILTIN_UINT32);
1398 : 21808 : this->register_builtin_type(gogo, "uint64", BUILTIN_UINT64);
1399 : 21808 : this->register_builtin_type(gogo, "float32", BUILTIN_FLOAT32);
1400 : 21808 : this->register_builtin_type(gogo, "float64", BUILTIN_FLOAT64);
1401 : 21808 : this->register_builtin_type(gogo, "complex64", BUILTIN_COMPLEX64);
1402 : 21808 : this->register_builtin_type(gogo, "complex128", BUILTIN_COMPLEX128);
1403 : 21808 : this->register_builtin_type(gogo, "int", BUILTIN_INT);
1404 : 21808 : this->register_builtin_type(gogo, "uint", BUILTIN_UINT);
1405 : 21808 : this->register_builtin_type(gogo, "uintptr", BUILTIN_UINTPTR);
1406 : 21808 : this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
1407 : 21808 : this->register_builtin_type(gogo, "string", BUILTIN_STRING);
1408 : 21808 : this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
1409 : 21808 : this->register_builtin_type(gogo, "byte", BUILTIN_BYTE);
1410 : 21808 : this->register_builtin_type(gogo, "rune", BUILTIN_RUNE);
1411 : 21808 : this->register_builtin_type(gogo, "any", BUILTIN_ANY);
1412 : 21808 : }
1413 : :
1414 : : // Register a single builtin type.
1415 : :
1416 : : void
1417 : 457968 : Import::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
1418 : : {
1419 : 457968 : Named_object* named_object = gogo->lookup_global(name);
1420 : 457968 : go_assert(named_object != NULL && named_object->is_type());
1421 : 457968 : int index = - static_cast<int>(code);
1422 : 457968 : go_assert(index > 0
1423 : : && static_cast<size_t>(index) < this->builtin_types_.size());
1424 : 457968 : this->builtin_types_[index] = named_object->type_value();
1425 : 457968 : }
1426 : :
1427 : : // Characters that stop read_identifier. We base this on the
1428 : : // characters that stop an identifier, without worrying about
1429 : : // characters that are permitted in an identifier. That lets us skip
1430 : : // UTF-8 parsing.
1431 : : static const char * const identifier_stop = " \n;:,()[]";
1432 : :
1433 : : // Read an identifier from the stream.
1434 : :
1435 : : std::string
1436 : 27880101 : Import::read_identifier()
1437 : : {
1438 : 27880101 : std::string ret;
1439 : 27880101 : Stream* stream = this->stream_;
1440 : 162964950 : int c;
1441 : 298049799 : while (true)
1442 : : {
1443 : 162964950 : c = stream->peek_char();
1444 : 162964950 : if (c == -1 || strchr(identifier_stop, c) != NULL)
1445 : : break;
1446 : :
1447 : : // FIXME: Probably we shouldn't accept '.', but that might break
1448 : : // some existing imports.
1449 : 135084849 : if (c == '.' && stream->match_c_string("..."))
1450 : : break;
1451 : :
1452 : 135084849 : ret += c;
1453 : 135084849 : stream->advance(1);
1454 : : }
1455 : 27880101 : return ret;
1456 : : }
1457 : :
1458 : : // Read a possibly qualified identifier from IMP. The qualification
1459 : : // is <pID>, where ID is a package number. If the name has a leading
1460 : : // '.', it is not exported; otherwise, it is. Set *NAME, *PKG and
1461 : : // *IS_EXPORTED. Reports whether the read succeeded.
1462 : :
1463 : : bool
1464 : 3454531 : Import::read_qualified_identifier(Import_expression* imp, std::string* name,
1465 : : Package** pkg, bool* is_exported)
1466 : : {
1467 : 3454531 : *pkg = NULL;
1468 : 3454531 : if (imp->match_c_string("<p"))
1469 : : {
1470 : 246614 : imp->advance(2);
1471 : 246614 : char buf[50];
1472 : 246614 : char *pbuf = &buf[0];
1473 : 958780 : while (true)
1474 : : {
1475 : 602697 : int next = imp->peek_char();
1476 : 602697 : if (next == -1 || static_cast<size_t>(pbuf - buf) >= sizeof buf - 1)
1477 : 0 : return false;
1478 : 602697 : if (next == '>')
1479 : : {
1480 : 246614 : imp->advance(1);
1481 : 246614 : break;
1482 : : }
1483 : 356083 : *pbuf = static_cast<char>(next);
1484 : 356083 : ++pbuf;
1485 : 356083 : imp->advance(1);
1486 : 356083 : }
1487 : :
1488 : 246614 : *pbuf = '\0';
1489 : 246614 : char *end;
1490 : 246614 : long index = strtol(buf, &end, 10);
1491 : 246614 : if (*end != '\0'
1492 : 246614 : || index <= 0
1493 : 493228 : || static_cast<size_t>(index) > imp->max_package_index())
1494 : 0 : return false;
1495 : :
1496 : 246614 : *pkg = imp->package_at_index(index);
1497 : 246614 : go_assert(*pkg != NULL);
1498 : : }
1499 : :
1500 : 3454531 : *is_exported = true;
1501 : 3454531 : if (imp->match_c_string("."))
1502 : : {
1503 : 1648177 : imp->advance(1);
1504 : 1648177 : *is_exported = false;
1505 : : }
1506 : :
1507 : 3454531 : *name = imp->read_identifier();
1508 : :
1509 : 3454531 : return !name->empty();
1510 : : }
1511 : :
1512 : : // Read a name from the stream.
1513 : :
1514 : : std::string
1515 : 6597967 : Import::read_name()
1516 : : {
1517 : 6597967 : std::string ret = this->read_identifier();
1518 : 6597967 : if (ret == "?")
1519 : 625070 : ret.clear();
1520 : 6597967 : return ret;
1521 : : }
1522 : :
1523 : : // Read LENGTH bytes from the stream.
1524 : :
1525 : : void
1526 : 506685 : Import::read(size_t length, std::string* out)
1527 : : {
1528 : 506685 : const char* data;
1529 : 506685 : if (!this->stream_->peek(length, &data))
1530 : : {
1531 : 0 : if (!this->stream_->saw_error())
1532 : 0 : go_error_at(this->location_, "import error at %d: expected %d bytes",
1533 : 0 : this->stream_->pos(), static_cast<int>(length));
1534 : 0 : this->stream_->set_saw_error();
1535 : 0 : *out = std::string("");
1536 : 0 : return;
1537 : : }
1538 : 506685 : *out = std::string(data, length);
1539 : 506685 : this->advance(length);
1540 : : }
1541 : :
1542 : : // Turn a string into a integer with appropriate error handling.
1543 : :
1544 : : bool
1545 : 24145609 : Import::string_to_int(const std::string &s, bool is_neg_ok, int* ret)
1546 : : {
1547 : 24145609 : char* end;
1548 : 24145609 : long prio = strtol(s.c_str(), &end, 10);
1549 : 24145609 : if (*end != '\0' || prio > 0x7fffffff || (prio < 0 && !is_neg_ok))
1550 : : {
1551 : 0 : go_error_at(this->location_, "invalid integer in import data at %d",
1552 : 0 : this->stream_->pos());
1553 : 0 : this->stream_->set_saw_error();
1554 : 0 : return false;
1555 : : }
1556 : 24145609 : *ret = prio;
1557 : 24145609 : return true;
1558 : : }
1559 : :
1560 : : // Class Import::Stream.
1561 : :
1562 : 1998402 : Import::Stream::Stream()
1563 : 1998402 : : pos_(0), saw_error_(false)
1564 : : {
1565 : 1998402 : }
1566 : :
1567 : 1998402 : Import::Stream::~Stream()
1568 : : {
1569 : 1998402 : }
1570 : :
1571 : : // Return the next character to come from the stream.
1572 : :
1573 : : int
1574 : 267166873 : Import::Stream::peek_char()
1575 : : {
1576 : 267166873 : const char* read;
1577 : 267166873 : if (!this->do_peek(1, &read))
1578 : : return -1;
1579 : : // Make sure we return an unsigned char, so that we don't get
1580 : : // confused by \xff.
1581 : 267145065 : unsigned char ret = *read;
1582 : 267145065 : return ret;
1583 : : }
1584 : :
1585 : : // Return true if the next LENGTH characters from the stream match
1586 : : // BYTES
1587 : :
1588 : : bool
1589 : 60818909 : Import::Stream::match_bytes(const char* bytes, size_t length)
1590 : : {
1591 : 60818909 : const char* read;
1592 : 60818909 : if (!this->do_peek(length, &read))
1593 : : return false;
1594 : 59994332 : return memcmp(bytes, read, length) == 0;
1595 : : }
1596 : :
1597 : : // Require that the next LENGTH bytes from the stream match BYTES.
1598 : :
1599 : : void
1600 : 74512178 : Import::Stream::require_bytes(Location location, const char* bytes,
1601 : : size_t length)
1602 : : {
1603 : 74512178 : const char* read;
1604 : 74512178 : if (!this->do_peek(length, &read)
1605 : 74512178 : || memcmp(bytes, read, length) != 0)
1606 : : {
1607 : 0 : if (!this->saw_error_)
1608 : 0 : go_error_at(location, "import error at %d: expected %<%.*s%>",
1609 : : this->pos(), static_cast<int>(length), bytes);
1610 : 0 : this->saw_error_ = true;
1611 : 0 : return;
1612 : : }
1613 : 74512178 : this->advance(length);
1614 : : }
1615 : :
1616 : : // Class Stream_from_file.
1617 : :
1618 : 0 : Stream_from_file::Stream_from_file(int fd)
1619 : 0 : : fd_(fd), data_()
1620 : : {
1621 : 0 : if (lseek(fd, 0, SEEK_SET) != 0)
1622 : : {
1623 : 0 : go_fatal_error(Linemap::unknown_location(), "lseek failed: %m");
1624 : 0 : this->set_saw_error();
1625 : : }
1626 : 0 : }
1627 : :
1628 : 0 : Stream_from_file::~Stream_from_file()
1629 : : {
1630 : 0 : close(this->fd_);
1631 : 0 : }
1632 : :
1633 : : // Read next bytes.
1634 : :
1635 : : bool
1636 : 0 : Stream_from_file::do_peek(size_t length, const char** bytes)
1637 : : {
1638 : 0 : if (this->data_.length() >= length)
1639 : : {
1640 : 0 : *bytes = this->data_.data();
1641 : 0 : return true;
1642 : : }
1643 : :
1644 : 0 : this->data_.resize(length);
1645 : 0 : ssize_t got = ::read(this->fd_, &this->data_[0], length);
1646 : :
1647 : 0 : if (got < 0)
1648 : : {
1649 : 0 : if (!this->saw_error())
1650 : 0 : go_fatal_error(Linemap::unknown_location(), "read failed: %m");
1651 : 0 : this->set_saw_error();
1652 : 0 : return false;
1653 : : }
1654 : :
1655 : 0 : if (lseek(this->fd_, - got, SEEK_CUR) < 0)
1656 : : {
1657 : 0 : if (!this->saw_error())
1658 : 0 : go_fatal_error(Linemap::unknown_location(), "lseek failed: %m");
1659 : 0 : this->set_saw_error();
1660 : 0 : return false;
1661 : : }
1662 : :
1663 : 0 : if (static_cast<size_t>(got) < length)
1664 : : return false;
1665 : :
1666 : 0 : *bytes = this->data_.data();
1667 : 0 : return true;
1668 : : }
1669 : :
1670 : : // Advance.
1671 : :
1672 : : void
1673 : 0 : Stream_from_file::do_advance(size_t skip)
1674 : : {
1675 : 0 : if (lseek(this->fd_, skip, SEEK_CUR) < 0)
1676 : : {
1677 : 0 : if (!this->saw_error())
1678 : 0 : go_fatal_error(Linemap::unknown_location(), "lseek failed: %m");
1679 : 0 : this->set_saw_error();
1680 : : }
1681 : 0 : if (!this->data_.empty())
1682 : : {
1683 : 0 : if (this->data_.length() > skip)
1684 : 0 : this->data_.erase(0, skip);
1685 : : else
1686 : 0 : this->data_.clear();
1687 : : }
1688 : 0 : }
1689 : :
1690 : : // Class Import_function_body.
1691 : :
1692 : 12247 : Import_function_body::Import_function_body(Gogo* gogo,
1693 : : Import* imp,
1694 : : Named_object* named_object,
1695 : : const std::string& body,
1696 : : size_t off,
1697 : : Block* block,
1698 : 12247 : int indent)
1699 : 12247 : : gogo_(gogo), imp_(imp), named_object_(named_object), body_(body),
1700 : 12247 : off_(off), indent_(indent), temporaries_(), labels_(),
1701 : 12247 : saw_error_(false)
1702 : : {
1703 : 12247 : this->blocks_.push_back(block);
1704 : 12247 : }
1705 : :
1706 : 12247 : Import_function_body::~Import_function_body()
1707 : : {
1708 : : // At this point we should be left with the original outer block only.
1709 : 12247 : go_assert(saw_errors() || this->blocks_.size() == 1);
1710 : 12247 : }
1711 : :
1712 : : // The name of the function we are parsing.
1713 : :
1714 : : const std::string&
1715 : 23999 : Import_function_body::name() const
1716 : : {
1717 : 23999 : return this->named_object_->name();
1718 : : }
1719 : :
1720 : : // Class Import_function_body.
1721 : :
1722 : : // Require that the next bytes match STR, issuing an error if not.
1723 : : // Advance past the string.
1724 : :
1725 : : void
1726 : 213628 : Import_function_body::require_c_string(const char* str)
1727 : : {
1728 : 213628 : if (!this->match_c_string(str))
1729 : : {
1730 : 0 : if (!this->saw_error_)
1731 : 0 : go_error_at(this->location(),
1732 : : "invalid export data for %qs: expected %qs at %lu",
1733 : 0 : this->name().c_str(), str,
1734 : 0 : static_cast<unsigned long>(this->off_));
1735 : 0 : this->saw_error_ = true;
1736 : 0 : return;
1737 : : }
1738 : 213628 : this->advance(strlen(str));
1739 : : }
1740 : :
1741 : : // Read an identifier.
1742 : :
1743 : : std::string
1744 : 98951 : Import_function_body::read_identifier()
1745 : : {
1746 : 98951 : size_t start = this->off_;
1747 : 536275 : for (size_t i = start; i < this->body_.length(); i++)
1748 : : {
1749 : 536275 : int c = static_cast<unsigned char>(this->body_[i]);
1750 : 536275 : if (strchr(identifier_stop, c) != NULL)
1751 : : {
1752 : 98657 : this->off_ = i;
1753 : 98657 : return this->body_.substr(start, i - start);
1754 : : }
1755 : :
1756 : : // FIXME: Probably we shouldn't accept '.', but that might break
1757 : : // some existing imports.
1758 : 437618 : if (c == '.'
1759 : 880 : && i + 2 < this->body_.length()
1760 : 880 : && this->body_[i + 1] == '.'
1761 : 437915 : && this->body_[i + 2] == '.')
1762 : : {
1763 : 294 : this->off_ = i;
1764 : 294 : return this->body_.substr(start, i - start);
1765 : : }
1766 : : }
1767 : 0 : this->off_ = this->body_.length();
1768 : 0 : return this->body_.substr(start);
1769 : : }
1770 : :
1771 : : // Read a type.
1772 : :
1773 : : Type*
1774 : 23999 : Import_function_body::read_type()
1775 : : {
1776 : 23999 : this->require_c_string("<type ");
1777 : 23999 : size_t start = this->off_;
1778 : 23999 : size_t i;
1779 : 23999 : int c = '\0';
1780 : 86597 : for (i = start; i < this->body_.length(); ++i)
1781 : : {
1782 : 86597 : c = static_cast<unsigned char>(this->body_[i]);
1783 : 86597 : if (c != '-' && (c < '0' || c > '9'))
1784 : : break;
1785 : : }
1786 : 23999 : this->off_ = i + 1;
1787 : :
1788 : 23999 : char *end;
1789 : 23999 : std::string num = this->body_.substr(start, i - start);
1790 : 23999 : long val = strtol(num.c_str(), &end, 10);
1791 : 23999 : if (*end != '\0' || val > 0x7fffffff)
1792 : : {
1793 : 0 : if (!this->saw_error_)
1794 : 0 : go_error_at(this->location(),
1795 : : "invalid export data for %qs: expected integer at %lu",
1796 : 0 : this->name().c_str(),
1797 : : static_cast<unsigned long>(start));
1798 : 0 : this->saw_error_ = true;
1799 : 0 : return Type::make_error_type();
1800 : : }
1801 : :
1802 : 23999 : if (c != '>')
1803 : : {
1804 : 0 : if (!this->saw_error_)
1805 : 0 : go_error_at(this->location(),
1806 : : "invalid export data for %qs: expected %<>%> at %lu",
1807 : 0 : this->name().c_str(),
1808 : : static_cast<unsigned long>(i));
1809 : 0 : this->saw_error_ = true;
1810 : 0 : return Type::make_error_type();
1811 : : }
1812 : :
1813 : 23999 : bool parsed;
1814 : 23999 : Type* type = this->imp_->type_for_index(static_cast<int>(val), this->name(),
1815 : : static_cast<unsigned long>(start),
1816 : : &parsed);
1817 : :
1818 : : // If we just read this type's information, its methods will not
1819 : : // have been finalized. Do that now.
1820 : 23999 : if (parsed)
1821 : 563 : this->gogo_->finalize_methods_for_type(type);
1822 : :
1823 : : return type;
1824 : 23999 : }
1825 : :
1826 : : // Return the next size to use for a vector mapping indexes to values.
1827 : :
1828 : : size_t
1829 : 1378 : Import_function_body::next_size(size_t have)
1830 : : {
1831 : 1378 : if (have == 0)
1832 : : return 8;
1833 : 0 : else if (have < 256)
1834 : 0 : return have * 2;
1835 : : else
1836 : 0 : return have + 64;
1837 : : }
1838 : :
1839 : : // Record the index of a temporary statement.
1840 : :
1841 : : void
1842 : 2661 : Import_function_body::record_temporary(Temporary_statement* temp,
1843 : : unsigned int idx)
1844 : : {
1845 : 2661 : size_t have = this->temporaries_.size();
1846 : 3353 : while (static_cast<size_t>(idx) >= have)
1847 : : {
1848 : 692 : size_t want = Import_function_body::next_size(have);
1849 : 692 : this->temporaries_.resize(want, NULL);
1850 : 692 : have = want;
1851 : : }
1852 : 2661 : this->temporaries_[idx] = temp;
1853 : 2661 : }
1854 : :
1855 : : // Return a temporary statement given an index.
1856 : :
1857 : : Temporary_statement*
1858 : 3923 : Import_function_body::temporary_statement(unsigned int idx)
1859 : : {
1860 : 3923 : if (static_cast<size_t>(idx) >= this->temporaries_.size())
1861 : : return NULL;
1862 : 3923 : return this->temporaries_[idx];
1863 : : }
1864 : :
1865 : : // Return an unnamed label given an index, defining the label if we
1866 : : // haven't seen it already.
1867 : :
1868 : : Unnamed_label*
1869 : 2955 : Import_function_body::unnamed_label(unsigned int idx, Location loc)
1870 : : {
1871 : 2955 : size_t have = this->labels_.size();
1872 : 3641 : while (static_cast<size_t>(idx) >= have)
1873 : : {
1874 : 686 : size_t want = Import_function_body::next_size(have);
1875 : 686 : this->labels_.resize(want, NULL);
1876 : 686 : have = want;
1877 : : }
1878 : 2955 : Unnamed_label* label = this->labels_[idx];
1879 : 2955 : if (label == NULL)
1880 : : {
1881 : 1433 : label = new Unnamed_label(loc);
1882 : 1433 : this->labels_[idx] = label;
1883 : : }
1884 : 2955 : return label;
1885 : : }
|