Use backend interface for function types.
authorIan Lance Taylor <iant@google.com>
Mon, 25 Apr 2011 17:21:28 +0000 (17:21 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Mon, 25 Apr 2011 17:21:28 +0000 (17:21 +0000)
Drop type_tree() functions for Float_type and Complex_type.
Don't define builtin functions until gogo is created.

* go-gcc.cc (Gcc_backend::error_type): Implement.
(Gcc_backend::string_type): Remove.
(Gcc_backend::function_type): Change signature and implement.
(Gcc_backend::struct_type): Change signature.
(Gcc_backend::slice_type, Gcc_backend::map_type): Remove.
(Gcc_backend::channel_type, Gcc_backend::interface_type): Remove.
(Gcc_backend::pointer_type): Check for error.
* Make-lang.in (go/types.o): Depend on go/gofrontend/backend.h.

From-SVN: r172932

gcc/go/ChangeLog
gcc/go/Make-lang.in
gcc/go/go-gcc.cc
gcc/go/gofrontend/backend.h
gcc/go/gofrontend/go.cc
gcc/go/gofrontend/gogo-tree.cc
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/gogo.h
gcc/go/gofrontend/types.cc
gcc/go/gofrontend/types.h

index ad7ec733fe8ba4b34a237ef7c5efff60ff0d98c8..9ed4e47c7cbfb9962cbf3beec2016387c5b691c0 100644 (file)
@@ -1,3 +1,14 @@
+2011-04-25  Ian Lance Taylor  <iant@google.com>
+
+       * go-gcc.cc (Gcc_backend::error_type): Implement.
+       (Gcc_backend::string_type): Remove.
+       (Gcc_backend::function_type): Change signature and implement.
+       (Gcc_backend::struct_type): Change signature.
+       (Gcc_backend::slice_type, Gcc_backend::map_type): Remove.
+       (Gcc_backend::channel_type, Gcc_backend::interface_type): Remove.
+       (Gcc_backend::pointer_type): Check for error.
+       * Make-lang.in (go/types.o): Depend on go/gofrontend/backend.h.
+
 2011-04-25  Evan Shaw  <edsrzf@gmail.com>
 
        * go-gcc.c (class Gcc_tree): Make get_tree const.
index 6dc0895865ec6128d69f516a607ecc11e46dd690..8b52cf23df0c3dd2808573cf6dbf4b8b5e7742d7 100644 (file)
@@ -287,6 +287,7 @@ go/statements.o: go/gofrontend/statements.cc $(GO_SYSTEM_H) \
 go/types.o: go/gofrontend/types.cc $(GO_SYSTEM_H) $(TOPLEV_H) intl.h $(TREE_H) \
        $(GIMPLE_H) $(REAL_H) convert.h $(GO_C_H) $(GO_GOGO_H) \
        go/gofrontend/operator.h $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) \
-       go/gofrontend/export.h $(GO_IMPORT_H) $(GO_TYPES_H)
+       go/gofrontend/export.h $(GO_IMPORT_H) go/gofrontend/backend.h \
+       $(GO_TYPES_H)
 go/unsafe.o: go/gofrontend/unsafe.cc $(GO_SYSTEM_H) $(GO_C_H) $(GO_TYPES_H) \
        $(GO_GOGO_H)
index 96375220638272c9007063ccf869d3ec525725a6..d250646ecda24e2772810c28bebc9b73bafd1597 100644 (file)
@@ -129,7 +129,7 @@ class Gcc_backend : public Backend
 
   Btype*
   error_type()
-  { gcc_unreachable(); }
+  { return this->make_type(error_mark_node); }
 
   Btype*
   void_type()
@@ -149,43 +149,22 @@ class Gcc_backend : public Backend
   complex_type(int);
 
   Btype*
-  string_type()
-  { gcc_unreachable(); }
+  pointer_type(Btype*);
 
   Btype*
-  pointer_type(const Btype*);
-
-  Btype*
-  function_type(const Function_type*, Btype* /* receiver */,
-               const Btypes* /* parameters */,
-               const Btypes* /* results */)
-  { gcc_unreachable(); }
+  function_type(const Btyped_identifier&,
+               const std::vector<Btyped_identifier>&,
+               const std::vector<Btyped_identifier>&,
+               source_location);
 
   Btype*
-  struct_type(const Struct_type*, const Btypes* /* field_types */)
+  struct_type(const std::vector<Btyped_identifier>&)
   { gcc_unreachable(); }
 
   Btype*
   array_type(const Btype* /* element_type */, const Bexpression* /* length */)
   { gcc_unreachable(); }
 
-  Btype*
-  slice_type(const Btype* /* element_type */)
-  { gcc_unreachable(); }
-
-  Btype*
-  map_type(const Btype* /* key_type */, const Btype* /* value_type */,
-          source_location)
-  { gcc_unreachable(); }
-
-  Btype*
-  channel_type(const Btype* /* element_type */)
-  { gcc_unreachable(); }
-
-  Btype*
-  interface_type(const Interface_type*, const Btypes* /* method_types */)
-  { gcc_unreachable(); }
-
   // Statements.
 
   Bstatement*
@@ -387,12 +366,89 @@ Gcc_backend::complex_type(int bits)
 // Get a pointer type.
 
 Btype*
-Gcc_backend::pointer_type(const Btype* to_type)
+Gcc_backend::pointer_type(Btype* to_type)
 {
-  tree type = build_pointer_type(to_type->get_tree());
+  tree to_type_tree = to_type->get_tree();
+  if (to_type_tree == error_mark_node)
+    return this->error_type();
+  tree type = build_pointer_type(to_type_tree);
   return this->make_type(type);
 }
 
+// Make a function type.
+
+Btype*
+Gcc_backend::function_type(const Btyped_identifier& receiver,
+                          const std::vector<Btyped_identifier>& parameters,
+                          const std::vector<Btyped_identifier>& results,
+                          source_location location)
+{
+  tree args = NULL_TREE;
+  tree* pp = &args;
+  if (receiver.btype != NULL)
+    {
+      tree t = receiver.btype->get_tree();
+      if (t == error_mark_node)
+       return this->error_type();
+      *pp = tree_cons(NULL_TREE, t, NULL_TREE);
+      pp = &TREE_CHAIN(*pp);
+    }
+
+  for (std::vector<Btyped_identifier>::const_iterator p = parameters.begin();
+       p != parameters.end();
+       ++p)
+    {
+      tree t = p->btype->get_tree();
+      if (t == error_mark_node)
+       return this->error_type();
+      *pp = tree_cons(NULL_TREE, t, NULL_TREE);
+      pp = &TREE_CHAIN(*pp);
+    }
+
+  // Varargs is handled entirely at the Go level.  When converted to
+  // GENERIC functions are not varargs.
+  *pp = void_list_node;
+
+  tree result;
+  if (results.empty())
+    result = void_type_node;
+  else if (results.size() == 1)
+    result = results.front().btype->get_tree();
+  else
+    {
+      result = make_node(RECORD_TYPE);
+      tree field_trees = NULL_TREE;
+      pp = &field_trees;
+      for (std::vector<Btyped_identifier>::const_iterator p = results.begin();
+          p != results.end();
+          ++p)
+       {
+         const std::string name = (p->name.empty()
+                                   ? "UNNAMED"
+                                   : p->name);
+         tree name_tree = get_identifier_from_string(name);
+         tree field_type_tree = p->btype->get_tree();
+         if (field_type_tree == error_mark_node)
+           return this->error_type();
+         tree field = build_decl(location, FIELD_DECL, name_tree,
+                                 field_type_tree);
+         DECL_CONTEXT(field) = result;
+         *pp = field;
+         pp = &DECL_CHAIN(field);
+       }
+      TYPE_FIELDS(result) = field_trees;
+      layout_type(result);
+    }
+  if (result == error_mark_node)
+    return this->error_type();
+
+  tree fntype = build_function_type(result, args);
+  if (fntype == error_mark_node)
+    return this->error_type();
+
+  return this->make_type(build_pointer_type(fntype));
+}
+
 // An expression as a statement.
 
 Bstatement*
index 2d7300c72242ee8a10d73b2a351c5ca3b4f062fe..33f4e58595290df9d96b269c9344f6946007d049 100644 (file)
@@ -7,10 +7,6 @@
 #ifndef GO_BACKEND_H
 #define GO_BACKEND_H
 
-class Function_type;
-class Struct_type;
-class Interface_type;
-
 // Pointers to these types are created by the backend, passed to the
 // frontend, and passed back to the backend.  The types must be
 // defined by the backend using these names.
@@ -36,9 +32,6 @@ class Bvariable;
 // The backend representation of a label.
 class Blabel;
 
-// A list of backend types.
-typedef std::vector<Btype*> Btypes;
-
 // The backend interface.  This is a pure abstract class that a
 // specific backend will implement.
 
@@ -47,6 +40,24 @@ class Backend
  public:
   virtual ~Backend() { }
 
+  // Name/type/location.  Used for function parameters, struct fields,
+  // interface methods.
+  struct Btyped_identifier
+  {
+    std::string name;
+    Btype* btype;
+    source_location location;
+
+    Btyped_identifier()
+      : name(), btype(NULL), location(UNKNOWN_LOCATION)
+    { }
+
+    Btyped_identifier(const std::string& a_name, Btype* a_btype,
+                    source_location a_location)
+      : name(a_name), btype(a_btype), location(a_location)
+    { }
+  };
+
   // Types.
 
   // Produce an error type.  Actually the backend could probably just
@@ -69,56 +80,36 @@ class Backend
   virtual Btype*
   integer_type(bool is_unsigned, int bits) = 0;
 
-  // Get an unnamed floating point type with the given number of bits.
+  // Get an unnamed floating point type with the given number of bits
+  // (32 or 64).
   virtual Btype*
   float_type(int bits) = 0;
 
-  // Get an unnamed complex type with the given number of bits.
+  // Get an unnamed complex type with the given number of bits (64 or 128).
   virtual Btype*
   complex_type(int bits) = 0;
 
-  // Get the unnamed string type.
-  virtual Btype*
-  string_type() = 0;
-
   // Get a pointer type.
   virtual Btype*
-  pointer_type(const Btype* to_type) = 0;
+  pointer_type(Btype* to_type) = 0;
 
   // Get a function type.  The receiver, parameter, and results are
   // generated from the types in the Function_type.  The Function_type
   // is provided so that the names are available.
   virtual Btype*
-  function_type(const Function_type*, Btype* receiver,
-               const Btypes* parameters,
-               const Btypes* results) = 0;
+  function_type(const Btyped_identifier& receiver,
+               const std::vector<Btyped_identifier>& parameters,
+               const std::vector<Btyped_identifier>& results,
+               source_location location) = 0;
 
-  // Get a struct type.  The Struct_type is provided to get the field
-  // names.
+  // Get a struct type.
   virtual Btype*
-  struct_type(const Struct_type*, const Btypes* field_types) = 0;
+  struct_type(const std::vector<Btyped_identifier>& fields) = 0;
 
   // Get an array type.
   virtual Btype*
   array_type(const Btype* element_type, const Bexpression* length) = 0;
 
-  // Get a slice type.
-  virtual Btype*
-  slice_type(const Btype* element_type) = 0;
-
-  // Get a map type.
-  virtual Btype*
-  map_type(const Btype* key_type, const Btype* value_type, source_location) = 0;
-
-  // Get a channel type.
-  virtual Btype*
-  channel_type(const Btype* element_type) = 0;
-
-  // Get an interface type.  The Interface_type is provided to get the
-  // method names.
-  virtual Btype*
-  interface_type(const Interface_type*, const Btypes* method_types) = 0;
-
   // Statements.
 
   // Create an error statement.  This is used for cases which should
index 3da1404129bed55d9a38f1513d1c094e09f4473f..3dc344027657c8dfc3182c413bead3d5e4d7ee96 100644 (file)
@@ -31,6 +31,9 @@ go_create_gogo(int int_type_size, int pointer_size)
   ::gogo = new Gogo(go_get_backend(), int_type_size, pointer_size);
   if (!unique_prefix.empty())
     ::gogo->set_unique_prefix(unique_prefix);
+
+  // FIXME: This should be in the gcc dependent code.
+  ::gogo->define_builtin_function_trees();
 }
 
 // Set the unique prefix we use for exported symbols.
index c24ff98fbd423e470bf0ac462d592d6dd8af596f..b1ccfc3ae62b8e3cfb4241470727d5a9e9a0fbf4 100644 (file)
@@ -1743,7 +1743,7 @@ go_type_for_mode(enum machine_mode mode, int unsignedp)
            return long_double_type_node;
          return NULL_TREE;
        }
-      return type->float_type()->type_tree();
+      return type->get_tree(go_get_gogo());
     }
   else if (mc == MODE_COMPLEX_FLOAT)
     {
@@ -1763,7 +1763,7 @@ go_type_for_mode(enum machine_mode mode, int unsignedp)
            return complex_long_double_type_node;
          return NULL_TREE;
        }
-      return type->complex_type()->type_tree();
+      return type->get_tree(go_get_gogo());
     }
   else
     return NULL_TREE;
index d9f604a5f229a89f787d158cf8680e0e1a3b4040..c0dd9884a543234552df148bbdbec30e54ae0cac 100644 (file)
@@ -203,8 +203,6 @@ Gogo::Gogo(Backend* backend, int int_type_size, int pointer_size)
   imag_type->set_is_varargs();
   imag_type->set_is_builtin();
   this->globals_->add_function_declaration("imag", NULL, imag_type, loc);
-
-  this->define_builtin_function_trees();
 }
 
 // Munge name for use in an error message.
index 788c80a454d218bce14da9edcd437cc29d3974c6..6a0b994ab60b2301caad7bc08dfcafd433c89d5b 100644 (file)
@@ -439,6 +439,10 @@ class Gogo
   void
   write_globals();
 
+  // Create trees for implicit builtin functions.
+  void
+  define_builtin_function_trees();
+
   // Build a call to a builtin function.  PDECL should point to a NULL
   // initialized static pointer which will hold the fndecl.  NAME is
   // the name of the function.  NARGS is the number of arguments.
@@ -558,10 +562,6 @@ class Gogo
   // The stack of functions.
   typedef std::vector<Open_function> Open_functions;
 
-  // Create trees for implicit builtin functions.
-  void
-  define_builtin_function_trees();
-
   // Set up the built-in unsafe package.
   void
   import_unsafe(const std::string&, bool is_exported, source_location);
index f8d705b374a223ccf5819f80ddbafa1eb976ebf4..6c344cefae9188717a7651d85c4d3d0e4dbdada0 100644 (file)
@@ -850,10 +850,10 @@ Type::get_tree(Gogo* gogo)
   if (this->is_error_type())
     return error_mark_node;
 
-  // To avoid confusing GIMPLE, we need to translate all identical Go
-  // types to the same GIMPLE type.  We use a hash table to do that.
-  // There is no need to use the hash table for named types, as named
-  // types are only identical to themselves.
+  // To avoid confusing the backend, translate all identical Go types
+  // to the same backend type.  We use a hash table to do that.  There
+  // is no need to use the hash table for named types, as named types
+  // are only identical to themselves.
 
   std::pair<Type*, tree> val(this, NULL);
   std::pair<Type_trees::iterator, bool> ins =
@@ -1802,10 +1802,10 @@ Integer_type::do_hash_for_method(Gogo*) const
          + ((this->is_abstract_ ? 1 : 0) << 9));
 }
 
-// Get the tree for an Integer_type.
+// Convert an Integer_type to the backend representation.
 
 tree
-Integer_type::do_get_tree(Gogo*)
+Integer_type::do_get_tree(Gogo* gogo)
 {
   if (this->is_abstract_)
     {
@@ -1813,9 +1813,8 @@ Integer_type::do_get_tree(Gogo*)
       return error_mark_node;
     }
 
-  // FIXME: GOGO can be NULL when called from go_type_for_size, so call
-  // go_get_backend() instead of gogo->backend().
-  Btype* btype = go_get_backend()->integer_type(this->is_unsigned_, this->bits_);
+  Btype* btype = gogo->backend()->integer_type(this->is_unsigned_,
+                                              this->bits_);
   return type_to_tree(btype);
 }
 
@@ -1944,23 +1943,15 @@ Float_type::do_hash_for_method(Gogo*) const
   return (this->bits_ << 4) + ((this->is_abstract_ ? 1 : 0) << 8);
 }
 
-// Get a tree without using a Gogo*.
+// Convert to the backend representation.
 
 tree
-Float_type::type_tree() const
+Float_type::do_get_tree(Gogo* gogo)
 {
-  Btype* btype = go_get_backend()->float_type(this->bits_);
+  Btype* btype = gogo->backend()->float_type(this->bits_);
   return type_to_tree(btype);
 }
 
-// Get a tree.
-
-tree
-Float_type::do_get_tree(Gogo*)
-{
-  return this->type_tree();
-}
-
 tree
 Float_type::do_get_init_tree(Gogo*, tree type_tree, bool is_clear)
 {
@@ -2089,21 +2080,12 @@ Complex_type::do_hash_for_method(Gogo*) const
   return (this->bits_ << 4) + ((this->is_abstract_ ? 1 : 0) << 8);
 }
 
-// Get a tree without using a Gogo*.
+// Convert to the backend representation.
 
 tree
-Complex_type::type_tree() const
+Complex_type::do_get_tree(Gogo* gogo)
 {
-  Btype* btype = go_get_backend()->complex_type(this->bits_);
-  return type_to_tree(btype);
-}
-
-// Get a tree.
-
-tree
-Complex_type::do_get_tree(Gogo*)
-{
-  return this->type_tree();
+  return type_to_tree(gogo->backend()->complex_type(this->bits_));
 }
 
 // Zero initializer.
@@ -2175,8 +2157,8 @@ Type::lookup_complex_type(const char* name)
 
 // Class String_type.
 
-// Return the tree for String_type.  A string is a struct with two
-// fields: a pointer to the characters and a length.
+// Convert String_type to the backend representation.  A string is a
+// struct with two fields: a pointer to the characters and a length.
 
 tree
 String_type::do_get_tree(Gogo*)
@@ -2608,83 +2590,55 @@ Function_type::do_hash_for_method(Gogo* gogo) const
 tree
 Function_type::do_get_tree(Gogo* gogo)
 {
-  tree args = NULL_TREE;
-  tree* pp = &args;
-
+  Backend::Btyped_identifier breceiver;
   if (this->receiver_ != NULL)
     {
-      Type* rtype = this->receiver_->type();
-      tree ptype = rtype->get_tree(gogo);
-      if (ptype == error_mark_node)
-       return error_mark_node;
+      breceiver.name = this->receiver_->name();
 
       // We always pass the address of the receiver parameter, in
       // order to make interface calls work with unknown types.
+      Type* rtype = this->receiver_->type();
       if (rtype->points_to() == NULL)
-       ptype = build_pointer_type(ptype);
-
-      *pp = tree_cons (NULL_TREE, ptype, NULL_TREE);
-      pp = &TREE_CHAIN (*pp);
+       rtype = Type::make_pointer_type(rtype);
+      breceiver.btype = tree_to_type(rtype->get_tree(gogo));
+      breceiver.location = this->receiver_->location();
     }
 
+  std::vector<Backend::Btyped_identifier> bparameters;
   if (this->parameters_ != NULL)
     {
+      bparameters.resize(this->parameters_->size());
+      size_t i = 0;
       for (Typed_identifier_list::const_iterator p = this->parameters_->begin();
           p != this->parameters_->end();
-          ++p)
+          ++p, ++i)
        {
-         tree ptype = p->type()->get_tree(gogo);
-         if (ptype == error_mark_node)
-           return error_mark_node;
-         *pp = tree_cons (NULL_TREE, ptype, NULL_TREE);
-         pp = &TREE_CHAIN (*pp);
+         bparameters[i].name = p->name();
+         bparameters[i].btype = tree_to_type(p->type()->get_tree(gogo));
+         bparameters[i].location = p->location();
        }
+      gcc_assert(i == bparameters.size());
     }
 
-  // Varargs is handled entirely at the Go level.  At the tree level,
-  // functions are not varargs.
-  *pp = void_list_node;
-
-  tree result;
-  if (this->results_ == NULL)
-    result = void_type_node;
-  else if (this->results_->size() == 1)
-    result = this->results_->begin()->type()->get_tree(gogo);
-  else
+  std::vector<Backend::Btyped_identifier> bresults;
+  if (this->results_ != NULL)
     {
-      result = make_node(RECORD_TYPE);
-      tree field_trees = NULL_TREE;
-      tree* pp = &field_trees;
+      bresults.resize(this->results_->size());
+      size_t i = 0;
       for (Typed_identifier_list::const_iterator p = this->results_->begin();
           p != this->results_->end();
-          ++p)
+          ++p, ++i)
        {
-         const std::string name = (p->name().empty()
-                                   ? "UNNAMED"
-                                   : Gogo::unpack_hidden_name(p->name()));
-         tree name_tree = get_identifier_with_length(name.data(),
-                                                     name.length());
-         tree field_type_tree = p->type()->get_tree(gogo);
-         if (field_type_tree == error_mark_node)
-           return error_mark_node;
-         tree field = build_decl(this->location_, FIELD_DECL, name_tree,
-                                 field_type_tree);
-         DECL_CONTEXT(field) = result;
-         *pp = field;
-         pp = &DECL_CHAIN(field);
+         bresults[i].name = p->name();
+         bresults[i].btype = tree_to_type(p->type()->get_tree(gogo));
+         bresults[i].location = p->location();
        }
-      TYPE_FIELDS(result) = field_trees;
-      layout_type(result);
+      gcc_assert(i == bresults.size());
     }
 
-  if (result == error_mark_node)
-    return error_mark_node;
-
-  tree fntype = build_function_type(result, args);
-  if (fntype == error_mark_node)
-    return fntype;
-
-  return build_pointer_type(fntype);
+  Btype* fntype = gogo->backend()->function_type(breceiver, bparameters,
+                                                bresults, this->location());
+  return type_to_tree(fntype);
 }
 
 // Functions are initialized to NULL.
index cf8b409e923d09592849610312f904ce9929a1d3..5e6da62e514a1a38b3f299517e95748f63e735f9 100644 (file)
@@ -1396,10 +1396,6 @@ class Float_type : public Type
   bool
   is_identical(const Float_type* t) const;
 
-  // Return a tree for this type without using a Gogo*.
-  tree
-  type_tree() const;
-
  protected:
   unsigned int
   do_hash_for_method(Gogo*) const;
@@ -1468,10 +1464,6 @@ class Complex_type : public Type
   bool
   is_identical(const Complex_type* t) const;
 
-  // Return a tree for this type without using a Gogo*.
-  tree
-  type_tree() const;
-
  protected:
   unsigned int
   do_hash_for_method(Gogo*) const;