This patch by Chris Manghane changes the Go frontend to use the backend interface for the length of an array. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline.
Ian
diff -r f4135c695c00 go/types.cc --- a/go/types.cc Mon May 05 20:10:20 2014 -0400 +++ b/go/types.cc Mon May 05 21:00:16 2014 -0400 @@ -245,7 +245,7 @@ return ptype == NULL ? NULL : ptype->points_to(); } -// Return whether this is an open array type. +// Return whether this is a slice type. bool Type::is_slice_type() const @@ -5839,14 +5839,85 @@ gogo->add_statement(s); } -// Get a tree for the length of a fixed array. The length may be +// Get the backend representation of the fields of a slice. This is +// not declared in types.h so that types.h doesn't have to #include +// backend.h. +// +// We use int for the count and capacity fields. This matches 6g. +// The language more or less assumes that we can't allocate space of a +// size which does not fit in int. + +static void +get_backend_slice_fields(Gogo* gogo, Array_type* type, bool use_placeholder, + std::vector<Backend::Btyped_identifier>* bfields) +{ + bfields->resize(3); + + Type* pet = Type::make_pointer_type(type->element_type()); + Btype* pbet = (use_placeholder + ? pet->get_backend_placeholder(gogo) + : pet->get_backend(gogo)); + Location ploc = Linemap::predeclared_location(); + + Backend::Btyped_identifier* p = &(*bfields)[0]; + p->name = "__values"; + p->btype = pbet; + p->location = ploc; + + Type* int_type = Type::lookup_integer_type("int"); + + p = &(*bfields)[1]; + p->name = "__count"; + p->btype = int_type->get_backend(gogo); + p->location = ploc; + + p = &(*bfields)[2]; + p->name = "__capacity"; + p->btype = int_type->get_backend(gogo); + p->location = ploc; +} + +// Get a tree for the type of this array. A fixed array is simply +// represented as ARRAY_TYPE with the appropriate index--i.e., it is +// just like an array in C. A slice is a struct with three +// fields: a data pointer, the length, and the capacity. + +Btype* +Array_type::do_get_backend(Gogo* gogo) +{ + if (this->length_ == NULL) + { + std::vector<Backend::Btyped_identifier> bfields; + get_backend_slice_fields(gogo, this, false, &bfields); + return gogo->backend()->struct_type(bfields); + } + else + { + Btype* element = this->get_backend_element(gogo, false); + Bexpression* len = this->get_backend_length(gogo); + return gogo->backend()->array_type(element, len); + } +} + +// Return the backend representation of the element type. + +Btype* +Array_type::get_backend_element(Gogo* gogo, bool use_placeholder) +{ + if (use_placeholder) + return this->element_type_->get_backend_placeholder(gogo); + else + return this->element_type_->get_backend(gogo); +} + +// Return the backend representation of the length. The length may be // computed using a function call, so we must only evaluate it once. -tree -Array_type::get_length_tree(Gogo* gogo) +Bexpression* +Array_type::get_backend_length(Gogo* gogo) { go_assert(this->length_ != NULL); - if (this->length_tree_ == NULL_TREE) + if (this->blength_ == NULL) { Numeric_constant nc; mpz_t val; @@ -5854,8 +5925,8 @@ { if (mpz_sgn(val) < 0) { - this->length_tree_ = error_mark_node; - return this->length_tree_; + this->blength_ = gogo->backend()->error_expression(); + return this->blength_; } Type* t = nc.type(); if (t == NULL) @@ -5863,9 +5934,8 @@ else if (t->is_abstract()) t = t->make_non_abstract_type(); Btype* btype = t->get_backend(gogo); - Bexpression* iexpr = - gogo->backend()->integer_constant_expression(btype, val); - this->length_tree_ = expr_to_tree(iexpr); + this->blength_ = + gogo->backend()->integer_constant_expression(btype, val); mpz_clear(val); } else @@ -5873,97 +5943,15 @@ // Make up a translation context for the array length // expression. FIXME: This won't work in general. Translate_context context(gogo, NULL, NULL, NULL); - tree len = this->length_->get_tree(&context); - if (len != error_mark_node) - { - Type* int_type = Type::lookup_integer_type("int"); - tree int_type_tree = type_to_tree(int_type->get_backend(gogo)); - len = convert_to_integer(int_type_tree, len); - len = save_expr(len); - } - this->length_tree_ = len; - } - } - return this->length_tree_; -} - -// Get the backend representation of the fields of a slice. This is -// not declared in types.h so that types.h doesn't have to #include -// backend.h. -// -// We use int for the count and capacity fields. This matches 6g. -// The language more or less assumes that we can't allocate space of a -// size which does not fit in int. - -static void -get_backend_slice_fields(Gogo* gogo, Array_type* type, bool use_placeholder, - std::vector<Backend::Btyped_identifier>* bfields) -{ - bfields->resize(3); - - Type* pet = Type::make_pointer_type(type->element_type()); - Btype* pbet = (use_placeholder - ? pet->get_backend_placeholder(gogo) - : pet->get_backend(gogo)); - Location ploc = Linemap::predeclared_location(); - - Backend::Btyped_identifier* p = &(*bfields)[0]; - p->name = "__values"; - p->btype = pbet; - p->location = ploc; - - Type* int_type = Type::lookup_integer_type("int"); - - p = &(*bfields)[1]; - p->name = "__count"; - p->btype = int_type->get_backend(gogo); - p->location = ploc; - - p = &(*bfields)[2]; - p->name = "__capacity"; - p->btype = int_type->get_backend(gogo); - p->location = ploc; -} - -// Get a tree for the type of this array. A fixed array is simply -// represented as ARRAY_TYPE with the appropriate index--i.e., it is -// just like an array in C. An open array is a struct with three -// fields: a data pointer, the length, and the capacity. - -Btype* -Array_type::do_get_backend(Gogo* gogo) -{ - if (this->length_ == NULL) - { - std::vector<Backend::Btyped_identifier> bfields; - get_backend_slice_fields(gogo, this, false, &bfields); - return gogo->backend()->struct_type(bfields); - } - else - { - Btype* element = this->get_backend_element(gogo, false); - Bexpression* len = this->get_backend_length(gogo); - return gogo->backend()->array_type(element, len); - } -} - -// Return the backend representation of the element type. - -Btype* -Array_type::get_backend_element(Gogo* gogo, bool use_placeholder) -{ - if (use_placeholder) - return this->element_type_->get_backend_placeholder(gogo); - else - return this->element_type_->get_backend(gogo); -} - -// Return the backend representation of the length. - -Bexpression* -Array_type::get_backend_length(Gogo* gogo) -{ - return tree_to_expr(this->get_length_tree(gogo)); + this->blength_ = tree_to_expr(this->length_->get_tree(&context)); + + Btype* ibtype = Type::lookup_integer_type("int")->get_backend(gogo); + this->blength_ = + gogo->backend()->convert_expression(ibtype, this->blength_, + this->length_->location()); + } + } + return this->blength_; } // Finish backend representation of the array. @@ -5997,7 +5985,7 @@ array->location()); } - // Open array. + // Slice. return Expression::make_slice_info(array, Expression::SLICE_INFO_VALUE_POINTER, array->location()); @@ -6012,7 +6000,7 @@ if (this->length_ != NULL) return this->length_; - // This is an open array. We need to read the length field. + // This is a slice. We need to read the length field. return Expression::make_slice_info(array, Expression::SLICE_INFO_LENGTH, array->location()); } @@ -6026,7 +6014,7 @@ if (this->length_ != NULL) return this->length_; - // This is an open array. We need to read the capacity field. + // This is a slice. We need to read the capacity field. return Expression::make_slice_info(array, Expression::SLICE_INFO_CAPACITY, array->location()); } diff -r f4135c695c00 go/types.h --- a/go/types.h Mon May 05 20:10:20 2014 -0400 +++ b/go/types.h Mon May 05 21:00:16 2014 -0400 @@ -2305,7 +2305,7 @@ public: Array_type(Type* element_type, Expression* length) : Type(TYPE_ARRAY), - element_type_(element_type), length_(length), length_tree_(NULL) + element_type_(element_type), length_(length), blength_(NULL) { } // Return the element type. @@ -2313,7 +2313,7 @@ element_type() const { return this->element_type_; } - // Return the length. This will return NULL for an open array. + // Return the length. This will return NULL for a slice. Expression* length() const { return this->length_; } @@ -2407,9 +2407,6 @@ bool verify_length(); - tree - get_length_tree(Gogo*); - Expression* array_type_descriptor(Gogo*, Named_type*); @@ -2420,8 +2417,9 @@ Type* element_type_; // The number of elements. This may be NULL. Expression* length_; - // The length as a tree. We only want to compute this once. - tree length_tree_; + // The backend representation of the length. + // We only want to compute this once. + Bexpression* blength_; }; // The type of a map.