Mercurial > hg > CbC > CbC_gcc
comparison gcc/go/gofrontend/export.cc @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
24 const int Export::magic_len; | 24 const int Export::magic_len; |
25 | 25 |
26 // Current version magic string. | 26 // Current version magic string. |
27 const char Export::cur_magic[Export::magic_len] = | 27 const char Export::cur_magic[Export::magic_len] = |
28 { | 28 { |
29 'v', '2', ';', '\n' | 29 'v', '3', ';', '\n' |
30 }; | 30 }; |
31 | 31 |
32 // Magic string for previous version (still supported) | 32 // Magic strings for previous versions (still supported). |
33 const char Export::v1_magic[Export::magic_len] = | 33 const char Export::v1_magic[Export::magic_len] = |
34 { | 34 { |
35 'v', '1', ';', '\n' | 35 'v', '1', ';', '\n' |
36 }; | 36 }; |
37 const char Export::v2_magic[Export::magic_len] = | |
38 { | |
39 'v', '2', ';', '\n' | |
40 }; | |
37 | 41 |
38 const int Export::checksum_len; | 42 const int Export::checksum_len; |
39 | 43 |
40 // Constructor. | 44 // Constructor. |
41 | 45 |
42 Export::Export(Stream* stream) | 46 Export::Export(Stream* stream) |
43 : stream_(stream), type_refs_(), type_index_(1), packages_() | 47 : stream_(stream), type_index_(1), packages_() |
44 { | 48 { |
45 go_assert(Export::checksum_len == Go_sha1_helper::checksum_len); | 49 go_assert(Export::checksum_len == Go_sha1_helper::checksum_len); |
46 } | 50 } |
51 | |
52 // Type hash table operations, treating aliases as distinct. | |
53 | |
54 class Type_hash_alias_identical | |
55 { | |
56 public: | |
57 unsigned int | |
58 operator()(const Type* type) const | |
59 { | |
60 return type->hash_for_method(NULL, | |
61 (Type::COMPARE_ERRORS | |
62 | Type::COMPARE_TAGS | |
63 | Type::COMPARE_ALIASES)); | |
64 } | |
65 }; | |
66 | |
67 class Type_alias_identical | |
68 { | |
69 public: | |
70 bool | |
71 operator()(const Type* t1, const Type* t2) const | |
72 { | |
73 return Type::are_identical(t1, t2, | |
74 (Type::COMPARE_ERRORS | |
75 | Type::COMPARE_TAGS | |
76 | Type::COMPARE_ALIASES), | |
77 NULL); | |
78 } | |
79 }; | |
80 | |
81 // Mapping from Type objects to a constant index. This would be nicer | |
82 // as a field in Export, but then export.h would have to #include | |
83 // types.h. | |
84 | |
85 typedef Unordered_map_hash(const Type*, int, Type_hash_alias_identical, | |
86 Type_alias_identical) Type_refs; | |
87 | |
88 static Type_refs type_refs; | |
47 | 89 |
48 // A functor to sort Named_object pointers by name. | 90 // A functor to sort Named_object pointers by name. |
49 | 91 |
50 struct Sort_bindings | 92 struct Sort_bindings |
51 { | 93 { |
69 | 111 |
70 // We don't export hidden names. | 112 // We don't export hidden names. |
71 if (Gogo::is_hidden_name(no->name())) | 113 if (Gogo::is_hidden_name(no->name())) |
72 return false; | 114 return false; |
73 | 115 |
74 // We don't export nested functions. | 116 // We don't export various special functions. |
75 if (no->is_function() && no->func_value()->enclosing() != NULL) | 117 if (Gogo::is_special_name(no->name())) |
76 return false; | |
77 | |
78 // We don't export thunks. | |
79 if (no->is_function() && Gogo::is_thunk(no)) | |
80 return false; | 118 return false; |
81 | 119 |
82 // Methods are exported with the type, not here. | 120 // Methods are exported with the type, not here. |
83 if (no->is_function() | 121 if (no->is_function() |
84 && no->func_value()->type()->is_method()) | 122 && no->func_value()->type()->is_method()) |
137 exports.push_back(p->second); | 175 exports.push_back(p->second); |
138 } | 176 } |
139 | 177 |
140 std::sort(exports.begin(), exports.end(), Sort_bindings()); | 178 std::sort(exports.begin(), exports.end(), Sort_bindings()); |
141 | 179 |
180 // Assign indexes to all exported types and types referenced by | |
181 // exported types, and collect all packages mentioned. | |
182 Unordered_set(const Package*) type_imports; | |
183 int unexported_type_index = this->prepare_types(&exports, &type_imports); | |
184 | |
142 // Although the export data is readable, at least this version is, | 185 // Although the export data is readable, at least this version is, |
143 // it is conceptually a binary format. Start with a four byte | 186 // it is conceptually a binary format. Start with a four byte |
144 // version number. | 187 // version number. |
145 this->write_bytes(Export::cur_magic, Export::magic_len); | 188 this->write_bytes(Export::cur_magic, Export::magic_len); |
146 | 189 |
147 // The package name. | 190 // The package name. |
148 this->write_c_string("package "); | 191 this->write_c_string("package "); |
149 this->write_string(package_name); | 192 this->write_string(package_name); |
150 this->write_c_string(";\n"); | 193 this->write_c_string("\n"); |
151 | 194 |
152 // The prefix or package path, used for all global symbols. | 195 // The prefix or package path, used for all global symbols. |
153 if (prefix.empty()) | 196 if (prefix.empty()) |
154 { | 197 { |
155 go_assert(!pkgpath.empty()); | 198 go_assert(!pkgpath.empty()); |
159 else | 202 else |
160 { | 203 { |
161 this->write_c_string("prefix "); | 204 this->write_c_string("prefix "); |
162 this->write_string(prefix); | 205 this->write_string(prefix); |
163 } | 206 } |
164 this->write_c_string(";\n"); | 207 this->write_c_string("\n"); |
165 | 208 |
166 this->write_packages(packages); | 209 this->write_packages(packages); |
167 | 210 |
168 this->write_imports(imports); | 211 this->write_imports(imports, type_imports); |
169 | 212 |
170 this->write_imported_init_fns(package_name, import_init_fn, | 213 this->write_imported_init_fns(package_name, import_init_fn, |
171 imported_init_fns); | 214 imported_init_fns); |
172 | 215 |
173 // FIXME: It might be clever to add something about the processor | 216 // FIXME: It might be clever to add something about the processor |
174 // and ABI being used, although ideally any problems in that area | 217 // and ABI being used, although ideally any problems in that area |
175 // would be caught by the linker. | 218 // would be caught by the linker. |
176 | 219 |
220 // Write out all the types, both exported and not. | |
221 this->write_types(unexported_type_index); | |
222 | |
223 // Write out the non-type export data. | |
177 for (std::vector<Named_object*>::const_iterator p = exports.begin(); | 224 for (std::vector<Named_object*>::const_iterator p = exports.begin(); |
178 p != exports.end(); | 225 p != exports.end(); |
179 ++p) | 226 ++p) |
180 (*p)->export_named_object(this); | 227 { |
228 if (!(*p)->is_type()) | |
229 (*p)->export_named_object(this); | |
230 } | |
181 | 231 |
182 std::string checksum = this->stream_->checksum(); | 232 std::string checksum = this->stream_->checksum(); |
183 std::string s = "checksum "; | 233 std::string s = "checksum "; |
184 for (std::string::const_iterator p = checksum.begin(); | 234 for (std::string::const_iterator p = checksum.begin(); |
185 p != checksum.end(); | 235 p != checksum.end(); |
189 unsigned int dig = c >> 4; | 239 unsigned int dig = c >> 4; |
190 s += dig < 10 ? '0' + dig : 'A' + dig - 10; | 240 s += dig < 10 ? '0' + dig : 'A' + dig - 10; |
191 dig = c & 0xf; | 241 dig = c & 0xf; |
192 s += dig < 10 ? '0' + dig : 'A' + dig - 10; | 242 s += dig < 10 ? '0' + dig : 'A' + dig - 10; |
193 } | 243 } |
194 s += ";\n"; | 244 s += "\n"; |
195 this->stream_->write_checksum(s); | 245 this->stream_->write_checksum(s); |
246 } | |
247 | |
248 // Traversal class to find referenced types. | |
249 | |
250 class Find_types_to_prepare : public Traverse | |
251 { | |
252 public: | |
253 Find_types_to_prepare(Export* exp, | |
254 Unordered_set(const Package*)* imports) | |
255 : Traverse(traverse_types), | |
256 exp_(exp), imports_(imports) | |
257 { } | |
258 | |
259 int | |
260 type(Type* type); | |
261 | |
262 // Traverse the components of a function type. | |
263 void | |
264 traverse_function(Function_type*); | |
265 | |
266 // Traverse the methods of a named type, and register its package. | |
267 void | |
268 traverse_named_type(Named_type*); | |
269 | |
270 private: | |
271 // Exporters. | |
272 Export* exp_; | |
273 // List of packages we are building. | |
274 Unordered_set(const Package*)* imports_; | |
275 }; | |
276 | |
277 // Set type index of referenced type, record package imports, and make | |
278 // sure we traverse methods of named types. | |
279 | |
280 int | |
281 Find_types_to_prepare::type(Type* type) | |
282 { | |
283 // Skip forwarders; don't try to give them a type index. | |
284 if (type->forward_declaration_type() != NULL) | |
285 return TRAVERSE_CONTINUE; | |
286 | |
287 // Skip the void type, which we'll see when exporting | |
288 // unsafe.Pointer. The void type is not itself exported, because | |
289 // Pointer_type::do_export checks for it. | |
290 if (type->is_void_type()) | |
291 return TRAVERSE_SKIP_COMPONENTS; | |
292 | |
293 if (!this->exp_->set_type_index(type)) | |
294 { | |
295 // We've already seen this type. | |
296 return TRAVERSE_SKIP_COMPONENTS; | |
297 } | |
298 | |
299 // At this stage of compilation traversing interface types traverses | |
300 // the final list of methods, but we export the locally defined | |
301 // methods. If there is an embedded interface type we need to make | |
302 // sure to export that. Check classification, rather than calling | |
303 // the interface_type method, because we want to handle named types | |
304 // below. | |
305 if (type->classification() == Type::TYPE_INTERFACE) | |
306 { | |
307 Interface_type* it = type->interface_type(); | |
308 const Typed_identifier_list* methods = it->local_methods(); | |
309 if (methods != NULL) | |
310 { | |
311 for (Typed_identifier_list::const_iterator p = methods->begin(); | |
312 p != methods->end(); | |
313 ++p) | |
314 { | |
315 if (p->name().empty()) | |
316 Type::traverse(p->type(), this); | |
317 else | |
318 this->traverse_function(p->type()->function_type()); | |
319 } | |
320 } | |
321 return TRAVERSE_SKIP_COMPONENTS; | |
322 } | |
323 | |
324 Named_type* nt = type->named_type(); | |
325 if (nt != NULL) | |
326 this->traverse_named_type(nt); | |
327 | |
328 return TRAVERSE_CONTINUE; | |
329 } | |
330 | |
331 // Traverse the types in a function type. We don't need the function | |
332 // type itself, just the receiver, parameter, and result types. | |
333 | |
334 void | |
335 Find_types_to_prepare::traverse_function(Function_type* type) | |
336 { | |
337 go_assert(type != NULL); | |
338 if (this->remember_type(type)) | |
339 return; | |
340 const Typed_identifier* receiver = type->receiver(); | |
341 if (receiver != NULL) | |
342 Type::traverse(receiver->type(), this); | |
343 const Typed_identifier_list* parameters = type->parameters(); | |
344 if (parameters != NULL) | |
345 parameters->traverse(this); | |
346 const Typed_identifier_list* results = type->results(); | |
347 if (results != NULL) | |
348 results->traverse(this); | |
349 } | |
350 | |
351 // Traverse the methods of a named type, and record its package. | |
352 | |
353 void | |
354 Find_types_to_prepare::traverse_named_type(Named_type* nt) | |
355 { | |
356 const Package* package = nt->named_object()->package(); | |
357 if (package != NULL) | |
358 this->imports_->insert(package); | |
359 | |
360 // We have to traverse the methods of named types, because we are | |
361 // going to export them. This is not done by ordinary type | |
362 // traversal. | |
363 const Bindings* methods = nt->local_methods(); | |
364 if (methods != NULL) | |
365 { | |
366 for (Bindings::const_definitions_iterator pm = | |
367 methods->begin_definitions(); | |
368 pm != methods->end_definitions(); | |
369 ++pm) | |
370 this->traverse_function((*pm)->func_value()->type()); | |
371 | |
372 for (Bindings::const_declarations_iterator pm = | |
373 methods->begin_declarations(); | |
374 pm != methods->end_declarations(); | |
375 ++pm) | |
376 { | |
377 Named_object* mno = pm->second; | |
378 if (mno->is_function_declaration()) | |
379 this->traverse_function(mno->func_declaration_value()->type()); | |
380 } | |
381 } | |
382 } | |
383 | |
384 // Prepare to export types by assigning a type index to every exported | |
385 // type and every type referenced by an exported type. Also collect | |
386 // all the packages we see in types, so that if we refer to any types | |
387 // from indirectly imported packages we can tell the importer about | |
388 // the package. This returns the number of exported types. | |
389 | |
390 int | |
391 Export::prepare_types(const std::vector<Named_object*>* exports, | |
392 Unordered_set(const Package*)* imports) | |
393 { | |
394 // Assign indexes to all the exported types. | |
395 for (std::vector<Named_object*>::const_iterator p = exports->begin(); | |
396 p != exports->end(); | |
397 ++p) | |
398 { | |
399 if (!(*p)->is_type()) | |
400 continue; | |
401 this->set_type_index((*p)->type_value()); | |
402 } | |
403 | |
404 int ret = this->type_index_; | |
405 | |
406 // Use a single instance of the traversal class because traversal | |
407 // classes keep track of which types they've already seen. That | |
408 // lets us avoid type reference loops. | |
409 Find_types_to_prepare find(this, imports); | |
410 | |
411 // Traverse all the exported objects and assign indexes to all types. | |
412 for (std::vector<Named_object*>::const_iterator p = exports->begin(); | |
413 p != exports->end(); | |
414 ++p) | |
415 { | |
416 Named_object* no = *p; | |
417 switch (no->classification()) | |
418 { | |
419 case Named_object::NAMED_OBJECT_CONST: | |
420 { | |
421 Type* t = no->const_value()->type(); | |
422 if (t != NULL && !t->is_abstract()) | |
423 Type::traverse(t, &find); | |
424 } | |
425 break; | |
426 | |
427 case Named_object::NAMED_OBJECT_TYPE: | |
428 Type::traverse(no->type_value()->real_type(), &find); | |
429 find.traverse_named_type(no->type_value()); | |
430 break; | |
431 | |
432 case Named_object::NAMED_OBJECT_VAR: | |
433 Type::traverse(no->var_value()->type(), &find); | |
434 break; | |
435 | |
436 case Named_object::NAMED_OBJECT_FUNC: | |
437 find.traverse_function(no->func_value()->type()); | |
438 break; | |
439 | |
440 case Named_object::NAMED_OBJECT_FUNC_DECLARATION: | |
441 find.traverse_function(no->func_declaration_value()->type()); | |
442 break; | |
443 | |
444 default: | |
445 // We shouldn't see anything else. If we do we'll give an | |
446 // error later when we try to actually export it. | |
447 break; | |
448 } | |
449 } | |
450 | |
451 return ret; | |
452 } | |
453 | |
454 // Give a type an index if it doesn't already have one. Return true | |
455 // if we set the type index, false if it was already known. | |
456 | |
457 bool | |
458 Export::set_type_index(Type* type) | |
459 { | |
460 type = type->forwarded(); | |
461 | |
462 std::pair<Type_refs::iterator, bool> ins = | |
463 type_refs.insert(std::make_pair(type, 0)); | |
464 if (!ins.second) | |
465 { | |
466 // We've already seen this type. | |
467 return false; | |
468 } | |
469 | |
470 int index = this->type_index_; | |
471 ++this->type_index_; | |
472 ins.first->second = index; | |
473 | |
474 return true; | |
196 } | 475 } |
197 | 476 |
198 // Sort packages. | 477 // Sort packages. |
199 | 478 |
200 static bool | 479 static bool |
231 this->write_string((*p)->package_name()); | 510 this->write_string((*p)->package_name()); |
232 this->write_c_string(" "); | 511 this->write_c_string(" "); |
233 this->write_string((*p)->pkgpath()); | 512 this->write_string((*p)->pkgpath()); |
234 this->write_c_string(" "); | 513 this->write_c_string(" "); |
235 this->write_string((*p)->pkgpath_symbol()); | 514 this->write_string((*p)->pkgpath_symbol()); |
236 this->write_c_string(";\n"); | 515 this->write_c_string("\n"); |
237 } | 516 } |
238 } | 517 } |
239 | 518 |
240 // Sort imported packages. | 519 // Sort imported packages. |
241 | 520 |
247 } | 526 } |
248 | 527 |
249 // Write out the imported packages. | 528 // Write out the imported packages. |
250 | 529 |
251 void | 530 void |
252 Export::write_imports(const std::map<std::string, Package*>& imports) | 531 Export::write_imports(const std::map<std::string, Package*>& imports, |
532 const Unordered_set(const Package*)& type_imports) | |
253 { | 533 { |
254 // Sort the imports for more consistent output. | 534 // Sort the imports for more consistent output. |
535 Unordered_set(const Package*) seen; | |
255 std::vector<std::pair<std::string, Package*> > sorted_imports; | 536 std::vector<std::pair<std::string, Package*> > sorted_imports; |
256 for (std::map<std::string, Package*>::const_iterator p = imports.begin(); | 537 for (std::map<std::string, Package*>::const_iterator p = imports.begin(); |
257 p != imports.end(); | 538 p != imports.end(); |
258 ++p) | 539 ++p) |
259 sorted_imports.push_back(std::make_pair(p->first, p->second)); | 540 { |
541 sorted_imports.push_back(std::make_pair(p->first, p->second)); | |
542 seen.insert(p->second); | |
543 } | |
260 | 544 |
261 std::sort(sorted_imports.begin(), sorted_imports.end(), import_compare); | 545 std::sort(sorted_imports.begin(), sorted_imports.end(), import_compare); |
262 | 546 |
263 for (std::vector<std::pair<std::string, Package*> >::const_iterator p = | 547 for (std::vector<std::pair<std::string, Package*> >::const_iterator p = |
264 sorted_imports.begin(); | 548 sorted_imports.begin(); |
269 this->write_string(p->second->package_name()); | 553 this->write_string(p->second->package_name()); |
270 this->write_c_string(" "); | 554 this->write_c_string(" "); |
271 this->write_string(p->second->pkgpath()); | 555 this->write_string(p->second->pkgpath()); |
272 this->write_c_string(" \""); | 556 this->write_c_string(" \""); |
273 this->write_string(p->first); | 557 this->write_string(p->first); |
274 this->write_c_string("\";\n"); | 558 this->write_c_string("\"\n"); |
275 | 559 |
276 this->packages_.insert(p->second); | 560 this->packages_.insert(p->second); |
561 } | |
562 | |
563 // Write out a separate list of indirectly imported packages. | |
564 std::vector<const Package*> indirect_imports; | |
565 for (Unordered_set(const Package*)::const_iterator p = | |
566 type_imports.begin(); | |
567 p != type_imports.end(); | |
568 ++p) | |
569 { | |
570 if (seen.find(*p) == seen.end()) | |
571 indirect_imports.push_back(*p); | |
572 } | |
573 | |
574 std::sort(indirect_imports.begin(), indirect_imports.end(), | |
575 packages_compare); | |
576 | |
577 for (std::vector<const Package*>::const_iterator p = | |
578 indirect_imports.begin(); | |
579 p != indirect_imports.end(); | |
580 ++p) | |
581 { | |
582 this->write_c_string("indirectimport "); | |
583 this->write_string((*p)->package_name()); | |
584 this->write_c_string(" "); | |
585 this->write_string((*p)->pkgpath()); | |
586 this->write_c_string("\n"); | |
277 } | 587 } |
278 } | 588 } |
279 | 589 |
280 void | 590 void |
281 Export::add_init_graph_edge(Init_graph* init_graph, unsigned src, unsigned sink) | 591 Export::add_init_graph_edge(Init_graph* init_graph, unsigned src, unsigned sink) |
345 init_idx[import_init_fn] = 0; | 655 init_idx[import_init_fn] = 0; |
346 } | 656 } |
347 | 657 |
348 if (imported_init_fns.empty()) | 658 if (imported_init_fns.empty()) |
349 { | 659 { |
350 this->write_c_string(";\n"); | 660 this->write_c_string("\n"); |
351 return; | 661 return; |
352 } | 662 } |
353 | 663 |
354 typedef std::map<int, std::vector<std::string> > level_map; | 664 typedef std::map<int, std::vector<std::string> > level_map; |
355 Init_graph init_graph; | 665 Init_graph init_graph; |
392 } | 702 } |
393 else | 703 else |
394 it->second.push_back(ii->init_name()); | 704 it->second.push_back(ii->init_name()); |
395 } | 705 } |
396 } | 706 } |
397 this->write_c_string(";\n"); | 707 this->write_c_string("\n"); |
398 | 708 |
399 // Create the init graph. Start by populating the graph with | 709 // Create the init graph. Start by populating the graph with |
400 // all the edges we inherited from imported packages. | 710 // all the edges we inherited from imported packages. |
401 populate_init_graph(&init_graph, imported_init_fns, init_idx); | 711 populate_init_graph(&init_graph, imported_init_fns, init_idx); |
402 | 712 |
492 unsigned sink = (*vi); | 802 unsigned sink = (*vi); |
493 this->write_c_string(" "); | 803 this->write_c_string(" "); |
494 this->write_unsigned(sink); | 804 this->write_unsigned(sink); |
495 } | 805 } |
496 } | 806 } |
497 this->write_c_string(";\n"); | 807 this->write_c_string("\n"); |
808 } | |
809 | |
810 // Write the types to the export stream. | |
811 | |
812 void | |
813 Export::write_types(int unexported_type_index) | |
814 { | |
815 // Map from type index to type. | |
816 std::vector<const Type*> types(static_cast<size_t>(this->type_index_)); | |
817 for (Type_refs::const_iterator p = type_refs.begin(); | |
818 p != type_refs.end(); | |
819 ++p) | |
820 { | |
821 if (p->second >= 0) | |
822 types.at(p->second) = p->first; | |
823 } | |
824 | |
825 // Write the type information to a buffer. | |
826 Stream_to_string type_data; | |
827 Export::Stream* orig_stream = this->stream_; | |
828 this->stream_ = &type_data; | |
829 | |
830 std::vector<size_t> type_sizes(static_cast<size_t>(this->type_index_)); | |
831 type_sizes[0] = 0; | |
832 | |
833 // Start at 1 because type index 0 is not used. | |
834 size_t start_size = 0; | |
835 for (int i = 1; i < this->type_index_; ++i) | |
836 { | |
837 this->write_type_definition(types[i], i); | |
838 | |
839 size_t cur_size = type_data.string().size(); | |
840 type_sizes[i] = cur_size - start_size; | |
841 start_size = cur_size; | |
842 } | |
843 | |
844 // Back to original stream. | |
845 this->stream_ = orig_stream; | |
846 | |
847 // The line "types MAXP1 EXPORTEDP1 SIZES..." appears before the | |
848 // types. MAXP1 is one more than the maximum type index used; that | |
849 // is, it is the size of the array we need to allocate to hold all | |
850 // the values. Indexes 1 up to but not including EXPORTEDP1 are the | |
851 // exported types. The other types are not exported. SIZES... is a | |
852 // list of MAXP1-1 entries listing the size of the type definition | |
853 // for each type, starting at index 1. | |
854 char buf[100]; | |
855 snprintf(buf, sizeof buf, "types %d %d", this->type_index_, | |
856 unexported_type_index); | |
857 this->write_c_string(buf); | |
858 | |
859 // Start at 1 because type index 0 is not used. | |
860 for (int i = 1; i < this->type_index_; ++i) | |
861 { | |
862 snprintf(buf, sizeof buf, " %lu", | |
863 static_cast<unsigned long>(type_sizes[i])); | |
864 this->write_c_string(buf); | |
865 } | |
866 this->write_c_string("\n"); | |
867 this->write_string(type_data.string()); | |
868 } | |
869 | |
870 // Write a single type to the export stream. | |
871 | |
872 void | |
873 Export::write_type_definition(const Type* type, int index) | |
874 { | |
875 this->write_c_string("type "); | |
876 | |
877 char buf[30]; | |
878 snprintf(buf, sizeof buf, "%d ", index); | |
879 this->write_c_string(buf); | |
880 | |
881 const Named_type* nt = type->named_type(); | |
882 if (nt != NULL) | |
883 { | |
884 const Named_object* no = nt->named_object(); | |
885 const Package* package = no->package(); | |
886 | |
887 this->write_c_string("\""); | |
888 if (package != NULL && !Gogo::is_hidden_name(no->name())) | |
889 { | |
890 this->write_string(package->pkgpath()); | |
891 this->write_c_string("."); | |
892 } | |
893 this->write_string(nt->named_object()->name()); | |
894 this->write_c_string("\" "); | |
895 | |
896 if (nt->is_alias()) | |
897 this->write_c_string("= "); | |
898 } | |
899 | |
900 type->export_type(this); | |
901 | |
902 // Type::export_type will print a newline for a named type, but not | |
903 // otherwise. | |
904 if (nt == NULL) | |
905 this->write_c_string("\n"); | |
498 } | 906 } |
499 | 907 |
500 // Write a name to the export stream. | 908 // Write a name to the export stream. |
501 | 909 |
502 void | 910 void |
526 char buf[100]; | 934 char buf[100]; |
527 snprintf(buf, sizeof buf, "%u", value); | 935 snprintf(buf, sizeof buf, "%u", value); |
528 this->write_c_string(buf); | 936 this->write_c_string(buf); |
529 } | 937 } |
530 | 938 |
531 // Export a type. We have to ensure that on import we create a single | 939 // Export a type. |
532 // Named_type node for each named type. We do this by keeping a hash | |
533 // table mapping named types to reference numbers. The first time we | |
534 // see a named type we assign it a reference number by making an entry | |
535 // in the hash table. If we see it again, we just refer to the | |
536 // reference number. | |
537 | |
538 // Named types are, of course, associated with packages. Note that we | |
539 // may see a named type when importing one package, and then later see | |
540 // the same named type when importing a different package. The home | |
541 // package may or may not be imported during this compilation. The | |
542 // reference number scheme has to get this all right. Basic approach | |
543 // taken from "On the Linearization of Graphs and Writing Symbol | |
544 // Files" by Robert Griesemer. | |
545 | 940 |
546 void | 941 void |
547 Export::write_type(const Type* type) | 942 Export::write_type(const Type* type) |
548 { | 943 { |
549 // We don't want to assign a reference number to a forward | |
550 // declaration to a type which was defined later. | |
551 type = type->forwarded(); | 944 type = type->forwarded(); |
552 | 945 Type_refs::const_iterator p = type_refs.find(type); |
553 Type_refs::const_iterator p = this->type_refs_.find(type); | 946 go_assert(p != type_refs.end()); |
554 if (p != this->type_refs_.end()) | 947 int index = p->second; |
555 { | 948 go_assert(index != 0); |
556 // This type was already in the table. | |
557 int index = p->second; | |
558 go_assert(index != 0); | |
559 char buf[30]; | |
560 snprintf(buf, sizeof buf, "<type %d>", index); | |
561 this->write_c_string(buf); | |
562 return; | |
563 } | |
564 | |
565 const Named_type* named_type = type->named_type(); | |
566 const Forward_declaration_type* forward = type->forward_declaration_type(); | |
567 | |
568 int index = this->type_index_; | |
569 ++this->type_index_; | |
570 | |
571 char buf[30]; | 949 char buf[30]; |
572 snprintf(buf, sizeof buf, "<type %d ", index); | 950 snprintf(buf, sizeof buf, "<type %d>", index); |
573 this->write_c_string(buf); | 951 this->write_c_string(buf); |
574 | |
575 if (named_type != NULL || forward != NULL) | |
576 { | |
577 const Named_object* named_object; | |
578 if (named_type != NULL) | |
579 { | |
580 // The builtin types should have been predefined. | |
581 go_assert(!Linemap::is_predeclared_location(named_type->location()) | |
582 || (named_type->named_object()->package()->package_name() | |
583 == "unsafe")); | |
584 named_object = named_type->named_object(); | |
585 } | |
586 else | |
587 named_object = forward->named_object(); | |
588 | |
589 const Package* package = named_object->package(); | |
590 | |
591 std::string s = "\""; | |
592 if (package != NULL && !Gogo::is_hidden_name(named_object->name())) | |
593 { | |
594 s += package->pkgpath(); | |
595 s += '.'; | |
596 } | |
597 s += named_object->name(); | |
598 s += "\" "; | |
599 this->write_string(s); | |
600 | |
601 // It is possible that this type was imported indirectly, and is | |
602 // not in a package in the import list. If we have not | |
603 // mentioned this package before, write out the package name | |
604 // here so that any package importing this one will know it. | |
605 if (package != NULL | |
606 && this->packages_.find(package) == this->packages_.end()) | |
607 { | |
608 this->write_c_string("\""); | |
609 this->write_string(package->package_name()); | |
610 this->packages_.insert(package); | |
611 this->write_c_string("\" "); | |
612 } | |
613 | |
614 // We must add a named type to the table now, since the | |
615 // definition of the type may refer to the named type via a | |
616 // pointer. | |
617 this->type_refs_[type] = index; | |
618 | |
619 if (named_type != NULL && named_type->is_alias()) | |
620 this->write_c_string("= "); | |
621 } | |
622 | |
623 type->export_type(this); | |
624 | |
625 this->write_c_string(">"); | |
626 | |
627 if (named_type == NULL) | |
628 this->type_refs_[type] = index; | |
629 } | 952 } |
630 | 953 |
631 // Export escape note. | 954 // Export escape note. |
632 | 955 |
633 void | 956 void |
676 Export::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code) | 999 Export::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code) |
677 { | 1000 { |
678 Named_object* named_object = gogo->lookup_global(name); | 1001 Named_object* named_object = gogo->lookup_global(name); |
679 go_assert(named_object != NULL && named_object->is_type()); | 1002 go_assert(named_object != NULL && named_object->is_type()); |
680 std::pair<Type_refs::iterator, bool> ins = | 1003 std::pair<Type_refs::iterator, bool> ins = |
681 this->type_refs_.insert(std::make_pair(named_object->type_value(), code)); | 1004 type_refs.insert(std::make_pair(named_object->type_value(), code)); |
682 go_assert(ins.second); | 1005 go_assert(ins.second); |
683 | 1006 |
684 // We also insert the underlying type. We can see the underlying | 1007 // We also insert the underlying type. We can see the underlying |
685 // type at least for string and bool. We skip the type aliases byte | 1008 // type at least for string and bool. It's OK if this insert |
686 // and rune here. | 1009 // fails--we expect duplications here, and it doesn't matter when |
687 if (code != BUILTIN_BYTE && code != BUILTIN_RUNE) | 1010 // they occur. |
688 { | 1011 Type* real_type = named_object->type_value()->real_type(); |
689 Type* real_type = named_object->type_value()->real_type(); | 1012 type_refs.insert(std::make_pair(real_type, code)); |
690 ins = this->type_refs_.insert(std::make_pair(real_type, code)); | |
691 go_assert(ins.second); | |
692 } | |
693 } | 1013 } |
694 | 1014 |
695 // Class Export::Stream. | 1015 // Class Export::Stream. |
696 | 1016 |
697 Export::Stream::Stream() | 1017 Export::Stream::Stream() |