]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
compiler: Use backend interface for function code expressions.
authorChris Manghane <cmang@google.com>
Fri, 11 Oct 2013 22:17:47 +0000 (22:17 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 11 Oct 2013 22:17:47 +0000 (22:17 +0000)
* go-gcc.cc (Gcc_backend::function_code_expression): New
function.

From-SVN: r203467

gcc/go/ChangeLog
gcc/go/go-gcc.cc
gcc/go/gofrontend/backend.h
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/expressions.h
gcc/go/gofrontend/gogo-tree.cc
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/gogo.h

index 6d6217b266e7661b25f0bde46989715a4d6c6510..4d0dd11f662412b94f4129a7e06b51a85e2528b2 100644 (file)
@@ -1,26 +1,31 @@
+2013-10-11  Chris Manghane  <cmang@google.com>
+
+       * go-gcc.cc (Gcc_backend::function_code_expression): New
+       function.
+
 2013-10-10  Chris Manghane  <cmang@google.com>
 
-       * go-gcc.cc (Backend::error_function): New function.
-       (Backend::function): New function.
-       (Backend::make_function): New function.
+       * go-gcc.cc (Gcc_backend::error_function): New function.
+       (Gcc_backend::function): New function.
+       (Gcc_backend::make_function): New function.
        (function_to_tree): New function.
 
 2013-10-04  Chris Manghane  <cmang@google.com>
 
-       * go-gcc.cc (Backend::convert_expression): New function.
+       * go-gcc.cc (Gcc_backend::convert_expression): New function.
 
 2013-10-02  Chris Manghane  <cmang@google.com>
 
        * go-gcc.cc: Include "real.h" and "realmpfr.h".
-       (Backend::integer_constant_expression): New function.
-       (Backend::float_constant_expression): New function.
-       (Backend::complex_constant_expression): New function.
+       (Gcc_backend::integer_constant_expression): New function.
+       (Gcc_backend::float_constant_expression): New function.
+       (Gcc_backend::complex_constant_expression): New function.
 
 2013-09-30  Chris Manghane  <cmang@google.com>
 
-       * go-gcc.cc (Backend::error_expression): New function.
-       (Backend::var_expression): New function.
-       (Backend::indirect_expression): New function.
+       * go-gcc.cc (Gcc_backend::error_expression): New function.
+       (Gcc_backend::var_expression): New function.
+       (Gcc_backend::indirect_expression): New function.
 
 2013-09-25  Tom Tromey  <tromey@redhat.com>
 
 
 2011-04-14  Ian Lance Taylor  <iant@google.com>
 
-       * go-gcc.cc (Backend::error_statement): New function.
+       * go-gcc.cc (Gcc_backend::error_statement): New function.
 
 2011-04-13  Ian Lance Taylor  <iant@google.com>
 
index 6b77d947c9c2bbad676399583646bea363ecefff..81e9ad18610a7878b2ff34366d7799e6d700573e 100644 (file)
@@ -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* type, Bexpression* expr, Location)
   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 e73c98ca68a0319e631088f46954351740b5aa19..ca997f08adeb721aa249f4da336ce7311810ce75 100644 (file)
@@ -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 258953f205ac5e77c70f37ef9dbc0c65214a867a..6ba351e2f42ceb0f033628ca95ee114dc4612060 100644 (file)
@@ -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* gogo, Named_object* no, Location loc)
       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* gogo, Named_object* no, Location loc)
   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 : public Expression
 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_context* context)
   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 bc7a25f766a7bd1d015b6e2f06e8199d952d011b..35bfcfe8e4f248e436426ee31d63c03816332244 100644 (file)
@@ -1514,8 +1514,8 @@ class Func_expression : public Expression
   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 78a8c6a724b25703770a2967212cd6cb50f68872..fbc46526ef0d684dd951e76da5101f9c560b0cf3 100644 (file)
@@ -1089,7 +1089,7 @@ Named_object::get_tree(Gogo* gogo, Named_object* function)
     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, Named_object* function, tree var_decl)
   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(Gogo* gogo, Named_object* no)
          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(Gogo* gogo, Named_object* no)
                                     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(const Interface_type* interface,
       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 a8f77549e8aa06ae9fb3016d931ee4c58f5e65a0..0796caaa94ca8e3b032ab85ebf4ae75018758159 100644 (file)
@@ -3819,6 +3819,80 @@ Function::import_func(Import* imp, std::string* pname,
   *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 5b416b0c0588a644fd6053e765aeb0bcc499e458..8c4ccf981797aaf00395a23f6786dfe3be36a5b6 100644 (file)
@@ -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