diff gcc/go/gofrontend/types.h @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
line wrap: on
line diff
--- a/gcc/go/gofrontend/types.h	Thu Oct 25 07:37:49 2018 +0900
+++ b/gcc/go/gofrontend/types.h	Thu Feb 13 11:34:05 2020 +0900
@@ -186,6 +186,22 @@
     this->stub_ = no;
   }
 
+  // Get the direct interface method stub object.
+  Named_object*
+  iface_stub_object() const
+  {
+    go_assert(this->iface_stub_ != NULL);
+    return this->iface_stub_;
+  }
+
+  // Set the direct interface method stub object.
+  void
+  set_iface_stub_object(Named_object* no)
+  {
+    go_assert(this->iface_stub_ == NULL);
+    this->iface_stub_ = no;
+  }
+
   // Return true if this method should not participate in any
   // interfaces.
   bool
@@ -196,7 +212,7 @@
   // These objects are only built by the child classes.
   Method(const Field_indexes* field_indexes, unsigned int depth,
 	 bool is_value_method, bool needs_stub_method)
-    : field_indexes_(field_indexes), depth_(depth), stub_(NULL),
+    : field_indexes_(field_indexes), depth_(depth), stub_(NULL), iface_stub_(NULL),
       is_value_method_(is_value_method), needs_stub_method_(needs_stub_method),
       is_ambiguous_(false)
   { }
@@ -230,6 +246,9 @@
   // If a stub method is required, this is its object.  This is only
   // set after stub methods are built in finalize_methods.
   Named_object* stub_;
+  // Stub object for direct interface type.  This is only set after
+  // stub methods are built in finalize_methods.
+  Named_object* iface_stub_;
   // Whether this is a value method--a method that does not require a
   // pointer.
   bool is_value_method_;
@@ -577,6 +596,11 @@
   // Compare aliases: treat an alias to T as distinct from T.
   static const int COMPARE_ALIASES = 4;
 
+  // When comparing interface types compare the interface embedding heirarchy,
+  // if any, rather than only comparing method sets. Useful primarily when
+  // exporting types.
+  static const int COMPARE_EMBEDDED_INTERFACES = 8;
+
   // Return true if two types are identical.  If this returns false,
   // and REASON is not NULL, it may set *REASON.
   static bool
@@ -635,6 +659,12 @@
   needs_key_update()
   { return this->do_needs_key_update(); }
 
+  // Return whether the hash function of this type might panic.  This
+  // is only called for types used as a key in a map type.
+  bool
+  hash_might_panic()
+  { return this->do_hash_might_panic(); }
+
   // Whether the type is permitted in the heap.
   bool
   in_heap()
@@ -912,6 +942,11 @@
   is_unsafe_pointer_type() const
   { return this->points_to() != NULL && this->points_to()->is_void_type(); }
 
+  // Return whether this type is stored directly in an interface's
+  // data word.
+  bool
+  is_direct_iface_type() const;
+
   // Return a version of this type with any expressions copied, but
   // only if copying the expressions will affect the size of the type.
   // If there are no such expressions in the type (expressions can
@@ -1018,19 +1053,26 @@
   bool
   needs_specific_type_functions(Gogo*);
 
-  // Get the hash and equality functions for a type.
+  // Get the equality function for a type.  Returns NULL if the type
+  // is not comparable.
+  Named_object*
+  equal_function(Gogo*, Named_type* name, Function_type* equal_fntype);
+
+  // Get the hash function for a type.  Returns NULL if the type is
+  // not comparable.
+  Named_object*
+  hash_function(Gogo*, Function_type* hash_fntype);
+
+  // Write the equal function for a type.
   void
-  type_functions(Gogo*, Named_type* name, Function_type* hash_fntype,
-		 Function_type* equal_fntype, Named_object** hash_fn,
-		 Named_object** equal_fn);
-
-  // Write the hash and equality type functions.
+  write_equal_function(Gogo*, Named_type*, int64_t size,
+		       const std::string& equal_name,
+		       Function_type* equal_fntype);
+
+  // Write the hash function for a type.
   void
-  write_specific_type_functions(Gogo*, Named_type*, int64_t size,
-				const std::string& hash_name,
-				Function_type* hash_fntype,
-				const std::string& equal_name,
-				Function_type* equal_fntype);
+  write_hash_function(Gogo*, int64_t size, const std::string& hash_name,
+		      Function_type* hash_fntype);
 
   // Return the alignment required by the memequalN function.
   static int64_t memequal_align(Gogo*, int size);
@@ -1074,6 +1116,10 @@
   { return false; }
 
   virtual bool
+  do_hash_might_panic()
+  { return false; }
+
+  virtual bool
   do_in_heap()
   { return true; }
 
@@ -1151,10 +1197,6 @@
   append_mangled_name(const Type* type, Gogo* gogo, std::string* ret) const
   { type->do_mangled_name(gogo, ret); }
 
-  // Incorporate a string into a hash code.
-  static unsigned int
-  hash_string(const std::string&, unsigned int);
-
   // Return the backend representation for the underlying type of a
   // named type.
   static Btype*
@@ -1239,13 +1281,14 @@
   Expression*
   gcprog_constructor(Gogo*, int64_t ptrsize, int64_t ptrdata);
 
-  // Build the hash and equality type functions for a type which needs
-  // specific functions.
-  void
-  specific_type_functions(Gogo*, Named_type*, int64_t size,
-			  Function_type* hash_fntype,
-			  Function_type* equal_fntype, Named_object** hash_fn,
-			  Named_object** equal_fn);
+  // Build the hash function for a type that needs specific functions.
+  Named_object*
+  build_hash_function(Gogo*, int64_t size, Function_type* hash_fntype);
+
+  // Build the equal function for a type that needs specific functions.
+  Named_object*
+  build_equal_function(Gogo*, Named_type*, int64_t size,
+		       Function_type* equal_fntype);
 
   void
   write_identity_hash(Gogo*, int64_t size);
@@ -1254,10 +1297,6 @@
   write_identity_equal(Gogo*, int64_t size);
 
   void
-  write_named_hash(Gogo*, Named_type*, Function_type* hash_fntype,
-		   Function_type* equal_fntype);
-
-  void
   write_named_equal(Gogo*, Named_type*);
 
   // Build a composite literal for the uncommon type information.
@@ -1310,6 +1349,15 @@
 			const Typed_identifier_list*, bool is_varargs,
 			Location);
 
+  // Build direct interface stub methods for a type.
+  static void
+  build_direct_iface_stub_methods(Gogo*, const Type*, Methods*, Location);
+
+  static void
+  build_one_iface_stub_method(Gogo*, Method*, const char*,
+                              const Typed_identifier_list*,
+                              bool, Location);
+
   static Expression*
   apply_field_indexes(Expression*, const Method::Field_indexes*,
 		      Location);
@@ -1322,6 +1370,11 @@
 		       bool* is_method, bool* found_pointer_method,
 		       std::string* ambig1, std::string* ambig2);
 
+  // Helper function for is_direct_iface_type, to prevent infinite
+  // recursion.
+  bool
+  is_direct_iface_type_helper(Unordered_set(const Type*)*) const;
+
   // Get the backend representation for a type without looking in the
   // hash table for identical types.
   Btype*
@@ -1345,13 +1398,13 @@
   // A list of builtin named types.
   static std::vector<Named_type*> named_builtin_types;
 
-  // A map from types which need specific type functions to the type
-  // functions themselves.
-  typedef std::pair<Named_object*, Named_object*> Hash_equal_fn;
-  typedef Unordered_map_hash(const Type*, Hash_equal_fn, Type_hash_identical,
-			     Type_identical) Type_functions;
-
-  static Type_functions type_functions_table;
+  // A map from types that need a specific hash or equality function
+  // to the hash or equality function.
+  typedef Unordered_map_hash(const Type*, Named_object*, Type_hash_identical,
+			     Type_identical) Type_function;
+
+  static Type_function type_hash_functions_table;
+  static Type_function type_equal_functions_table;
 
   // Cache for reusing existing pointer types; maps from pointed-to-type
   // to pointer type.
@@ -1360,7 +1413,7 @@
   static Pointer_type_table pointer_types;
 
   // List of placeholder pointer types.
-  static std::vector<Pointer_type*> placeholder_pointers;
+  static std::vector<Type*> placeholder_pointers;
 
   // The type classification.
   Type_classification classification_;
@@ -1445,7 +1498,12 @@
   // Set the escape note.
   void
   set_note(const std::string& note)
-  { this->note_ = new std::string(note); }
+  {
+    if (this->note_ != NULL)
+      go_assert(*this->note_ == note);
+    else
+      this->note_ = new std::string(note);
+  }
 
  private:
   // Identifier name.
@@ -2432,7 +2490,7 @@
   Struct_type(Struct_field_list* fields, Location location)
     : Type(TYPE_STRUCT),
       fields_(fields), location_(location), all_methods_(NULL),
-      is_struct_incomparable_(false)
+      is_struct_incomparable_(false), has_padding_(false)
   { }
 
   // Return the field NAME.  This only looks at local fields, not at
@@ -2552,9 +2610,20 @@
   set_is_struct_incomparable()
   { this->is_struct_incomparable_ = true; }
 
+  // Return whether this struct's backend type has padding, due to
+  // trailing zero-sized field.
+  bool
+  has_padding() const
+  { return this->has_padding_; }
+
+  // Record that this struct's backend type has padding.
+  void
+  set_has_padding()
+  { this->has_padding_ = true; }
+
   // Write the hash function for this type.
   void
-  write_hash_function(Gogo*, Named_type*, Function_type*, Function_type*);
+  write_hash_function(Gogo*, Function_type*);
 
   // Write the equality function for this type.
   void
@@ -2590,6 +2659,9 @@
   do_needs_key_update();
 
   bool
+  do_hash_might_panic();
+
+  bool
   do_in_heap();
 
   unsigned int
@@ -2656,6 +2728,9 @@
   // True if this is a generated struct that is not considered to be
   // comparable.
   bool is_struct_incomparable_;
+  // True if this struct's backend type has padding, due to trailing
+  // zero-sized field.
+  bool has_padding_;
 };
 
 // The type of an array.
@@ -2683,7 +2758,7 @@
   // length can not be determined.  This will assert if called for a
   // slice.
   bool
-  int_length(int64_t* plen);
+  int_length(int64_t* plen) const;
 
   // Whether this type is identical with T.
   bool
@@ -2735,7 +2810,7 @@
 
   // Write the hash function for this type.
   void
-  write_hash_function(Gogo*, Named_type*, Function_type*, Function_type*);
+  write_hash_function(Gogo*, Function_type*);
 
   // Write the equality function for this type.
   void
@@ -2765,6 +2840,10 @@
   { return this->element_type_->needs_key_update(); }
 
   bool
+  do_hash_might_panic()
+  { return this->length_ != NULL && this->element_type_->hash_might_panic(); }
+
+  bool
   do_in_heap()
   { return this->length_ == NULL || this->element_type_->in_heap(); }
 
@@ -2842,6 +2921,27 @@
   Expression*
   fat_zero_value(Gogo*);
 
+  // Map algorithm to use for this map type.  We may use specialized
+  // fast map routines for certain key types.
+  enum Map_alg
+    {
+      // 32-bit key.
+      MAP_ALG_FAST32,
+      // 32-bit pointer key.
+      MAP_ALG_FAST32PTR,
+      // 64-bit key.
+      MAP_ALG_FAST64,
+      // 64-bit pointer key.
+      MAP_ALG_FAST64PTR,
+      // String key.
+      MAP_ALG_FASTSTR,
+      // Anything else.
+      MAP_ALG_SLOW,
+    };
+
+  Map_alg
+  algorithm(Gogo*);
+
   // Return whether VAR is the map zero value.
   static bool
   is_zero_value(Variable* var);
@@ -2861,7 +2961,7 @@
   static Type*
   make_map_type_descriptor_type();
 
-  // This must be in  sync with libgo/go/runtime/hashmap.go.
+  // This must be in  sync with libgo/go/runtime/map.go.
   static const int bucket_size = 8;
 
  protected:
@@ -2904,7 +3004,7 @@
   do_export(Export*) const;
 
  private:
-  // These must be in sync with libgo/go/runtime/hashmap.go.
+  // These must be in sync with libgo/go/runtime/map.go.
   static const int max_key_size = 128;
   static const int max_val_size = 128;
   static const int max_zero_size = 1024;
@@ -3059,7 +3159,7 @@
     return this->all_methods_ == NULL;
   }
 
-  // Return the list of locally defined methos.  This will return NULL
+  // Return the list of locally defined methods.  This will return NULL
   // for an empty interface.  Embedded interfaces will appear in this
   // list as an entry with no name.
   const Typed_identifier_list*
@@ -3133,6 +3233,20 @@
   static Type*
   make_interface_type_descriptor_type();
 
+  // Return whether methods are finalized for this interface.
+  bool
+  methods_are_finalized() const
+  { return this->methods_are_finalized_; }
+
+  // Sort embedded interfaces by name. Needed when we are preparing
+  // to emit types into the export data.
+  void
+  sort_embedded()
+  {
+    if (parse_methods_ != NULL)
+      parse_methods_->sort_by_name();
+  }
+
  protected:
   int
   do_traverse(Traverse*);
@@ -3156,6 +3270,11 @@
   do_needs_key_update()
   { return true; }
 
+  // Hashing an unhashable type stored in an interface might panic.
+  bool
+  do_hash_might_panic()
+  { return true; }
+
   unsigned int
   do_hash_for_method(Gogo*, int) const;