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