diff mbox

Go patch committed: Use backend interface for initialization function

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

Commit Message

Ian Lance Taylor April 22, 2014, 11:46 p.m. UTC
This patch from Chris Manghane changes the Go frontend to use the
backend interface for the initialization function.  Bootstrapped and ran
Go testsuite on x86_64-unknown-linux-gnu.  Committed to mainline.

Ian


2014-04-22  Chris Manghane  <cmang@google.com>

	* go-gcc.cc (Gcc_backend::temporary_variable): Push cfun around
	call to create_tmp_var.  Require that function be non-NULL.
diff mbox

Patch

Index: gcc/go/go-gcc.cc
===================================================================
--- gcc/go/go-gcc.cc	(revision 209495)
+++ gcc/go/go-gcc.cc	(working copy)
@@ -2214,10 +2214,21 @@  Gcc_backend::temporary_variable(Bfunctio
       return this->error_variable();
     }
 
+  go_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))
-    var = create_tmp_var(type_tree, "GOTMP");
+    {
+      if (DECL_STRUCT_FUNCTION(decl) == NULL)
+      	push_struct_function(decl);
+      else
+      	push_cfun(DECL_STRUCT_FUNCTION(decl));
+
+      var = create_tmp_var(type_tree, "GOTMP");
+      pop_cfun();
+    }
   else
     {
       gcc_assert(bblock != NULL);
@@ -2227,16 +2238,7 @@  Gcc_backend::temporary_variable(Bfunctio
       DECL_ARTIFICIAL(var) = 1;
       DECL_IGNORED_P(var) = 1;
       TREE_USED(var) = 1;
-      // FIXME: Permitting function to be NULL here is a temporary
-      // measure until we have a proper representation of the init
-      // function.
-      if (function != NULL)
-	DECL_CONTEXT(var) = function->get_tree();
-      else
-	{
-	  gcc_assert(current_function_decl != NULL_TREE);
-	  DECL_CONTEXT(var) = current_function_decl;
-	}
+      DECL_CONTEXT(var) = decl;
 
       // We have to add this variable to the BLOCK and the BIND_EXPR.
       tree bind_tree = bblock->get_tree();
Index: gcc/go/gofrontend/gogo-tree.cc
===================================================================
--- gcc/go/gofrontend/gogo-tree.cc	(revision 209495)
+++ gcc/go/gofrontend/gogo-tree.cc	(working copy)
@@ -236,32 +236,6 @@  Gogo::define_builtin_function_trees()
 		 false);
 }
 
-// Get the name to use for the import control function.  If there is a
-// global function or variable, then we know that that name must be
-// unique in the link, and we use it as the basis for our name.
-
-const std::string&
-Gogo::get_init_fn_name()
-{
-  if (this->init_fn_name_.empty())
-    {
-      go_assert(this->package_ != NULL);
-      if (this->is_main_package())
-	{
-	  // Use a name which the runtime knows.
-	  this->init_fn_name_ = "__go_init_main";
-	}
-      else
-	{
-	  std::string s = this->pkgpath_symbol();
-	  s.append("..import");
-	  this->init_fn_name_ = s;
-	}
-    }
-
-  return this->init_fn_name_;
-}
-
 // Add statements to INIT_STMT_LIST which run the initialization
 // functions for imported packages.  This is only used for the "main"
 // package.
@@ -434,65 +408,31 @@  Gogo::register_gc_vars(const std::vector
     append_to_statement_list(call, init_stmt_list);
 }
 
-// Build the decl for the initialization function.
-
-tree
-Gogo::initialization_function_decl()
-{
-  // The tedious details of building your own function.  There doesn't
-  // seem to be a helper function for this.
-  std::string name = this->package_name() + ".init";
-  tree fndecl = build_decl(this->package_->location().gcc_location(),
-			   FUNCTION_DECL, get_identifier_from_string(name),
-			   build_function_type(void_type_node,
-					       void_list_node));
-  const std::string& asm_name(this->get_init_fn_name());
-  SET_DECL_ASSEMBLER_NAME(fndecl, get_identifier_from_string(asm_name));
-
-  tree resdecl = build_decl(this->package_->location().gcc_location(),
-			    RESULT_DECL, NULL_TREE, void_type_node);
-  DECL_ARTIFICIAL(resdecl) = 1;
-  DECL_CONTEXT(resdecl) = fndecl;
-  DECL_RESULT(fndecl) = resdecl;
-
-  TREE_STATIC(fndecl) = 1;
-  TREE_USED(fndecl) = 1;
-  DECL_ARTIFICIAL(fndecl) = 1;
-  TREE_PUBLIC(fndecl) = 1;
-
-  DECL_INITIAL(fndecl) = make_node(BLOCK);
-  TREE_USED(DECL_INITIAL(fndecl)) = 1;
-
-  return fndecl;
-}
-
 // Create the magic initialization function.  INIT_STMT_LIST is the
 // code that it needs to run.
 
 void
-Gogo::write_initialization_function(tree fndecl, tree init_stmt_list)
+Gogo::write_initialization_function(Named_object* initfn, tree init_stmt_list)
 {
   // Make sure that we thought we needed an initialization function,
   // as otherwise we will not have reported it in the export data.
   go_assert(this->is_main_package() || this->need_init_fn_);
 
-  if (fndecl == NULL_TREE)
-    fndecl = this->initialization_function_decl();
-
-  DECL_SAVED_TREE(fndecl) = init_stmt_list;
-
-  if (DECL_STRUCT_FUNCTION(fndecl) == NULL)
-    push_struct_function(fndecl);
-  else
-    push_cfun(DECL_STRUCT_FUNCTION(fndecl));
-  cfun->function_start_locus = this->package_->location().gcc_location();
-  cfun->function_end_locus = cfun->function_start_locus;
+  if (initfn == NULL)
+    initfn = this->initialization_function_decl();
 
-  gimplify_function_tree(fndecl);
+  Bfunction* fndecl = initfn->func_value()->get_or_make_decl(this, initfn);
+  Location loc = this->package_->location();
+  std::vector<Bvariable*> vars;
+  this->backend()->block(fndecl, NULL, vars, loc, loc);
 
-  cgraph_add_new_function(fndecl, false);
-
-  pop_cfun();
+  if (!this->backend()->function_set_body(fndecl, tree_to_stat(init_stmt_list)))
+    {
+      go_assert(saw_errors());
+      return;
+    }
+  gimplify_function_tree(function_to_tree(fndecl));
+  cgraph_add_new_function(function_to_tree(fndecl), false);
 }
 
 // Search for references to VAR in any statements or called functions.
@@ -775,7 +715,7 @@  Gogo::write_globals()
 
   tree* vec = new tree[count];
 
-  tree init_fndecl = NULL_TREE;
+  Named_object* init_fndecl = NULL;
   tree init_stmt_list = NULL_TREE;
 
   if (this->is_main_package())
@@ -902,17 +842,12 @@  Gogo::write_globals()
 	    {
 	      // We are going to create temporary variables which
 	      // means that we need an fndecl.
-	      if (init_fndecl == NULL_TREE)
+	      if (init_fndecl == NULL)
 		init_fndecl = this->initialization_function_decl();
-	      if (DECL_STRUCT_FUNCTION(init_fndecl) == NULL)
-		push_struct_function(init_fndecl);
-	      else
-		push_cfun(DECL_STRUCT_FUNCTION(init_fndecl));
+
 	      Bvariable* var_decl = is_sink ? NULL : var;
               var_init_stmt =
-                  no->var_value()->get_init_block(this, NULL, var_decl);
-
-	      pop_cfun();
+                  no->var_value()->get_init_block(this, init_fndecl, var_decl);
 	    }
 
 	  if (var_init_stmt != NULL)
@@ -975,7 +910,7 @@  Gogo::write_globals()
 
   // Set up a magic function to do all the initialization actions.
   // This will be called if this package is imported.
-  if (init_stmt_list != NULL_TREE
+  if (init_stmt_list != NULL
       || this->need_init_fn_
       || this->is_main_package())
     this->write_initialization_function(init_fndecl, init_stmt_list);
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 209393)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -575,6 +575,45 @@  Gogo::current_bindings() const
     return this->globals_;
 }
 
+// Get the name to use for the import control function.  If there is a
+// global function or variable, then we know that that name must be
+// unique in the link, and we use it as the basis for our name.
+
+const std::string&
+Gogo::get_init_fn_name()
+{
+  if (this->init_fn_name_.empty())
+    {
+      go_assert(this->package_ != NULL);
+      if (this->is_main_package())
+	{
+	  // Use a name which the runtime knows.
+	  this->init_fn_name_ = "__go_init_main";
+	}
+      else
+	{
+	  std::string s = this->pkgpath_symbol();
+	  s.append("..import");
+	  this->init_fn_name_ = s;
+	}
+    }
+
+  return this->init_fn_name_;
+}
+
+// Build the decl for the initialization function.
+
+Named_object*
+Gogo::initialization_function_decl()
+{
+  std::string name = this->get_init_fn_name();
+  Location loc = this->package_->location();
+
+  Function_type* fntype = Type::make_function_type(NULL, NULL, NULL, loc);
+  Function* initfn = new Function(fntype, NULL, NULL, loc);
+  return Named_object::make_function(name, NULL, initfn);
+}
+
 // Return the current block.
 
 Block*
@@ -4071,7 +4110,12 @@  Function::get_or_make_decl(Gogo* gogo, N
         ;
       else if (Gogo::unpack_hidden_name(no->name()) == "init"
                && !this->type_->is_method())
-        ;
+	;
+      else if (no->name() == gogo->get_init_fn_name())
+	{
+	  is_visible = true;
+	  asm_name = no->name();
+	}
       else if (Gogo::unpack_hidden_name(no->name()) == "main"
                && gogo->is_main_package())
         is_visible = true;
@@ -4647,13 +4691,9 @@  Block::get_backend(Translate_context* co
 	vars.push_back((*pv)->get_backend_variable(gogo, function));
     }
 
-  // FIXME: Permitting FUNCTION to be NULL here is a temporary measure
-  // until we have a proper representation of the init function.
-  Bfunction* bfunction;
-  if (function == NULL)
-    bfunction = NULL;
-  else
-    bfunction = tree_to_function(function->func_value()->get_decl());
+  go_assert(function != NULL);
+  Bfunction* bfunction =
+    function->func_value()->get_or_make_decl(gogo, function);
   Bblock* ret = context->backend()->block(bfunction, context->bblock(),
 					  vars, this->start_location_,
 					  this->end_location_);
Index: gcc/go/gofrontend/gogo.h
===================================================================
--- gcc/go/gofrontend/gogo.h	(revision 209393)
+++ gcc/go/gofrontend/gogo.h	(working copy)
@@ -616,6 +616,10 @@  class Gogo
   Expression*
   allocate_memory(Type *type, Location);
 
+  // Get the name of the magic initialization function.
+  const std::string&
+  get_init_fn_name();
+
  private:
   // During parsing, we keep a stack of functions.  Each function on
   // the stack is one that we are currently parsing.  For each
@@ -642,17 +646,13 @@  class Gogo
   const Bindings*
   current_bindings() const;
 
-  // Get the name of the magic initialization function.
-  const std::string&
-  get_init_fn_name();
-
   // Get the decl for the magic initialization function.
-  tree
+  Named_object*
   initialization_function_decl();
 
   // Write the magic initialization function.
   void
-  write_initialization_function(tree fndecl, tree init_stmt_list);
+  write_initialization_function(Named_object* fndecl, tree init_stmt_list);
 
   // Initialize imported packages.
   void