aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2018-02-07 01:52:48 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-02-07 01:52:48 +0000
commit84c71bb8ecc84f6ca5cbc56786b9ba74eb05057e (patch)
tree24d63e86412abc324b20ce986151d07c70bf01a2 /gcc
parent95b88fd400cdc0300ed5a7ec7abaf90958aef58d (diff)
downloadgcc-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/MERGE2
-rw-r--r--gcc/go/gofrontend/types.cc44
-rw-r--r--gcc/go/gofrontend/types.h14
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.