diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-02-07 01:52:48 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-02-07 01:52:48 +0000 |
commit | 84c71bb8ecc84f6ca5cbc56786b9ba74eb05057e (patch) | |
tree | 24d63e86412abc324b20ce986151d07c70bf01a2 /gcc | |
parent | 95b88fd400cdc0300ed5a7ec7abaf90958aef58d (diff) | |
download | gcc-84c71bb8ecc84f6ca5cbc56786b9ba74eb05057e.zip gcc-84c71bb8ecc84f6ca5cbc56786b9ba74eb05057e.tar.gz gcc-84c71bb8ecc84f6ca5cbc56786b9ba74eb05057e.tar.bz2 |
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
Diffstat (limited to 'gcc')
-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. |