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 function code exprs


This patch by Chris Manghane changes the Go frontend to use the backend
interface for function code expressions.  Bootstrapped and ran Go
testsuite on x86_64-unknown-linux-gnu.  Committed to mainline.

Ian


2013-10-11  Chris Manghane  <cmang@google.com>

	* go-gcc.cc (Gcc_backend::function_code_expression): New
	function.


Index: gcc/go/gofrontend/gogo.h
===================================================================
--- gcc/go/gofrontend/gogo.h	(revision 203403)
+++ gcc/go/gofrontend/gogo.h	(working copy)
@@ -1090,8 +1090,8 @@ class Function
     this->descriptor_ = descriptor;
   }
 
-  // Return the function's decl given an identifier.
-  tree
+  // Return the backend representation.
+  Bfunction*
   get_or_make_decl(Gogo*, Named_object*);
 
   // Return the function's decl after it has been built.
@@ -1262,8 +1262,8 @@ class Function_declaration
   has_descriptor() const
   { return this->descriptor_ != NULL; }
 
-  // Return a decl for the function given an identifier.
-  tree
+  // Return a backend representation.
+  Bfunction*
   get_or_make_decl(Gogo*, Named_object*);
 
   // If there is a descriptor, build it into the backend
Index: gcc/go/gofrontend/gogo-tree.cc
===================================================================
--- gcc/go/gofrontend/gogo-tree.cc	(revision 203403)
+++ gcc/go/gofrontend/gogo-tree.cc	(working copy)
@@ -1089,7 +1089,7 @@ Named_object::get_tree(Gogo* gogo, Named
     case NAMED_OBJECT_FUNC:
       {
 	Function* func = this->u_.func_value;
-	decl = func->get_or_make_decl(gogo, this);
+	decl = function_to_tree(func->get_or_make_decl(gogo, this));
 	if (decl != error_mark_node)
 	  {
 	    if (func->block() != NULL)
@@ -1214,83 +1214,9 @@ Variable::get_init_block(Gogo* gogo, Nam
   return block_tree;
 }
 
-// Get a tree for a function decl.
+// Get the backend representation.
 
-tree
-Function::get_or_make_decl(Gogo* gogo, Named_object* no)
-{
-  if (this->fndecl_ == NULL)
-    {
-      std::string asm_name;
-      bool is_visible = false;
-      if (no->package() != NULL)
-        ;
-      else if (this->enclosing_ != NULL || Gogo::is_thunk(no))
-        ;
-      else if (Gogo::unpack_hidden_name(no->name()) == "init"
-               && !this->type_->is_method())
-        ;
-      else if (Gogo::unpack_hidden_name(no->name()) == "main"
-               && gogo->is_main_package())
-        is_visible = true;
-      // Methods have to be public even if they are hidden because
-      // they can be pulled into type descriptors when using
-      // anonymous fields.
-      else if (!Gogo::is_hidden_name(no->name())
-               || this->type_->is_method())
-        {
-          is_visible = true;
-          std::string pkgpath = gogo->pkgpath_symbol();
-          if (this->type_->is_method()
-              && Gogo::is_hidden_name(no->name())
-              && Gogo::hidden_name_pkgpath(no->name()) != gogo->pkgpath())
-            {
-              // This is a method we created for an unexported
-              // method of an imported embedded type.  We need to
-              // use the pkgpath of the imported package to avoid
-              // a possible name collision.  See bug478 for a test
-              // case.
-              pkgpath = Gogo::hidden_name_pkgpath(no->name());
-              pkgpath = Gogo::pkgpath_for_symbol(pkgpath);
-            }
-
-          asm_name = pkgpath;
-          asm_name.append(1, '.');
-          asm_name.append(Gogo::unpack_hidden_name(no->name()));
-          if (this->type_->is_method())
-            {
-              asm_name.append(1, '.');
-              Type* rtype = this->type_->receiver()->type();
-              asm_name.append(rtype->mangled_name(gogo));
-            }
-        }
-
-      // If a function calls the predeclared recover function, we
-      // can't inline it, because recover behaves differently in a
-      // function passed directly to defer.  If this is a recover
-      // thunk that we built to test whether a function can be
-      // recovered, we can't inline it, because that will mess up
-      // our return address comparison.
-      bool is_inlinable = !(this->calls_recover_ || this->is_recover_thunk_);
-
-      // If this is a thunk created to call a function which calls
-      // the predeclared recover function, we need to disable
-      // stack splitting for the thunk.
-      bool disable_split_stack = this->is_recover_thunk_;
-
-      Btype* functype = this->type_->get_backend_fntype(gogo);
-      this->fndecl_ =
-          gogo->backend()->function(functype, no->get_id(gogo), asm_name,
-                                    is_visible, false, is_inlinable,
-                                    disable_split_stack,
-                                    this->in_unique_section_, this->location());
-    }
-  return function_to_tree(this->fndecl_);
-}
-
-// Get a tree for a function declaration.
-
-tree
+Bfunction*
 Function_declaration::get_or_make_decl(Gogo* gogo, Named_object* no)
 {
   if (this->fndecl_ == NULL)
@@ -1304,7 +1230,7 @@ Function_declaration::get_or_make_decl(G
 	  if (p != builtin_functions.end())
 	    {
 	      this->fndecl_ = tree_to_function(p->second);
-	      return p->second;
+	      return this->fndecl_;
 	    }
 	}
 
@@ -1331,7 +1257,7 @@ Function_declaration::get_or_make_decl(G
                                     this->location());
     }
 
-  return function_to_tree(this->fndecl_);
+  return this->fndecl_;
 }
 
 // Return the function's decl after it has been built.
@@ -2202,14 +2128,14 @@ Gogo::interface_method_table_for_type(co
       go_assert(m != NULL);
 
       Named_object* no = m->named_object();
-      tree fndecl;
+      Bfunction* bf;
       if (no->is_function())
-	fndecl = no->func_value()->get_or_make_decl(this, no);
+	bf = no->func_value()->get_or_make_decl(this, no);
       else if (no->is_function_declaration())
-	fndecl = no->func_declaration_value()->get_or_make_decl(this, no);
+	bf = no->func_declaration_value()->get_or_make_decl(this, no);
       else
 	go_unreachable();
-      fndecl = build_fold_addr_expr(fndecl);
+      tree fndecl = build_fold_addr_expr(function_to_tree(bf));
 
       elt = pointers->quick_push(empty);
       elt->index = size_int(i);
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 203403)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -3819,6 +3819,80 @@ Function::import_func(Import* imp, std::
   *presults = results;
 }
 
+// Get the backend representation.
+
+Bfunction*
+Function::get_or_make_decl(Gogo* gogo, Named_object* no)
+{
+  if (this->fndecl_ == NULL)
+    {
+      std::string asm_name;
+      bool is_visible = false;
+      if (no->package() != NULL)
+        ;
+      else if (this->enclosing_ != NULL || Gogo::is_thunk(no))
+        ;
+      else if (Gogo::unpack_hidden_name(no->name()) == "init"
+               && !this->type_->is_method())
+        ;
+      else if (Gogo::unpack_hidden_name(no->name()) == "main"
+               && gogo->is_main_package())
+        is_visible = true;
+      // Methods have to be public even if they are hidden because
+      // they can be pulled into type descriptors when using
+      // anonymous fields.
+      else if (!Gogo::is_hidden_name(no->name())
+               || this->type_->is_method())
+        {
+          is_visible = true;
+          std::string pkgpath = gogo->pkgpath_symbol();
+          if (this->type_->is_method()
+              && Gogo::is_hidden_name(no->name())
+              && Gogo::hidden_name_pkgpath(no->name()) != gogo->pkgpath())
+            {
+              // This is a method we created for an unexported
+              // method of an imported embedded type.  We need to
+              // use the pkgpath of the imported package to avoid
+              // a possible name collision.  See bug478 for a test
+              // case.
+              pkgpath = Gogo::hidden_name_pkgpath(no->name());
+              pkgpath = Gogo::pkgpath_for_symbol(pkgpath);
+            }
+
+          asm_name = pkgpath;
+          asm_name.append(1, '.');
+          asm_name.append(Gogo::unpack_hidden_name(no->name()));
+          if (this->type_->is_method())
+            {
+              asm_name.append(1, '.');
+              Type* rtype = this->type_->receiver()->type();
+              asm_name.append(rtype->mangled_name(gogo));
+            }
+        }
+
+      // If a function calls the predeclared recover function, we
+      // can't inline it, because recover behaves differently in a
+      // function passed directly to defer.  If this is a recover
+      // thunk that we built to test whether a function can be
+      // recovered, we can't inline it, because that will mess up
+      // our return address comparison.
+      bool is_inlinable = !(this->calls_recover_ || this->is_recover_thunk_);
+
+      // If this is a thunk created to call a function which calls
+      // the predeclared recover function, we need to disable
+      // stack splitting for the thunk.
+      bool disable_split_stack = this->is_recover_thunk_;
+
+      Btype* functype = this->type_->get_backend_fntype(gogo);
+      this->fndecl_ =
+          gogo->backend()->function(functype, no->get_id(gogo), asm_name,
+                                    is_visible, false, is_inlinable,
+                                    disable_split_stack,
+                                    this->in_unique_section_, this->location());
+    }
+  return this->fndecl_;
+}
+
 // Class Block.
 
 Block::Block(Block* enclosing, Location location)
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 203454)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -1219,7 +1219,7 @@ Func_expression::do_type()
 
 // Get the tree for the code of a function expression.
 
-tree
+Bexpression*
 Func_expression::get_code_pointer(Gogo* gogo, Named_object* no, Location loc)
 {
   Function_type* fntype;
@@ -1237,10 +1237,10 @@ Func_expression::get_code_pointer(Gogo*
       error_at(loc,
 	       "invalid use of special builtin function %qs; must be called",
 	       no->message_name().c_str());
-      return error_mark_node;
+      return gogo->backend()->error_expression();
     }
 
-  tree fndecl;
+  Bfunction* fndecl;
   if (no->is_function())
     fndecl = no->func_value()->get_or_make_decl(gogo, no);
   else if (no->is_function_declaration())
@@ -1248,10 +1248,7 @@ Func_expression::get_code_pointer(Gogo*
   else
     go_unreachable();
 
-  if (fndecl == error_mark_node)
-    return error_mark_node;
-
-  return build_fold_addr_expr_loc(loc.gcc_location(), fndecl);
+  return gogo->backend()->function_code_expression(fndecl, loc);
 }
 
 // Get the tree for a function expression.  This is used when we take
@@ -1488,8 +1485,10 @@ class Func_code_reference_expression : p
 tree
 Func_code_reference_expression::do_get_tree(Translate_context* context)
 {
-  return Func_expression::get_code_pointer(context->gogo(), this->function_,
-					   this->location());
+  Bexpression* ret =
+      Func_expression::get_code_pointer(context->gogo(), this->function_,
+                                        this->location());
+  return expr_to_tree(ret);
 }
 
 // Make a reference to the code of a function.
@@ -9846,7 +9845,7 @@ Call_expression::do_get_tree(Translate_c
   if (func != NULL)
     {
       Named_object* no = func->named_object();
-      fn = Func_expression::get_code_pointer(gogo, no, location);
+      fn = expr_to_tree(Func_expression::get_code_pointer(gogo, no, location));
       if (!has_closure)
 	closure_tree = NULL_TREE;
       else
Index: gcc/go/gofrontend/expressions.h
===================================================================
--- gcc/go/gofrontend/expressions.h	(revision 203292)
+++ gcc/go/gofrontend/expressions.h	(working copy)
@@ -1514,8 +1514,8 @@ class Func_expression : public Expressio
   closure()
   { return this->closure_; }
 
-  // Return a tree for the code for a function.
-  static tree
+  // Return a backend expression for the code of a function.
+  static Bexpression*
   get_code_pointer(Gogo*, Named_object* function, Location loc);
 
  protected:
Index: gcc/go/gofrontend/backend.h
===================================================================
--- gcc/go/gofrontend/backend.h	(revision 203403)
+++ gcc/go/gofrontend/backend.h	(working copy)
@@ -266,6 +266,11 @@ class Backend
   virtual Bexpression*
   convert_expression(Btype* type, Bexpression* expr, Location) = 0;
 
+  // Create an expression for the address of a function.  This is used to
+  // get the address of the code for a function.
+  virtual Bexpression*
+  function_code_expression(Bfunction*, Location) = 0;
+
   // Statements.
 
   // Create an error statement.  This is used for cases which should
Index: gcc/go/go-gcc.cc
===================================================================
--- gcc/go/go-gcc.cc	(revision 203403)
+++ gcc/go/go-gcc.cc	(working copy)
@@ -232,6 +232,9 @@ class Gcc_backend : public Backend
   Bexpression*
   convert_expression(Btype* type, Bexpression* expr, Location);
 
+  Bexpression*
+  function_code_expression(Bfunction*, Location);
+
   // Statements.
 
   Bstatement*
@@ -981,6 +984,19 @@ Gcc_backend::convert_expression(Btype* t
   return tree_to_expr(ret);
 }
 
+// Get the address of a function.
+
+Bexpression*
+Gcc_backend::function_code_expression(Bfunction* bfunc, Location location)
+{
+  tree func = bfunc->get_tree();
+  if (func == error_mark_node)
+    return this->error_expression();
+
+  tree ret = build_fold_addr_expr_loc(location.gcc_location(), func);
+  return this->make_expression(ret);
+}
+
 // An expression as a statement.
 
 Bstatement*

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