diff mbox

Go patch committed: Use backend interface for array length

Message ID mcrlhufr9ms.fsf@iant-glaptop.roam.corp.google.com
State New
Headers show

Commit Message

Ian Lance Taylor May 6, 2014, 1:14 a.m. UTC
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 mbox

Patch

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.