From 84c71bb8ecc84f6ca5cbc56786b9ba74eb05057e Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 7 Feb 2018 01:52:48 +0000 Subject: [PATCH] compiler: make single Btype for methods table of identical interface type Normally we ensure to build a single Btype for identical types. We did not do this for methods table of identical interface types, however. If there are two identical interface type I, I2, they have the same Btype BI, but different Btypes for their methods tables, BM and BM2. From the backend's point of view only one of them is linked to BI. This can cause inconsitency in the backend's type system, like unresolved placeholder. This CL ensures we create a single Btype for methods table of identical interface type. Reviewed-on: https://go-review.googlesource.com/92436 From-SVN: r257436 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/types.cc | 44 ++++++++++++++++++++++++++++++++++---- gcc/go/gofrontend/types.h | 14 ++++++++++++ 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 8c49b2b12da..81e11d1946f 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -02f11a2d5cf0db2c2675c13d92bb69529f2175dd +5fe998e4a18cc1dbbd4869be5c8202bda55adb33 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/types.cc b/gcc/go/gofrontend/types.cc index 34edf762835..eb04fe1e229 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -9096,6 +9096,8 @@ Interface_type::get_backend_empty_interface_type(Gogo* gogo) return empty_interface_type; } +Interface_type::Bmethods_map Interface_type::bmethods_map; + // Return a pointer to the backend representation of the method table. Btype* @@ -9104,6 +9106,21 @@ Interface_type::get_backend_methods(Gogo* gogo) if (this->bmethods_ != NULL && !this->bmethods_is_placeholder_) return this->bmethods_; + std::pair val; + val.first = this; + val.second.btype = NULL; + val.second.is_placeholder = false; + std::pair ins = + Interface_type::bmethods_map.insert(val); + if (!ins.second + && ins.first->second.btype != NULL + && !ins.first->second.is_placeholder) + { + this->bmethods_ = ins.first->second.btype; + this->bmethods_is_placeholder_ = false; + return this->bmethods_; + } + Location loc = this->location(); std::vector @@ -9160,10 +9177,14 @@ Interface_type::get_backend_methods(Gogo* gogo) Btype* st = gogo->backend()->struct_type(mfields); Btype* ret = gogo->backend()->pointer_type(st); - if (this->bmethods_ != NULL && this->bmethods_is_placeholder_) - gogo->backend()->set_placeholder_pointer_type(this->bmethods_, ret); + if (ins.first->second.btype != NULL + && ins.first->second.is_placeholder) + gogo->backend()->set_placeholder_pointer_type(ins.first->second.btype, + ret); this->bmethods_ = ret; + ins.first->second.btype = ret; this->bmethods_is_placeholder_ = false; + ins.first->second.is_placeholder = false; return ret; } @@ -9174,10 +9195,25 @@ Interface_type::get_backend_methods_placeholder(Gogo* gogo) { if (this->bmethods_ == NULL) { + std::pair val; + val.first = this; + val.second.btype = NULL; + val.second.is_placeholder = false; + std::pair ins = + Interface_type::bmethods_map.insert(val); + if (!ins.second && ins.first->second.btype != NULL) + { + this->bmethods_ = ins.first->second.btype; + this->bmethods_is_placeholder_ = ins.first->second.is_placeholder; + return this->bmethods_; + } + Location loc = this->location(); - this->bmethods_ = gogo->backend()->placeholder_pointer_type("", loc, - false); + Btype* bt = gogo->backend()->placeholder_pointer_type("", loc, false); + this->bmethods_ = bt; + ins.first->second.btype = bt; this->bmethods_is_placeholder_ = true; + ins.first->second.is_placeholder = true; } return this->bmethods_; } diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index 648773131ca..234e0a6abbd 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -3185,6 +3185,20 @@ class Interface_type : public Type bool assume_identical(const Interface_type*, const Interface_type*) const; + struct Bmethods_map_entry + { + Btype *btype; + bool is_placeholder; + }; + + // A mapping from Interface_type to the backend type of its bmethods_, + // used to ensure that the backend representation of identical types + // is identical. + typedef Unordered_map_hash(const Interface_type*, Bmethods_map_entry, + Type_hash_identical, Type_identical) Bmethods_map; + + static Bmethods_map bmethods_map; + // The list of methods associated with the interface from the // parser. This will be NULL for the empty interface. This may // include unnamed interface types. -- 2.30.2