]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
compiler: support export/import of unsafe.Add/Slice
authorIan Lance Taylor <iant@golang.org>
Fri, 6 Aug 2021 19:01:04 +0000 (12:01 -0700)
committerIan Lance Taylor <iant@golang.org>
Sat, 7 Aug 2021 20:37:58 +0000 (13:37 -0700)
For golang/go#19367
For golang/go#40481

Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/340549

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/export.cc
gcc/go/gofrontend/export.h
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/expressions.h
gcc/go/gofrontend/gogo.h
gcc/go/gofrontend/import.cc
gcc/go/gofrontend/unsafe.cc

index 9ed527f7eb495885817ba1856336b16fc691efc8..b983fdab35c0793621a98430b8e67a0c20b5acdf 100644 (file)
@@ -1,4 +1,4 @@
-747f3a2d78c073e9b03dd81914d0edb7ddc5be14
+d5d51242efc432fa62d4e9b141b01c280af32d19
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index e99c680f709fcfaba032f935736e7310ddfd5a64..3d11334884da54b2341a52545edec567b570e0c8 100644 (file)
@@ -106,11 +106,12 @@ class Collect_export_references : public Traverse
 {
  public:
   Collect_export_references(Export* exp,
+                           const std::map<std::string, Package*>& packages,
                             Unordered_set(Named_object*)* exports,
                             Unordered_set(const Package*)* imports)
     : Traverse(traverse_expressions
                | traverse_types),
-      exp_(exp), exports_(exports), imports_(imports),
+      exp_(exp), packages_(packages), exports_(exports), imports_(imports),
       inline_fcn_worklist_(NULL), exports_finalized_(false)
   { }
 
@@ -150,6 +151,8 @@ class Collect_export_references : public Traverse
 
   // The exporter.
   Export* exp_;
+  // The list of packages known to this compilation.
+  const std::map<std::string, Package*>& packages_;
   // The set of named objects to export.
   Unordered_set(Named_object*)* exports_;
   // Set containing all directly and indirectly imported packages.
@@ -257,6 +260,24 @@ Collect_export_references::expression(Expression** pexpr)
       return TRAVERSE_CONTINUE;
     }
 
+  const Call_expression* call = expr->call_expression();
+  if (call != NULL)
+    {
+      const Builtin_call_expression* bce = call->builtin_call_expression();
+      if (bce != NULL
+         && (bce->code() == Builtin_call_expression::BUILTIN_ADD
+             || bce->code() == Builtin_call_expression::BUILTIN_SLICE))
+       {
+         // This is a reference to unsafe.Add or unsafe.Slice.  Make
+         // sure we list the "unsafe" package in the imports and give
+         // it a package index.
+         const std::map<std::string, Package*>::const_iterator p =
+           this->packages_.find("unsafe");
+         go_assert(p != this->packages_.end());
+         this->imports_->insert(p->second);
+       }
+    }
+
   return TRAVERSE_CONTINUE;
 }
 
@@ -589,7 +610,7 @@ Export::export_globals(const std::string& package_name,
   // Track all imported packages mentioned in export data.
   Unordered_set(const Package*) all_imports;
 
-  Collect_export_references collect(this, &exports, &all_imports);
+  Collect_export_references collect(this, packages, &exports, &all_imports);
 
   // Walk the set of inlinable routine bodies collected above. This
   // can potentially expand the exports set.
@@ -1274,6 +1295,25 @@ Export::package_index(const Package* pkg) const
   return index;
 }
 
+// Return the index of the "unsafe" package.
+
+int
+Export::unsafe_package_index() const
+{
+  for (Unordered_map(const Package*, int)::const_iterator p =
+        this->packages_.begin();
+       p != this->packages_.end();
+       ++p)
+    {
+      if (p->first->pkgpath() == "unsafe")
+       {
+         go_assert(p->second != 0);
+         return p->second;
+       }
+    }
+  go_unreachable();
+}
+
 // Return the index of a type.
 
 int
index c93bced4eb49f9a7614b9e7c61e365a7086d80d1..1f613434cabc1943ea7e2ddbb6deb58c7a3a82ce 100644 (file)
@@ -216,6 +216,11 @@ class Export : public String_dump
   int
   package_index(const Package* p) const;
 
+  // Return the index of the "unsafe" package, which must be one of
+  // the exported packages.
+  int
+  unsafe_package_index() const;
+
  private:
   Export(const Export&);
   Export& operator=(const Export&);
@@ -377,6 +382,11 @@ class Export_function_body : public String_dump
   package_index(const Package* p) const
   { return this->exp_->package_index(p); }
 
+  // Return the index of the "unsafe" package.
+  int
+  unsafe_package_index() const
+  { return this->exp_->unsafe_package_index(); }
+
   // Record a temporary statement and return its index.
   unsigned int
   record_temporary(const Temporary_statement*);
index 33177a709ab5af9ddcb280f339fb664026be4601..f462b0e2a34f86f57ad28ab5d3889b1475e17726 100644 (file)
@@ -11039,6 +11039,14 @@ Builtin_call_expression::do_export(Export_function_body* efb) const
       // A trailing space lets us reliably identify the end of the number.
       efb->write_c_string(" ");
     }
+  else if (this->code_ == BUILTIN_ADD || this->code_ == BUILTIN_SLICE)
+    {
+      char buf[50];
+      snprintf(buf, sizeof buf, "<p%d>%s", efb->unsafe_package_index(),
+              (this->code_ == BUILTIN_ADD ? "Add" : "Slice"));
+      efb->write_c_string(buf);
+      this->export_arguments(efb);
+    }
   else
     {
       const char *s = NULL;
index 79a8785b69d129876bd2093bc52c93c6913e61fe..9f8f4e9255b65369d6f761cdf9b3ad69987d88e2 100644 (file)
@@ -732,6 +732,10 @@ class Expression
   call_expression()
   { return this->convert<Call_expression, EXPRESSION_CALL>(); }
 
+  const Call_expression*
+  call_expression() const
+  { return this->convert<const Call_expression, EXPRESSION_CALL>(); }
+
   // If this is a call_result expression, return the Call_result_expression
   // structure.  Otherwise, return NULL.  This is a controlled dynamic
   // cast.
@@ -2460,13 +2464,16 @@ class Call_expression : public Expression
 
   // Whether this is a call to builtin function.
   virtual bool
-  is_builtin()
+  is_builtin() const
   { return false; }
 
   // Convert to a Builtin_call_expression, or return NULL.
   inline Builtin_call_expression*
   builtin_call_expression();
 
+  inline const Builtin_call_expression*
+  builtin_call_expression() const;
+
  protected:
   int
   do_traverse(Traverse*);
@@ -2625,12 +2632,12 @@ class Builtin_call_expression : public Call_expression
     };
 
   Builtin_function_code
-  code()
+  code() const
   { return this->code_; }
 
   // This overrides Call_expression::is_builtin.
   bool
-  is_builtin()
+  is_builtin() const
   { return true; }
 
   // Return whether EXPR, of array type, is a constant if passed to
@@ -2726,6 +2733,14 @@ Call_expression::builtin_call_expression()
           : NULL);
 }
 
+inline const Builtin_call_expression*
+Call_expression::builtin_call_expression() const
+{
+  return (this->is_builtin()
+          ? static_cast<const Builtin_call_expression*>(this)
+          : NULL);
+}
+
 // A single result from a call which returns multiple results.
 
 class Call_result_expression : public Expression
index c49bc92b3e073a95e4f6eac7b137dfac42a43b96..9ffd120290d90f1585369737c387e9ee26b2caa8 100644 (file)
@@ -533,6 +533,10 @@ class Gogo
   register_package(const std::string& pkgpath,
                   const std::string& pkgpath_symbol, Location);
 
+  // Add the unsafe bindings to the unsafe package.
+  void
+  add_unsafe_bindings(Package*);
+
   // Look up a package by pkgpath, and return its pkgpath_symbol.
   std::string
   pkgpath_symbol_for_package(const std::string&);
index f671416a42319956dd44644d8259ca5185801627..6a5491be949e7106b53740a7e3c844678f5875d7 100644 (file)
@@ -497,6 +497,9 @@ Import::read_one_import()
   p->set_package_name(package_name, this->location());
 
   this->packages_.push_back(p);
+
+  if (pkgpath == "unsafe")
+    this->gogo_->add_unsafe_bindings(p);
 }
 
 // Read an indirectimport line.
@@ -515,6 +518,9 @@ Import::read_one_indirect_import()
   p->set_package_name(package_name, this->location());
 
   this->packages_.push_back(p);
+
+  if (pkgpath == "unsafe")
+    this->gogo_->add_unsafe_bindings(p);
 }
 
 // Read the list of import control functions and/or init graph.
index 18bd99eca15af451f66dae8c969d34164392f1b1..c4a9346ca3e331c22a657c156f2246bfbd416b9c 100644 (file)
 #include "types.h"
 #include "gogo.h"
 
-// Set up the builtin unsafe package.  This should probably be driven
-// by a table.
+// Set up the builtin unsafe package.
 
 void
 Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported,
                    Location location)
 {
-  Location bloc = Linemap::predeclared_location();
-
   bool add_to_globals;
   Package* package = this->add_imported_package("unsafe", local_name,
                                                is_local_name_exported,
@@ -34,10 +31,40 @@ Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported,
   package->set_location(location);
   this->imports_.insert(std::make_pair("unsafe", package));
 
+  this->add_unsafe_bindings(package);
+
+  Named_object* pointer_no = package->bindings()->lookup_local("Pointer");
+  pointer_no->type_value()->set_is_visible();
+
+  if (add_to_globals)
+    {
+      Bindings* bindings = package->bindings();
+      for (Bindings::const_declarations_iterator p =
+            bindings->begin_declarations();
+          p != bindings->end_declarations();
+          ++p)
+       this->add_dot_import_object(p->second);
+    }
+}
+
+// Add the unsafe bindings to the Package object.  This should
+// probably be driven by a table.
+
+void
+Gogo::add_unsafe_bindings(Package* package)
+{
   Bindings* bindings = package->bindings();
 
+  if (bindings->lookup_local("Sizeof") != NULL)
+    {
+      // Already done by an earlier import.
+      return;
+    }
+
+  Location bloc = Linemap::predeclared_location();
+
   // The type may have already been created by an import.
-  Named_object* no = package->bindings()->lookup("Pointer");
+  Named_object* no = bindings->lookup("Pointer");
   if (no == NULL)
     {
       Type* type = Type::make_pointer_type(Type::make_void_type());
@@ -49,11 +76,12 @@ Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported,
       go_assert(no->package() == package);
       go_assert(no->is_type());
       go_assert(no->type_value()->is_unsafe_pointer_type());
-      no->type_value()->set_is_visible();
     }
   Named_type* pointer_type = no->type_value();
-  if (add_to_globals)
-    this->add_named_type(pointer_type);
+
+  // This may be called during an import, so the type may not be
+  // visible yet.
+  pointer_type->clear_is_visible();
 
   Type* uintptr_type = Type::lookup_integer_type("uintptr");
 
@@ -62,9 +90,7 @@ Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported,
   results->push_back(Typed_identifier("", uintptr_type, bloc));
   Function_type* fntype = Type::make_function_type(NULL, NULL, results, bloc);
   fntype->set_is_builtin();
-  no = bindings->add_function_declaration("Sizeof", package, fntype, bloc);
-  if (add_to_globals)
-    this->add_dot_import_object(no);
+  bindings->add_function_declaration("Sizeof", package, fntype, bloc);
 
   // Offsetof.
   results = new Typed_identifier_list;
@@ -72,9 +98,7 @@ Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported,
   fntype = Type::make_function_type(NULL, NULL, results, bloc);
   fntype->set_is_varargs();
   fntype->set_is_builtin();
-  no = bindings->add_function_declaration("Offsetof", package, fntype, bloc);
-  if (add_to_globals)
-    this->add_dot_import_object(no);
+  bindings->add_function_declaration("Offsetof", package, fntype, bloc);
 
   // Alignof.
   results = new Typed_identifier_list;
@@ -82,25 +106,19 @@ Gogo::import_unsafe(const std::string& local_name, bool is_local_name_exported,
   fntype = Type::make_function_type(NULL, NULL, results, bloc);
   fntype->set_is_varargs();
   fntype->set_is_builtin();
-  no = bindings->add_function_declaration("Alignof", package, fntype, bloc);
-  if (add_to_globals)
-    this->add_dot_import_object(no);
+  bindings->add_function_declaration("Alignof", package, fntype, bloc);
 
   // Add.
   results = new Typed_identifier_list;
   results->push_back(Typed_identifier("", pointer_type, bloc));
   fntype = Type::make_function_type(NULL, NULL, results, bloc);
   fntype->set_is_builtin();
-  no = bindings->add_function_declaration("Add", package, fntype, bloc);
-  if (add_to_globals)
-    this->add_dot_import_object(no);
+  bindings->add_function_declaration("Add", package, fntype, bloc);
 
   // Slice.
   fntype = Type::make_function_type(NULL, NULL, NULL, bloc);
   fntype->set_is_builtin();
-  no = bindings->add_function_declaration("Slice", package, fntype, bloc);
-  if (add_to_globals)
-    this->add_dot_import_object(no);
+  bindings->add_function_declaration("Slice", package, fntype, bloc);
 
   if (!this->imported_unsafe_)
     {