da3d67f115215f3ee5eb9473ba645e4fe58519b3
[gcc.git] / gcc / go / gofrontend / export.cc
1 // export.cc -- Export declarations in Go frontend.
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 "go-sha1.h"
10 #include "go-c.h"
11
12 #include "gogo.h"
13 #include "types.h"
14 #include "statements.h"
15 #include "export.h"
16
17 #include "go-linemap.h"
18 #include "backend.h"
19
20 // This file handles exporting global declarations.
21
22 // Class Export.
23
24 const int Export::magic_len;
25
26 // Current version magic string.
27 const char Export::cur_magic[Export::magic_len] =
28 {
29 'v', '3', ';', '\n'
30 };
31
32 // Magic strings for previous versions (still supported).
33 const char Export::v1_magic[Export::magic_len] =
34 {
35 'v', '1', ';', '\n'
36 };
37 const char Export::v2_magic[Export::magic_len] =
38 {
39 'v', '2', ';', '\n'
40 };
41
42 const int Export::checksum_len;
43
44 // Constructor.
45
46 Export::Export(Stream* stream)
47 : stream_(stream), type_refs_(), type_index_(1), packages_()
48 {
49 go_assert(Export::checksum_len == Go_sha1_helper::checksum_len);
50 }
51
52 // A functor to sort Named_object pointers by name.
53
54 struct Sort_bindings
55 {
56 bool
57 operator()(const Named_object* n1, const Named_object* n2) const
58 { return n1->name() < n2->name(); }
59 };
60
61 // Return true if we should export NO.
62
63 static bool
64 should_export(Named_object* no)
65 {
66 // We only export objects which are locally defined.
67 if (no->package() != NULL)
68 return false;
69
70 // We don't export packages.
71 if (no->is_package())
72 return false;
73
74 // We don't export hidden names.
75 if (Gogo::is_hidden_name(no->name()))
76 return false;
77
78 // We don't export nested functions.
79 if (no->is_function() && no->func_value()->enclosing() != NULL)
80 return false;
81
82 // We don't export thunks.
83 if (no->is_function() && Gogo::is_thunk(no))
84 return false;
85
86 // Methods are exported with the type, not here.
87 if (no->is_function()
88 && no->func_value()->type()->is_method())
89 return false;
90 if (no->is_function_declaration()
91 && no->func_declaration_value()->type()->is_method())
92 return false;
93
94 // Don't export dummy global variables created for initializers when
95 // used with sinks.
96 if (no->is_variable() && no->name()[0] == '_' && no->name()[1] == '.')
97 return false;
98
99 return true;
100 }
101
102 // Export those identifiers marked for exporting.
103
104 void
105 Export::export_globals(const std::string& package_name,
106 const std::string& prefix,
107 const std::string& pkgpath,
108 const std::map<std::string, Package*>& packages,
109 const std::map<std::string, Package*>& imports,
110 const std::string& import_init_fn,
111 const Import_init_set& imported_init_fns,
112 const Bindings* bindings)
113 {
114 // If there have been any errors so far, don't try to export
115 // anything. That way the export code doesn't have to worry about
116 // mismatched types or other confusions.
117 if (saw_errors())
118 return;
119
120 // Export the symbols in sorted order. That will reduce cases where
121 // irrelevant changes to the source code affect the exported
122 // interface.
123 std::vector<Named_object*> exports;
124 exports.reserve(bindings->size_definitions());
125
126 for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
127 p != bindings->end_definitions();
128 ++p)
129 if (should_export(*p))
130 exports.push_back(*p);
131
132 for (Bindings::const_declarations_iterator p =
133 bindings->begin_declarations();
134 p != bindings->end_declarations();
135 ++p)
136 {
137 // We export a function declaration as it may be implemented in
138 // supporting C code. We do not export type declarations.
139 if (p->second->is_function_declaration()
140 && should_export(p->second))
141 exports.push_back(p->second);
142 }
143
144 std::sort(exports.begin(), exports.end(), Sort_bindings());
145
146 // Find all packages not explicitly imported but mentioned by types.
147 Unordered_set(const Package*) type_imports;
148 this->prepare_types(&exports, &type_imports);
149
150 // Although the export data is readable, at least this version is,
151 // it is conceptually a binary format. Start with a four byte
152 // version number.
153 this->write_bytes(Export::cur_magic, Export::magic_len);
154
155 // The package name.
156 this->write_c_string("package ");
157 this->write_string(package_name);
158 this->write_c_string("\n");
159
160 // The prefix or package path, used for all global symbols.
161 if (prefix.empty())
162 {
163 go_assert(!pkgpath.empty());
164 this->write_c_string("pkgpath ");
165 this->write_string(pkgpath);
166 }
167 else
168 {
169 this->write_c_string("prefix ");
170 this->write_string(prefix);
171 }
172 this->write_c_string("\n");
173
174 this->write_packages(packages);
175
176 this->write_imports(imports, type_imports);
177
178 this->write_imported_init_fns(package_name, import_init_fn,
179 imported_init_fns);
180
181 // FIXME: It might be clever to add something about the processor
182 // and ABI being used, although ideally any problems in that area
183 // would be caught by the linker.
184
185 for (std::vector<Named_object*>::const_iterator p = exports.begin();
186 p != exports.end();
187 ++p)
188 (*p)->export_named_object(this);
189
190 std::string checksum = this->stream_->checksum();
191 std::string s = "checksum ";
192 for (std::string::const_iterator p = checksum.begin();
193 p != checksum.end();
194 ++p)
195 {
196 unsigned char c = *p;
197 unsigned int dig = c >> 4;
198 s += dig < 10 ? '0' + dig : 'A' + dig - 10;
199 dig = c & 0xf;
200 s += dig < 10 ? '0' + dig : 'A' + dig - 10;
201 }
202 s += "\n";
203 this->stream_->write_checksum(s);
204 }
205
206 // Traversal class to find referenced types.
207
208 class Find_types_to_prepare : public Traverse
209 {
210 public:
211 Find_types_to_prepare(Unordered_set(const Package*)* imports)
212 : Traverse(traverse_types),
213 imports_(imports)
214 { }
215
216 int
217 type(Type* type);
218
219 // Traverse the components of a function type.
220 void
221 traverse_function(Function_type*);
222
223 // Traverse the methods of a named type, and register its package.
224 void
225 traverse_named_type(Named_type*);
226
227 private:
228 // List of packages we are building.
229 Unordered_set(const Package*)* imports_;
230 };
231
232 // Traverse a type.
233
234 int
235 Find_types_to_prepare::type(Type* type)
236 {
237 // Skip forwarders.
238 if (type->forward_declaration_type() != NULL)
239 return TRAVERSE_CONTINUE;
240
241 // At this stage of compilation traversing interface types traverses
242 // the final list of methods, but we export the locally defined
243 // methods. If there is an embedded interface type we need to make
244 // sure to export that. Check classification, rather than calling
245 // the interface_type method, because we want to handle named types
246 // below.
247 if (type->classification() == Type::TYPE_INTERFACE)
248 {
249 Interface_type* it = type->interface_type();
250 const Typed_identifier_list* methods = it->local_methods();
251 if (methods != NULL)
252 {
253 for (Typed_identifier_list::const_iterator p = methods->begin();
254 p != methods->end();
255 ++p)
256 {
257 if (p->name().empty())
258 Type::traverse(p->type(), this);
259 else
260 this->traverse_function(p->type()->function_type());
261 }
262 }
263 return TRAVERSE_SKIP_COMPONENTS;
264 }
265
266 Named_type* nt = type->named_type();
267 if (nt != NULL)
268 this->traverse_named_type(nt);
269
270 return TRAVERSE_CONTINUE;
271 }
272
273 // Traverse the types in a function type. We don't need the function
274 // type tself, just the receiver, parameter, and result types.
275
276 void
277 Find_types_to_prepare::traverse_function(Function_type* type)
278 {
279 go_assert(type != NULL);
280 if (this->remember_type(type))
281 return;
282 const Typed_identifier* receiver = type->receiver();
283 if (receiver != NULL)
284 Type::traverse(receiver->type(), this);
285 const Typed_identifier_list* parameters = type->parameters();
286 if (parameters != NULL)
287 parameters->traverse(this);
288 const Typed_identifier_list* results = type->results();
289 if (results != NULL)
290 results->traverse(this);
291 }
292
293 // Traverse the methods of a named type, and record its package.
294
295 void
296 Find_types_to_prepare::traverse_named_type(Named_type* nt)
297 {
298 const Package* package = nt->named_object()->package();
299 if (package != NULL)
300 this->imports_->insert(package);
301
302 // We have to traverse the methods of named types, because we are
303 // going to export them. This is not done by ordinary type
304 // traversal.
305 const Bindings* methods = nt->local_methods();
306 if (methods != NULL)
307 {
308 for (Bindings::const_definitions_iterator pm =
309 methods->begin_definitions();
310 pm != methods->end_definitions();
311 ++pm)
312 this->traverse_function((*pm)->func_value()->type());
313
314 for (Bindings::const_declarations_iterator pm =
315 methods->begin_declarations();
316 pm != methods->end_declarations();
317 ++pm)
318 {
319 Named_object* mno = pm->second;
320 if (mno->is_function_declaration())
321 this->traverse_function(mno->func_declaration_value()->type());
322 }
323 }
324 }
325
326 // Collect all the pacakges we see in types, so that if we refer to
327 // any types from indirectly importe packages we can tell the importer
328 // about the package.
329
330 void
331 Export::prepare_types(const std::vector<Named_object*>* exports,
332 Unordered_set(const Package*)* imports)
333 {
334 // Use a single index of the traversal class because traversal
335 // classes keep track of which types they've already seen. That
336 // lets us avoid type reference loops.
337 Find_types_to_prepare find(imports);
338
339 // Traverse all the exported objects.
340 for (std::vector<Named_object*>::const_iterator p = exports->begin();
341 p != exports->end();
342 ++p)
343 {
344 Named_object* no = *p;
345 switch (no->classification())
346 {
347 case Named_object::NAMED_OBJECT_CONST:
348 {
349 Type* t = no->const_value()->type();
350 if (t != NULL && !t->is_abstract())
351 Type::traverse(t, &find);
352 }
353 break;
354
355 case Named_object::NAMED_OBJECT_TYPE:
356 Type::traverse(no->type_value(), &find);
357 break;
358
359 case Named_object::NAMED_OBJECT_VAR:
360 Type::traverse(no->var_value()->type(), &find);
361 break;
362
363 case Named_object::NAMED_OBJECT_FUNC:
364 find.traverse_function(no->func_value()->type());
365 break;
366
367 case Named_object::NAMED_OBJECT_FUNC_DECLARATION:
368 find.traverse_function(no->func_declaration_value()->type());
369 break;
370
371 default:
372 // We shouldn't see anything else. If we do we'll give an
373 // error later when we try to actually export it.
374 break;
375 }
376 }
377 }
378
379 // Sort packages.
380
381 static bool
382 packages_compare(const Package* a, const Package* b)
383 {
384 return a->package_name() < b->package_name();
385 }
386
387 // Write out all the known packages whose pkgpath symbol is not a
388 // simple transformation of the pkgpath, so that the importing code
389 // can reliably know it.
390
391 void
392 Export::write_packages(const std::map<std::string, Package*>& packages)
393 {
394 // Sort for consistent output.
395 std::vector<Package*> out;
396 for (std::map<std::string, Package*>::const_iterator p = packages.begin();
397 p != packages.end();
398 ++p)
399 {
400 if (p->second->pkgpath_symbol()
401 != Gogo::pkgpath_for_symbol(p->second->pkgpath()))
402 out.push_back(p->second);
403 }
404
405 std::sort(out.begin(), out.end(), packages_compare);
406
407 for (std::vector<Package*>::const_iterator p = out.begin();
408 p != out.end();
409 ++p)
410 {
411 this->write_c_string("package ");
412 this->write_string((*p)->package_name());
413 this->write_c_string(" ");
414 this->write_string((*p)->pkgpath());
415 this->write_c_string(" ");
416 this->write_string((*p)->pkgpath_symbol());
417 this->write_c_string("\n");
418 }
419 }
420
421 // Sort imported packages.
422
423 static bool
424 import_compare(const std::pair<std::string, Package*>& a,
425 const std::pair<std::string, Package*>& b)
426 {
427 return a.first < b.first;
428 }
429
430 // Write out the imported packages.
431
432 void
433 Export::write_imports(const std::map<std::string, Package*>& imports,
434 const Unordered_set(const Package*)& type_imports)
435 {
436 // Sort the imports for more consistent output.
437 Unordered_set(const Package*) seen;
438 std::vector<std::pair<std::string, Package*> > sorted_imports;
439 for (std::map<std::string, Package*>::const_iterator p = imports.begin();
440 p != imports.end();
441 ++p)
442 {
443 sorted_imports.push_back(std::make_pair(p->first, p->second));
444 seen.insert(p->second);
445 }
446
447 std::sort(sorted_imports.begin(), sorted_imports.end(), import_compare);
448
449 for (std::vector<std::pair<std::string, Package*> >::const_iterator p =
450 sorted_imports.begin();
451 p != sorted_imports.end();
452 ++p)
453 {
454 this->write_c_string("import ");
455 this->write_string(p->second->package_name());
456 this->write_c_string(" ");
457 this->write_string(p->second->pkgpath());
458 this->write_c_string(" \"");
459 this->write_string(p->first);
460 this->write_c_string("\"\n");
461
462 this->packages_.insert(p->second);
463 }
464
465 // Write out a separate list of indirectly imported packages.
466 std::vector<const Package*> indirect_imports;
467 for (Unordered_set(const Package*)::const_iterator p =
468 type_imports.begin();
469 p != type_imports.end();
470 ++p)
471 {
472 if (seen.find(*p) == seen.end())
473 indirect_imports.push_back(*p);
474 }
475
476 std::sort(indirect_imports.begin(), indirect_imports.end(),
477 packages_compare);
478
479 for (std::vector<const Package*>::const_iterator p =
480 indirect_imports.begin();
481 p != indirect_imports.end();
482 ++p)
483 {
484 this->write_c_string("indirectimport ");
485 this->write_string((*p)->package_name());
486 this->write_c_string(" ");
487 this->write_string((*p)->pkgpath());
488 this->write_c_string("\n");
489 }
490 }
491
492 void
493 Export::add_init_graph_edge(Init_graph* init_graph, unsigned src, unsigned sink)
494 {
495 Init_graph::iterator it = init_graph->find(src);
496 if (it != init_graph->end())
497 it->second.insert(sink);
498 else
499 {
500 std::set<unsigned> succs;
501 succs.insert(sink);
502 (*init_graph)[src] = succs;
503 }
504 }
505
506 // Constructs the imported portion of the init graph, e.g. those
507 // edges that we read from imported packages.
508
509 void
510 Export::populate_init_graph(Init_graph* init_graph,
511 const Import_init_set& imported_init_fns,
512 const std::map<std::string, unsigned>& init_idx)
513 {
514 for (Import_init_set::const_iterator p = imported_init_fns.begin();
515 p != imported_init_fns.end();
516 ++p)
517 {
518 const Import_init* ii = *p;
519 std::map<std::string, unsigned>::const_iterator srcit =
520 init_idx.find(ii->init_name());
521 go_assert(srcit != init_idx.end());
522 unsigned src = srcit->second;
523 for (std::set<std::string>::const_iterator pci = ii->precursors().begin();
524 pci != ii->precursors().end();
525 ++pci)
526 {
527 std::map<std::string, unsigned>::const_iterator it =
528 init_idx.find(*pci);
529 go_assert(it != init_idx.end());
530 unsigned sink = it->second;
531 add_init_graph_edge(init_graph, src, sink);
532 }
533 }
534 }
535
536 // Write out the initialization functions which need to run for this
537 // package.
538
539 void
540 Export::write_imported_init_fns(const std::string& package_name,
541 const std::string& import_init_fn,
542 const Import_init_set& imported_init_fns)
543 {
544 if (import_init_fn.empty() && imported_init_fns.empty()) return;
545
546 // Maps a given init function to the its index in the exported "init" clause.
547 std::map<std::string, unsigned> init_idx;
548
549 this->write_c_string("init");
550
551 if (!import_init_fn.empty())
552 {
553 this->write_c_string(" ");
554 this->write_string(package_name);
555 this->write_c_string(" ");
556 this->write_string(import_init_fn);
557 init_idx[import_init_fn] = 0;
558 }
559
560 if (imported_init_fns.empty())
561 {
562 this->write_c_string("\n");
563 return;
564 }
565
566 typedef std::map<int, std::vector<std::string> > level_map;
567 Init_graph init_graph;
568 level_map inits_at_level;
569
570 // Walk through the set of import inits (already sorted by
571 // init fcn name) and write them out to the exports.
572 for (Import_init_set::const_iterator p = imported_init_fns.begin();
573 p != imported_init_fns.end();
574 ++p)
575 {
576 const Import_init* ii = *p;
577
578 if (ii->init_name() == import_init_fn)
579 continue;
580
581 this->write_c_string(" ");
582 this->write_string(ii->package_name());
583 this->write_c_string(" ");
584 this->write_string(ii->init_name());
585
586 // Populate init_idx.
587 go_assert(init_idx.find(ii->init_name()) == init_idx.end());
588 unsigned idx = init_idx.size();
589 init_idx[ii->init_name()] = idx;
590
591 // If the init function has a non-negative priority value, this
592 // is an indication that it was referred to in an older version
593 // export data section (e.g. we read a legacy object
594 // file). Record such init fcns so that we can fix up the graph
595 // for them (handled later in this function).
596 if (ii->priority() > 0)
597 {
598 level_map::iterator it = inits_at_level.find(ii->priority());
599 if (it == inits_at_level.end())
600 {
601 std::vector<std::string> l;
602 l.push_back(ii->init_name());
603 inits_at_level[ii->priority()] = l;
604 }
605 else
606 it->second.push_back(ii->init_name());
607 }
608 }
609 this->write_c_string("\n");
610
611 // Create the init graph. Start by populating the graph with
612 // all the edges we inherited from imported packages.
613 populate_init_graph(&init_graph, imported_init_fns, init_idx);
614
615 // Now add edges from the local init function to each of the
616 // imported fcns.
617 if (!import_init_fn.empty())
618 {
619 unsigned src = 0;
620 go_assert(init_idx[import_init_fn] == 0);
621 for (Import_init_set::const_iterator p = imported_init_fns.begin();
622 p != imported_init_fns.end();
623 ++p)
624 {
625 const Import_init* ii = *p;
626 unsigned sink = init_idx[ii->init_name()];
627 add_init_graph_edge(&init_graph, src, sink);
628 }
629 }
630
631 // In the scenario where one or more of the packages we imported
632 // was written with the legacy export data format, add dummy edges
633 // to capture the priority relationships. Here is a package import
634 // graph as an example:
635 //
636 // *A
637 // /|
638 // / |
639 // B *C
640 // /|
641 // / |
642 // *D *E
643 // | /|
644 // |/ |
645 // *F *G
646 //
647 // Let's suppose that the object for package "C" is from an old
648 // gccgo, e.g. it has the old export data format. All other
649 // packages are compiled with the new compiler and have the new
650 // format. Packages with *'s have init functions. The scenario is
651 // that we're compiling a package "A"; during this process we'll
652 // read the export data for "C". It should look something like
653 //
654 // init F F..import 1 G G..import 1 D D..import 2 E E..import 2;
655 //
656 // To capture this information and convey it to the consumers of
657 // "A", the code below adds edges to the graph from each priority K
658 // function to every priority K-1 function for appropriate values
659 // of K. This will potentially add more edges than we need (for
660 // example, an edge from D to G), but given that we don't expect
661 // to see large numbers of old objects, this will hopefully be OK.
662
663 if (inits_at_level.size() > 0)
664 {
665 for (level_map::reverse_iterator it = inits_at_level.rbegin();
666 it != inits_at_level.rend(); ++it)
667 {
668 int level = it->first;
669 if (level < 2) break;
670 const std::vector<std::string>& fcns_at_level = it->second;
671 for (std::vector<std::string>::const_iterator sit =
672 fcns_at_level.begin();
673 sit != fcns_at_level.end(); ++sit)
674 {
675 unsigned src = init_idx[*sit];
676 level_map::iterator it2 = inits_at_level.find(level - 1);
677 if (it2 != inits_at_level.end())
678 {
679 const std::vector<std::string> fcns_at_lm1 = it2->second;
680 for (std::vector<std::string>::const_iterator mit =
681 fcns_at_lm1.begin();
682 mit != fcns_at_lm1.end(); ++mit)
683 {
684 unsigned sink = init_idx[*mit];
685 add_init_graph_edge(&init_graph, src, sink);
686 }
687 }
688 }
689 }
690 }
691
692 // Write out the resulting graph.
693 this->write_c_string("init_graph");
694 for (Init_graph::const_iterator ki = init_graph.begin();
695 ki != init_graph.end(); ++ki)
696 {
697 unsigned src = ki->first;
698 const std::set<unsigned>& successors = ki->second;
699 for (std::set<unsigned>::const_iterator vi = successors.begin();
700 vi != successors.end(); ++vi)
701 {
702 this->write_c_string(" ");
703 this->write_unsigned(src);
704 unsigned sink = (*vi);
705 this->write_c_string(" ");
706 this->write_unsigned(sink);
707 }
708 }
709 this->write_c_string("\n");
710 }
711
712 // Write a name to the export stream.
713
714 void
715 Export::write_name(const std::string& name)
716 {
717 if (name.empty())
718 this->write_c_string("?");
719 else
720 this->write_string(Gogo::message_name(name));
721 }
722
723 // Write an integer value to the export stream.
724
725 void
726 Export::write_int(int value)
727 {
728 char buf[100];
729 snprintf(buf, sizeof buf, "%d", value);
730 this->write_c_string(buf);
731 }
732
733 // Write an integer value to the export stream.
734
735 void
736 Export::write_unsigned(unsigned value)
737 {
738 char buf[100];
739 snprintf(buf, sizeof buf, "%u", value);
740 this->write_c_string(buf);
741 }
742
743 // Export a type. We have to ensure that on import we create a single
744 // Named_type node for each named type. We do this by keeping a hash
745 // table mapping named types to reference numbers. The first time we
746 // see a named type we assign it a reference number by making an entry
747 // in the hash table. If we see it again, we just refer to the
748 // reference number.
749
750 // Named types are, of course, associated with packages. Note that we
751 // may see a named type when importing one package, and then later see
752 // the same named type when importing a different package. The home
753 // package may or may not be imported during this compilation. The
754 // reference number scheme has to get this all right. Basic approach
755 // taken from "On the Linearization of Graphs and Writing Symbol
756 // Files" by Robert Griesemer.
757
758 void
759 Export::write_type(const Type* type)
760 {
761 // We don't want to assign a reference number to a forward
762 // declaration to a type which was defined later.
763 type = type->forwarded();
764
765 Type_refs::const_iterator p = this->type_refs_.find(type);
766 if (p != this->type_refs_.end())
767 {
768 // This type was already in the table.
769 int index = p->second;
770 go_assert(index != 0);
771 char buf[30];
772 snprintf(buf, sizeof buf, "<type %d>", index);
773 this->write_c_string(buf);
774 return;
775 }
776
777 const Named_type* named_type = type->named_type();
778 const Forward_declaration_type* forward = type->forward_declaration_type();
779
780 int index = this->type_index_;
781 ++this->type_index_;
782
783 char buf[30];
784 snprintf(buf, sizeof buf, "<type %d ", index);
785 this->write_c_string(buf);
786
787 if (named_type != NULL || forward != NULL)
788 {
789 const Named_object* named_object;
790 if (named_type != NULL)
791 {
792 // The builtin types should have been predefined.
793 go_assert(!Linemap::is_predeclared_location(named_type->location())
794 || (named_type->named_object()->package()->package_name()
795 == "unsafe"));
796 named_object = named_type->named_object();
797 }
798 else
799 named_object = forward->named_object();
800
801 const Package* package = named_object->package();
802
803 std::string s = "\"";
804 if (package != NULL && !Gogo::is_hidden_name(named_object->name()))
805 {
806 s += package->pkgpath();
807 s += '.';
808 }
809 s += named_object->name();
810 s += "\" ";
811 this->write_string(s);
812
813 // We must add a named type to the table now, since the
814 // definition of the type may refer to the named type via a
815 // pointer.
816 this->type_refs_[type] = index;
817
818 if (named_type != NULL && named_type->is_alias())
819 this->write_c_string("= ");
820 }
821
822 type->export_type(this);
823
824 this->write_c_string(">");
825
826 if (named_type == NULL)
827 this->type_refs_[type] = index;
828 }
829
830 // Export escape note.
831
832 void
833 Export::write_escape(std::string* note)
834 {
835 if (note != NULL && *note != "esc:0x0")
836 {
837 this->write_c_string(" ");
838 char buf[50];
839 go_assert(note->find("esc:") != std::string::npos);
840 snprintf(buf, sizeof buf, "<%s>", note->c_str());
841 this->write_c_string(buf);
842 }
843 }
844
845 // Add the builtin types to the export table.
846
847 void
848 Export::register_builtin_types(Gogo* gogo)
849 {
850 this->register_builtin_type(gogo, "int8", BUILTIN_INT8);
851 this->register_builtin_type(gogo, "int16", BUILTIN_INT16);
852 this->register_builtin_type(gogo, "int32", BUILTIN_INT32);
853 this->register_builtin_type(gogo, "int64", BUILTIN_INT64);
854 this->register_builtin_type(gogo, "uint8", BUILTIN_UINT8);
855 this->register_builtin_type(gogo, "uint16", BUILTIN_UINT16);
856 this->register_builtin_type(gogo, "uint32", BUILTIN_UINT32);
857 this->register_builtin_type(gogo, "uint64", BUILTIN_UINT64);
858 this->register_builtin_type(gogo, "float32", BUILTIN_FLOAT32);
859 this->register_builtin_type(gogo, "float64", BUILTIN_FLOAT64);
860 this->register_builtin_type(gogo, "complex64", BUILTIN_COMPLEX64);
861 this->register_builtin_type(gogo, "complex128", BUILTIN_COMPLEX128);
862 this->register_builtin_type(gogo, "int", BUILTIN_INT);
863 this->register_builtin_type(gogo, "uint", BUILTIN_UINT);
864 this->register_builtin_type(gogo, "uintptr", BUILTIN_UINTPTR);
865 this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
866 this->register_builtin_type(gogo, "string", BUILTIN_STRING);
867 this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
868 this->register_builtin_type(gogo, "byte", BUILTIN_BYTE);
869 this->register_builtin_type(gogo, "rune", BUILTIN_RUNE);
870 }
871
872 // Register one builtin type in the export table.
873
874 void
875 Export::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
876 {
877 Named_object* named_object = gogo->lookup_global(name);
878 go_assert(named_object != NULL && named_object->is_type());
879 std::pair<Type_refs::iterator, bool> ins =
880 this->type_refs_.insert(std::make_pair(named_object->type_value(), code));
881 go_assert(ins.second);
882
883 // We also insert the underlying type. We can see the underlying
884 // type at least for string and bool. We skip the type aliases byte
885 // and rune here.
886 if (code != BUILTIN_BYTE && code != BUILTIN_RUNE)
887 {
888 Type* real_type = named_object->type_value()->real_type();
889 ins = this->type_refs_.insert(std::make_pair(real_type, code));
890 go_assert(ins.second);
891 }
892 }
893
894 // Class Export::Stream.
895
896 Export::Stream::Stream()
897 {
898 this->sha1_helper_ = go_create_sha1_helper();
899 go_assert(this->sha1_helper_ != NULL);
900 }
901
902 Export::Stream::~Stream()
903 {
904 }
905
906 // Write bytes to the stream. This keeps a checksum of bytes as they
907 // go by.
908
909 void
910 Export::Stream::write_and_sum_bytes(const char* bytes, size_t length)
911 {
912 this->sha1_helper_->process_bytes(bytes, length);
913 this->do_write(bytes, length);
914 }
915
916 // Get the checksum.
917
918 std::string
919 Export::Stream::checksum()
920 {
921 std::string rval = this->sha1_helper_->finish();
922 delete this->sha1_helper_;
923 return rval;
924 }
925
926 // Write the checksum string to the export data.
927
928 void
929 Export::Stream::write_checksum(const std::string& s)
930 {
931 this->do_write(s.data(), s.length());
932 }
933
934 // Class Stream_to_section.
935
936 Stream_to_section::Stream_to_section(Backend* backend)
937 : backend_(backend)
938 {
939 }
940
941 // Write data to a section.
942
943 void
944 Stream_to_section::do_write(const char* bytes, size_t length)
945 {
946 this->backend_->write_export_data (bytes, length);
947 }