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.
14 #include "statements.h"
17 #include "go-linemap.h"
20 // This file handles exporting global declarations.
24 const int Export::magic_len
;
26 // Current version magic string.
27 const char Export::cur_magic
[Export::magic_len
] =
32 // Magic string for previous version (still supported)
33 const char Export::v1_magic
[Export::magic_len
] =
38 const int Export::checksum_len
;
42 Export::Export(Stream
* stream
)
43 : stream_(stream
), type_refs_(), type_index_(1), packages_()
45 go_assert(Export::checksum_len
== Go_sha1_helper::checksum_len
);
48 // A functor to sort Named_object pointers by name.
53 operator()(const Named_object
* n1
, const Named_object
* n2
) const
54 { return n1
->name() < n2
->name(); }
57 // Return true if we should export NO.
60 should_export(Named_object
* no
)
62 // We only export objects which are locally defined.
63 if (no
->package() != NULL
)
66 // We don't export packages.
70 // We don't export hidden names.
71 if (Gogo::is_hidden_name(no
->name()))
74 // We don't export nested functions.
75 if (no
->is_function() && no
->func_value()->enclosing() != NULL
)
78 // We don't export thunks.
79 if (no
->is_function() && Gogo::is_thunk(no
))
82 // Methods are exported with the type, not here.
84 && no
->func_value()->type()->is_method())
86 if (no
->is_function_declaration()
87 && no
->func_declaration_value()->type()->is_method())
90 // Don't export dummy global variables created for initializers when
92 if (no
->is_variable() && no
->name()[0] == '_' && no
->name()[1] == '.')
98 // Export those identifiers marked for exporting.
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.
116 // Export the symbols in sorted order. That will reduce cases where
117 // irrelevant changes to the source code affect the exported
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();
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();
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 // Although the export data is readable, at least this version is,
143 // it is conceptually a binary format. Start with a four byte
145 this->write_bytes(Export::cur_magic
, Export::magic_len
);
148 this->write_c_string("package ");
149 this->write_string(package_name
);
150 this->write_c_string(";\n");
152 // The prefix or package path, used for all global symbols.
155 go_assert(!pkgpath
.empty());
156 this->write_c_string("pkgpath ");
157 this->write_string(pkgpath
);
161 this->write_c_string("prefix ");
162 this->write_string(prefix
);
164 this->write_c_string(";\n");
166 this->write_packages(packages
);
168 this->write_imports(imports
);
170 this->write_imported_init_fns(package_name
, import_init_fn
,
173 // FIXME: It might be clever to add something about the processor
174 // and ABI being used, although ideally any problems in that area
175 // would be caught by the linker.
177 for (std::vector
<Named_object
*>::const_iterator p
= exports
.begin();
180 (*p
)->export_named_object(this);
182 std::string checksum
= this->stream_
->checksum();
183 std::string s
= "checksum ";
184 for (std::string::const_iterator p
= checksum
.begin();
188 unsigned char c
= *p
;
189 unsigned int dig
= c
>> 4;
190 s
+= dig
< 10 ? '0' + dig
: 'A' + dig
- 10;
192 s
+= dig
< 10 ? '0' + dig
: 'A' + dig
- 10;
195 this->stream_
->write_checksum(s
);
201 packages_compare(const Package
* a
, const Package
* b
)
203 return a
->package_name() < b
->package_name();
206 // Write out all the known packages whose pkgpath symbol is not a
207 // simple transformation of the pkgpath, so that the importing code
208 // can reliably know it.
211 Export::write_packages(const std::map
<std::string
, Package
*>& packages
)
213 // Sort for consistent output.
214 std::vector
<Package
*> out
;
215 for (std::map
<std::string
, Package
*>::const_iterator p
= packages
.begin();
219 if (p
->second
->pkgpath_symbol()
220 != Gogo::pkgpath_for_symbol(p
->second
->pkgpath()))
221 out
.push_back(p
->second
);
224 std::sort(out
.begin(), out
.end(), packages_compare
);
226 for (std::vector
<Package
*>::const_iterator p
= out
.begin();
230 this->write_c_string("package ");
231 this->write_string((*p
)->package_name());
232 this->write_c_string(" ");
233 this->write_string((*p
)->pkgpath());
234 this->write_c_string(" ");
235 this->write_string((*p
)->pkgpath_symbol());
236 this->write_c_string(";\n");
240 // Sort imported packages.
243 import_compare(const std::pair
<std::string
, Package
*>& a
,
244 const std::pair
<std::string
, Package
*>& b
)
246 return a
.first
< b
.first
;
249 // Write out the imported packages.
252 Export::write_imports(const std::map
<std::string
, Package
*>& imports
)
254 // Sort the imports for more consistent output.
255 std::vector
<std::pair
<std::string
, Package
*> > sorted_imports
;
256 for (std::map
<std::string
, Package
*>::const_iterator p
= imports
.begin();
259 sorted_imports
.push_back(std::make_pair(p
->first
, p
->second
));
261 std::sort(sorted_imports
.begin(), sorted_imports
.end(), import_compare
);
263 for (std::vector
<std::pair
<std::string
, Package
*> >::const_iterator p
=
264 sorted_imports
.begin();
265 p
!= sorted_imports
.end();
268 this->write_c_string("import ");
269 this->write_string(p
->second
->package_name());
270 this->write_c_string(" ");
271 this->write_string(p
->second
->pkgpath());
272 this->write_c_string(" \"");
273 this->write_string(p
->first
);
274 this->write_c_string("\";\n");
276 this->packages_
.insert(p
->second
);
281 Export::add_init_graph_edge(Init_graph
* init_graph
, unsigned src
, unsigned sink
)
283 Init_graph::iterator it
= init_graph
->find(src
);
284 if (it
!= init_graph
->end())
285 it
->second
.insert(sink
);
288 std::set
<unsigned> succs
;
290 (*init_graph
)[src
] = succs
;
294 // Constructs the imported portion of the init graph, e.g. those
295 // edges that we read from imported packages.
298 Export::populate_init_graph(Init_graph
* init_graph
,
299 const Import_init_set
& imported_init_fns
,
300 const std::map
<std::string
, unsigned>& init_idx
)
302 for (Import_init_set::const_iterator p
= imported_init_fns
.begin();
303 p
!= imported_init_fns
.end();
306 const Import_init
* ii
= *p
;
307 std::map
<std::string
, unsigned>::const_iterator srcit
=
308 init_idx
.find(ii
->init_name());
309 go_assert(srcit
!= init_idx
.end());
310 unsigned src
= srcit
->second
;
311 for (std::set
<std::string
>::const_iterator pci
= ii
->precursors().begin();
312 pci
!= ii
->precursors().end();
315 std::map
<std::string
, unsigned>::const_iterator it
=
317 go_assert(it
!= init_idx
.end());
318 unsigned sink
= it
->second
;
319 add_init_graph_edge(init_graph
, src
, sink
);
324 // Write out the initialization functions which need to run for this
328 Export::write_imported_init_fns(const std::string
& package_name
,
329 const std::string
& import_init_fn
,
330 const Import_init_set
& imported_init_fns
)
332 if (import_init_fn
.empty() && imported_init_fns
.empty()) return;
334 // Maps a given init function to the its index in the exported "init" clause.
335 std::map
<std::string
, unsigned> init_idx
;
337 this->write_c_string("init");
339 if (!import_init_fn
.empty())
341 this->write_c_string(" ");
342 this->write_string(package_name
);
343 this->write_c_string(" ");
344 this->write_string(import_init_fn
);
345 init_idx
[import_init_fn
] = 0;
348 if (imported_init_fns
.empty())
350 this->write_c_string(";\n");
354 typedef std::map
<int, std::vector
<std::string
> > level_map
;
355 Init_graph init_graph
;
356 level_map inits_at_level
;
358 // Walk through the set of import inits (already sorted by
359 // init fcn name) and write them out to the exports.
360 for (Import_init_set::const_iterator p
= imported_init_fns
.begin();
361 p
!= imported_init_fns
.end();
364 const Import_init
* ii
= *p
;
366 if (ii
->init_name() == import_init_fn
)
369 this->write_c_string(" ");
370 this->write_string(ii
->package_name());
371 this->write_c_string(" ");
372 this->write_string(ii
->init_name());
374 // Populate init_idx.
375 go_assert(init_idx
.find(ii
->init_name()) == init_idx
.end());
376 unsigned idx
= init_idx
.size();
377 init_idx
[ii
->init_name()] = idx
;
379 // If the init function has a non-negative priority value, this
380 // is an indication that it was referred to in an older version
381 // export data section (e.g. we read a legacy object
382 // file). Record such init fcns so that we can fix up the graph
383 // for them (handled later in this function).
384 if (ii
->priority() > 0)
386 level_map::iterator it
= inits_at_level
.find(ii
->priority());
387 if (it
== inits_at_level
.end())
389 std::vector
<std::string
> l
;
390 l
.push_back(ii
->init_name());
391 inits_at_level
[ii
->priority()] = l
;
394 it
->second
.push_back(ii
->init_name());
397 this->write_c_string(";\n");
399 // Create the init graph. Start by populating the graph with
400 // all the edges we inherited from imported packages.
401 populate_init_graph(&init_graph
, imported_init_fns
, init_idx
);
403 // Now add edges from the local init function to each of the
405 if (!import_init_fn
.empty())
408 go_assert(init_idx
[import_init_fn
] == 0);
409 for (Import_init_set::const_iterator p
= imported_init_fns
.begin();
410 p
!= imported_init_fns
.end();
413 const Import_init
* ii
= *p
;
414 unsigned sink
= init_idx
[ii
->init_name()];
415 add_init_graph_edge(&init_graph
, src
, sink
);
419 // In the scenario where one or more of the packages we imported
420 // was written with the legacy export data format, add dummy edges
421 // to capture the priority relationships. Here is a package import
422 // graph as an example:
435 // Let's suppose that the object for package "C" is from an old
436 // gccgo, e.g. it has the old export data format. All other
437 // packages are compiled with the new compiler and have the new
438 // format. Packages with *'s have init functions. The scenario is
439 // that we're compiling a package "A"; during this process we'll
440 // read the export data for "C". It should look something like
442 // init F F..import 1 G G..import 1 D D..import 2 E E..import 2;
444 // To capture this information and convey it to the consumers of
445 // "A", the code below adds edges to the graph from each priority K
446 // function to every priority K-1 function for appropriate values
447 // of K. This will potentially add more edges than we need (for
448 // example, an edge from D to G), but given that we don't expect
449 // to see large numbers of old objects, this will hopefully be OK.
451 if (inits_at_level
.size() > 0)
453 for (level_map::reverse_iterator it
= inits_at_level
.rbegin();
454 it
!= inits_at_level
.rend(); ++it
)
456 int level
= it
->first
;
457 if (level
< 2) break;
458 const std::vector
<std::string
>& fcns_at_level
= it
->second
;
459 for (std::vector
<std::string
>::const_iterator sit
=
460 fcns_at_level
.begin();
461 sit
!= fcns_at_level
.end(); ++sit
)
463 unsigned src
= init_idx
[*sit
];
464 level_map::iterator it2
= inits_at_level
.find(level
- 1);
465 if (it2
!= inits_at_level
.end())
467 const std::vector
<std::string
> fcns_at_lm1
= it2
->second
;
468 for (std::vector
<std::string
>::const_iterator mit
=
470 mit
!= fcns_at_lm1
.end(); ++mit
)
472 unsigned sink
= init_idx
[*mit
];
473 add_init_graph_edge(&init_graph
, src
, sink
);
480 // Write out the resulting graph.
481 this->write_c_string("init_graph");
482 for (Init_graph::const_iterator ki
= init_graph
.begin();
483 ki
!= init_graph
.end(); ++ki
)
485 unsigned src
= ki
->first
;
486 const std::set
<unsigned>& successors
= ki
->second
;
487 for (std::set
<unsigned>::const_iterator vi
= successors
.begin();
488 vi
!= successors
.end(); ++vi
)
490 this->write_c_string(" ");
491 this->write_unsigned(src
);
492 unsigned sink
= (*vi
);
493 this->write_c_string(" ");
494 this->write_unsigned(sink
);
497 this->write_c_string(";\n");
500 // Write a name to the export stream.
503 Export::write_name(const std::string
& name
)
506 this->write_c_string("?");
508 this->write_string(Gogo::message_name(name
));
511 // Write an integer value to the export stream.
514 Export::write_int(int value
)
517 snprintf(buf
, sizeof buf
, "%d", value
);
518 this->write_c_string(buf
);
521 // Write an integer value to the export stream.
524 Export::write_unsigned(unsigned value
)
527 snprintf(buf
, sizeof buf
, "%u", value
);
528 this->write_c_string(buf
);
531 // Export a type. We have to ensure that on import we create a single
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
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.
547 Export::write_type(const Type
* type
)
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();
553 Type_refs::const_iterator p
= this->type_refs_
.find(type
);
554 if (p
!= this->type_refs_
.end())
556 // This type was already in the table.
557 int index
= p
->second
;
558 go_assert(index
!= 0);
560 snprintf(buf
, sizeof buf
, "<type %d>", index
);
561 this->write_c_string(buf
);
565 const Named_type
* named_type
= type
->named_type();
566 const Forward_declaration_type
* forward
= type
->forward_declaration_type();
568 int index
= this->type_index_
;
572 snprintf(buf
, sizeof buf
, "<type %d ", index
);
573 this->write_c_string(buf
);
575 if (named_type
!= NULL
|| forward
!= NULL
)
577 const Named_object
* named_object
;
578 if (named_type
!= NULL
)
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()
584 named_object
= named_type
->named_object();
587 named_object
= forward
->named_object();
589 const Package
* package
= named_object
->package();
591 std::string s
= "\"";
592 if (package
!= NULL
&& !Gogo::is_hidden_name(named_object
->name()))
594 s
+= package
->pkgpath();
597 s
+= named_object
->name();
599 this->write_string(s
);
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.
606 && this->packages_
.find(package
) == this->packages_
.end())
608 this->write_c_string("\"");
609 this->write_string(package
->package_name());
610 this->packages_
.insert(package
);
611 this->write_c_string("\" ");
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
617 this->type_refs_
[type
] = index
;
619 if (named_type
!= NULL
&& named_type
->is_alias())
620 this->write_c_string("= ");
623 type
->export_type(this);
625 this->write_c_string(">");
627 if (named_type
== NULL
)
628 this->type_refs_
[type
] = index
;
631 // Export escape note.
634 Export::write_escape(std::string
* note
)
636 if (note
!= NULL
&& *note
!= "esc:0x0")
638 this->write_c_string(" ");
640 go_assert(note
->find("esc:") != std::string::npos
);
641 snprintf(buf
, sizeof buf
, "<%s>", note
->c_str());
642 this->write_c_string(buf
);
646 // Add the builtin types to the export table.
649 Export::register_builtin_types(Gogo
* gogo
)
651 this->register_builtin_type(gogo
, "int8", BUILTIN_INT8
);
652 this->register_builtin_type(gogo
, "int16", BUILTIN_INT16
);
653 this->register_builtin_type(gogo
, "int32", BUILTIN_INT32
);
654 this->register_builtin_type(gogo
, "int64", BUILTIN_INT64
);
655 this->register_builtin_type(gogo
, "uint8", BUILTIN_UINT8
);
656 this->register_builtin_type(gogo
, "uint16", BUILTIN_UINT16
);
657 this->register_builtin_type(gogo
, "uint32", BUILTIN_UINT32
);
658 this->register_builtin_type(gogo
, "uint64", BUILTIN_UINT64
);
659 this->register_builtin_type(gogo
, "float32", BUILTIN_FLOAT32
);
660 this->register_builtin_type(gogo
, "float64", BUILTIN_FLOAT64
);
661 this->register_builtin_type(gogo
, "complex64", BUILTIN_COMPLEX64
);
662 this->register_builtin_type(gogo
, "complex128", BUILTIN_COMPLEX128
);
663 this->register_builtin_type(gogo
, "int", BUILTIN_INT
);
664 this->register_builtin_type(gogo
, "uint", BUILTIN_UINT
);
665 this->register_builtin_type(gogo
, "uintptr", BUILTIN_UINTPTR
);
666 this->register_builtin_type(gogo
, "bool", BUILTIN_BOOL
);
667 this->register_builtin_type(gogo
, "string", BUILTIN_STRING
);
668 this->register_builtin_type(gogo
, "error", BUILTIN_ERROR
);
669 this->register_builtin_type(gogo
, "byte", BUILTIN_BYTE
);
670 this->register_builtin_type(gogo
, "rune", BUILTIN_RUNE
);
673 // Register one builtin type in the export table.
676 Export::register_builtin_type(Gogo
* gogo
, const char* name
, Builtin_code code
)
678 Named_object
* named_object
= gogo
->lookup_global(name
);
679 go_assert(named_object
!= NULL
&& named_object
->is_type());
680 std::pair
<Type_refs::iterator
, bool> ins
=
681 this->type_refs_
.insert(std::make_pair(named_object
->type_value(), code
));
682 go_assert(ins
.second
);
684 // 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
687 if (code
!= BUILTIN_BYTE
&& code
!= BUILTIN_RUNE
)
689 Type
* real_type
= named_object
->type_value()->real_type();
690 ins
= this->type_refs_
.insert(std::make_pair(real_type
, code
));
691 go_assert(ins
.second
);
695 // Class Export::Stream.
697 Export::Stream::Stream()
699 this->sha1_helper_
= go_create_sha1_helper();
700 go_assert(this->sha1_helper_
!= NULL
);
703 Export::Stream::~Stream()
707 // Write bytes to the stream. This keeps a checksum of bytes as they
711 Export::Stream::write_and_sum_bytes(const char* bytes
, size_t length
)
713 this->sha1_helper_
->process_bytes(bytes
, length
);
714 this->do_write(bytes
, length
);
720 Export::Stream::checksum()
722 std::string rval
= this->sha1_helper_
->finish();
723 delete this->sha1_helper_
;
727 // Write the checksum string to the export data.
730 Export::Stream::write_checksum(const std::string
& s
)
732 this->do_write(s
.data(), s
.length());
735 // Class Stream_to_section.
737 Stream_to_section::Stream_to_section(Backend
* backend
)
742 // Write data to a section.
745 Stream_to_section::do_write(const char* bytes
, size_t length
)
747 this->backend_
->write_export_data (bytes
, length
);