diff options
Diffstat (limited to 'gcc/go/gofrontend/types.h')
-rw-r--r-- | gcc/go/gofrontend/types.h | 346 |
1 files changed, 277 insertions, 69 deletions
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index 8d2a982533..47a70fcd08 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -7,11 +7,14 @@ #ifndef GO_TYPES_H #define GO_TYPES_H +#include <ostream> + #include "go-linemap.h" #include "escape.h" class Gogo; class Package; +class Variable; class Traverse; class Typed_identifier; class Typed_identifier_list; @@ -627,6 +630,18 @@ class Type compare_is_identity(Gogo* gogo) { return this->do_compare_is_identity(gogo); } + // Return whether values of this type are reflexive: if a comparison + // of a value with itself always returns true. + bool + is_reflexive() + { return this->do_is_reflexive(); } + + // Return whether values of this, when used as a key in map, + // requires the key to be updated when an assignment is made. + bool + needs_key_update() + { return this->do_needs_key_update(); } + // Return a hash code for this type for the method hash table. // Types which are equivalent according to are_identical will have // the same hash code. @@ -960,6 +975,10 @@ class Type bool is_backend_type_size_known(Gogo*); + // Return whether the type needs specially built type functions. + bool + needs_specific_type_functions(Gogo*); + // Get the hash and equality functions for a type. void type_functions(Gogo*, Named_type* name, Function_type* hash_fntype, @@ -968,12 +987,15 @@ class Type // Write the hash and equality type functions. void - write_specific_type_functions(Gogo*, Named_type*, + 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); + // Return the alignment required by the memequalN function. + static int64_t memequal_align(Gogo*, int size); + // Export the type. void export_type(Export* exp) const @@ -1004,6 +1026,14 @@ class Type virtual bool do_compare_is_identity(Gogo*) = 0; + virtual bool + do_is_reflexive() + { return true; } + + virtual bool + do_needs_key_update() + { return false; } + virtual unsigned int do_hash_for_method(Gogo*) const; @@ -1183,11 +1213,18 @@ class Type // Build the hash and equality type functions for a type which needs // specific functions. void - specific_type_functions(Gogo*, Named_type*, Function_type* hash_fntype, + 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); void + write_identity_hash(Gogo*, int64_t size); + + void + write_identity_equal(Gogo*, int64_t size); + + void write_named_hash(Gogo*, Named_type*, Function_type* hash_fntype, Function_type* equal_fntype); @@ -1325,7 +1362,7 @@ class Typed_identifier public: Typed_identifier(const std::string& name, Type* type, Location location) - : name_(name), type_(type), location_(location) + : name_(name), type_(type), location_(location), note_(NULL) { } // Get the name. @@ -1352,6 +1389,16 @@ class Typed_identifier this->type_ = type; } + // Get the escape note. + std::string* + note() const + { return this->note_; } + + // Set the escape note. + void + set_note(const std::string& note) + { this->note_ = new std::string(note); } + private: // Identifier name. std::string name_; @@ -1359,6 +1406,9 @@ class Typed_identifier Type* type_; // The location where the name was seen. Location location_; + // Escape note for this typed identifier. Used when importing and exporting + // functions. + std::string* note_; }; // A list of Typed_identifiers. @@ -1423,6 +1473,10 @@ class Typed_identifier_list back() const { return this->entries_.back(); } + Typed_identifier& + at(size_t i) + { return this->entries_.at(i); } + const Typed_identifier& at(size_t i) const { return this->entries_.at(i); } @@ -1620,6 +1674,15 @@ class Float_type : public Type do_compare_is_identity(Gogo*) { return false; } + bool + do_is_reflexive() + { return false; } + + // Distinction between +0 and -0 requires a key update. + bool + do_needs_key_update() + { return true; } + unsigned int do_hash_for_method(Gogo*) const; @@ -1693,6 +1756,15 @@ class Complex_type : public Type do_compare_is_identity(Gogo*) { return false; } + bool + do_is_reflexive() + { return false; } + + // Distinction between +0 and -0 requires a key update. + bool + do_needs_key_update() + { return true; } + unsigned int do_hash_for_method(Gogo*) const; @@ -1749,6 +1821,11 @@ class String_type : public Type do_compare_is_identity(Gogo*) { return false; } + // New string might have a smaller backing store. + bool + do_needs_key_update() + { return true; } + Btype* do_get_backend(Gogo*); @@ -1779,7 +1856,7 @@ class Function_type : public Type : Type(TYPE_FUNCTION), receiver_(receiver), parameters_(parameters), results_(results), location_(location), is_varargs_(false), is_builtin_(false), - has_escape_info_(false), fnbtype_(NULL), parameter_escape_states_(NULL) + fnbtype_(NULL), is_tagged_(false) { } // Get the receiver. @@ -1787,15 +1864,10 @@ class Function_type : public Type receiver() const { return this->receiver_; } - // Get the escape state of the receiver. - const Node::Escapement_lattice& - receiver_escape_state() const - { return this->receiver_escape_state_; } - - // Set the escape state of the receiver. + // Add an escape note for the receiver. void - set_receiver_escape_state(const Node::Escapement_lattice& e) - { this->receiver_escape_state_ = e; } + add_receiver_note(int encoding) + { this->receiver_->set_note(Escape_note::make_tag(encoding)); } // Get the return names and types. const Typed_identifier_list* @@ -1807,15 +1879,20 @@ class Function_type : public Type parameters() const { return this->parameters_; } - // Get the escape states associated with each parameter. - const Node::Escape_states* - parameter_escape_states() const - { return this->parameter_escape_states_; } + // Add an escape note for the ith parameter. + void + add_parameter_note(int index, int encoding) + { this->parameters_->at(index).set_note(Escape_note::make_tag(encoding)); } + + // Whether this function has been tagged during escape analysis. + bool + is_tagged() const + { return this->is_tagged_; } - // Set the escape states of the parameters. + // Mark this function as tagged after analyzing its escape. void - set_parameter_escape_states(Node::Escape_states* states) - { this->parameter_escape_states_ = states; } + set_is_tagged() + { this->is_tagged_ = true; } // Whether this is a varargs function. bool @@ -1827,11 +1904,6 @@ class Function_type : public Type is_builtin() const { return this->is_builtin_; } - // Whether this contains escape information. - bool - has_escape_info() const - { return this->has_escape_info_; } - // The location where this type was defined. Location location() const @@ -1862,11 +1934,6 @@ class Function_type : public Type set_is_builtin() { this->is_builtin_ = true; } - // Record that this has escape information. - void - set_has_escape_info() - { this->has_escape_info_ = true; } - // Import a function type. static Function_type* do_import(Import*); @@ -1978,16 +2045,12 @@ class Function_type : public Type // Whether this is a special builtin function which can not simply // be called. This is used for len, cap, etc. bool is_builtin_; - // Whether escape information for the receiver and parameters has been - // recorded. - bool has_escape_info_; // The backend representation of this type for backend function // declarations and definitions. Btype* fnbtype_; - // The escape state of the receiver. - Node::Escapement_lattice receiver_escape_state_; - // The escape states of each parameter. - Node::Escape_states* parameter_escape_states_; + // Whether this function has been analyzed by escape analysis. If this is + // TRUE, this function type's parameters contain a summary of the analysis. + bool is_tagged_; }; // The type of a function's backend representation. @@ -2213,7 +2276,8 @@ class Struct_type : public Type public: Struct_type(Struct_field_list* fields, Location location) : Type(TYPE_STRUCT), - fields_(fields), location_(location), all_methods_(NULL) + fields_(fields), location_(location), all_methods_(NULL), + is_struct_incomparable_(false) { } // Return the field NAME. This only looks at local fields, not at @@ -2318,6 +2382,16 @@ class Struct_type : public Type static Type* make_struct_type_descriptor_type(); + // Return whether this is a generated struct that is not comparable. + bool + is_struct_incomparable() const + { return this->is_struct_incomparable_; } + + // Record that this is a generated struct that is not comparable. + void + set_is_struct_incomparable() + { this->is_struct_incomparable_ = true; } + // Write the hash function for this type. void write_hash_function(Gogo*, Named_type*, Function_type*, Function_type*); @@ -2326,6 +2400,16 @@ class Struct_type : public Type void write_equal_function(Gogo*, Named_type*); + // Whether we can write this type to a C header file, to implement + // -fgo-c-header. + bool + can_write_to_c_header(std::vector<const Named_object*>*, + std::vector<const Named_object*>*) const; + + // Write this type to a C header file, to implement -fgo-c-header. + void + write_to_c_header(std::ostream&) const; + protected: int do_traverse(Traverse*); @@ -2339,6 +2423,12 @@ class Struct_type : public Type bool do_compare_is_identity(Gogo*); + bool + do_is_reflexive(); + + bool + do_needs_key_update(); + unsigned int do_hash_for_method(Gogo*) const; @@ -2361,6 +2451,14 @@ class Struct_type : public Type do_export(Export*) const; private: + bool + can_write_type_to_c_header(const Type*, + std::vector<const Named_object*>*, + std::vector<const Named_object*>*) const; + + void + write_field_to_c_header(std::ostream&, const std::string&, const Type*) const; + // Used to merge method sets of identical unnamed structs. typedef Unordered_map_hash(Struct_type*, Struct_type*, Type_hash_identical, Type_identical) Identical_structs; @@ -2395,6 +2493,9 @@ class Struct_type : public Type Location location_; // If this struct is unnamed, a list of methods. Methods* all_methods_; + // True if this is a generated struct that is not considered to be + // comparable. + bool is_struct_incomparable_; }; // The type of an array. @@ -2405,7 +2506,7 @@ class Array_type : public Type Array_type(Type* element_type, Expression* length) : Type(TYPE_ARRAY), element_type_(element_type), length_(length), blength_(NULL), - issued_length_error_(false) + issued_length_error_(false), is_array_incomparable_(false) { } // Return the element type. @@ -2456,6 +2557,16 @@ class Array_type : public Type static Type* make_slice_type_descriptor_type(); + // Return whether this is a generated array that is not comparable. + bool + is_array_incomparable() const + { return this->is_array_incomparable_; } + + // Record that this is a generated array that is not comparable. + void + set_is_array_incomparable() + { this->is_array_incomparable_ = true; } + // Write the hash function for this type. void write_hash_function(Gogo*, Named_type*, Function_type*, Function_type*); @@ -2480,6 +2591,16 @@ class Array_type : public Type bool do_compare_is_identity(Gogo*); + bool + do_is_reflexive() + { + return this->length_ != NULL && this->element_type_->is_reflexive(); + } + + bool + do_needs_key_update() + { return this->element_type_->needs_key_update(); } + unsigned int do_hash_for_method(Gogo*) const; @@ -2527,6 +2648,9 @@ class Array_type : public Type // Whether or not an invalid length error has been issued for this type, // to avoid knock-on errors. mutable bool issued_length_error_; + // True if this is a generated array that is not considered to be + // comparable. + bool is_array_incomparable_; }; // The type of a map. @@ -2536,7 +2660,8 @@ class Map_type : public Type public: Map_type(Type* key_type, Type* val_type, Location location) : Type(TYPE_MAP), - key_type_(key_type), val_type_(val_type), location_(location) + key_type_(key_type), val_type_(val_type), hmap_type_(NULL), + bucket_type_(NULL), hiter_type_(NULL), location_(location) { } // Return the key type. @@ -2549,6 +2674,24 @@ class Map_type : public Type val_type() const { return this->val_type_; } + // Return the type used for an iteration over this map. + Type* + hiter_type(Gogo*); + + // If this map requires the "fat" functions, returns the pointer to + // pass as the zero value to those functions. Otherwise, in the + // normal case, returns NULL. + Expression* + fat_zero_value(Gogo*); + + // Return whether VAR is the map zero value. + static bool + is_zero_value(Variable* var); + + // Return the backend representation of the map zero value. + static Bvariable* + backend_zero_value(Gogo*); + // Whether this type is identical with T. bool is_identical(const Map_type* t, bool errors_are_identical) const; @@ -2560,15 +2703,6 @@ class Map_type : public Type static Type* make_map_type_descriptor_type(); - static Type* - make_map_descriptor_type(); - - // Build a map descriptor for this type. Return a pointer to it. - // The location is the location which causes us to need the - // descriptor. - Bexpression* - map_descriptor_pointer(Gogo* gogo, Location); - protected: int do_traverse(Traverse*); @@ -2584,6 +2718,12 @@ class Map_type : public Type do_compare_is_identity(Gogo*) { return false; } + bool + do_is_reflexive() + { + return this->key_type_->is_reflexive() && this->val_type_->is_reflexive(); + } + unsigned int do_hash_for_method(Gogo*) const; @@ -2606,18 +2746,41 @@ class Map_type : public Type do_export(Export*) const; private: - // Mapping from map types to map descriptors. - typedef Unordered_map_hash(const Map_type*, Bvariable*, Type_hash_identical, - Type_identical) Map_descriptors; - static Map_descriptors map_descriptors; + // These must be in sync with libgo/go/runtime/hashmap.go. + static const int bucket_size = 8; + static const int max_key_size = 128; + static const int max_val_size = 128; + static const int max_zero_size = 1024; + + // Maps with value types larger than max_zero_size require passing a + // zero value pointer to the map functions. + + // The zero value variable. + static Named_object* zero_value; + + // The current size of the zero value. + static int64_t zero_value_size; - Bvariable* - map_descriptor(Gogo*); + // The current alignment of the zero value. + static int64_t zero_value_align; + + Type* + bucket_type(Gogo*, int64_t, int64_t); + + Type* + hmap_type(Type*); // The key type. Type* key_type_; // The value type. Type* val_type_; + // The hashmap type. At run time a map is represented as a pointer + // to this type. + Type* hmap_type_; + // The bucket type, the type used to hold keys and values at run time. + Type* bucket_type_; + // The iterator type. + Type* hiter_type_; // Where the type was defined. Location location_; }; @@ -2660,6 +2823,9 @@ class Channel_type : public Type static Type* make_chan_type_descriptor_type(); + static Type* + select_type(int ncases); + protected: int do_traverse(Traverse* traverse) @@ -2809,6 +2975,17 @@ class Interface_type : public Type do_compare_is_identity(Gogo*) { return false; } + // Not reflexive if it contains a float. + bool + do_is_reflexive() + { return false; } + + // Distinction between +0 and -0 requires a key update if it + // contains a float. + bool + do_needs_key_update() + { return true; } + unsigned int do_hash_for_method(Gogo*) const; @@ -2887,10 +3064,10 @@ class Named_type : public Type type_(type), local_methods_(NULL), all_methods_(NULL), interface_method_tables_(NULL), pointer_interface_method_tables_(NULL), location_(location), named_btype_(NULL), dependencies_(), - is_visible_(true), is_error_(false), is_placeholder_(false), - is_converted_(false), is_circular_(false), is_verified_(false), - seen_(false), seen_in_compare_is_identity_(false), - seen_in_get_backend_(false) + is_alias_(false), is_visible_(true), is_error_(false), + is_placeholder_(false), is_converted_(false), is_circular_(false), + is_verified_(false), seen_(false), seen_in_compare_is_identity_(false), + seen_in_get_backend_(false), seen_alias_(false) { } // Return the associated Named_object. This holds the actual name. @@ -2908,6 +3085,17 @@ class Named_type : public Type set_named_object(Named_object* no) { this->named_object_ = no; } + // Whether this is an alias (type T1 = T2) rather than an ordinary + // named type (type T1 T2). + bool + is_alias() const + { return this->is_alias_; } + + // Record that this type is an alias. + void + set_is_alias() + { this->is_alias_ = true; } + // Return the function in which this type is defined. This will // return NULL for a type defined in global scope. const Named_object* @@ -2969,11 +3157,6 @@ class Named_type : public Type is_builtin() const { return Linemap::is_predeclared_location(this->location_); } - // Whether this is an alias. There are currently two aliases: byte - // and rune. - bool - is_alias() const; - // Whether this named type is valid. A recursive named type is invalid. bool is_valid() const @@ -3021,8 +3204,7 @@ class Named_type : public Type // Return the list of local methods. const Bindings* - local_methods() const - { return this->local_methods_; } + local_methods() const; // Build the complete list of methods, including those from // anonymous fields, and build method stubs if needed. @@ -3032,14 +3214,12 @@ class Named_type : public Type // Return whether this type has any methods. This should only be // called after the finalize_methods pass. bool - has_any_methods() const - { return this->all_methods_ != NULL; } + has_any_methods() const; // Return the methods for this type. This should only be called // after the finalized_methods pass. const Methods* - methods() const - { return this->all_methods_; } + methods() const; // Return the method to use for NAME. This returns NULL if there is // no such method or if the method is ambiguous. When it returns @@ -3072,6 +3252,16 @@ class Named_type : public Type is_named_backend_type_size_known() const { return this->named_btype_ != NULL && !this->is_placeholder_; } + // Add to the reflection string as for Type::append_reflection, but + // if USE_ALIAS use the alias name rather than the alias target. + void + append_reflection_type_name(Gogo*, bool use_alias, std::string*) const; + + // Append the mangled type name as for Type::append_mangled_name, + // but if USE_ALIAS use the alias name rather than the alias target. + void + append_mangled_type_name(Gogo*, bool use_alias, std::string*) const; + // Export the type. void export_named_type(Export*, const std::string& name) const; @@ -3098,6 +3288,12 @@ class Named_type : public Type bool do_compare_is_identity(Gogo*); + bool + do_is_reflexive(); + + bool + do_needs_key_update(); + unsigned int do_hash_for_method(Gogo*) const; @@ -3160,6 +3356,8 @@ class Named_type : public Type // where we can't convert S2 to the backend representation unless we // have converted S1. std::vector<Named_type*> dependencies_; + // Whether this is an alias type. + bool is_alias_; // 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 @@ -3187,6 +3385,8 @@ class Named_type : public Type bool seen_in_compare_is_identity_; // Like seen_, but used only by do_get_backend. bool seen_in_get_backend_; + // Like seen_, but used when resolving aliases. + mutable bool seen_alias_; }; // A forward declaration. This handles a type which has been declared @@ -3245,6 +3445,14 @@ class Forward_declaration_type : public Type do_compare_is_identity(Gogo* gogo) { return this->real_type()->compare_is_identity(gogo); } + bool + do_is_reflexive() + { return this->real_type()->is_reflexive(); } + + bool + do_needs_key_update() + { return this->real_type()->needs_key_update(); } + unsigned int do_hash_for_method(Gogo* gogo) const { return this->real_type()->hash_for_method(gogo); } |