-aebd2d6303e4bb970b088e84f6c66279095dfea6
+ae7d7e05bce19aefaa27efe2ee797933aafbef06
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
++p)
{
const Import_init* ii = *p;
+ if (ii->is_dummy())
+ continue;
std::map<std::string, unsigned>::const_iterator srcit =
init_idx.find(ii->init_name());
go_assert(srcit != init_idx.end());
// Now add edges from the local init function to each of the
// imported fcns.
- if (!import_init_fn.empty())
+ if (!import_init_fn.empty() && import_init_fn[0] != '~')
{
unsigned src = 0;
go_assert(init_idx[import_init_fn] == 0);
++p)
{
const Import_init* ii = *p;
+ if (ii->is_dummy())
+ continue;
unsigned sink = init_idx[ii->init_name()];
add_init_graph_edge(&init_graph, src, sink);
}
p != this->imported_init_fns_.end();
++p)
{
+ // Don't include dummy inits. They are not real functions.
+ if ((*p)->is_dummy())
+ continue;
if ((*p)->priority() < 0)
go_error_at(Linemap::unknown_location(),
"internal error: failed to set init priority for %s",
Btype* bat = list_type->field(1)->type()->get_backend(this);
// Create the variable
- std::string name = this->type_descriptor_list_symbol(this->package_);
+ std::string name = this->type_descriptor_list_symbol(this->pkgpath_symbol());
Bvariable* bv = this->backend()->implicit_variable(name, name, bt,
false, true, false,
0);
Struct_type* list_type = type_descriptor_list_type(1);
Btype* bt = list_type->get_backend(this);
+ // Collect type lists from transitive imports.
+ std::vector<std::string> list_names;
+ for (Import_init_set::iterator it = this->imported_init_fns_.begin();
+ it != this->imported_init_fns_.end();
+ ++it)
+ {
+ std::string pkgpath =
+ this->pkgpath_from_init_fn_name((*it)->init_name());
+ list_names.push_back(this->type_descriptor_list_symbol(pkgpath));
+ }
+ // Add the main package itself.
+ list_names.push_back(this->type_descriptor_list_symbol("main"));
+
// Build a list of lists.
std::vector<unsigned long> indexes;
std::vector<Bexpression*> vals;
unsigned long i = 0;
- for (Packages::iterator it = this->packages_.begin();
- it != this->packages_.end();
- ++it)
+ for (std::vector<std::string>::iterator p = list_names.begin();
+ p != list_names.end();
+ ++p)
{
- if (it->second->pkgpath() == "unsafe")
- continue;
-
- std::string name = this->type_descriptor_list_symbol(it->second);
Bvariable* bv =
- this->backend()->implicit_variable_reference(name, name, bt);
+ this->backend()->implicit_variable_reference(*p, *p, bt);
Bexpression* bexpr = this->backend()->var_expression(bv, builtin_loc);
bexpr = this->backend()->address_expression(bexpr, builtin_loc);
else
prefix = "go";
+ std::string init_fn_name;
+ if (this->is_main_package())
+ init_fn_name = "";
+ else if (this->need_init_fn_)
+ init_fn_name = this->get_init_fn_name();
+ else
+ init_fn_name = this->dummy_init_fn_name();
+
Export exp(&stream);
exp.register_builtin_types(this);
exp.export_globals(this->package_name(),
pkgpath,
this->packages_,
this->imports_,
- (this->need_init_fn_ && !this->is_main_package()
- ? this->get_init_fn_name()
- : ""),
+ init_fn_name,
this->imported_init_fns_,
this->package_->bindings());
precursors() const
{ return this->precursor_functions_; }
+ // Whether this is a dummy init, which is used only to record transitive import.
+ bool
+ is_dummy() const
+ { return this->init_name_[0] == '~'; }
+
private:
// The name of the package being imported.
std::string package_name_;
const std::string&
get_init_fn_name();
+ // Return the name for a dummy init function, which is not a real
+ // function but only for tracking transitive import.
+ std::string
+ dummy_init_fn_name();
+
+ // Return the package path symbol from an init function name, which
+ // can be a real init function or a dummy one.
+ std::string
+ pkgpath_from_init_fn_name(std::string);
+
// Return the name for a type descriptor symbol.
std::string
type_descriptor_name(const Type*, Named_type*);
// Return the name of the type descriptor list symbol of a package.
std::string
- type_descriptor_list_symbol(Package*);
+ type_descriptor_list_symbol(std::string);
// Return the name of the list of all type descriptor lists.
std::string
//
// The import function for the main package is referenced by C code,
// and is named __go_init_main. For other packages it is
-// PKGPATH..import.
+// PKGPATH..import. If a package doesn't need an init function, it
+// will have a dummy one, named ~PKGPATH.
//
// In each pacakge there is a list of all the type descriptors defined
// in this package. The name of the list is PKGPATH..types.
return this->init_fn_name_;
}
+// Return the name for a dummy init function, which is not a real
+// function but only for tracking transitive import.
+
+std::string
+Gogo::dummy_init_fn_name()
+{
+ return "~" + this->pkgpath_symbol();
+}
+
+// Return the package path symbol from an init function name, which
+// can be a real init function or a dummy one.
+
+std::string
+Gogo::pkgpath_from_init_fn_name(std::string name)
+{
+ go_assert(!name.empty());
+ if (name[0] == '~')
+ return name.substr(1);
+ size_t pos = name.find("..import");
+ if (pos != std::string::npos)
+ return name.substr(0, pos);
+ go_unreachable();
+}
+
// Return a mangled name for a type. These names appear in symbol
// names in the assembler file for things like type descriptors and
// methods.
// Return the name of the type descriptor list symbol of a package.
std::string
-Gogo::type_descriptor_list_symbol(Package* pkg)
+Gogo::type_descriptor_list_symbol(std::string pkgpath)
{
- return pkg->pkgpath_symbol() + "..types";
+ return pkgpath + "..types";
}
// Return the name of the list of all type descriptor lists. This is