* 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
+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.
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.
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.
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();
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*
// 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.
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())
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
return Type::method_function(this->all_methods_, name, is_ambiguous);
}
-// Get the tree for a struct type.
+// 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.
-tree
-Struct_type::do_get_tree(Gogo* gogo)
+static void
+get_backend_struct_fields(Gogo* gogo, const Struct_field_list* fields,
+ std::vector<Backend::Btyped_identifier>* bfields)
{
- std::vector<Backend::Btyped_identifier> fields;
- fields.resize(this->fields_->size());
+ bfields->resize(fields->size());
size_t i = 0;
- for (Struct_field_list::const_iterator p = this->fields_->begin();
- p != this->fields_->end();
+ for (Struct_field_list::const_iterator p = fields->begin();
+ p != 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();
+ (*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 == this->fields_->size());
- Btype* btype = gogo->backend()->struct_type(fields);
- return type_to_tree(btype);
+ go_assert(i == fields->size());
}
-// Fill in the fields for a struct type.
+// Get the tree for a struct type.
tree
-Struct_type::fill_in_tree(Gogo* gogo, tree type)
+Struct_type::do_get_tree(Gogo* gogo)
{
- 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;
+ 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);
}
// Initialize struct fields.
}
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);
-
- 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;
-
- 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);
+ return tree_to_type(this->element_type_->get_tree(gogo));
+}
- 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 the backend representation of the length.
- 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
(*p)->convert(gogo);
// Complete this type.
- tree t = this->named_tree_;
+ Btype* bt = this->named_btype_;
Type* base = this->type_->base();
switch (base->classification())
{
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:
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;
}
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
// 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:
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;
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.
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
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:
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
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
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:
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;
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
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
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,
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();
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
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)
{ }
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