diff options
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.cc | 44 | ||||
-rw-r--r-- | 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 8c49b2b..81e11d1 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 34edf76..eb04fe1 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<Interface_type*, Bmethods_map_entry> val; + val.first = this; + val.second.btype = NULL; + val.second.is_placeholder = false; + std::pair<Bmethods_map::iterator, bool> 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<Backend::Btyped_identifier> @@ -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<Interface_type*, Bmethods_map_entry> val; + val.first = this; + val.second.btype = NULL; + val.second.is_placeholder = false; + std::pair<Bmethods_map::iterator, bool> 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 6487731..234e0a6 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. |