compiler: clean up unresolved placeholders for pointer types
authorIan Lance Taylor <ian@gcc.gnu.org>
Tue, 25 Jul 2017 22:54:23 +0000 (22:54 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 25 Jul 2017 22:54:23 +0000 (22:54 +0000)
    Add a new helper routine Type::finish_pointer_types that walks through
    the pointer type cache and looks for placeholder types that may have
    been created at some point before conversion of named types, and
    invokes Type::finish_backend() on said placeholders.  This is needed
    to handle cases where the compiler manufactures a pointer type as part
    of lowering, then a placeholder is created for it due to a call to
    Type::backend_type_size(), but there is no explicit reference to the
    type in user code.

    Reviewed-on: https://go-review.googlesource.com/51131

From-SVN: r250548

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/types.cc
gcc/go/gofrontend/types.h

index 4c0b827d66f1d498d113641878ff802c7b0d932e..78905fe39c4779a86b6267ea361934354968317e 100644 (file)
@@ -1,4 +1,4 @@
-e1bd9ea4dc16e228164c92a12c5229ddf20f2b50
+61ce3b80ab20cb1f16960c1784bc0937abaa440a
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index a9d72ff4aa06675ed7f43ffac703f37e2efe8342..ca4b454a2381a06f52b1b151d0b5066a7078a0dd 100644 (file)
@@ -4824,6 +4824,8 @@ Gogo::convert_named_types()
   Runtime::convert_types(this);
 
   this->named_types_are_converted_ = true;
+
+  Type::finish_pointer_types(this);
 }
 
 // Convert all names types in a set of bindings.
index ca5f5121d3699035ee61a24b3564691812c41e15..91d6091f54496031eba8a383ad722c2c3a0a9d82 100644 (file)
@@ -5516,14 +5516,17 @@ Pointer_type::do_import(Import* imp)
   return Type::make_pointer_type(to);
 }
 
+// Cache of pointer types. Key is "to" type, value is pointer type
+// that points to key.
+
+Type::Pointer_type_table Type::pointer_types;
+
 // Make a pointer type.
 
 Pointer_type*
 Type::make_pointer_type(Type* to_type)
 {
-  typedef Unordered_map(Type*, Pointer_type*) Hashtable;
-  static Hashtable pointer_types;
-  Hashtable::const_iterator p = pointer_types.find(to_type);
+  Pointer_type_table::const_iterator p = pointer_types.find(to_type);
   if (p != pointer_types.end())
     return p->second;
   Pointer_type* ret = new Pointer_type(to_type);
@@ -5531,6 +5534,37 @@ Type::make_pointer_type(Type* to_type)
   return ret;
 }
 
+// This helper is invoked immediately after named types have been
+// converted, to clean up any unresolved pointer types remaining in
+// the pointer type cache.
+//
+// The motivation for this routine: occasionally the compiler creates
+// some specific pointer type as part of a lowering operation (ex:
+// pointer-to-void), then Type::backend_type_size() is invoked on the
+// type (which creates a Btype placeholder for it), that placeholder
+// passed somewhere along the line to the back end, but since there is
+// no reference to the type in user code, there is never a call to
+// Type::finish_backend for the type (hence the Btype remains as an
+// unresolved placeholder).  Calling this routine will clean up such
+// instances.
+
+void
+Type::finish_pointer_types(Gogo* gogo)
+{
+  for (Pointer_type_table::const_iterator i = pointer_types.begin();
+       i != pointer_types.end();
+       ++i)
+    {
+      Pointer_type* pt = i->second;
+      Type_btypes::iterator tbti = Type::type_btypes.find(pt);
+      if (tbti != Type::type_btypes.end() && tbti->second.is_placeholder)
+        {
+          pt->finish_backend(gogo, tbti->second.btype);
+          tbti->second.is_placeholder = false;
+        }
+    }
+}
+
 // The nil type.  We use a special type for nil because it is not the
 // same as any other type.  In C term nil has type void*, but there is
 // no such type in Go.
index aeb04d6c50f56cc77689481993824c9f070b982b..f659f3848456fb0187e5f33c2a37bca01e0c07fd 100644 (file)
@@ -504,6 +504,9 @@ class Type
   static Pointer_type*
   make_pointer_type(Type*);
 
+  static void
+  finish_pointer_types(Gogo* gogo);
+
   static Type*
   make_nil_type();
 
@@ -1341,6 +1344,12 @@ class Type
 
   static Type_functions type_functions_table;
 
+  // Cache for reusing existing pointer types; maps from pointed-to-type
+  // to pointer type.
+  typedef Unordered_map(Type*, Pointer_type*) Pointer_type_table;
+
+  static Pointer_type_table pointer_types;
+
   // The type classification.
   Type_classification classification_;
   // The backend representation of the type, once it has been