Commit 08327dfa by Ian Lance Taylor

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
parent c2830789
e1bd9ea4dc16e228164c92a12c5229ddf20f2b50 61ce3b80ab20cb1f16960c1784bc0937abaa440a
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -4824,6 +4824,8 @@ Gogo::convert_named_types() ...@@ -4824,6 +4824,8 @@ Gogo::convert_named_types()
Runtime::convert_types(this); Runtime::convert_types(this);
this->named_types_are_converted_ = true; this->named_types_are_converted_ = true;
Type::finish_pointer_types(this);
} }
// Convert all names types in a set of bindings. // Convert all names types in a set of bindings.
......
...@@ -5516,14 +5516,17 @@ Pointer_type::do_import(Import* imp) ...@@ -5516,14 +5516,17 @@ Pointer_type::do_import(Import* imp)
return Type::make_pointer_type(to); 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. // Make a pointer type.
Pointer_type* Pointer_type*
Type::make_pointer_type(Type* to_type) Type::make_pointer_type(Type* to_type)
{ {
typedef Unordered_map(Type*, Pointer_type*) Hashtable; Pointer_type_table::const_iterator p = pointer_types.find(to_type);
static Hashtable pointer_types;
Hashtable::const_iterator p = pointer_types.find(to_type);
if (p != pointer_types.end()) if (p != pointer_types.end())
return p->second; return p->second;
Pointer_type* ret = new Pointer_type(to_type); Pointer_type* ret = new Pointer_type(to_type);
...@@ -5531,6 +5534,37 @@ Type::make_pointer_type(Type* to_type) ...@@ -5531,6 +5534,37 @@ Type::make_pointer_type(Type* to_type)
return ret; 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 // 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 // same as any other type. In C term nil has type void*, but there is
// no such type in Go. // no such type in Go.
......
...@@ -504,6 +504,9 @@ class Type ...@@ -504,6 +504,9 @@ class Type
static Pointer_type* static Pointer_type*
make_pointer_type(Type*); make_pointer_type(Type*);
static void
finish_pointer_types(Gogo* gogo);
static Type* static Type*
make_nil_type(); make_nil_type();
...@@ -1341,6 +1344,12 @@ class Type ...@@ -1341,6 +1344,12 @@ class Type
static Type_functions type_functions_table; 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. // The type classification.
Type_classification classification_; Type_classification classification_;
// The backend representation of the type, once it has been // The backend representation of the type, once it has been
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment