diff options
Diffstat (limited to 'gcc/go/gofrontend/types.cc')
-rw-r--r-- | gcc/go/gofrontend/types.cc | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index ca5f5121d36..4d923733667 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -1057,6 +1057,8 @@ Type::get_backend_placeholder(Gogo* gogo) { Location loc = Linemap::unknown_location(); bt = gogo->backend()->placeholder_pointer_type("", loc, false); + Pointer_type* pt = this->convert<Pointer_type, TYPE_POINTER>(); + Type::placeholder_pointers.push_back(pt); } break; @@ -5516,14 +5518,22 @@ 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; + +// A list of placeholder pointer types. We keep this so we can ensure +// they are finalized. + +std::vector<Pointer_type*> Type::placeholder_pointers; + // 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 +5541,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) +{ + // We don't use begin() and end() because it is possible to add new + // placeholder pointer types as we finalized existing ones. + for (size_t i = 0; i < Type::placeholder_pointers.size(); i++) + { + Pointer_type* pt = Type::placeholder_pointers[i]; + 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. |