Use backend interface for named types and array types.
* go-gcc.cc (Gcc_backend::struct_type): Call fill_in_struct. (Gcc_backend::fill_in_struct): New function. (Gcc_backend::array_type): Implement. (Gcc_backend::fill_in_array): New function. (Gcc_backend::placeholder_pointer_type): New function. (Gcc_backend::set_placeholder_pointer_type): New function. (Gcc_backend::set_placeholder_function_type): New function. (Gcc_backend::placeholder_struct_type): New function. (Gcc_backend::set_placeholder_struct_type): New function. (Gcc_backend::placeholder_array_type): New function. (Gcc_backend::set_placeholder_array_type): New function. (Gcc_backend::named_type): New function. (Gcc_backend::circular_pointer_type): New function. (Gcc_backend::is_circular_pointer_type): New function. From-SVN: r173380
This commit is contained in:
parent
f81b1a3d37
commit
7fc2f86b5f
@ -1,3 +1,20 @@
|
||||
2011-05-04 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* go-gcc.cc (Gcc_backend::struct_type): Call fill_in_struct.
|
||||
(Gcc_backend::fill_in_struct): New function.
|
||||
(Gcc_backend::array_type): Implement.
|
||||
(Gcc_backend::fill_in_array): New function.
|
||||
(Gcc_backend::placeholder_pointer_type): New function.
|
||||
(Gcc_backend::set_placeholder_pointer_type): New function.
|
||||
(Gcc_backend::set_placeholder_function_type): New function.
|
||||
(Gcc_backend::placeholder_struct_type): New function.
|
||||
(Gcc_backend::set_placeholder_struct_type): New function.
|
||||
(Gcc_backend::placeholder_array_type): New function.
|
||||
(Gcc_backend::set_placeholder_array_type): New function.
|
||||
(Gcc_backend::named_type): New function.
|
||||
(Gcc_backend::circular_pointer_type): New function.
|
||||
(Gcc_backend::is_circular_pointer_type): New function.
|
||||
|
||||
2011-04-26 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* go-gcc.cc (Gcc_backend::struct_type): Implement.
|
||||
|
234
gcc/go/go-gcc.cc
234
gcc/go/go-gcc.cc
@ -161,8 +161,38 @@ class Gcc_backend : public Backend
|
||||
struct_type(const std::vector<Btyped_identifier>&);
|
||||
|
||||
Btype*
|
||||
array_type(const Btype* /* element_type */, const Bexpression* /* length */)
|
||||
{ gcc_unreachable(); }
|
||||
array_type(Btype*, Bexpression*);
|
||||
|
||||
Btype*
|
||||
placeholder_pointer_type(const std::string&, source_location, bool);
|
||||
|
||||
bool
|
||||
set_placeholder_pointer_type(Btype*, Btype*);
|
||||
|
||||
bool
|
||||
set_placeholder_function_type(Btype*, Btype*);
|
||||
|
||||
Btype*
|
||||
placeholder_struct_type(const std::string&, source_location);
|
||||
|
||||
bool
|
||||
set_placeholder_struct_type(Btype* placeholder,
|
||||
const std::vector<Btyped_identifier>&);
|
||||
|
||||
Btype*
|
||||
placeholder_array_type(const std::string&, source_location);
|
||||
|
||||
bool
|
||||
set_placeholder_array_type(Btype*, Btype*, Bexpression*);
|
||||
|
||||
Btype*
|
||||
named_type(const std::string&, Btype*, source_location);
|
||||
|
||||
Btype*
|
||||
circular_pointer_type(Btype*, bool);
|
||||
|
||||
bool
|
||||
is_circular_pointer_type(Btype*);
|
||||
|
||||
// Statements.
|
||||
|
||||
@ -270,6 +300,12 @@ class Gcc_backend : public Backend
|
||||
Btype*
|
||||
make_type(tree t)
|
||||
{ return new Btype(t); }
|
||||
|
||||
Btype*
|
||||
fill_in_struct(Btype*, const std::vector<Btyped_identifier>&);
|
||||
|
||||
Btype*
|
||||
fill_in_array(Btype*, Btype*, Bexpression*);
|
||||
};
|
||||
|
||||
// A helper function.
|
||||
@ -453,7 +489,16 @@ Gcc_backend::function_type(const Btyped_identifier& receiver,
|
||||
Btype*
|
||||
Gcc_backend::struct_type(const std::vector<Btyped_identifier>& fields)
|
||||
{
|
||||
tree ret = make_node(RECORD_TYPE);
|
||||
return this->fill_in_struct(this->make_type(make_node(RECORD_TYPE)), fields);
|
||||
}
|
||||
|
||||
// Fill in the fields of a struct type.
|
||||
|
||||
Btype*
|
||||
Gcc_backend::fill_in_struct(Btype* fill,
|
||||
const std::vector<Btyped_identifier>& fields)
|
||||
{
|
||||
tree fill_tree = fill->get_tree();
|
||||
tree field_trees = NULL_TREE;
|
||||
tree* pp = &field_trees;
|
||||
for (std::vector<Btyped_identifier>::const_iterator p = fields.begin();
|
||||
@ -465,15 +510,192 @@ Gcc_backend::struct_type(const std::vector<Btyped_identifier>& fields)
|
||||
if (type_tree == error_mark_node)
|
||||
return this->error_type();
|
||||
tree field = build_decl(p->location, FIELD_DECL, name_tree, type_tree);
|
||||
DECL_CONTEXT(field) = ret;
|
||||
DECL_CONTEXT(field) = fill_tree;
|
||||
*pp = field;
|
||||
pp = &DECL_CHAIN(field);
|
||||
}
|
||||
TYPE_FIELDS(ret) = field_trees;
|
||||
layout_type(ret);
|
||||
TYPE_FIELDS(fill_tree) = field_trees;
|
||||
layout_type(fill_tree);
|
||||
return fill;
|
||||
}
|
||||
|
||||
// Make an array type.
|
||||
|
||||
Btype*
|
||||
Gcc_backend::array_type(Btype* element_btype, Bexpression* length)
|
||||
{
|
||||
return this->fill_in_array(this->make_type(make_node(ARRAY_TYPE)),
|
||||
element_btype, length);
|
||||
}
|
||||
|
||||
// Fill in an array type.
|
||||
|
||||
Btype*
|
||||
Gcc_backend::fill_in_array(Btype* fill, Btype* element_type,
|
||||
Bexpression* length)
|
||||
{
|
||||
tree element_type_tree = element_type->get_tree();
|
||||
tree length_tree = length->get_tree();
|
||||
if (element_type_tree == error_mark_node || length_tree == error_mark_node)
|
||||
return this->error_type();
|
||||
|
||||
gcc_assert(TYPE_SIZE(element_type_tree) != NULL_TREE);
|
||||
|
||||
length_tree = fold_convert(sizetype, length_tree);
|
||||
|
||||
// build_index_type takes the maximum index, which is one less than
|
||||
// the length.
|
||||
tree index_type_tree = build_index_type(fold_build2(MINUS_EXPR, sizetype,
|
||||
length_tree,
|
||||
size_one_node));
|
||||
|
||||
tree fill_tree = fill->get_tree();
|
||||
TREE_TYPE(fill_tree) = element_type_tree;
|
||||
TYPE_DOMAIN(fill_tree) = index_type_tree;
|
||||
TYPE_ADDR_SPACE(fill_tree) = TYPE_ADDR_SPACE(element_type_tree);
|
||||
layout_type(fill_tree);
|
||||
|
||||
if (TYPE_STRUCTURAL_EQUALITY_P(element_type_tree))
|
||||
SET_TYPE_STRUCTURAL_EQUALITY(fill_tree);
|
||||
else if (TYPE_CANONICAL(element_type_tree) != element_type_tree
|
||||
|| TYPE_CANONICAL(index_type_tree) != index_type_tree)
|
||||
TYPE_CANONICAL(fill_tree) =
|
||||
build_array_type(TYPE_CANONICAL(element_type_tree),
|
||||
TYPE_CANONICAL(index_type_tree));
|
||||
|
||||
return fill;
|
||||
}
|
||||
|
||||
// Create a placeholder for a pointer type.
|
||||
|
||||
Btype*
|
||||
Gcc_backend::placeholder_pointer_type(const std::string& name,
|
||||
source_location location, bool)
|
||||
{
|
||||
tree ret = build_variant_type_copy(ptr_type_node);
|
||||
tree decl = build_decl(location, TYPE_DECL,
|
||||
get_identifier_from_string(name),
|
||||
ret);
|
||||
TYPE_NAME(ret) = decl;
|
||||
return this->make_type(ret);
|
||||
}
|
||||
|
||||
// Set the real target type for a placeholder pointer type.
|
||||
|
||||
bool
|
||||
Gcc_backend::set_placeholder_pointer_type(Btype* placeholder,
|
||||
Btype* to_type)
|
||||
{
|
||||
tree pt = placeholder->get_tree();
|
||||
if (pt == error_mark_node)
|
||||
return false;
|
||||
gcc_assert(TREE_CODE(pt) == POINTER_TYPE);
|
||||
tree tt = to_type->get_tree();
|
||||
if (tt == error_mark_node)
|
||||
{
|
||||
TREE_TYPE(pt) = tt;
|
||||
return false;
|
||||
}
|
||||
gcc_assert(TREE_CODE(tt) == POINTER_TYPE);
|
||||
TREE_TYPE(pt) = TREE_TYPE(tt);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set the real values for a placeholder function type.
|
||||
|
||||
bool
|
||||
Gcc_backend::set_placeholder_function_type(Btype* placeholder, Btype* ft)
|
||||
{
|
||||
return this->set_placeholder_pointer_type(placeholder, ft);
|
||||
}
|
||||
|
||||
// Create a placeholder for a struct type.
|
||||
|
||||
Btype*
|
||||
Gcc_backend::placeholder_struct_type(const std::string& name,
|
||||
source_location location)
|
||||
{
|
||||
tree ret = make_node(RECORD_TYPE);
|
||||
tree decl = build_decl(location, TYPE_DECL,
|
||||
get_identifier_from_string(name),
|
||||
ret);
|
||||
TYPE_NAME(ret) = decl;
|
||||
return this->make_type(ret);
|
||||
}
|
||||
|
||||
// Fill in the fields of a placeholder struct type.
|
||||
|
||||
bool
|
||||
Gcc_backend::set_placeholder_struct_type(
|
||||
Btype* placeholder,
|
||||
const std::vector<Btyped_identifier>& fields)
|
||||
{
|
||||
tree t = placeholder->get_tree();
|
||||
gcc_assert(TREE_CODE(t) == RECORD_TYPE && TYPE_FIELDS(t) == NULL_TREE);
|
||||
Btype* r = this->fill_in_struct(placeholder, fields);
|
||||
return r->get_tree() != error_mark_node;
|
||||
}
|
||||
|
||||
// Create a placeholder for an array type.
|
||||
|
||||
Btype*
|
||||
Gcc_backend::placeholder_array_type(const std::string& name,
|
||||
source_location location)
|
||||
{
|
||||
tree ret = make_node(ARRAY_TYPE);
|
||||
tree decl = build_decl(location, TYPE_DECL,
|
||||
get_identifier_from_string(name),
|
||||
ret);
|
||||
TYPE_NAME(ret) = decl;
|
||||
return this->make_type(ret);
|
||||
}
|
||||
|
||||
// Fill in the fields of a placeholder array type.
|
||||
|
||||
bool
|
||||
Gcc_backend::set_placeholder_array_type(Btype* placeholder,
|
||||
Btype* element_btype,
|
||||
Bexpression* length)
|
||||
{
|
||||
tree t = placeholder->get_tree();
|
||||
gcc_assert(TREE_CODE(t) == ARRAY_TYPE && TREE_TYPE(t) == NULL_TREE);
|
||||
Btype* r = this->fill_in_array(placeholder, element_btype, length);
|
||||
return r->get_tree() != error_mark_node;
|
||||
}
|
||||
|
||||
// Return a named version of a type.
|
||||
|
||||
Btype*
|
||||
Gcc_backend::named_type(const std::string& name, Btype* btype,
|
||||
source_location location)
|
||||
{
|
||||
tree type = btype->get_tree();
|
||||
if (type == error_mark_node)
|
||||
return this->error_type();
|
||||
type = build_variant_type_copy(type);
|
||||
tree decl = build_decl(location, TYPE_DECL,
|
||||
get_identifier_from_string(name),
|
||||
type);
|
||||
TYPE_NAME(type) = decl;
|
||||
return this->make_type(type);
|
||||
}
|
||||
|
||||
// Return a pointer type used as a marker for a circular type.
|
||||
|
||||
Btype*
|
||||
Gcc_backend::circular_pointer_type(Btype*, bool)
|
||||
{
|
||||
return this->make_type(ptr_type_node);
|
||||
}
|
||||
|
||||
// Return whether we might be looking at a circular type.
|
||||
|
||||
bool
|
||||
Gcc_backend::is_circular_pointer_type(Btype* btype)
|
||||
{
|
||||
return btype->get_tree() == ptr_type_node;
|
||||
}
|
||||
|
||||
// An expression as a statement.
|
||||
|
||||
Bstatement*
|
||||
|
@ -108,7 +108,93 @@ class Backend
|
||||
|
||||
// Get an array type.
|
||||
virtual Btype*
|
||||
array_type(const Btype* element_type, const Bexpression* length) = 0;
|
||||
array_type(Btype* element_type, Bexpression* length) = 0;
|
||||
|
||||
// Create a placeholder pointer type. This is used for a named
|
||||
// pointer type, since in Go a pointer type may refer to itself.
|
||||
// NAME is the name of the type, and the location is where the named
|
||||
// type is defined. FOR_FUNCTION is true if this is for a Go
|
||||
// function type, which corresponds to a C/C++ pointer to function
|
||||
// type. The return value will later be passed as the first
|
||||
// parameter to set_placeholder_pointer_type or
|
||||
// set_placeholder_function_type.
|
||||
virtual Btype*
|
||||
placeholder_pointer_type(const std::string& name, source_location,
|
||||
bool for_function) = 0;
|
||||
|
||||
// Fill in a placeholder pointer type as a pointer. This takes a
|
||||
// type returned by placeholder_pointer_type and arranges for it to
|
||||
// point to to_type. Returns true on success, false on failure.
|
||||
virtual bool
|
||||
set_placeholder_pointer_type(Btype* placeholder, Btype* to_type) = 0;
|
||||
|
||||
// Fill in a placeholder pointer type as a function. This takes a
|
||||
// type returned by placeholder_pointer_type and arranges for it to
|
||||
// become a real Go function type (which corresponds to a C/C++
|
||||
// pointer to function type). FT will be something returned by the
|
||||
// function_type method. Returns true on success, false on failure.
|
||||
virtual bool
|
||||
set_placeholder_function_type(Btype* placeholder, Btype* ft) = 0;
|
||||
|
||||
// Create a placeholder struct type. This is used for a named
|
||||
// struct type, as with placeholder_pointer_type.
|
||||
virtual Btype*
|
||||
placeholder_struct_type(const std::string& name, source_location) = 0;
|
||||
|
||||
// Fill in a placeholder struct type. This takes a type returned by
|
||||
// placeholder_struct_type and arranges for it to become a real
|
||||
// struct type. The parameter is as for struct_type. Returns true
|
||||
// on success, false on failure.
|
||||
virtual bool
|
||||
set_placeholder_struct_type(Btype* placeholder,
|
||||
const std::vector<Btyped_identifier>& fields)
|
||||
= 0;
|
||||
|
||||
// Create a placeholder array type. This is used for a named array
|
||||
// type, as with placeholder_pointer_type, to handle cases like
|
||||
// type A []*A.
|
||||
virtual Btype*
|
||||
placeholder_array_type(const std::string& name, source_location) = 0;
|
||||
|
||||
// Fill in a placeholder array type. This takes a type returned by
|
||||
// placeholder_array_type and arranges for it to become a real array
|
||||
// type. The parameters are as for array_type. Returns true on
|
||||
// success, false on failure.
|
||||
virtual bool
|
||||
set_placeholder_array_type(Btype* placeholder, Btype* element_type,
|
||||
Bexpression* length) = 0;
|
||||
|
||||
// Return a named version of a type. The location is the location
|
||||
// of the type definition. This will not be called for a type
|
||||
// created via placeholder_pointer_type, placeholder_struct_type, or
|
||||
// placeholder_array_type.. (It may be called for a pointer,
|
||||
// struct, or array type in a case like "type P *byte; type Q P".)
|
||||
virtual Btype*
|
||||
named_type(const std::string& name, Btype*, source_location) = 0;
|
||||
|
||||
// Create a marker for a circular pointer type. Go pointer and
|
||||
// function types can refer to themselves in ways that are not
|
||||
// permitted in C/C++. When a circular type is found, this function
|
||||
// is called for the circular reference. This permits the backend
|
||||
// to decide how to handle such a type. PLACEHOLDER is the
|
||||
// placeholder type which has already been created; if the backend
|
||||
// is prepared to handle a circular pointer type, it may simply
|
||||
// return PLACEHOLDER. FOR_FUNCTION is true if this is for a
|
||||
// function type.
|
||||
//
|
||||
// For "type P *P" the sequence of calls will be
|
||||
// bt1 = placeholder_pointer_type();
|
||||
// bt2 = circular_pointer_type(bt1, false);
|
||||
// set_placeholder_pointer_type(bt1, bt2);
|
||||
virtual Btype*
|
||||
circular_pointer_type(Btype* placeholder, bool for_function) = 0;
|
||||
|
||||
// Return whether the argument could be a special type created by
|
||||
// circular_pointer_type. This is used to introduce explicit type
|
||||
// conversions where needed. If circular_pointer_type returns its
|
||||
// PLACEHOLDER parameter, this may safely always return false.
|
||||
virtual bool
|
||||
is_circular_pointer_type(Btype*) = 0;
|
||||
|
||||
// Statements.
|
||||
|
||||
|
@ -896,10 +896,11 @@ Type::get_tree_without_hash(Gogo* gogo)
|
||||
tree t = this->do_get_tree(gogo);
|
||||
|
||||
// For a recursive function or pointer type, we will temporarily
|
||||
// return ptr_type_node during the recursion. We don't want to
|
||||
// record that for a forwarding type, as it may confuse us
|
||||
// later.
|
||||
if (t == ptr_type_node && this->forward_declaration_type() != NULL)
|
||||
// return a circular pointer type during the recursion. We
|
||||
// don't want to record that for a forwarding type, as it may
|
||||
// confuse us later.
|
||||
if (this->forward_declaration_type() != NULL
|
||||
&& gogo->backend()->is_circular_pointer_type(tree_to_type(t)))
|
||||
return t;
|
||||
|
||||
if (gogo == NULL || !gogo->named_types_are_converted())
|
||||
@ -912,6 +913,16 @@ Type::get_tree_without_hash(Gogo* gogo)
|
||||
return this->tree_;
|
||||
}
|
||||
|
||||
// Return the backend representation for a type without looking in the
|
||||
// hash table for identical types. This is used for named types,
|
||||
// since a named type is never identical to any other type.
|
||||
|
||||
Btype*
|
||||
Type::get_btype_without_hash(Gogo* gogo)
|
||||
{
|
||||
return tree_to_type(this->get_tree_without_hash(gogo));
|
||||
}
|
||||
|
||||
// Return a tree representing a zero initialization for this type.
|
||||
|
||||
tree
|
||||
@ -3748,60 +3759,38 @@ Struct_type::method_function(const std::string& name, bool* is_ambiguous) const
|
||||
return Type::method_function(this->all_methods_, name, is_ambiguous);
|
||||
}
|
||||
|
||||
// Convert struct fields to the backend representation. This is not
|
||||
// declared in types.h so that types.h doesn't have to #include
|
||||
// backend.h.
|
||||
|
||||
static void
|
||||
get_backend_struct_fields(Gogo* gogo, const Struct_field_list* fields,
|
||||
std::vector<Backend::Btyped_identifier>* bfields)
|
||||
{
|
||||
bfields->resize(fields->size());
|
||||
size_t i = 0;
|
||||
for (Struct_field_list::const_iterator p = fields->begin();
|
||||
p != fields->end();
|
||||
++p, ++i)
|
||||
{
|
||||
(*bfields)[i].name = Gogo::unpack_hidden_name(p->field_name());
|
||||
(*bfields)[i].btype = tree_to_type(p->type()->get_tree(gogo));
|
||||
(*bfields)[i].location = p->location();
|
||||
}
|
||||
go_assert(i == fields->size());
|
||||
}
|
||||
|
||||
// Get the tree for a struct type.
|
||||
|
||||
tree
|
||||
Struct_type::do_get_tree(Gogo* gogo)
|
||||
{
|
||||
std::vector<Backend::Btyped_identifier> fields;
|
||||
fields.resize(this->fields_->size());
|
||||
size_t i = 0;
|
||||
for (Struct_field_list::const_iterator p = this->fields_->begin();
|
||||
p != this->fields_->end();
|
||||
++p, ++i)
|
||||
{
|
||||
fields[i].name = Gogo::unpack_hidden_name(p->field_name());
|
||||
fields[i].btype = tree_to_type(p->type()->get_tree(gogo));
|
||||
fields[i].location = p->location();
|
||||
}
|
||||
go_assert(i == this->fields_->size());
|
||||
Btype* btype = gogo->backend()->struct_type(fields);
|
||||
std::vector<Backend::Btyped_identifier> bfields;
|
||||
get_backend_struct_fields(gogo, this->fields_, &bfields);
|
||||
Btype* btype = gogo->backend()->struct_type(bfields);
|
||||
return type_to_tree(btype);
|
||||
}
|
||||
|
||||
// Fill in the fields for a struct type.
|
||||
|
||||
tree
|
||||
Struct_type::fill_in_tree(Gogo* gogo, tree type)
|
||||
{
|
||||
tree field_trees = NULL_TREE;
|
||||
tree* pp = &field_trees;
|
||||
for (Struct_field_list::const_iterator p = this->fields_->begin();
|
||||
p != this->fields_->end();
|
||||
++p)
|
||||
{
|
||||
std::string name = Gogo::unpack_hidden_name(p->field_name());
|
||||
tree name_tree = get_identifier_with_length(name.data(), name.length());
|
||||
|
||||
tree field_type_tree = p->type()->get_tree(gogo);
|
||||
if (field_type_tree == error_mark_node)
|
||||
return error_mark_node;
|
||||
go_assert(TYPE_SIZE(field_type_tree) != NULL_TREE);
|
||||
|
||||
tree field = build_decl(p->location(), FIELD_DECL, name_tree,
|
||||
field_type_tree);
|
||||
DECL_CONTEXT(field) = type;
|
||||
*pp = field;
|
||||
pp = &DECL_CHAIN(field);
|
||||
}
|
||||
|
||||
TYPE_FIELDS(type) = field_trees;
|
||||
|
||||
layout_type(type);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
// Initialize struct fields.
|
||||
|
||||
tree
|
||||
@ -4425,50 +4414,26 @@ Array_type::do_get_tree(Gogo* gogo)
|
||||
}
|
||||
else
|
||||
{
|
||||
tree array_type = make_node(ARRAY_TYPE);
|
||||
return this->fill_in_array_tree(gogo, array_type);
|
||||
Btype* element = this->get_backend_element(gogo);
|
||||
Bexpression* len = this->get_backend_length(gogo);
|
||||
Btype* ret = gogo->backend()->array_type(element, len);
|
||||
return type_to_tree(ret);
|
||||
}
|
||||
}
|
||||
|
||||
// Fill in the fields for an array type. This is used for named array
|
||||
// types.
|
||||
|
||||
tree
|
||||
Array_type::fill_in_array_tree(Gogo* gogo, tree array_type)
|
||||
// Return the backend representation of the element type.
|
||||
Btype*
|
||||
Array_type::get_backend_element(Gogo* gogo)
|
||||
{
|
||||
go_assert(this->length_ != NULL);
|
||||
return tree_to_type(this->element_type_->get_tree(gogo));
|
||||
}
|
||||
|
||||
tree element_type_tree = this->element_type_->get_tree(gogo);
|
||||
tree length_tree = this->get_length_tree(gogo);
|
||||
if (element_type_tree == error_mark_node
|
||||
|| length_tree == error_mark_node)
|
||||
return error_mark_node;
|
||||
// Return the backend representation of the length.
|
||||
|
||||
go_assert(TYPE_SIZE(element_type_tree) != NULL_TREE);
|
||||
|
||||
length_tree = fold_convert(sizetype, length_tree);
|
||||
|
||||
// build_index_type takes the maximum index, which is one less than
|
||||
// the length.
|
||||
tree index_type = build_index_type(fold_build2(MINUS_EXPR, sizetype,
|
||||
length_tree,
|
||||
size_one_node));
|
||||
|
||||
TREE_TYPE(array_type) = element_type_tree;
|
||||
TYPE_DOMAIN(array_type) = index_type;
|
||||
TYPE_ADDR_SPACE(array_type) = TYPE_ADDR_SPACE(element_type_tree);
|
||||
layout_type(array_type);
|
||||
|
||||
if (TYPE_STRUCTURAL_EQUALITY_P(element_type_tree)
|
||||
|| TYPE_STRUCTURAL_EQUALITY_P(index_type))
|
||||
SET_TYPE_STRUCTURAL_EQUALITY(array_type);
|
||||
else if (TYPE_CANONICAL(element_type_tree) != element_type_tree
|
||||
|| TYPE_CANONICAL(index_type) != index_type)
|
||||
TYPE_CANONICAL(array_type) =
|
||||
build_array_type(TYPE_CANONICAL(element_type_tree),
|
||||
TYPE_CANONICAL(index_type));
|
||||
|
||||
return array_type;
|
||||
Bexpression*
|
||||
Array_type::get_backend_length(Gogo* gogo)
|
||||
{
|
||||
return tree_to_expr(this->get_length_tree(gogo));
|
||||
}
|
||||
|
||||
// Fill in the fields for a slice type. This is used for named slice
|
||||
@ -7073,7 +7038,7 @@ Named_type::convert(Gogo* gogo)
|
||||
(*p)->convert(gogo);
|
||||
|
||||
// Complete this type.
|
||||
tree t = this->named_tree_;
|
||||
Btype* bt = this->named_btype_;
|
||||
Type* base = this->type_->base();
|
||||
switch (base->classification())
|
||||
{
|
||||
@ -7092,21 +7057,37 @@ Named_type::convert(Gogo* gogo)
|
||||
|
||||
case TYPE_FUNCTION:
|
||||
case TYPE_POINTER:
|
||||
// The size of these types is already correct.
|
||||
// The size of these types is already correct. We don't worry
|
||||
// about filling them in until later, when we also track
|
||||
// circular references.
|
||||
break;
|
||||
|
||||
case TYPE_STRUCT:
|
||||
t = base->struct_type()->fill_in_tree(gogo, t);
|
||||
{
|
||||
std::vector<Backend::Btyped_identifier> bfields;
|
||||
get_backend_struct_fields(gogo, base->struct_type()->fields(),
|
||||
&bfields);
|
||||
if (!gogo->backend()->set_placeholder_struct_type(bt, bfields))
|
||||
bt = gogo->backend()->error_type();
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_ARRAY:
|
||||
if (!base->is_open_array_type())
|
||||
t = base->array_type()->fill_in_array_tree(gogo, t);
|
||||
{
|
||||
Btype* bet = base->array_type()->get_backend_element(gogo);
|
||||
Bexpression* blen = base->array_type()->get_backend_length(gogo);
|
||||
if (!gogo->backend()->set_placeholder_array_type(bt, bet, blen))
|
||||
bt = gogo->backend()->error_type();
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_INTERFACE:
|
||||
if (!base->interface_type()->is_empty())
|
||||
t = base->interface_type()->fill_in_tree(gogo, t);
|
||||
{
|
||||
tree t = type_to_tree(bt);
|
||||
bt = tree_to_type(base->interface_type()->fill_in_tree(gogo, t));
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_ERROR:
|
||||
@ -7120,13 +7101,7 @@ Named_type::convert(Gogo* gogo)
|
||||
go_unreachable();
|
||||
}
|
||||
|
||||
this->named_tree_ = t;
|
||||
|
||||
if (t == error_mark_node)
|
||||
this->is_error_ = true;
|
||||
else
|
||||
go_assert(TYPE_SIZE(t) != NULL_TREE);
|
||||
|
||||
this->named_btype_ = bt;
|
||||
this->is_converted_ = true;
|
||||
}
|
||||
|
||||
@ -7137,9 +7112,9 @@ void
|
||||
Named_type::create_placeholder(Gogo* gogo)
|
||||
{
|
||||
if (this->is_error_)
|
||||
this->named_tree_ = error_mark_node;
|
||||
this->named_btype_ = gogo->backend()->error_type();
|
||||
|
||||
if (this->named_tree_ != NULL_TREE)
|
||||
if (this->named_btype_ != NULL)
|
||||
return;
|
||||
|
||||
// Create the structure for this type. Note that because we call
|
||||
@ -7147,12 +7122,13 @@ Named_type::create_placeholder(Gogo* gogo)
|
||||
// as another named type. Instead both named types will point to
|
||||
// different base representations.
|
||||
Type* base = this->type_->base();
|
||||
tree t;
|
||||
Btype* bt;
|
||||
bool set_name = true;
|
||||
switch (base->classification())
|
||||
{
|
||||
case TYPE_ERROR:
|
||||
this->is_error_ = true;
|
||||
this->named_tree_ = error_mark_node;
|
||||
this->named_btype_ = gogo->backend()->error_type();
|
||||
return;
|
||||
|
||||
case TYPE_VOID:
|
||||
@ -7164,55 +7140,50 @@ Named_type::create_placeholder(Gogo* gogo)
|
||||
case TYPE_NIL:
|
||||
// These are simple basic types, we can just create them
|
||||
// directly.
|
||||
t = Type::get_named_type_tree(gogo, base);
|
||||
if (t == error_mark_node)
|
||||
{
|
||||
this->is_error_ = true;
|
||||
this->named_tree_ = error_mark_node;
|
||||
return;
|
||||
}
|
||||
t = build_variant_type_copy(t);
|
||||
bt = Type::get_named_base_btype(gogo, base);
|
||||
break;
|
||||
|
||||
case TYPE_MAP:
|
||||
case TYPE_CHANNEL:
|
||||
// All maps and channels have the same type in GENERIC.
|
||||
t = Type::get_named_type_tree(gogo, base);
|
||||
if (t == error_mark_node)
|
||||
{
|
||||
this->is_error_ = true;
|
||||
this->named_tree_ = error_mark_node;
|
||||
return;
|
||||
}
|
||||
t = build_variant_type_copy(t);
|
||||
// All maps and channels have the same backend representation.
|
||||
bt = Type::get_named_base_btype(gogo, base);
|
||||
break;
|
||||
|
||||
case TYPE_FUNCTION:
|
||||
case TYPE_POINTER:
|
||||
t = build_variant_type_copy(ptr_type_node);
|
||||
{
|
||||
bool for_function = base->classification() == TYPE_FUNCTION;
|
||||
bt = gogo->backend()->placeholder_pointer_type(this->name(),
|
||||
this->location_,
|
||||
for_function);
|
||||
set_name = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_STRUCT:
|
||||
t = make_node(RECORD_TYPE);
|
||||
bt = gogo->backend()->placeholder_struct_type(this->name(),
|
||||
this->location_);
|
||||
set_name = false;
|
||||
break;
|
||||
|
||||
case TYPE_ARRAY:
|
||||
if (base->is_open_array_type())
|
||||
t = gogo->slice_type_tree(void_type_node);
|
||||
bt = tree_to_type(gogo->slice_type_tree(void_type_node));
|
||||
else
|
||||
t = make_node(ARRAY_TYPE);
|
||||
{
|
||||
bt = gogo->backend()->placeholder_array_type(this->name(),
|
||||
this->location_);
|
||||
set_name = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_INTERFACE:
|
||||
if (base->interface_type()->is_empty())
|
||||
{
|
||||
t = Interface_type::empty_type_tree(gogo);
|
||||
t = build_variant_type_copy(t);
|
||||
}
|
||||
bt = tree_to_type(Interface_type::empty_type_tree(gogo));
|
||||
else
|
||||
{
|
||||
source_location loc = base->interface_type()->location();
|
||||
t = Interface_type::non_empty_type_tree(loc);
|
||||
bt = tree_to_type(Interface_type::non_empty_type_tree(loc));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -7224,13 +7195,10 @@ Named_type::create_placeholder(Gogo* gogo)
|
||||
go_unreachable();
|
||||
}
|
||||
|
||||
// Create the named type.
|
||||
if (set_name)
|
||||
bt = gogo->backend()->named_type(this->name(), bt, this->location_);
|
||||
|
||||
tree id = this->named_object_->get_id(gogo);
|
||||
tree decl = build_decl(this->location_, TYPE_DECL, id, t);
|
||||
TYPE_NAME(t) = decl;
|
||||
|
||||
this->named_tree_ = t;
|
||||
this->named_btype_ = bt;
|
||||
}
|
||||
|
||||
// Get a tree for a named type.
|
||||
@ -7241,24 +7209,22 @@ Named_type::do_get_tree(Gogo* gogo)
|
||||
if (this->is_error_)
|
||||
return error_mark_node;
|
||||
|
||||
tree t = this->named_tree_;
|
||||
Btype* bt = this->named_btype_;
|
||||
|
||||
// FIXME: GOGO can be NULL when called from go_type_for_size, which
|
||||
// is only used for basic types.
|
||||
if (gogo == NULL || !gogo->named_types_are_converted())
|
||||
if (!gogo->named_types_are_converted())
|
||||
{
|
||||
// We have not completed converting named types. NAMED_TREE_ is
|
||||
// a placeholder and we shouldn't do anything further.
|
||||
if (t != NULL_TREE)
|
||||
return t;
|
||||
// We have not completed converting named types. NAMED_BTYPE_
|
||||
// is a placeholder and we shouldn't do anything further.
|
||||
if (bt != NULL)
|
||||
return type_to_tree(bt);
|
||||
|
||||
// We don't build dependencies for types whose sizes do not
|
||||
// change or are not relevant, so we may see them here while
|
||||
// converting types.
|
||||
this->create_placeholder(gogo);
|
||||
t = this->named_tree_;
|
||||
go_assert(t != NULL_TREE);
|
||||
return t;
|
||||
bt = this->named_btype_;
|
||||
go_assert(bt != NULL);
|
||||
return type_to_tree(bt);
|
||||
}
|
||||
|
||||
// We are not converting types. This should only be called if the
|
||||
@ -7269,11 +7235,11 @@ Named_type::do_get_tree(Gogo* gogo)
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
go_assert(t != NULL_TREE && TYPE_SIZE(t) != NULL_TREE);
|
||||
go_assert(bt != NULL);
|
||||
|
||||
// Complete the tree.
|
||||
Type* base = this->type_->base();
|
||||
tree t1;
|
||||
Btype* bt1;
|
||||
switch (base->classification())
|
||||
{
|
||||
case TYPE_ERROR:
|
||||
@ -7290,7 +7256,7 @@ Named_type::do_get_tree(Gogo* gogo)
|
||||
case TYPE_CHANNEL:
|
||||
case TYPE_STRUCT:
|
||||
case TYPE_INTERFACE:
|
||||
return t;
|
||||
return type_to_tree(bt);
|
||||
|
||||
case TYPE_FUNCTION:
|
||||
// Don't build a circular data structure. GENERIC can't handle
|
||||
@ -7298,19 +7264,17 @@ Named_type::do_get_tree(Gogo* gogo)
|
||||
if (this->seen_ > 0)
|
||||
{
|
||||
this->is_circular_ = true;
|
||||
return ptr_type_node;
|
||||
bt1 = gogo->backend()->circular_pointer_type(bt, true);
|
||||
return type_to_tree(bt1);
|
||||
}
|
||||
++this->seen_;
|
||||
t1 = Type::get_named_type_tree(gogo, base);
|
||||
bt1 = Type::get_named_base_btype(gogo, base);
|
||||
--this->seen_;
|
||||
if (t1 == error_mark_node)
|
||||
return error_mark_node;
|
||||
if (this->is_circular_)
|
||||
t1 = ptr_type_node;
|
||||
go_assert(t != NULL_TREE && TREE_CODE(t) == POINTER_TYPE);
|
||||
go_assert(TREE_CODE(t1) == POINTER_TYPE);
|
||||
TREE_TYPE(t) = TREE_TYPE(t1);
|
||||
return t;
|
||||
bt1 = gogo->backend()->circular_pointer_type(bt, true);
|
||||
if (!gogo->backend()->set_placeholder_pointer_type(bt, bt1))
|
||||
bt = gogo->backend()->error_type();
|
||||
return type_to_tree(bt);
|
||||
|
||||
case TYPE_POINTER:
|
||||
// Don't build a circular data structure. GENERIC can't handle
|
||||
@ -7318,33 +7282,33 @@ Named_type::do_get_tree(Gogo* gogo)
|
||||
if (this->seen_ > 0)
|
||||
{
|
||||
this->is_circular_ = true;
|
||||
return ptr_type_node;
|
||||
bt1 = gogo->backend()->circular_pointer_type(bt, false);
|
||||
return type_to_tree(bt1);
|
||||
}
|
||||
++this->seen_;
|
||||
t1 = Type::get_named_type_tree(gogo, base);
|
||||
bt1 = Type::get_named_base_btype(gogo, base);
|
||||
--this->seen_;
|
||||
if (t1 == error_mark_node)
|
||||
return error_mark_node;
|
||||
if (this->is_circular_)
|
||||
t1 = ptr_type_node;
|
||||
go_assert(t != NULL_TREE && TREE_CODE(t) == POINTER_TYPE);
|
||||
go_assert(TREE_CODE(t1) == POINTER_TYPE);
|
||||
TREE_TYPE(t) = TREE_TYPE(t1);
|
||||
return t;
|
||||
bt1 = gogo->backend()->circular_pointer_type(bt, false);
|
||||
if (!gogo->backend()->set_placeholder_pointer_type(bt, bt1))
|
||||
bt = gogo->backend()->error_type();
|
||||
return type_to_tree(bt);
|
||||
|
||||
case TYPE_ARRAY:
|
||||
if (base->is_open_array_type())
|
||||
{
|
||||
if (this->seen_ > 0)
|
||||
return t;
|
||||
return type_to_tree(bt);
|
||||
else
|
||||
{
|
||||
++this->seen_;
|
||||
t = base->array_type()->fill_in_slice_tree(gogo, t);
|
||||
tree t = base->array_type()->fill_in_slice_tree(gogo,
|
||||
type_to_tree(bt));
|
||||
bt = tree_to_type(t);
|
||||
--this->seen_;
|
||||
}
|
||||
}
|
||||
return t;
|
||||
return type_to_tree(bt);
|
||||
|
||||
default:
|
||||
case TYPE_SINK:
|
||||
@ -8467,7 +8431,7 @@ tree
|
||||
Forward_declaration_type::do_get_tree(Gogo* gogo)
|
||||
{
|
||||
if (this->is_defined())
|
||||
return Type::get_named_type_tree(gogo, this->real_type());
|
||||
return type_to_tree(Type::get_named_base_btype(gogo, this->real_type()));
|
||||
|
||||
if (this->warned_)
|
||||
return error_mark_node;
|
||||
|
@ -42,6 +42,8 @@ class Function;
|
||||
class Translate_context;
|
||||
class Export;
|
||||
class Import;
|
||||
class Btype;
|
||||
class Bexpression;
|
||||
|
||||
// Type codes used in type descriptors. These must match the values
|
||||
// in libgo/runtime/go-type.h. They also match the values in the gc
|
||||
@ -973,10 +975,11 @@ class Type
|
||||
static unsigned int
|
||||
hash_string(const std::string&, unsigned int);
|
||||
|
||||
// Return a tree for the underlying type of a named type.
|
||||
static tree
|
||||
get_named_type_tree(Gogo* gogo, Type* base_type)
|
||||
{ return base_type->get_tree_without_hash(gogo); }
|
||||
// Return the backend representation for the underlying type of a
|
||||
// named type.
|
||||
static Btype*
|
||||
get_named_base_btype(Gogo* gogo, Type* base_type)
|
||||
{ return base_type->get_btype_without_hash(gogo); }
|
||||
|
||||
private:
|
||||
// Convert to the desired type classification, or return NULL. This
|
||||
@ -1100,6 +1103,11 @@ class Type
|
||||
tree
|
||||
get_tree_without_hash(Gogo*);
|
||||
|
||||
// Get the backend representation for a type without looking in the
|
||||
// hash table for identical types.
|
||||
Btype*
|
||||
get_btype_without_hash(Gogo*);
|
||||
|
||||
// A mapping from Type to tree, used to ensure that the GIMPLE
|
||||
// representation of identical types is identical.
|
||||
typedef Unordered_map_hash(const Type*, tree, Type_hash_identical,
|
||||
@ -1952,10 +1960,6 @@ class Struct_type : public Type
|
||||
static Struct_type*
|
||||
do_import(Import*);
|
||||
|
||||
// Fill in the fields for a named struct type.
|
||||
tree
|
||||
fill_in_tree(Gogo*, tree);
|
||||
|
||||
static Type*
|
||||
make_struct_type_descriptor_type();
|
||||
|
||||
@ -2056,9 +2060,13 @@ class Array_type : public Type
|
||||
static Array_type*
|
||||
do_import(Import*);
|
||||
|
||||
// Fill in the fields for a named array type.
|
||||
tree
|
||||
fill_in_array_tree(Gogo*, tree);
|
||||
// Return the backend representation of the element type.
|
||||
Btype*
|
||||
get_backend_element(Gogo*);
|
||||
|
||||
// Return the backend representation of the length.
|
||||
Bexpression*
|
||||
get_backend_length(Gogo*);
|
||||
|
||||
// Fill in the fields for a named slice type.
|
||||
tree
|
||||
@ -2430,7 +2438,7 @@ class Named_type : public Type
|
||||
named_object_(named_object), in_function_(NULL), type_(type),
|
||||
local_methods_(NULL), all_methods_(NULL),
|
||||
interface_method_tables_(NULL), pointer_interface_method_tables_(NULL),
|
||||
location_(location), named_tree_(NULL), dependencies_(),
|
||||
location_(location), named_btype_(NULL), dependencies_(),
|
||||
is_visible_(true), is_error_(false), is_converted_(false),
|
||||
is_circular_(false), seen_(0)
|
||||
{ }
|
||||
@ -2676,9 +2684,10 @@ class Named_type : public Type
|
||||
Interface_method_tables* pointer_interface_method_tables_;
|
||||
// The location where this type was defined.
|
||||
source_location location_;
|
||||
// The tree for this type while converting to GENERIC. This is used
|
||||
// to avoid endless recursion when a named type refers to itself.
|
||||
tree named_tree_;
|
||||
// The backend representation of this type during backend
|
||||
// conversion. This is used to avoid endless recursion when a named
|
||||
// type refers to itself.
|
||||
Btype* named_btype_;
|
||||
// A list of types which must be converted to the backend
|
||||
// representation before this type can be converted. This is for
|
||||
// cases like
|
||||
|
Loading…
Reference in New Issue
Block a user