compiler: Add pkgpath symbol information to export data.
authorIan Lance Taylor <ian@gcc.gnu.org>
Fri, 30 Jan 2015 15:57:59 +0000 (15:57 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 30 Jan 2015 15:57:59 +0000 (15:57 +0000)
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
gcc/go/gofrontend/export.h
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/import.cc
gcc/go/gofrontend/import.h

index e37f03446c1b3763b21daf511c95121297a5a857..5c0094d8795a210e5d915f1850de25799fa40483 100644 (file)
@@ -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<std::string, Package*>& packages,
                       const std::map<std::string, Package*>& imports,
                       const std::string& import_init_fn,
                       const std::set<Import_init>& 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<std::string, Package*>& packages)
+{
+  // Sort for consistent output.
+  std::vector<Package*> out;
+  for (std::map<std::string, Package*>::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<Package*>::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
index c010a14686c115f608c539a7488e29f2327aa751..0526e9a3f6defe86d4b8060b1f7f8e9374abf176 100644 (file)
@@ -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<std::string, Package*>& packages,
                 const std::map<std::string, Package*>& imports,
                 const std::string& import_init_fn,
                 const std::set<Import_init>& 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<std::string, Package*>& packages);
+
   // Write out the imported packages.
   void
   write_imports(const std::map<std::string, Package*>& imports);
index 9039ce3ab9d3db958fb05e29b1739f9f36a489e8..6196f03ae2c9597962a5d89d5b715859cebb709f 100644 (file)
@@ -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_;
 }
 
index cfc042976f3e7b77fcd77bfb1858f04101c4b424..e1fba78818fb1b0021f799e10fdec1841119b73c 100644 (file)
@@ -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
index 9917937e4d3ba3abaa3f85642be2a0c93d61aecb..2a9ac80e7e227fc74ff7660310bbe885412e0c11 100644 (file)
@@ -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();