summaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/types.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/go/gofrontend/types.h')
-rw-r--r--gcc/go/gofrontend/types.h346
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); }