diff mbox

Go patch committed: Clean up unresolved placeholders for pointer types

Message ID CAOyqgcXyB3p8yUjMtwsGCJPbg2AhwUH=OdHGKzYzjFWaGg3UWQ@mail.gmail.com
State New
Headers show

Commit Message

Ian Lance Taylor July 25, 2017, 10:54 p.m. UTC
This patch to the Go frontend by Than McIntosh adds 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.  Bootstrapped and ran Go testsuite on
x86_64-pc-linux-gnu.  Committed to mainline.

Ian
diff mbox

Patch

Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 250443)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -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: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 250406)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -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: gcc/go/gofrontend/types.cc
===================================================================
--- gcc/go/gofrontend/types.cc	(revision 250406)
+++ gcc/go/gofrontend/types.cc	(working copy)
@@ -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: gcc/go/gofrontend/types.h
===================================================================
--- gcc/go/gofrontend/types.h	(revision 250406)
+++ gcc/go/gofrontend/types.h	(working copy)
@@ -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