Commit 84c71bb8 by Ian Lance Taylor

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
parent 95b88fd4
02f11a2d5cf0db2c2675c13d92bb69529f2175dd 5fe998e4a18cc1dbbd4869be5c8202bda55adb33
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -9096,6 +9096,8 @@ Interface_type::get_backend_empty_interface_type(Gogo* gogo) ...@@ -9096,6 +9096,8 @@ Interface_type::get_backend_empty_interface_type(Gogo* gogo)
return empty_interface_type; return empty_interface_type;
} }
Interface_type::Bmethods_map Interface_type::bmethods_map;
// Return a pointer to the backend representation of the method table. // Return a pointer to the backend representation of the method table.
Btype* Btype*
...@@ -9104,6 +9106,21 @@ Interface_type::get_backend_methods(Gogo* gogo) ...@@ -9104,6 +9106,21 @@ Interface_type::get_backend_methods(Gogo* gogo)
if (this->bmethods_ != NULL && !this->bmethods_is_placeholder_) if (this->bmethods_ != NULL && !this->bmethods_is_placeholder_)
return this->bmethods_; 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(); Location loc = this->location();
std::vector<Backend::Btyped_identifier> std::vector<Backend::Btyped_identifier>
...@@ -9160,10 +9177,14 @@ Interface_type::get_backend_methods(Gogo* gogo) ...@@ -9160,10 +9177,14 @@ Interface_type::get_backend_methods(Gogo* gogo)
Btype* st = gogo->backend()->struct_type(mfields); Btype* st = gogo->backend()->struct_type(mfields);
Btype* ret = gogo->backend()->pointer_type(st); Btype* ret = gogo->backend()->pointer_type(st);
if (this->bmethods_ != NULL && this->bmethods_is_placeholder_) if (ins.first->second.btype != NULL
gogo->backend()->set_placeholder_pointer_type(this->bmethods_, ret); && ins.first->second.is_placeholder)
gogo->backend()->set_placeholder_pointer_type(ins.first->second.btype,
ret);
this->bmethods_ = ret; this->bmethods_ = ret;
ins.first->second.btype = ret;
this->bmethods_is_placeholder_ = false; this->bmethods_is_placeholder_ = false;
ins.first->second.is_placeholder = false;
return ret; return ret;
} }
...@@ -9174,10 +9195,25 @@ Interface_type::get_backend_methods_placeholder(Gogo* gogo) ...@@ -9174,10 +9195,25 @@ Interface_type::get_backend_methods_placeholder(Gogo* gogo)
{ {
if (this->bmethods_ == NULL) 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(); Location loc = this->location();
this->bmethods_ = gogo->backend()->placeholder_pointer_type("", loc, Btype* bt = gogo->backend()->placeholder_pointer_type("", loc, false);
false); this->bmethods_ = bt;
ins.first->second.btype = bt;
this->bmethods_is_placeholder_ = true; this->bmethods_is_placeholder_ = true;
ins.first->second.is_placeholder = true;
} }
return this->bmethods_; return this->bmethods_;
} }
......
...@@ -3185,6 +3185,20 @@ class Interface_type : public Type ...@@ -3185,6 +3185,20 @@ class Interface_type : public Type
bool bool
assume_identical(const Interface_type*, const Interface_type*) const; 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 // The list of methods associated with the interface from the
// parser. This will be NULL for the empty interface. This may // parser. This will be NULL for the empty interface. This may
// include unnamed interface types. // include unnamed interface types.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment