From 08327dfa73c3cc2daf15a0c4405ae1bcfa940ef3 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 25 Jul 2017 22:54:23 +0000 Subject: [PATCH] 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 From-SVN: r250548 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/gogo.cc | 2 ++ gcc/go/gofrontend/types.cc | 40 +++++++++++++++++++++++++++++++++++--- gcc/go/gofrontend/types.h | 9 +++++++++ 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 -- 2.30.2