This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Go patch committed: Use backend interface for variables


This patch to the Go frontend uses the backend interface for variables.
Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline.

Ian


2011-04-18  Ian Lance Taylor  <iant@google.com>

	* go-gcc.cc: Include "go-c.h".
	(class Bvariable): Define.
	(Gcc_backend::init_statement): New function.
	(Gcc_backend::global_variable): New function.
	(Gcc_backend::global_variable_set_init): New function.
	(Gcc_backend::local_variable): New function.
	(Gcc_backend::parameter_variable): New function.
	(tree_to_type, var_to_tree): New functions.
	* Make-lang.in (go/go-gcc.o): Depend on $(GO_C_H).
	* (go/gogo-tree.o): Depend on go/gofrontend/backend.h.


Index: gcc/go/Make-lang.in
===================================================================
--- gcc/go/Make-lang.in	(revision 172402)
+++ gcc/go/Make-lang.in	(working copy)
@@ -239,7 +239,7 @@ go/go-lang.o: go/go-lang.c $(CONFIG_H) $
 GOINCLUDES = -I $(srcdir)/go -I $(srcdir)/go/gofrontend
 
 go/go-gcc.o: go/go-gcc.cc $(GO_SYSTEM_H) $(TREE_H) tree-iterator.h \
-		$(GIMPLE_H) $(GO_GOGO_H) go/gofrontend/backend.h
+		$(GIMPLE_H) $(GO_C_H) $(GO_GOGO_H) go/gofrontend/backend.h
 	$(CXX) -c $(GOINCLUDES) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) $< $(OUTPUT_OPTION)
 
 go/%.o: go/gofrontend/%.cc
@@ -262,7 +262,8 @@ go/go-dump.o: go/gofrontend/go-dump.cc $
 go/gogo-tree.o: go/gofrontend/gogo-tree.cc $(GO_SYSTEM_H) $(TOPLEV_H) \
 	$(TREE_H) $(GIMPLE_H) tree-iterator.h $(CGRAPH_H) langhooks.h \
 	convert.h output.h $(DIAGNOSTIC_H) $(GO_TYPES_H) \
-	$(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) $(GO_RUNTIME_H) $(GO_GOGO_H)
+	$(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) $(GO_RUNTIME_H) \
+	go/gofrontend/backend.h $(GO_GOGO_H)
 go/gogo.o: go/gofrontend/gogo.cc $(GO_SYSTEM_H) $(GO_C_H) \
 	go/gofrontend/go-dump.h $(GO_LEX_H) $(GO_TYPES_H) $(GO_STATEMENTS_H) \
 	$(GO_EXPRESSIONS_H) go/gofrontend/dataflow.h $(GO_RUNTIME_H) \
Index: gcc/go/go-gcc.cc
===================================================================
--- gcc/go/go-gcc.cc	(revision 172521)
+++ gcc/go/go-gcc.cc	(working copy)
@@ -37,6 +37,8 @@ extern "C"
 }
 #endif
 
+#include "go-c.h"
+
 #include "gogo.h"
 #include "backend.h"
 
@@ -90,6 +92,14 @@ class Bfunction : public Gcc_tree
   { }
 };
 
+class Bvariable : public Gcc_tree
+{
+ public:
+  Bvariable(tree t)
+    : Gcc_tree(t)
+  { }
+};
+
 class Blabel : public Gcc_tree
 {
  public:
@@ -174,6 +184,9 @@ class Gcc_backend : public Backend
   expression_statement(Bexpression*);
 
   Bstatement*
+  init_statement(Bvariable* var, Bexpression* init);
+
+  Bstatement*
   assignment_statement(Bexpression* lhs, Bexpression* rhs, source_location);
 
   Bstatement*
@@ -196,6 +209,32 @@ class Gcc_backend : public Backend
   Bstatement*
   statement_list(const std::vector<Bstatement*>&);
 
+  // Variables.
+
+  Bvariable*
+  error_variable()
+  { return new Bvariable(error_mark_node); }
+
+  Bvariable*
+  global_variable(const std::string& package_name,
+		  const std::string& unique_prefix,
+		  const std::string& name,
+		  Btype* btype,
+		  bool is_external,
+		  bool is_hidden,
+		  source_location location);
+
+  void
+  global_variable_set_init(Bvariable*, Bexpression*);
+
+  Bvariable*
+  local_variable(Bfunction*, const std::string& name, Btype* type,
+		 source_location);
+
+  Bvariable*
+  parameter_variable(Bfunction*, const std::string& name, Btype* type,
+		     source_location);
+
   // Labels.
 
   Blabel*
@@ -238,6 +277,21 @@ Gcc_backend::expression_statement(Bexpre
   return this->make_statement(expr->get_tree());
 }
 
+// Variable initialization.
+
+Bstatement*
+Gcc_backend::init_statement(Bvariable* var, Bexpression* init)
+{
+  tree var_tree = var->get_tree();
+  tree init_tree = init->get_tree();
+  if (var_tree == error_mark_node || init_tree == error_mark_node)
+    return this->error_statement();
+  gcc_assert(TREE_CODE(var_tree) == VAR_DECL);
+  DECL_INITIAL(var_tree) = init_tree;
+  return this->make_statement(build1_loc(DECL_SOURCE_LOCATION(var_tree),
+					 DECL_EXPR, void_type_node, var_tree));
+}
+
 // Assignment.
 
 Bstatement*
@@ -427,6 +481,99 @@ Gcc_backend::statement_list(const std::v
   return this->make_statement(stmt_list);
 }
 
+// Make a global variable.
+
+Bvariable*
+Gcc_backend::global_variable(const std::string& package_name,
+			     const std::string& unique_prefix,
+			     const std::string& name,
+			     Btype* btype,
+			     bool is_external,
+			     bool is_hidden,
+			     source_location location)
+{
+  tree type_tree = btype->get_tree();
+  if (type_tree == error_mark_node)
+    return this->error_variable();
+
+  std::string var_name(package_name);
+  var_name.push_back('.');
+  var_name.append(name);
+  tree decl = build_decl(location, VAR_DECL,
+			 get_identifier_from_string(var_name),
+			 type_tree);
+  if (is_external)
+    DECL_EXTERNAL(decl) = 1;
+  else
+    TREE_STATIC(decl) = 1;
+  if (!is_hidden)
+    {
+      TREE_PUBLIC(decl) = 1;
+
+      std::string asm_name(unique_prefix);
+      asm_name.push_back('.');
+      asm_name.append(var_name);
+      SET_DECL_ASSEMBLER_NAME(decl, get_identifier_from_string(asm_name));
+    }
+  TREE_USED(decl) = 1;
+
+  go_preserve_from_gc(decl);
+
+  return new Bvariable(decl);
+}
+
+// Set the initial value of a global variable.
+
+void
+Gcc_backend::global_variable_set_init(Bvariable* var, Bexpression* expr)
+{
+  tree expr_tree = expr->get_tree();
+  if (expr_tree == error_mark_node)
+    return;
+  gcc_assert(TREE_CONSTANT(expr_tree));
+  tree var_decl = var->get_tree();
+  if (var_decl == error_mark_node)
+    return;
+  DECL_INITIAL(var_decl) = expr_tree;
+}
+
+// Make a local variable.
+
+Bvariable*
+Gcc_backend::local_variable(Bfunction* function, const std::string& name,
+			    Btype* btype, source_location location)
+{
+  tree type_tree = btype->get_tree();
+  if (type_tree == error_mark_node)
+    return this->error_variable();
+  tree decl = build_decl(location, VAR_DECL,
+			 get_identifier_from_string(name),
+			 type_tree);
+  DECL_CONTEXT(decl) = function->get_tree();
+  TREE_USED(decl) = 1;
+  go_preserve_from_gc(decl);
+  return new Bvariable(decl);
+}
+
+// Make a function parameter variable.
+
+Bvariable*
+Gcc_backend::parameter_variable(Bfunction* function, const std::string& name,
+				Btype* btype, source_location location)
+{
+  tree type_tree = btype->get_tree();
+  if (type_tree == error_mark_node)
+    return this->error_variable();
+  tree decl = build_decl(location, PARM_DECL,
+			 get_identifier_from_string(name),
+			 type_tree);
+  DECL_CONTEXT(decl) = function->get_tree();
+  DECL_ARG_TYPE(decl) = type_tree;
+  TREE_USED(decl) = 1;
+  go_preserve_from_gc(decl);
+  return new Bvariable(decl);
+}
+
 // Make a label.
 
 Blabel*
@@ -494,6 +641,12 @@ go_get_backend()
 // FIXME: Temporary functions while converting to the new backend
 // interface.
 
+Btype*
+tree_to_type(tree t)
+{
+  return new Btype(t);
+}
+
 Bexpression*
 tree_to_expr(tree t)
 {
@@ -523,3 +676,9 @@ stat_to_tree(Bstatement* bs)
 {
   return bs->get_tree();
 }
+
+tree
+var_to_tree(Bvariable* bv)
+{
+  return bv->get_tree();
+}
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 172402)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -2659,7 +2659,8 @@ Function::create_result_variables(Gogo* 
 	  ++result_counter;
 	  name = gogo->pack_hidden_name(buf, false);
 	}
-      Result_variable* result = new Result_variable(p->type(), this, index);
+      Result_variable* result = new Result_variable(p->type(), this, index,
+						    p->location());
       Named_object* no = block->bindings()->add_result_variable(name, result);
       if (no->is_result_variable())
 	this->results_->push_back(no);
@@ -3290,7 +3291,7 @@ Variable::Variable(Type* type, Expressio
 		   bool is_parameter, bool is_receiver,
 		   source_location location)
   : type_(type), init_(init), preinit_(NULL), location_(location),
-    is_global_(is_global), is_parameter_(is_parameter),
+    backend_(NULL), is_global_(is_global), is_parameter_(is_parameter),
     is_receiver_(is_receiver), is_varargs_parameter_(false),
     is_address_taken_(false), seen_(false), init_is_lowered_(false),
     type_from_init_tuple_(false), type_from_range_index_(false),
@@ -3636,6 +3637,93 @@ Variable::import_var(Import* imp, std::s
   imp->require_c_string(";\n");
 }
 
+// Convert a variable to the backend representation.
+
+Bvariable*
+Variable::get_backend_variable(Gogo* gogo, Named_object* function,
+			       const Package* package, const std::string& name)
+{
+  if (this->backend_ == NULL)
+    {
+      Backend* backend = gogo->backend();
+      Type* type = this->type_;
+      if (type->is_error_type()
+	  || (type->is_undefined()
+	      && (!this->is_global_ || package == NULL)))
+	this->backend_ = backend->error_variable();
+      else
+	{
+	  bool is_parameter = this->is_parameter_;
+	  if (this->is_receiver_ && type->points_to() == NULL)
+	    is_parameter = false;
+	  if (this->is_in_heap())
+	    {
+	      is_parameter = false;
+	      type = Type::make_pointer_type(type);
+	    }
+
+	  std::string n = Gogo::unpack_hidden_name(name);
+	  Btype* btype = tree_to_type(type->get_tree(gogo));
+
+	  Bvariable* bvar;
+	  if (this->is_global_)
+	    bvar = backend->global_variable((package == NULL
+					     ? gogo->package_name()
+					     : package->name()),
+					    (package == NULL
+					     ? gogo->unique_prefix()
+					     : package->unique_prefix()),
+					    n,
+					    btype,
+					    package != NULL,
+					    Gogo::is_hidden_name(name),
+					    this->location_);
+	  else
+	    {
+	      tree fndecl = function->func_value()->get_decl();
+	      Bfunction* bfunction = tree_to_function(fndecl);
+	      if (is_parameter)
+		bvar = backend->parameter_variable(bfunction, n, btype,
+						   this->location_);
+	      else
+		bvar = backend->local_variable(bfunction, n, btype,
+					       this->location_);
+	    }
+	  this->backend_ = bvar;
+	}
+    }
+  return this->backend_;
+}
+
+// Class Result_variable.
+
+// Convert a result variable to the backend representation.
+
+Bvariable*
+Result_variable::get_backend_variable(Gogo* gogo, Named_object* function,
+				      const std::string& name)
+{
+  if (this->backend_ == NULL)
+    {
+      Backend* backend = gogo->backend();
+      Type* type = this->type_;
+      if (type->is_error())
+	this->backend_ = backend->error_variable();
+      else
+	{
+	  if (this->is_in_heap())
+	    type = Type::make_pointer_type(type);
+	  Btype* btype = tree_to_type(type->get_tree(gogo));
+	  tree fndecl = function->func_value()->get_decl();
+	  Bfunction* bfunction = tree_to_function(fndecl);
+	  std::string n = Gogo::unpack_hidden_name(name);
+	  this->backend_ = backend->local_variable(bfunction, n, btype,
+						   this->location_);
+	}
+    }
+  return this->backend_;
+}
+
 // Class Named_constant.
 
 // Traverse the initializer expression.
@@ -3997,7 +4085,7 @@ Named_object::location() const
       return this->var_value()->location();
 
     case NAMED_OBJECT_RESULT_VAR:
-      return this->result_var_value()->function()->location();
+      return this->result_var_value()->location();
 
     case NAMED_OBJECT_SINK:
       gcc_unreachable();
@@ -4057,6 +4145,21 @@ Named_object::export_named_object(Export
     }
 }
 
+// Convert a variable to the backend representation.
+
+Bvariable*
+Named_object::get_backend_variable(Gogo* gogo, Named_object* function)
+{
+  if (this->classification_ == NAMED_OBJECT_VAR)
+    return this->var_value()->get_backend_variable(gogo, function,
+						   this->package_, this->name_);
+  else if (this->classification_ == NAMED_OBJECT_RESULT_VAR)
+    return this->result_var_value()->get_backend_variable(gogo, function,
+							  this->name_);
+  else
+    gcc_unreachable();
+}
+
 // Class Bindings.
 
 Bindings::Bindings(Bindings* enclosing)
Index: gcc/go/gofrontend/gogo.h
===================================================================
--- gcc/go/gofrontend/gogo.h	(revision 172519)
+++ gcc/go/gofrontend/gogo.h	(working copy)
@@ -43,6 +43,7 @@ class Export;
 class Import;
 class Bexpression;
 class Bstatement;
+class Bvariable;
 class Blabel;
 
 // This file declares the basic classes used to hold the internal
@@ -1270,6 +1271,11 @@ class Variable
   set_address_taken()
   { this->is_address_taken_ = true; }
 
+  // Get the backend representation of the variable.
+  Bvariable*
+  get_backend_variable(Gogo*, Named_object*, const Package*,
+		       const std::string&);
+
   // Get the initial value of the variable as a tree.  This may only
   // be called if has_pre_init() returns false.
   tree
@@ -1312,6 +1318,8 @@ class Variable
   Block* preinit_;
   // Location of variable definition.
   source_location location_;
+  // Backend representation.
+  Bvariable* backend_;
   // Whether this is a global variable.
   bool is_global_ : 1;
   // Whether this is a function parameter.
@@ -1346,9 +1354,10 @@ class Variable
 class Result_variable
 {
  public:
-  Result_variable(Type* type, Function* function, int index)
-    : type_(type), function_(function), index_(index),
-      is_address_taken_(false)
+  Result_variable(Type* type, Function* function, int index,
+		  source_location location)
+    : type_(type), function_(function), index_(index), location_(location),
+      backend_(NULL), is_address_taken_(false)
   { }
 
   // Get the type of the result variable.
@@ -1366,6 +1375,11 @@ class Result_variable
   index() const
   { return this->index_; }
 
+  // The location of the variable definition.
+  source_location
+  location() const
+  { return this->location_; }
+
   // Whether this variable's address is taken.
   bool
   is_address_taken() const
@@ -1387,6 +1401,10 @@ class Result_variable
   set_function(Function* function)
   { this->function_ = function; }
 
+  // Get the backend representation of the variable.
+  Bvariable*
+  get_backend_variable(Gogo*, Named_object*, const std::string&);
+
  private:
   // Type of result variable.
   Type* type_;
@@ -1394,6 +1412,10 @@ class Result_variable
   Function* function_;
   // Index in list of results.
   int index_;
+  // Where the result variable is defined.
+  source_location location_;
+  // Backend representation.
+  Bvariable* backend_;
   // Whether something takes the address of this variable.
   bool is_address_taken_;
 };
@@ -1868,6 +1890,10 @@ class Named_object
   source_location
   location() const;
 
+  // Convert a variable to the backend representation.
+  Bvariable*
+  get_backend_variable(Gogo*, Named_object* function);
+
   // Return a tree for the external identifier for this object.
   tree
   get_id(Gogo*);
Index: gcc/go/gofrontend/statements.cc
===================================================================
--- gcc/go/gofrontend/statements.cc	(revision 172521)
+++ gcc/go/gofrontend/statements.cc	(working copy)
@@ -251,37 +251,46 @@ Variable_declaration_statement::do_trave
 tree
 Variable_declaration_statement::do_get_tree(Translate_context* context)
 {
-  tree val = this->var_->get_tree(context->gogo(), context->function());
-  if (val == error_mark_node || TREE_TYPE(val) == error_mark_node)
-    return error_mark_node;
-  Variable* variable = this->var_->var_value();
-
-  tree init = variable->get_init_tree(context->gogo(), context->function());
-  if (init == error_mark_node)
-    return error_mark_node;
-
-  // If this variable lives on the heap, we need to allocate it now.
-  if (!variable->is_in_heap())
+  Variable* var = this->var_->var_value();
+  Bvariable* bvar = this->var_->get_backend_variable(context->gogo(),
+						     context->function());
+  tree init = var->get_init_tree(context->gogo(), context->function());
+  Bexpression* binit = init == NULL_TREE ? NULL : tree_to_expr(init);
+  Bstatement* ret;
+  if (!var->is_in_heap())
     {
-      DECL_INITIAL(val) = init;
-      return this->build_stmt_1(DECL_EXPR, val);
+      gcc_assert(binit != NULL);
+      ret = context->backend()->init_statement(bvar, binit);
     }
   else
     {
-      gcc_assert(TREE_CODE(val) == INDIRECT_REF);
-      tree decl = TREE_OPERAND(val, 0);
-      gcc_assert(TREE_CODE(decl) == VAR_DECL);
-      tree type = TREE_TYPE(decl);
-      gcc_assert(POINTER_TYPE_P(type));
-      tree size = TYPE_SIZE_UNIT(TREE_TYPE(type));
-      tree space = context->gogo()->allocate_memory(variable->type(), size,
-						    this->location());
-      space = fold_convert(TREE_TYPE(decl), space);
-      DECL_INITIAL(decl) = space;
-      return build2(COMPOUND_EXPR, void_type_node,
-		    this->build_stmt_1(DECL_EXPR, decl),
-		    build2(MODIFY_EXPR, void_type_node, val, init));
+      // Something takes the address of this variable, so the value is
+      // stored in the heap.  Initialize it to newly allocated memory
+      // space, and assign the initial value to the new space.
+      source_location loc = this->location();
+      tree decl = var_to_tree(bvar);
+      tree decl_type = TREE_TYPE(decl);
+      gcc_assert(POINTER_TYPE_P(decl_type));
+      tree size = TYPE_SIZE_UNIT(TREE_TYPE(decl_type));
+      tree space = context->gogo()->allocate_memory(var->type(), size, loc);
+      if (binit != NULL)
+	space = save_expr(space);
+      space = fold_convert_loc(loc, decl_type, space);
+      Bstatement* s1 = context->backend()->init_statement(bvar,
+							  tree_to_expr(space));
+      if (binit == NULL)
+	ret = s1;
+      else
+	{
+	  tree indir = build_fold_indirect_ref_loc(loc, space);
+	  Bexpression* bindir = tree_to_expr(indir);
+	  Bstatement* s2 = context->backend()->assignment_statement(bindir,
+								    binit,
+								    loc);
+	  ret = context->backend()->compound_statement(s1, s2);
+	}
     }
+  return stat_to_tree(ret);
 }
 
 // Make a variable declaration.
@@ -2421,6 +2430,8 @@ Return_statement::do_lower(Gogo*, Named_
 tree
 Return_statement::do_get_tree(Translate_context* context)
 {
+  source_location loc = this->location();
+
   Function* function = context->function()->func_value();
   tree fndecl = function->get_decl();
 
@@ -2433,14 +2444,14 @@ Return_statement::do_get_tree(Translate_
 	   p != results->end();
 	   p++)
 	{
-	  tree rv = (*p)->get_tree(context->gogo(), context->function());
-	  retvals.push_back(tree_to_expr(rv));
+	  Expression* vr = Expression::make_var_reference(*p, loc);
+	  retvals.push_back(tree_to_expr(vr->get_tree(context)));
 	}
     }
 
   Bstatement* ret;
   ret = context->backend()->return_statement(tree_to_function(fndecl),
-					     retvals, this->location());
+					     retvals, loc);
   return stat_to_tree(ret);
 }
 
Index: gcc/go/gofrontend/gogo-tree.cc
===================================================================
--- gcc/go/gofrontend/gogo-tree.cc	(revision 172519)
+++ gcc/go/gofrontend/gogo-tree.cc	(working copy)
@@ -32,6 +32,7 @@ extern "C"
 #include "expressions.h"
 #include "statements.h"
 #include "runtime.h"
+#include "backend.h"
 #include "gogo.h"
 
 // Whether we have seen any errors.
@@ -277,7 +278,8 @@ Gogo::register_gc_vars(const std::vector
       constructor_elt* elt = VEC_quick_push(constructor_elt, init, NULL);
       tree field = TYPE_FIELDS(root_type);
       elt->index = field;
-      tree decl = (*p)->get_tree(this, NULL);
+      Bvariable* bvar = (*p)->get_backend_variable(this, NULL);
+      tree decl = var_to_tree(bvar);
       gcc_assert(TREE_CODE(decl) == VAR_DECL);
       elt->value = build_fold_addr_expr(decl);
 
@@ -704,24 +706,31 @@ Gogo::write_globals()
 	    }
 	}
 
-      vec[i] = no->get_tree(this, NULL);
-
-      if (vec[i] == error_mark_node)
+      if (!no->is_variable())
 	{
-	  gcc_assert(saw_errors());
-	  --i;
-	  --count;
-	  continue;
+	  vec[i] = no->get_tree(this, NULL);
+	  if (vec[i] == error_mark_node)
+	    {
+	      gcc_assert(saw_errors());
+	      --i;
+	      --count;
+	      continue;
+	    }
 	}
-
-      // If a variable is initialized to a non-constant value, do the
-      // initialization in an initialization function.
-      if (TREE_CODE(vec[i]) == VAR_DECL)
+      else
 	{
-	  gcc_assert(no->is_variable());
+	  Bvariable* var = no->get_backend_variable(this, NULL);
+	  vec[i] = var_to_tree(var);
+	  if (vec[i] == error_mark_node)
+	    {
+	      gcc_assert(saw_errors());
+	      --i;
+	      --count;
+	      continue;
+	    }
 
-	  // Check for a sink variable, which may be used to run
-	  // an initializer purely for its side effects.
+	  // Check for a sink variable, which may be used to run an
+	  // initializer purely for its side effects.
 	  bool is_sink = no->name()[0] == '_' && no->name()[1] == '.';
 
 	  tree var_init_tree = NULL_TREE;
@@ -733,7 +742,8 @@ Gogo::write_globals()
 	      else if (init == NULL_TREE)
 		;
 	      else if (TREE_CONSTANT(init))
-		DECL_INITIAL(vec[i]) = init;
+		this->backend()->global_variable_set_init(var,
+							  tree_to_expr(init));
 	      else if (is_sink)
 		var_init_tree = init;
 	      else
@@ -828,16 +838,15 @@ Gogo::write_globals()
 tree
 Named_object::get_id(Gogo* gogo)
 {
+  gcc_assert(!this->is_variable() && !this->is_result_variable());
   std::string decl_name;
   if (this->is_function_declaration()
       && !this->func_declaration_value()->asm_name().empty())
     decl_name = this->func_declaration_value()->asm_name();
-  else if ((this->is_variable() && !this->var_value()->is_global())
-	   || (this->is_type()
-	       && this->type_value()->location() == BUILTINS_LOCATION))
+  else if (this->is_type()
+	   && this->type_value()->location() == BUILTINS_LOCATION)
     {
-      // We don't need the package name for local variables or builtin
-      // types.
+      // We don't need the package name for builtin types.
       decl_name = Gogo::unpack_hidden_name(this->name_);
     }
   else
@@ -878,22 +887,7 @@ tree
 Named_object::get_tree(Gogo* gogo, Named_object* function)
 {
   if (this->tree_ != NULL_TREE)
-    {
-      // If this is a variable whose address is taken, we must rebuild
-      // the INDIRECT_REF each time to avoid invalid sharing.
-      tree ret = this->tree_;
-      if (((this->classification_ == NAMED_OBJECT_VAR
-	    && this->var_value()->is_in_heap())
-	   || (this->classification_ == NAMED_OBJECT_RESULT_VAR
-	       && this->result_var_value()->is_in_heap()))
-	  && ret != error_mark_node)
-	{
-	  gcc_assert(TREE_CODE(ret) == INDIRECT_REF);
-	  ret = build_fold_indirect_ref(TREE_OPERAND(ret, 0));
-	  TREE_THIS_NOTRAP(ret) = 1;
-	}
-      return ret;
-    }
+    return this->tree_;
 
   tree name;
   if (this->classification_ == NAMED_OBJECT_TYPE)
@@ -976,117 +970,7 @@ Named_object::get_tree(Gogo* gogo, Named
       return error_mark_node;
 
     case NAMED_OBJECT_VAR:
-      {
-	Variable* var = this->u_.var_value;
-	Type* type = var->type();
-	if (type->is_error_type()
-	    || (type->is_undefined()
-		&& (!var->is_global() || this->package() == NULL)))
-	  {
-	    // Force the error for an undefined type, just in case.
-	    type->base();
-	    decl = error_mark_node;
-	  }
-	else
-	  {
-	    tree var_type = type->get_tree(gogo);
-	    bool is_parameter = var->is_parameter();
-	    if (var->is_receiver() && type->points_to() == NULL)
-	      is_parameter = false;
-	    if (var->is_in_heap())
-	      {
-		is_parameter = false;
-		var_type = build_pointer_type(var_type);
-	      }
-	    decl = build_decl(var->location(),
-			      is_parameter ? PARM_DECL : VAR_DECL,
-			      name, var_type);
-	    if (!var->is_global())
-	      {
-		tree fnid = function->get_id(gogo);
-		tree fndecl = function->func_value()->get_or_make_decl(gogo,
-								       function,
-								       fnid);
-		DECL_CONTEXT(decl) = fndecl;
-	      }
-	    if (is_parameter)
-	      DECL_ARG_TYPE(decl) = TREE_TYPE(decl);
-
-	    if (var->is_global())
-	      {
-		const Package* package = this->package();
-		if (package == NULL)
-		  TREE_STATIC(decl) = 1;
-		else
-		  DECL_EXTERNAL(decl) = 1;
-		if (!Gogo::is_hidden_name(this->name_))
-		  {
-		    TREE_PUBLIC(decl) = 1;
-		    std::string asm_name = (package == NULL
-					    ? gogo->unique_prefix()
-					    : package->unique_prefix());
-		    asm_name.append(1, '.');
-		    asm_name.append(IDENTIFIER_POINTER(name),
-				    IDENTIFIER_LENGTH(name));
-		    tree asm_id = get_identifier_from_string(asm_name);
-		    SET_DECL_ASSEMBLER_NAME(decl, asm_id);
-		  }
-	      }
-
-	    // FIXME: We should only set this for variables which are
-	    // actually used somewhere.
-	    TREE_USED(decl) = 1;
-	  }
-      }
-      break;
-
     case NAMED_OBJECT_RESULT_VAR:
-      {
-	Result_variable* result = this->u_.result_var_value;
-	Type* type = result->type();
-	if (type->is_error())
-	  decl = error_mark_node;
-	else
-	  {
-	    gcc_assert(result->function() == function->func_value());
-	    source_location loc = function->location();
-	    tree result_type = type->get_tree(gogo);
-	    tree init;
-	    if (!result->is_in_heap())
-	      init = type->get_init_tree(gogo, false);
-	    else
-	      {
-		tree space = gogo->allocate_memory(type,
-						   TYPE_SIZE_UNIT(result_type),
-						   loc);
-		result_type = build_pointer_type(result_type);
-		tree subinit = type->get_init_tree(gogo, true);
-		if (subinit == NULL_TREE)
-		  init = fold_convert_loc(loc, result_type, space);
-		else
-		  {
-		    space = save_expr(space);
-		    space = fold_convert_loc(loc, result_type, space);
-		    tree spaceref = build_fold_indirect_ref_loc(loc, space);
-		    TREE_THIS_NOTRAP(spaceref) = 1;
-		    tree set = fold_build2_loc(loc, MODIFY_EXPR, void_type_node,
-					       spaceref, subinit);
-		    init = fold_build2_loc(loc, COMPOUND_EXPR, TREE_TYPE(space),
-					   set, space);
-		  }
-	      }
-	    decl = build_decl(loc, VAR_DECL, name, result_type);
-	    tree fnid = function->get_id(gogo);
-	    tree fndecl = function->func_value()->get_or_make_decl(gogo,
-								   function,
-								   fnid);
-	    DECL_CONTEXT(decl) = fndecl;
-	    DECL_INITIAL(decl) = init;
-	    TREE_USED(decl) = 1;
-	  }
-      }
-      break;
-
     case NAMED_OBJECT_SINK:
       gcc_unreachable();
 
@@ -1129,20 +1013,6 @@ Named_object::get_tree(Gogo* gogo, Named
 
   tree ret = decl;
 
-  // If this is a local variable whose address is taken, then we
-  // actually store it in the heap.  For uses of the variable we need
-  // to return a reference to that heap location.
-  if (((this->classification_ == NAMED_OBJECT_VAR
-	&& this->var_value()->is_in_heap())
-       || (this->classification_ == NAMED_OBJECT_RESULT_VAR
-	   && this->result_var_value()->is_in_heap()))
-      && ret != error_mark_node)
-    {
-      gcc_assert(POINTER_TYPE_P(TREE_TYPE(ret)));
-      ret = build_fold_indirect_ref(ret);
-      TREE_THIS_NOTRAP(ret) = 1;
-    }
-
   this->tree_ = ret;
 
   if (ret != error_mark_node)
@@ -1162,7 +1032,9 @@ Variable::get_init_tree(Gogo* gogo, Name
   if (this->init_ == NULL)
     {
       gcc_assert(!this->is_parameter_);
-      return this->type_->get_init_tree(gogo, this->is_global_);
+      return this->type_->get_init_tree(gogo,
+					(this->is_global_
+					 || this->is_in_heap()));
     }
   else
     {
@@ -1301,7 +1173,9 @@ Function::get_or_make_decl(Gogo* gogo, N
 	    {
 	      push_struct_function(decl);
 
-	      tree closure_decl = this->closure_var_->get_tree(gogo, no);
+	      Bvariable* bvar = this->closure_var_->get_backend_variable(gogo,
+									 no);
+	      tree closure_decl = var_to_tree(bvar);
 	      if (closure_decl == error_mark_node)
 		this->fndecl_ = error_mark_node;
 	      else
@@ -1384,26 +1258,15 @@ Function::make_receiver_parm_decl(Gogo* 
 {
   if (var_decl == error_mark_node)
     return error_mark_node;
-  // If the function takes the address of a receiver which is passed
-  // by value, then we will have an INDIRECT_REF here.  We need to get
-  // the real variable.
+  gcc_assert(TREE_CODE(var_decl) == VAR_DECL);
+  tree val_type = TREE_TYPE(var_decl);
   bool is_in_heap = no->var_value()->is_in_heap();
-  tree val_type;
-  if (TREE_CODE(var_decl) != INDIRECT_REF)
-    {
-      gcc_assert(!is_in_heap);
-      val_type = TREE_TYPE(var_decl);
-    }
-  else
+  if (is_in_heap)
     {
-      gcc_assert(is_in_heap);
-      var_decl = TREE_OPERAND(var_decl, 0);
-      if (var_decl == error_mark_node)
-	return error_mark_node;
-      gcc_assert(POINTER_TYPE_P(TREE_TYPE(var_decl)));
-      val_type = TREE_TYPE(TREE_TYPE(var_decl));
+      gcc_assert(POINTER_TYPE_P(val_type));
+      val_type = TREE_TYPE(val_type);
     }
-  gcc_assert(TREE_CODE(var_decl) == VAR_DECL);
+
   source_location loc = DECL_SOURCE_LOCATION(var_decl);
   std::string name = IDENTIFIER_POINTER(DECL_NAME(var_decl));
   name += ".pointer";
@@ -1456,14 +1319,8 @@ Function::make_receiver_parm_decl(Gogo* 
 // indirection.
 
 tree
-Function::copy_parm_to_heap(Gogo* gogo, Named_object* no, tree ref)
+Function::copy_parm_to_heap(Gogo* gogo, Named_object* no, tree var_decl)
 {
-  if (ref == error_mark_node)
-    return error_mark_node;
-
-  gcc_assert(TREE_CODE(ref) == INDIRECT_REF);
-
-  tree var_decl = TREE_OPERAND(ref, 0);
   if (var_decl == error_mark_node)
     return error_mark_node;
   gcc_assert(TREE_CODE(var_decl) == VAR_DECL);
@@ -1514,7 +1371,8 @@ Function::build_tree(Gogo* gogo, Named_o
     {
       if ((*p)->is_variable() && (*p)->var_value()->is_parameter())
 	{
-	  *pp = (*p)->get_tree(gogo, named_function);
+	  Bvariable* bvar = (*p)->get_backend_variable(gogo, named_function);
+	  *pp = var_to_tree(bvar);
 
 	  // We always pass the receiver to a method as a pointer.  If
 	  // the receiver is declared as a non-pointer type, then we
@@ -1524,8 +1382,6 @@ Function::build_tree(Gogo* gogo, Named_o
 	    {
 	      tree parm_decl = this->make_receiver_parm_decl(gogo, *p, *pp);
 	      tree var = *pp;
-	      if (TREE_CODE(var) == INDIRECT_REF)
-		var = TREE_OPERAND(var, 0);
 	      if (var != error_mark_node)
 		{
 		  gcc_assert(TREE_CODE(var) == VAR_DECL);
@@ -1539,16 +1395,12 @@ Function::build_tree(Gogo* gogo, Named_o
 	      // If we take the address of a parameter, then we need
 	      // to copy it into the heap.
 	      tree parm_decl = this->copy_parm_to_heap(gogo, *p, *pp);
-	      if (*pp != error_mark_node)
+	      tree var = *pp;
+	      if (var != error_mark_node)
 		{
-		  gcc_assert(TREE_CODE(*pp) == INDIRECT_REF);
-		  tree var_decl = TREE_OPERAND(*pp, 0);
-		  if (var_decl != error_mark_node)
-		    {
-		      gcc_assert(TREE_CODE(var_decl) == VAR_DECL);
-		      DECL_CHAIN(var_decl) = declare_vars;
-		      declare_vars = var_decl;
-		    }
+		  gcc_assert(TREE_CODE(var) == VAR_DECL);
+		  DECL_CHAIN(var) = declare_vars;
+		  declare_vars = var;
 		}
 	      *pp = parm_decl;
 	    }
@@ -1561,16 +1413,41 @@ Function::build_tree(Gogo* gogo, Named_o
 	}
       else if ((*p)->is_result_variable())
 	{
-	  tree var_decl = (*p)->get_tree(gogo, named_function);
-	  if (var_decl != error_mark_node
-	      && (*p)->result_var_value()->is_in_heap())
+	  Bvariable* bvar = (*p)->get_backend_variable(gogo, named_function);
+	  tree var_decl = var_to_tree(bvar);
+
+	  Type* type = (*p)->result_var_value()->type();
+	  tree init;
+	  if (!(*p)->result_var_value()->is_in_heap())
+	    init = type->get_init_tree(gogo, false);
+	  else
 	    {
-	      gcc_assert(TREE_CODE(var_decl) == INDIRECT_REF);
-	      var_decl = TREE_OPERAND(var_decl, 0);
+	      source_location loc = (*p)->location();
+	      tree type_tree = type->get_tree(gogo);
+	      tree space = gogo->allocate_memory(type,
+						 TYPE_SIZE_UNIT(type_tree),
+						 loc);
+	      tree ptr_type_tree = build_pointer_type(type_tree);
+	      tree subinit = type->get_init_tree(gogo, true);
+	      if (subinit == NULL_TREE)
+		init = fold_convert_loc(loc, ptr_type_tree, space);
+	      else
+		{
+		  space = save_expr(space);
+		  space = fold_convert_loc(loc, ptr_type_tree, space);
+		  tree spaceref = build_fold_indirect_ref_loc(loc, space);
+		  TREE_THIS_NOTRAP(spaceref) = 1;
+		  tree set = fold_build2_loc(loc, MODIFY_EXPR, void_type_node,
+					     spaceref, subinit);
+		  init = fold_build2_loc(loc, COMPOUND_EXPR, TREE_TYPE(space),
+					 set, space);
+		}
 	    }
+
 	  if (var_decl != error_mark_node)
 	    {
 	      gcc_assert(TREE_CODE(var_decl) == VAR_DECL);
+	      DECL_INITIAL(var_decl) = init;
 	      DECL_CHAIN(var_decl) = declare_vars;
 	      declare_vars = var_decl;
 	    }
@@ -1769,7 +1646,15 @@ Function::return_value(Gogo* gogo, Named
 
   tree retval;
   if (results->size() == 1)
-    return this->results_->front()->get_tree(gogo, named_function);
+    {
+      Bvariable* bvar =
+	this->results_->front()->get_backend_variable(gogo,
+						      named_function);
+      tree ret = var_to_tree(bvar);
+      if (this->results_->front()->result_var_value()->is_in_heap())
+	ret = build_fold_indirect_ref_loc(location, ret);
+      return ret;
+    }
   else
     {
       tree rettype = TREE_TYPE(DECL_RESULT(this->fndecl_));
@@ -1781,8 +1666,11 @@ Function::return_value(Gogo* gogo, Named
 	   ++pr, ++index, field = DECL_CHAIN(field))
 	{
 	  gcc_assert(field != NULL);
-	  tree val;
-	  val = (*this->results_)[index]->get_tree(gogo, named_function);
+	  Named_object* no = (*this->results_)[index];
+	  Bvariable* bvar = no->get_backend_variable(gogo, named_function);
+	  tree val = var_to_tree(bvar);
+	  if (no->result_var_value()->is_in_heap())
+	    val = build_fold_indirect_ref_loc(location, val);
 	  tree set = fold_build2_loc(location, MODIFY_EXPR, void_type_node,
 				     build3(COMPONENT_REF, TREE_TYPE(field),
 					    retval, field, NULL_TREE),
@@ -1847,28 +1735,18 @@ Block::get_tree(Translate_context* conte
        pv != this->bindings_->end_definitions();
        ++pv)
     {
-      if ((!(*pv)->is_variable() || !(*pv)->var_value()->is_parameter())
-	  && !(*pv)->is_result_variable()
-	  && !(*pv)->is_const())
+      if ((*pv)->is_variable() && !(*pv)->var_value()->is_parameter())
 	{
-	  tree var = (*pv)->get_tree(gogo, context->function());
-	  if (var != error_mark_node && TREE_TYPE(var) != error_mark_node)
-	    {
-	      if ((*pv)->is_variable() && (*pv)->var_value()->is_in_heap())
-		{
-		  gcc_assert(TREE_CODE(var) == INDIRECT_REF);
-		  var = TREE_OPERAND(var, 0);
-		  gcc_assert(TREE_CODE(var) == VAR_DECL);
-		}
-	      *pp = var;
-	      pp = &DECL_CHAIN(*pp);
-	    }
+	  Bvariable* var = (*pv)->get_backend_variable(gogo,
+						       context->function());
+	  *pp = var_to_tree(var);
+	  if (*pp != error_mark_node)
+	    pp = &DECL_CHAIN(*pp);
 	}
     }
   *pp = NULL_TREE;
 
-  Translate_context subcontext(context->gogo(), context->function(),
-			       this, block);
+  Translate_context subcontext(gogo, context->function(), this, block);
 
   tree statements = NULL_TREE;
 
Index: gcc/go/gofrontend/backend.h
===================================================================
--- gcc/go/gofrontend/backend.h	(revision 172521)
+++ gcc/go/gofrontend/backend.h	(working copy)
@@ -27,6 +27,9 @@ class Bstatement;
 // The backend representation of a function definition.
 class Bfunction;
 
+// The backend representation of a variable.
+class Bvariable;
+
 // The backend representation of a label.
 class Blabel;
 
@@ -117,6 +120,12 @@ class Backend
   virtual Bstatement*
   expression_statement(Bexpression*) = 0;
 
+  // Create a variable initialization statement.  This initializes a
+  // local variable at the point in the program flow where it is
+  // declared.
+  virtual Bstatement*
+  init_statement(Bvariable* var, Bexpression* init) = 0;
+
   // Create an assignment statement.
   virtual Bstatement*
   assignment_statement(Bexpression* lhs, Bexpression* rhs,
@@ -154,6 +163,57 @@ class Backend
   virtual Bstatement*
   statement_list(const std::vector<Bstatement*>&) = 0;
 
+  // Variables.
+
+  // Create an error variable.  This is used for cases which should
+  // not occur in a correct program, in order to keep the compilation
+  // going without crashing.
+  virtual Bvariable*
+  error_variable() = 0;
+
+  // Create a global variable.  PACKAGE_NAME is the name of the
+  // package where the variable is defined.  UNIQUE_PREFIX is the
+  // prefix for that package, from the -fgo-prefix option.  NAME is
+  // the name of the variable.  BTYPE is the type of the variable.
+  // IS_EXTERNAL is true if the variable is defined in some other
+  // package.  IS_HIDDEN is true if the variable is not exported (name
+  // begins with a lower case letter).  LOCATION is where the variable
+  // was defined.
+  virtual Bvariable*
+  global_variable(const std::string& package_name,
+		  const std::string& unique_prefix,
+		  const std::string& name,
+		  Btype* btype,
+		  bool is_external,
+		  bool is_hidden,
+		  source_location location) = 0;
+
+  // A global variable will 1) be initialized to zero, or 2) be
+  // initialized to a constant value, or 3) be initialized in the init
+  // function.  In case 2, the frontend will call
+  // global_variable_set_init to set the initial value.  If this is
+  // not called, the backend should initialize a global variable to 0.
+  // The init function may then assign a value to it.
+  virtual void
+  global_variable_set_init(Bvariable*, Bexpression*) = 0;
+
+  // Create a local variable.  The frontend will create the local
+  // variables first, and then create the block which contains them.
+  // FUNCTION is the function in which the variable is defined.  NAME
+  // is the name of the variable.  TYPE is the type.  LOCATION is
+  // where the variable is defined.  For each local variable the
+  // frontend will call init_statement to set the initial value.
+  virtual Bvariable*
+  local_variable(Bfunction* function, const std::string& name, Btype* type,
+		 source_location location) = 0;
+
+  // Create a function parameter.  This is an incoming parameter, not
+  // a result parameter (result parameters are treated as local
+  // variables).  The arguments are as for local_variable.
+  virtual Bvariable*
+  parameter_variable(Bfunction* function, const std::string& name,
+		     Btype* type, source_location location) = 0;
+
   // Labels.
   
   // Create a new label.  NAME will be empty if this is a label
@@ -186,10 +246,12 @@ extern Backend* go_get_backend();
 // FIXME: Temporary helper functions while converting to new backend
 // interface.
 
+extern Btype* tree_to_type(tree);
 extern Bexpression* tree_to_expr(tree);
 extern Bstatement* tree_to_stat(tree);
 extern Bfunction* tree_to_function(tree);
 extern tree expr_to_tree(Bexpression*);
 extern tree stat_to_tree(Bstatement*);
+extern tree var_to_tree(Bvariable*);
 
 #endif // !defined(GO_BACKEND_H)
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 172519)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -972,7 +972,24 @@ Var_expression::do_address_taken(bool es
 tree
 Var_expression::do_get_tree(Translate_context* context)
 {
-  return this->variable_->get_tree(context->gogo(), context->function());
+  Bvariable* bvar = this->variable_->get_backend_variable(context->gogo(),
+							  context->function());
+  tree ret = var_to_tree(bvar);
+  if (ret == error_mark_node)
+    return error_mark_node;
+  bool is_in_heap;
+  if (this->variable_->is_variable())
+    is_in_heap = this->variable_->var_value()->is_in_heap();
+  else if (this->variable_->is_result_variable())
+    is_in_heap = this->variable_->result_var_value()->is_in_heap();
+  else
+    gcc_unreachable();
+  if (is_in_heap)
+    {
+      ret = build_fold_indirect_ref_loc(this->location(), ret);
+      TREE_THIS_NOTRAP(ret) = 1;
+    }
+  return ret;
 }
 
 // Make a reference to a variable in an expression.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]