summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2017-07-25 22:54:23 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2017-07-25 22:54:23 +0000
commit9b0818e352ae5eea0f7eee6671d16e9b2a46066f (patch)
treed45157c11b96e49a3175cd09161923fe1925180c
parenta04c40d482507bed66329f1b4e9d8f23aa283ef5 (diff)
downloadgcc-9b0818e352ae5eea0f7eee6671d16e9b2a46066f.tar.gz
compiler: clean up unresolved placeholders for pointer types
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 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@250548 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/gogo.cc2
-rw-r--r--gcc/go/gofrontend/types.cc40
-rw-r--r--gcc/go/gofrontend/types.h9
4 files changed, 49 insertions, 4 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 4c0b827d66f..78905fe39c4 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -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.
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index a9d72ff4aa0..ca4b454a238 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -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.
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index ca5f5121d36..91d6091f544 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -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.
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index aeb04d6c50f..f659f384845 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -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