From b4d216f6e206dab4c37d80bfb91b76e2776cb9ef Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 30 Jan 2015 15:57:59 +0000 Subject: [PATCH] compiler: Add pkgpath symbol information to export data. This adds the pkgpath symbol to the export data whenever it is needed--whenever the pkgpath symbol is not the obvious transformation of the pkgpath. This lets us determine the correct symbol name for indirectly imported packages compiled with -fgo-prefix. From-SVN: r220291 --- gcc/go/gofrontend/export.cc | 45 +++++++++++++++++++++++++++++++++++++ gcc/go/gofrontend/export.h | 6 +++++ gcc/go/gofrontend/gogo.cc | 8 ++----- gcc/go/gofrontend/import.cc | 22 ++++++++++++++++++ gcc/go/gofrontend/import.h | 4 ++++ 5 files changed, 79 insertions(+), 6 deletions(-) diff --git a/gcc/go/gofrontend/export.cc b/gcc/go/gofrontend/export.cc index e37f03446c1..5c0094d8795 100644 --- a/gcc/go/gofrontend/export.cc +++ b/gcc/go/gofrontend/export.cc @@ -94,6 +94,7 @@ Export::export_globals(const std::string& package_name, const std::string& prefix, const std::string& pkgpath, int package_priority, + const std::map& packages, const std::map& imports, const std::string& import_init_fn, const std::set& imported_init_fns, @@ -160,6 +161,8 @@ Export::export_globals(const std::string& package_name, snprintf(buf, sizeof buf, "priority %d;\n", package_priority); this->write_c_string(buf); + this->write_packages(packages); + this->write_imports(imports); this->write_imported_init_fns(package_name, package_priority, import_init_fn, @@ -190,6 +193,48 @@ Export::export_globals(const std::string& package_name, this->stream_->write_checksum(s); } +// Sort packages. + +static bool +packages_compare(const Package* a, const Package* b) +{ + return a->package_name() < b->package_name(); +} + +// Write out all the known packages whose pkgpath symbol is not a +// simple transformation of the pkgpath, so that the importing code +// can reliably know it. + +void +Export::write_packages(const std::map& packages) +{ + // Sort for consistent output. + std::vector out; + for (std::map::const_iterator p = packages.begin(); + p != packages.end(); + ++p) + { + if (p->second->pkgpath_symbol() + != Gogo::pkgpath_for_symbol(p->second->pkgpath())) + out.push_back(p->second); + } + + std::sort(out.begin(), out.end(), packages_compare); + + for (std::vector::const_iterator p = out.begin(); + p != out.end(); + ++p) + { + this->write_c_string("package "); + this->write_string((*p)->package_name()); + this->write_c_string(" "); + this->write_string((*p)->pkgpath()); + this->write_c_string(" "); + this->write_string((*p)->pkgpath_symbol()); + this->write_c_string(";\n"); + } +} + // Sort imported packages. static bool diff --git a/gcc/go/gofrontend/export.h b/gcc/go/gofrontend/export.h index c010a14686c..0526e9a3f6d 100644 --- a/gcc/go/gofrontend/export.h +++ b/gcc/go/gofrontend/export.h @@ -120,6 +120,7 @@ class Export : public String_dump // PREFIX is the package prefix. PKGPATH is the package path. // Only one of PREFIX and PKGPATH will be non-empty. // PACKAGE_PRIORITY is the priority to use for this package. + // PACKAGES is all the packages we have seen. // IMPORTS is the explicitly imported packages. // IMPORT_INIT_FN is the name of the import initialization function // for this package; it will be empty if none is needed. @@ -130,6 +131,7 @@ class Export : public String_dump const std::string& prefix, const std::string& pkgpath, int package_priority, + const std::map& packages, const std::map& imports, const std::string& import_init_fn, const std::set& imported_init_fns, @@ -163,6 +165,10 @@ class Export : public String_dump Export(const Export&); Export& operator=(const Export&); + // Write out all known packages. + void + write_packages(const std::map& packages); + // Write out the imported packages. void write_imports(const std::map& imports); diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 9039ce3ab9d..6196f03ae2c 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -4364,6 +4364,7 @@ Gogo::do_exports() prefix, pkgpath, this->package_priority(), + this->packages_, this->imports_, (this->need_init_fn_ && !this->is_main_package() ? this->get_init_fn_name() @@ -7537,12 +7538,7 @@ std::string Package::pkgpath_symbol() const { if (this->pkgpath_symbol_.empty()) - { - // In the general case, this is wrong, because the package might - // have been compiled with -fprefix. However, it is what we - // used to do, so it is no more wrong than we were before. - return Gogo::pkgpath_for_symbol(this->pkgpath_); - } + return Gogo::pkgpath_for_symbol(this->pkgpath_); return this->pkgpath_symbol_; } diff --git a/gcc/go/gofrontend/import.cc b/gcc/go/gofrontend/import.cc index cfc042976f3..e1fba78818f 100644 --- a/gcc/go/gofrontend/import.cc +++ b/gcc/go/gofrontend/import.cc @@ -338,6 +338,9 @@ Import::import(Gogo* gogo, const std::string& local_name, this->package_->set_priority(prio); this->require_c_string(";\n"); + while (stream->match_c_string("package")) + this->read_one_package(); + while (stream->match_c_string("import")) this->read_one_import(); @@ -381,6 +384,25 @@ Import::import(Gogo* gogo, const std::string& local_name, return this->package_; } +// Read a package line. This let us reliably determine the pkgpath +// symbol, even if the package was compiled with a -fgo-prefix option. + +void +Import::read_one_package() +{ + this->require_c_string("package "); + std::string package_name = this->read_identifier(); + this->require_c_string(" "); + std::string pkgpath = this->read_identifier(); + this->require_c_string(" "); + std::string pkgpath_symbol = this->read_identifier(); + this->require_c_string(";\n"); + + Package* p = this->gogo_->register_package(pkgpath, pkgpath_symbol, + Linemap::unknown_location()); + p->set_package_name(package_name, this->location()); +} + // Read an import line. We don't actually care about these. void diff --git a/gcc/go/gofrontend/import.h b/gcc/go/gofrontend/import.h index 9917937e4d3..2a9ac80e7e2 100644 --- a/gcc/go/gofrontend/import.h +++ b/gcc/go/gofrontend/import.h @@ -220,6 +220,10 @@ class Import find_archive_export_data(const std::string& filename, int fd, Location); + // Read a package line. + void + read_one_package(); + // Read an import line. void read_one_import(); -- 2.30.2