Rewrite conversion of named types to backend representation.
[gcc.git] / gcc / go / gofrontend / types.h
index b9e8caf6c13fb29a9a30ef287127d119e7647c84..8e91dfcab072edf11caedbf3aff1a330a7c2d484 100644 (file)
@@ -799,6 +799,10 @@ class Type
   check_make_expression(Expression_list* args, source_location location)
   { return this->do_check_make_expression(args, location); }
 
+  // Convert the builtin named types.
+  static void
+  convert_builtin_named_types(Gogo*);
+
   // Return a tree representing this type.
   tree
   get_tree(Gogo*);
@@ -1082,6 +1086,9 @@ class Type
 
   static Type_trees type_trees;
 
+  // A list of builtin named types.
+  static std::vector<Named_type*> named_builtin_types;
+
   // The type classification.
   Type_classification classification_;
   // The tree representation of the type, once it has been determined.
@@ -1605,6 +1612,9 @@ class Function_type : public Type
   Function_type*
   copy_with_receiver(Type*) const;
 
+  static Type*
+  make_function_type_descriptor_type();
+
  protected:
   int
   do_traverse(Traverse*);
@@ -1636,9 +1646,6 @@ class Function_type : public Type
   do_export(Export*) const;
 
  private:
-  static Type*
-  make_function_type_descriptor_type();
-
   Expression*
   type_descriptor_params(Type*, const Typed_identifier*,
                         const Typed_identifier_list*);
@@ -1680,6 +1687,9 @@ class Pointer_type : public Type
   static Pointer_type*
   do_import(Import*);
 
+  static Type*
+  make_pointer_type_descriptor_type();
+
  protected:
   int
   do_traverse(Traverse*);
@@ -1710,9 +1720,6 @@ class Pointer_type : public Type
   do_export(Export*) const;
 
  private:
-  static Type*
-  make_pointer_type_descriptor_type();
-
   // The type to which this type points.
   Type* to_type_;
 };
@@ -1841,8 +1848,7 @@ class Struct_type : public Type
  public:
   Struct_type(Struct_field_list* fields, source_location location)
     : Type(TYPE_STRUCT),
-      fields_(fields), location_(location), all_methods_(NULL),
-      prerequisites_()
+      fields_(fields), location_(location), all_methods_(NULL)
   { }
 
   // Return the field NAME.  This only looks at local fields, not at
@@ -1937,16 +1943,8 @@ class Struct_type : public Type
   tree
   fill_in_tree(Gogo*, tree);
 
-  // Note that a struct must be converted to the backend
-  // representation before we convert this struct.
-  void
-  add_prerequisite(Named_type* nt)
-  { this->prerequisites_.push_back(nt); }
-
-  // If there are any structs which must be converted to the backend
-  // representation before this one, convert them.
-  void
-  convert_prerequisites(Gogo*);
+  static Type*
+  make_struct_type_descriptor_type();
 
  protected:
   int
@@ -1980,12 +1978,17 @@ class Struct_type : public Type
   do_export(Export*) const;
 
  private:
+  // Used to avoid infinite loops in field_reference_depth.
+  struct Saw_named_type
+  {
+    Saw_named_type* next;
+    Named_type* nt;
+  };
+
   Field_reference_expression*
   field_reference_depth(Expression* struct_expr, const std::string& name,
-                       source_location, unsigned int* depth) const;
-
-  static Type*
-  make_struct_type_descriptor_type();
+                       source_location, Saw_named_type*,
+                       unsigned int* depth) const;
 
   // The fields of the struct.
   Struct_field_list* fields_;
@@ -1993,16 +1996,6 @@ class Struct_type : public Type
   source_location location_;
   // If this struct is unnamed, a list of methods.
   Methods* all_methods_;
-  // A list of structs which must be converted to the backend
-  // representation before this struct can be converted.  This is for
-  // cases like
-  //   type S1 { p *S2 }
-  //   type S2 { s S1 }
-  // where we must start converting S2 before we start converting S1.
-  // That is because we can fully convert S1 before S2 is complete,
-  // but we can not fully convert S2 before S1 is complete.  If we
-  // start converting S1 first, we won't be able to convert S2.
-  std::vector<Named_type*> prerequisites_;
 };
 
 // The type of an array.
@@ -2050,9 +2043,19 @@ class Array_type : public Type
   static Array_type*
   do_import(Import*);
 
+  // Fill in the fields for a named array type.
+  tree
+  fill_in_array_tree(Gogo*, tree);
+
   // Fill in the fields for a named slice type.
   tree
-  fill_in_tree(Gogo*, tree);
+  fill_in_slice_tree(Gogo*, tree);
+
+  static Type*
+  make_array_type_descriptor_type();
+
+  static Type*
+  make_slice_type_descriptor_type();
 
  protected:
   int
@@ -2102,12 +2105,6 @@ class Array_type : public Type
   tree
   get_length_tree(Gogo*);
 
-  Type*
-  make_array_type_descriptor_type();
-
-  Type*
-  make_slice_type_descriptor_type();
-
   Expression*
   array_type_descriptor(Gogo*, Named_type*);
 
@@ -2150,6 +2147,9 @@ class Map_type : public Type
   static Map_type*
   do_import(Import*);
 
+  static Type*
+  make_map_type_descriptor_type();
+
  protected:
   int
   do_traverse(Traverse*);
@@ -2190,9 +2190,6 @@ class Map_type : public Type
   do_export(Export*) const;
 
  private:
-  static Type*
-  make_map_type_descriptor_type();
-
   // The key type.
   Type* key_type_;
   // The value type.
@@ -2236,6 +2233,9 @@ class Channel_type : public Type
   static Channel_type*
   do_import(Import*);
 
+  static Type*
+  make_chan_type_descriptor_type();
+
  protected:
   int
   do_traverse(Traverse* traverse)
@@ -2274,9 +2274,6 @@ class Channel_type : public Type
   do_export(Export*) const;
 
  private:
-  static Type*
-  make_chan_type_descriptor_type();
-
   // Whether this channel can send data.
   bool may_send_;
   // Whether this channel can receive data.
@@ -2296,6 +2293,11 @@ class Interface_type : public Type
       methods_(methods), location_(location)
   { gcc_assert(methods == NULL || !methods->empty()); }
 
+  // The location where the interface type was defined.
+  source_location
+  location() const
+  { return this->location_; }
+
   // Return whether this is an empty interface.
   bool
   is_empty() const
@@ -2349,10 +2351,21 @@ class Interface_type : public Type
   static Interface_type*
   do_import(Import*);
 
+  // Make a struct for an empty interface type.
+  static tree
+  empty_type_tree(Gogo*);
+
+  // Make a struct for non-empty interface type.
+  static tree
+  non_empty_type_tree(source_location);
+
   // Fill in the fields for a named interface type.
   tree
   fill_in_tree(Gogo*, tree);
 
+  static Type*
+  make_interface_type_descriptor_type();
+
  protected:
   int
   do_traverse(Traverse*);
@@ -2383,9 +2396,6 @@ class Interface_type : public Type
   do_export(Export*) const;
 
  private:
-  static Type*
-  make_interface_type_descriptor_type();
-
   // The list of methods associated with the interface.  This will be
   // NULL for the empty interface.
   Typed_identifier_list* methods_;
@@ -2407,8 +2417,9 @@ class Named_type : public Type
       named_object_(named_object), in_function_(NULL), type_(type),
       local_methods_(NULL), all_methods_(NULL),
       interface_method_tables_(NULL), pointer_interface_method_tables_(NULL),
-      location_(location), named_tree_(NULL), is_visible_(true),
-      is_error_(false), seen_(0)
+      location_(location), named_tree_(NULL), dependencies_(),
+      is_visible_(true), is_error_(false), is_converted_(false),
+      is_circular_(false), seen_(0)
   { }
 
   // Return the associated Named_object.  This holds the actual name.
@@ -2481,6 +2492,12 @@ class Named_type : public Type
   is_builtin() const
   { return this->location_ == BUILTINS_LOCATION; }
 
+  // Whether this is a circular type: a pointer or function type that
+  // refers to itself, which is not possible in C.
+  bool
+  is_circular() const
+  { return this->is_circular_; }
+
   // Return the base type for this type.
   Type*
   named_base();
@@ -2555,6 +2572,12 @@ class Named_type : public Type
   bool
   named_type_has_hidden_fields(std::string* reason) const;
 
+  // Note that a type must be converted to the backend representation
+  // before we convert this type.
+  void
+  add_dependency(Named_type* nt)
+  { this->dependencies_.push_back(nt); }
+
   // Export the type.
   void
   export_named_type(Export*, const std::string& name) const;
@@ -2563,6 +2586,10 @@ class Named_type : public Type
   static void
   import_named_type(Import*, Named_type**);
 
+  // Initial conversion to backend representation.
+  void
+  convert(Gogo*);
+
  protected:
   int
   do_traverse(Traverse* traverse)
@@ -2606,6 +2633,10 @@ class Named_type : public Type
   do_export(Export*) const;
 
  private:
+  // Create the placeholder during conversion.
+  void
+  create_placeholder(Gogo*);
+
   // A mapping from interfaces to the associated interface method
   // tables for this type.  This maps to a decl.
   typedef Unordered_map_hash(const Interface_type*, tree, Type_hash_identical,
@@ -2635,6 +2666,14 @@ class Named_type : public Type
   // The tree for this type while converting to GENERIC.  This is used
   // to avoid endless recursion when a named type refers to itself.
   tree named_tree_;
+  // A list of types which must be converted to the backend
+  // representation before this type can be converted.  This is for
+  // cases like
+  //   type S1 { p *S2 }
+  //   type S2 { s S1 }
+  // where we can't convert S2 to the backend representation unless we
+  // have converted S1.
+  std::vector<Named_type*> dependencies_;
   // Whether this type is visible.  This is false if this type was
   // created because it was referenced by an imported object, but the
   // type itself was not exported.  This will always be true for types
@@ -2642,6 +2681,12 @@ class Named_type : public Type
   bool is_visible_;
   // Whether this type is erroneous.
   bool is_error_;
+  // Whether this type has been converted to the backend
+  // representation.
+  bool is_converted_;
+  // Whether this is a pointer or function type which refers to the
+  // type itself.
+  bool is_circular_;
   // In a recursive operation such as has_hidden_fields, this flag is
   // used to prevent infinite recursion when a type refers to itself.
   // This is mutable because it is always reset to false when the