This patch by Chris Manghane change the Go frontend to move the handling
of indirecting through recursive pointer types to the backend.
Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline.

Ian


2014-05-05  Chris Manghane  <cm...@google.com>

        * go-gcc.cc (Gcc_backend::indirect_expression): Add btype
        parameter.
        (Gcc_backend::temporary_variable): Check for erroneous function.


Index: gcc/go/go-gcc.cc
===================================================================
--- gcc/go/go-gcc.cc	(revision 209941)
+++ gcc/go/go-gcc.cc	(working copy)
@@ -229,7 +229,7 @@ class Gcc_backend : public Backend
   var_expression(Bvariable* var, Location);
 
   Bexpression*
-  indirect_expression(Bexpression* expr, bool known_valid, Location);
+  indirect_expression(Btype*, Bexpression* expr, bool known_valid, Location);
 
   Bexpression*
   named_constant_expression(Btype* btype, const std::string& name,
@@ -1147,14 +1147,26 @@ Gcc_backend::var_expression(Bvariable* v
 // An expression that indirectly references an expression.
 
 Bexpression*
-Gcc_backend::indirect_expression(Bexpression* expr, bool known_valid,
-                                 Location location)
+Gcc_backend::indirect_expression(Btype* btype, Bexpression* expr,
+				 bool known_valid, Location location)
 {
+  tree expr_tree = expr->get_tree();
+  tree type_tree = btype->get_tree();
+  if (expr_tree == error_mark_node || type_tree == error_mark_node)
+    return this->error_expression();
+
+  // If the type of EXPR is a recursive pointer type, then we
+  // need to insert a cast before indirecting.
+  tree target_type_tree = TREE_TYPE(TREE_TYPE(expr_tree));
+  if (VOID_TYPE_P(target_type_tree))
+    expr_tree = fold_convert_loc(location.gcc_location(),
+				 build_pointer_type(type_tree), expr_tree);
+
   tree ret = build_fold_indirect_ref_loc(location.gcc_location(),
-                                         expr->get_tree());
+                                         expr_tree);
   if (known_valid)
     TREE_THIS_NOTRAP(ret) = 1;
-  return tree_to_expr(ret);
+  return this->make_expression(ret);
 }
 
 // Return an expression that declares a constant named NAME with the
@@ -2406,17 +2418,18 @@ Gcc_backend::temporary_variable(Bfunctio
 				Location location,
 				Bstatement** pstatement)
 {
+  gcc_assert(function != NULL);
+  tree decl = function->get_tree();
   tree type_tree = btype->get_tree();
   tree init_tree = binit == NULL ? NULL_TREE : binit->get_tree();
-  if (type_tree == error_mark_node || init_tree == error_mark_node)
+  if (type_tree == error_mark_node
+      || init_tree == error_mark_node
+      || decl == error_mark_node)
     {
       *pstatement = this->error_statement();
       return this->error_variable();
     }
 
-  gcc_assert(function != NULL);
-  tree decl = function->get_tree();
-
   tree var;
   // We can only use create_tmp_var if the type is not addressable.
   if (!TREE_ADDRESSABLE(type_tree))
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 209983)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -5210,7 +5210,10 @@ Function::return_value(Gogo* gogo, Named
       Bvariable* bvar = no->get_backend_variable(gogo, named_function);
       Bexpression* val = gogo->backend()->var_expression(bvar, location);
       if (no->result_var_value()->is_in_heap())
-        val = gogo->backend()->indirect_expression(val, true, location);
+	{
+	  Btype* bt = no->result_var_value()->type()->get_backend(gogo);
+	  val = gogo->backend()->indirect_expression(bt, val, true, location);
+	}
       vals[i] = val;
     }
   return gogo->backend()->return_statement(this->fndecl_, vals, location);
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 210084)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -760,16 +760,24 @@ Var_expression::do_get_tree(Translate_co
 							  context->function());
   bool is_in_heap;
   Location loc = this->location();
+  Btype* btype;
+  Gogo* gogo = context->gogo();
   if (this->variable_->is_variable())
-    is_in_heap = this->variable_->var_value()->is_in_heap();
+    {
+      is_in_heap = this->variable_->var_value()->is_in_heap();
+      btype = this->variable_->var_value()->type()->get_backend(gogo);
+    }
   else if (this->variable_->is_result_variable())
-    is_in_heap = this->variable_->result_var_value()->is_in_heap();
+    {
+      is_in_heap = this->variable_->result_var_value()->is_in_heap();
+      btype = this->variable_->result_var_value()->type()->get_backend(gogo);
+    }
   else
     go_unreachable();
 
   Bexpression* ret = context->backend()->var_expression(bvar, loc);
   if (is_in_heap)
-    ret = context->backend()->indirect_expression(ret, true, loc);
+    ret = context->backend()->indirect_expression(btype, ret, true, loc);
   return expr_to_tree(ret);
 }
 
@@ -4168,20 +4176,7 @@ Unary_expression::do_get_tree(Translate_
 
 	      }
 	  }
-
-	// If the type of EXPR is a recursive pointer type, then we
-	// need to insert a cast before indirecting.
-        tree expr = expr_to_tree(bexpr);
-        tree target_type_tree = TREE_TYPE(TREE_TYPE(expr));
-        if (VOID_TYPE_P(target_type_tree))
-          {
-            tree ind = type_to_tree(pbtype);
-            expr = fold_convert_loc(loc.gcc_location(),
-                                    build_pointer_type(ind), expr);
-            bexpr = tree_to_expr(expr);
-          }
-
-        ret = gogo->backend()->indirect_expression(bexpr, false, loc);
+        ret = gogo->backend()->indirect_expression(pbtype, bexpr, false, loc);
       }
       break;
 
@@ -10329,7 +10324,10 @@ Array_index_expression::do_get_tree(Tran
               array_type->get_value_pointer(gogo, this->array_);
 	  Bexpression* ptr = tree_to_expr(valptr->get_tree(context));
           ptr = gogo->backend()->pointer_offset_expression(ptr, start, loc);
-	  ret = gogo->backend()->indirect_expression(ptr, true, loc);
+
+	  Type* ele_type = this->array_->type()->array_type()->element_type();
+	  Btype* ele_btype = ele_type->get_backend(gogo);
+	  ret = gogo->backend()->indirect_expression(ele_btype, ptr, true, loc);
 	}
       return expr_to_tree(ret);
     }
@@ -10667,7 +10665,9 @@ String_index_expression::do_get_tree(Tra
       Bexpression* bstart = tree_to_expr(start->get_tree(context));
       Bexpression* ptr = tree_to_expr(bytes->get_tree(context));
       ptr = gogo->backend()->pointer_offset_expression(ptr, bstart, loc);
-      Bexpression* index = gogo->backend()->indirect_expression(ptr, true, loc);
+      Btype* ubtype = Type::lookup_integer_type("uint8")->get_backend(gogo);
+      Bexpression* index = 
+	gogo->backend()->indirect_expression(ubtype, ptr, true, loc);
 
       Btype* byte_btype = bytes->type()->points_to()->get_backend(gogo);
       Bexpression* index_error = tree_to_expr(bad_index->get_tree(context));
@@ -13816,7 +13816,9 @@ Heap_expression::do_get_tree(Translate_c
     gogo->backend()->temporary_variable(fndecl, context->bblock(), btype,
 					space, true, loc, &decl);
   space = gogo->backend()->var_expression(space_temp, loc);
-  Bexpression* ref = gogo->backend()->indirect_expression(space, true, loc);
+  Btype* expr_btype = this->expr_->type()->get_backend(gogo);
+  Bexpression* ref =
+    gogo->backend()->indirect_expression(expr_btype, space, true, loc);
 
   Bexpression* bexpr = tree_to_expr(this->expr_->get_tree(context));
   Bstatement* assn = gogo->backend()->assignment_statement(ref, bexpr, loc);
Index: gcc/go/gofrontend/backend.h
===================================================================
--- gcc/go/gofrontend/backend.h	(revision 209941)
+++ gcc/go/gofrontend/backend.h	(working copy)
@@ -253,9 +253,11 @@ class Backend
 
   // Create an expression that indirects through the pointer expression EXPR
   // (i.e., return the expression for *EXPR). KNOWN_VALID is true if the pointer
-  // is known to point to a valid memory location.
+  // is known to point to a valid memory location.  BTYPE is the expected type
+  // of the indirected EXPR.
   virtual Bexpression*
-  indirect_expression(Bexpression* expr, bool known_valid, Location) = 0;
+  indirect_expression(Btype* btype, Bexpression* expr, bool known_valid,
+		      Location) = 0;
 
   // Return an expression that declares a constant named NAME with the
   // constant value VAL in BTYPE.

Reply via email to