Commit 91349ecb by Ian Lance Taylor

Rewrite conversion of named types to backend representation.

From-SVN: r170627
parent f63f8a3c
...@@ -7013,6 +7013,8 @@ Builtin_call_expression::do_integer_constant_value(bool iota_is_constant, ...@@ -7013,6 +7013,8 @@ Builtin_call_expression::do_integer_constant_value(bool iota_is_constant,
return false; return false;
if (arg_type->is_abstract()) if (arg_type->is_abstract())
return false; return false;
if (arg_type->named_type() != NULL)
arg_type->named_type()->convert(this->gogo_);
tree arg_type_tree = arg_type->get_tree(this->gogo_); tree arg_type_tree = arg_type->get_tree(this->gogo_);
if (arg_type_tree == error_mark_node) if (arg_type_tree == error_mark_node)
return false; return false;
...@@ -7057,6 +7059,8 @@ Builtin_call_expression::do_integer_constant_value(bool iota_is_constant, ...@@ -7057,6 +7059,8 @@ Builtin_call_expression::do_integer_constant_value(bool iota_is_constant,
Type* st = struct_expr->type(); Type* st = struct_expr->type();
if (st->struct_type() == NULL) if (st->struct_type() == NULL)
return false; return false;
if (st->named_type() != NULL)
st->named_type()->convert(this->gogo_);
tree struct_tree = st->get_tree(this->gogo_); tree struct_tree = st->get_tree(this->gogo_);
gcc_assert(TREE_CODE(struct_tree) == RECORD_TYPE); gcc_assert(TREE_CODE(struct_tree) == RECORD_TYPE);
tree field = TYPE_FIELDS(struct_tree); tree field = TYPE_FIELDS(struct_tree);
...@@ -8793,10 +8797,21 @@ Call_expression::do_get_tree(Translate_context* context) ...@@ -8793,10 +8797,21 @@ Call_expression::do_get_tree(Translate_context* context)
return error_mark_node; return error_mark_node;
} }
// This is to support builtin math functions when using 80387 math.
tree fndecl = fn; tree fndecl = fn;
if (TREE_CODE(fndecl) == ADDR_EXPR) if (TREE_CODE(fndecl) == ADDR_EXPR)
fndecl = TREE_OPERAND(fndecl, 0); fndecl = TREE_OPERAND(fndecl, 0);
// Add a type cast in case the type of the function is a recursive
// type which refers to itself.
if (!DECL_P(fndecl) || !DECL_IS_BUILTIN(fndecl))
{
tree fnt = fntype->get_tree(gogo);
if (fnt == error_mark_node)
return error_mark_node;
fn = fold_convert_loc(location, fnt, fn);
}
// This is to support builtin math functions when using 80387 math.
tree excess_type = NULL_TREE; tree excess_type = NULL_TREE;
if (DECL_P(fndecl) if (DECL_P(fndecl)
&& DECL_IS_BUILTIN(fndecl) && DECL_IS_BUILTIN(fndecl)
...@@ -8842,7 +8857,7 @@ Call_expression::do_get_tree(Translate_context* context) ...@@ -8842,7 +8857,7 @@ Call_expression::do_get_tree(Translate_context* context)
// to the correct type. // to the correct type.
if (TREE_TYPE(ret) == ptr_type_node) if (TREE_TYPE(ret) == ptr_type_node)
{ {
tree t = this->type()->get_tree(gogo); tree t = this->type()->base()->get_tree(gogo);
ret = fold_convert_loc(location, t, ret); ret = fold_convert_loc(location, t, ret);
} }
......
...@@ -118,9 +118,6 @@ go_parse_input_files(const char** filenames, unsigned int filename_count, ...@@ -118,9 +118,6 @@ go_parse_input_files(const char** filenames, unsigned int filename_count,
// Export global identifiers as appropriate. // Export global identifiers as appropriate.
::gogo->do_exports(); ::gogo->do_exports();
// Build required interface method tables.
::gogo->build_interface_method_tables();
// Turn short-cut operators (&&, ||) into explicit if statements. // Turn short-cut operators (&&, ||) into explicit if statements.
::gogo->remove_shortcuts(); ::gogo->remove_shortcuts();
......
...@@ -640,6 +640,9 @@ sort_var_inits(Var_inits* var_inits) ...@@ -640,6 +640,9 @@ sort_var_inits(Var_inits* var_inits)
void void
Gogo::write_globals() Gogo::write_globals()
{ {
this->convert_named_types();
this->build_interface_method_tables();
Bindings* bindings = this->current_bindings(); Bindings* bindings = this->current_bindings();
size_t count = bindings->size_definitions(); size_t count = bindings->size_definitions();
......
...@@ -34,7 +34,8 @@ Gogo::Gogo(int int_type_size, int pointer_size) ...@@ -34,7 +34,8 @@ Gogo::Gogo(int int_type_size, int pointer_size)
imported_init_fns_(), imported_init_fns_(),
unique_prefix_(), unique_prefix_(),
unique_prefix_specified_(false), unique_prefix_specified_(false),
interface_types_() interface_types_(),
named_types_are_converted_(false)
{ {
const source_location loc = BUILTINS_LOCATION; const source_location loc = BUILTINS_LOCATION;
...@@ -1119,11 +1120,6 @@ class Verify_types : public Traverse ...@@ -1119,11 +1120,6 @@ class Verify_types : public Traverse
int int
Verify_types::type(Type* t) Verify_types::type(Type* t)
{ {
// Don't verify types defined in other packages.
Named_type* nt = t->named_type();
if (nt != NULL && nt->named_object()->package() != NULL)
return TRAVERSE_SKIP_COMPONENTS;
if (!t->verify()) if (!t->verify())
return TRAVERSE_SKIP_COMPONENTS; return TRAVERSE_SKIP_COMPONENTS;
return TRAVERSE_CONTINUE; return TRAVERSE_CONTINUE;
...@@ -2520,6 +2516,83 @@ Gogo::do_exports() ...@@ -2520,6 +2516,83 @@ Gogo::do_exports()
this->package_->bindings()); this->package_->bindings());
} }
// Find the blocks in order to convert named types defined in blocks.
class Convert_named_types : public Traverse
{
public:
Convert_named_types(Gogo* gogo)
: Traverse(traverse_blocks),
gogo_(gogo)
{ }
protected:
int
block(Block* block);
private:
Gogo* gogo_;
};
int
Convert_named_types::block(Block* block)
{
this->gogo_->convert_named_types_in_bindings(block->bindings());
return TRAVERSE_CONTINUE;
}
// Convert all named types to the backend representation. Since named
// types can refer to other types, this needs to be done in the right
// sequence, which is handled by Named_type::convert. Here we arrange
// to call that for each named type.
void
Gogo::convert_named_types()
{
this->convert_named_types_in_bindings(this->globals_);
for (Packages::iterator p = this->packages_.begin();
p != this->packages_.end();
++p)
{
Package* package = p->second;
this->convert_named_types_in_bindings(package->bindings());
}
Convert_named_types cnt(this);
this->traverse(&cnt);
// Make all the builtin named types used for type descriptors, and
// then convert them. They will only be written out if they are
// needed.
Type::make_type_descriptor_type();
Type::make_type_descriptor_ptr_type();
Function_type::make_function_type_descriptor_type();
Pointer_type::make_pointer_type_descriptor_type();
Struct_type::make_struct_type_descriptor_type();
Array_type::make_array_type_descriptor_type();
Array_type::make_slice_type_descriptor_type();
Map_type::make_map_type_descriptor_type();
Channel_type::make_chan_type_descriptor_type();
Interface_type::make_interface_type_descriptor_type();
Type::convert_builtin_named_types(this);
this->named_types_are_converted_ = true;
}
// Convert all names types in a set of bindings.
void
Gogo::convert_named_types_in_bindings(Bindings* bindings)
{
for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
p != bindings->end_definitions();
++p)
{
if ((*p)->is_type())
(*p)->type_value()->convert(this);
}
}
// Class Function. // Class Function.
Function::Function(Function_type* type, Function* enclosing, Block* block, Function::Function(Function_type* type, Function* enclosing, Block* block,
......
...@@ -405,6 +405,20 @@ class Gogo ...@@ -405,6 +405,20 @@ class Gogo
void void
simplify_thunk_statements(); simplify_thunk_statements();
// Convert named types to the backend representation.
void
convert_named_types();
// Convert named types in a list of bindings.
void
convert_named_types_in_bindings(Bindings*);
// True if named types have been converted to the backend
// representation.
bool
named_types_are_converted() const
{ return this->named_types_are_converted_; }
// Write out the global values. // Write out the global values.
void void
write_globals(); write_globals();
...@@ -661,6 +675,8 @@ class Gogo ...@@ -661,6 +675,8 @@ class Gogo
bool unique_prefix_specified_; bool unique_prefix_specified_;
// A list of interface types defined while parsing. // A list of interface types defined while parsing.
std::vector<Interface_type*> interface_types_; std::vector<Interface_type*> interface_types_;
// Whether named types have been converted.
bool named_types_are_converted_;
}; };
// A block of statements. // A block of statements.
......
...@@ -799,6 +799,10 @@ class Type ...@@ -799,6 +799,10 @@ class Type
check_make_expression(Expression_list* args, source_location location) check_make_expression(Expression_list* args, source_location location)
{ return this->do_check_make_expression(args, 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. // Return a tree representing this type.
tree tree
get_tree(Gogo*); get_tree(Gogo*);
...@@ -1082,6 +1086,9 @@ class Type ...@@ -1082,6 +1086,9 @@ class Type
static Type_trees type_trees; static Type_trees type_trees;
// A list of builtin named types.
static std::vector<Named_type*> named_builtin_types;
// The type classification. // The type classification.
Type_classification classification_; Type_classification classification_;
// The tree representation of the type, once it has been determined. // The tree representation of the type, once it has been determined.
...@@ -1605,6 +1612,9 @@ class Function_type : public Type ...@@ -1605,6 +1612,9 @@ class Function_type : public Type
Function_type* Function_type*
copy_with_receiver(Type*) const; copy_with_receiver(Type*) const;
static Type*
make_function_type_descriptor_type();
protected: protected:
int int
do_traverse(Traverse*); do_traverse(Traverse*);
...@@ -1636,9 +1646,6 @@ class Function_type : public Type ...@@ -1636,9 +1646,6 @@ class Function_type : public Type
do_export(Export*) const; do_export(Export*) const;
private: private:
static Type*
make_function_type_descriptor_type();
Expression* Expression*
type_descriptor_params(Type*, const Typed_identifier*, type_descriptor_params(Type*, const Typed_identifier*,
const Typed_identifier_list*); const Typed_identifier_list*);
...@@ -1680,6 +1687,9 @@ class Pointer_type : public Type ...@@ -1680,6 +1687,9 @@ class Pointer_type : public Type
static Pointer_type* static Pointer_type*
do_import(Import*); do_import(Import*);
static Type*
make_pointer_type_descriptor_type();
protected: protected:
int int
do_traverse(Traverse*); do_traverse(Traverse*);
...@@ -1710,9 +1720,6 @@ class Pointer_type : public Type ...@@ -1710,9 +1720,6 @@ class Pointer_type : public Type
do_export(Export*) const; do_export(Export*) const;
private: private:
static Type*
make_pointer_type_descriptor_type();
// The type to which this type points. // The type to which this type points.
Type* to_type_; Type* to_type_;
}; };
...@@ -1841,8 +1848,7 @@ class Struct_type : public Type ...@@ -1841,8 +1848,7 @@ class Struct_type : public Type
public: public:
Struct_type(Struct_field_list* fields, source_location location) Struct_type(Struct_field_list* fields, source_location location)
: Type(TYPE_STRUCT), : Type(TYPE_STRUCT),
fields_(fields), location_(location), all_methods_(NULL), fields_(fields), location_(location), all_methods_(NULL)
prerequisites_()
{ } { }
// Return the field NAME. This only looks at local fields, not at // Return the field NAME. This only looks at local fields, not at
...@@ -1937,16 +1943,8 @@ class Struct_type : public Type ...@@ -1937,16 +1943,8 @@ class Struct_type : public Type
tree tree
fill_in_tree(Gogo*, tree); fill_in_tree(Gogo*, tree);
// Note that a struct must be converted to the backend static Type*
// representation before we convert this struct. make_struct_type_descriptor_type();
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*);
protected: protected:
int int
...@@ -1992,25 +1990,12 @@ class Struct_type : public Type ...@@ -1992,25 +1990,12 @@ class Struct_type : public Type
source_location, Saw_named_type*, source_location, Saw_named_type*,
unsigned int* depth) const; unsigned int* depth) const;
static Type*
make_struct_type_descriptor_type();
// The fields of the struct. // The fields of the struct.
Struct_field_list* fields_; Struct_field_list* fields_;
// The place where the struct was declared. // The place where the struct was declared.
source_location location_; source_location location_;
// If this struct is unnamed, a list of methods. // If this struct is unnamed, a list of methods.
Methods* all_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. // The type of an array.
...@@ -2066,6 +2051,12 @@ class Array_type : public Type ...@@ -2066,6 +2051,12 @@ class Array_type : public Type
tree tree
fill_in_slice_tree(Gogo*, tree); fill_in_slice_tree(Gogo*, tree);
static Type*
make_array_type_descriptor_type();
static Type*
make_slice_type_descriptor_type();
protected: protected:
int int
do_traverse(Traverse* traverse); do_traverse(Traverse* traverse);
...@@ -2114,12 +2105,6 @@ class Array_type : public Type ...@@ -2114,12 +2105,6 @@ class Array_type : public Type
tree tree
get_length_tree(Gogo*); get_length_tree(Gogo*);
Type*
make_array_type_descriptor_type();
Type*
make_slice_type_descriptor_type();
Expression* Expression*
array_type_descriptor(Gogo*, Named_type*); array_type_descriptor(Gogo*, Named_type*);
...@@ -2162,6 +2147,9 @@ class Map_type : public Type ...@@ -2162,6 +2147,9 @@ class Map_type : public Type
static Map_type* static Map_type*
do_import(Import*); do_import(Import*);
static Type*
make_map_type_descriptor_type();
protected: protected:
int int
do_traverse(Traverse*); do_traverse(Traverse*);
...@@ -2202,9 +2190,6 @@ class Map_type : public Type ...@@ -2202,9 +2190,6 @@ class Map_type : public Type
do_export(Export*) const; do_export(Export*) const;
private: private:
static Type*
make_map_type_descriptor_type();
// The key type. // The key type.
Type* key_type_; Type* key_type_;
// The value type. // The value type.
...@@ -2248,6 +2233,9 @@ class Channel_type : public Type ...@@ -2248,6 +2233,9 @@ class Channel_type : public Type
static Channel_type* static Channel_type*
do_import(Import*); do_import(Import*);
static Type*
make_chan_type_descriptor_type();
protected: protected:
int int
do_traverse(Traverse* traverse) do_traverse(Traverse* traverse)
...@@ -2286,9 +2274,6 @@ class Channel_type : public Type ...@@ -2286,9 +2274,6 @@ class Channel_type : public Type
do_export(Export*) const; do_export(Export*) const;
private: private:
static Type*
make_chan_type_descriptor_type();
// Whether this channel can send data. // Whether this channel can send data.
bool may_send_; bool may_send_;
// Whether this channel can receive data. // Whether this channel can receive data.
...@@ -2308,6 +2293,11 @@ class Interface_type : public Type ...@@ -2308,6 +2293,11 @@ class Interface_type : public Type
methods_(methods), location_(location) methods_(methods), location_(location)
{ gcc_assert(methods == NULL || !methods->empty()); } { 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. // Return whether this is an empty interface.
bool bool
is_empty() const is_empty() const
...@@ -2361,10 +2351,21 @@ class Interface_type : public Type ...@@ -2361,10 +2351,21 @@ class Interface_type : public Type
static Interface_type* static Interface_type*
do_import(Import*); 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. // Fill in the fields for a named interface type.
tree tree
fill_in_tree(Gogo*, tree); fill_in_tree(Gogo*, tree);
static Type*
make_interface_type_descriptor_type();
protected: protected:
int int
do_traverse(Traverse*); do_traverse(Traverse*);
...@@ -2395,9 +2396,6 @@ class Interface_type : public Type ...@@ -2395,9 +2396,6 @@ class Interface_type : public Type
do_export(Export*) const; do_export(Export*) const;
private: private:
static Type*
make_interface_type_descriptor_type();
// The list of methods associated with the interface. This will be // The list of methods associated with the interface. This will be
// NULL for the empty interface. // NULL for the empty interface.
Typed_identifier_list* methods_; Typed_identifier_list* methods_;
...@@ -2419,8 +2417,9 @@ class Named_type : public Type ...@@ -2419,8 +2417,9 @@ class Named_type : public Type
named_object_(named_object), in_function_(NULL), type_(type), named_object_(named_object), in_function_(NULL), type_(type),
local_methods_(NULL), all_methods_(NULL), local_methods_(NULL), all_methods_(NULL),
interface_method_tables_(NULL), pointer_interface_method_tables_(NULL), interface_method_tables_(NULL), pointer_interface_method_tables_(NULL),
location_(location), named_tree_(NULL), is_visible_(true), location_(location), named_tree_(NULL), dependencies_(),
is_error_(false), seen_(0) is_visible_(true), is_error_(false), is_converted_(false),
is_circular_(false), seen_(0)
{ } { }
// Return the associated Named_object. This holds the actual name. // Return the associated Named_object. This holds the actual name.
...@@ -2493,6 +2492,12 @@ class Named_type : public Type ...@@ -2493,6 +2492,12 @@ class Named_type : public Type
is_builtin() const is_builtin() const
{ return this->location_ == BUILTINS_LOCATION; } { 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. // Return the base type for this type.
Type* Type*
named_base(); named_base();
...@@ -2567,6 +2572,12 @@ class Named_type : public Type ...@@ -2567,6 +2572,12 @@ class Named_type : public Type
bool bool
named_type_has_hidden_fields(std::string* reason) const; 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. // Export the type.
void void
export_named_type(Export*, const std::string& name) const; export_named_type(Export*, const std::string& name) const;
...@@ -2575,6 +2586,10 @@ class Named_type : public Type ...@@ -2575,6 +2586,10 @@ class Named_type : public Type
static void static void
import_named_type(Import*, Named_type**); import_named_type(Import*, Named_type**);
// Initial conversion to backend representation.
void
convert(Gogo*);
protected: protected:
int int
do_traverse(Traverse* traverse) do_traverse(Traverse* traverse)
...@@ -2618,6 +2633,10 @@ class Named_type : public Type ...@@ -2618,6 +2633,10 @@ class Named_type : public Type
do_export(Export*) const; do_export(Export*) const;
private: private:
// Create the placeholder during conversion.
void
create_placeholder(Gogo*);
// A mapping from interfaces to the associated interface method // A mapping from interfaces to the associated interface method
// tables for this type. This maps to a decl. // tables for this type. This maps to a decl.
typedef Unordered_map_hash(const Interface_type*, tree, Type_hash_identical, typedef Unordered_map_hash(const Interface_type*, tree, Type_hash_identical,
...@@ -2647,6 +2666,14 @@ class Named_type : public Type ...@@ -2647,6 +2666,14 @@ class Named_type : public Type
// The tree for this type while converting to GENERIC. This is used // The tree for this type while converting to GENERIC. This is used
// to avoid endless recursion when a named type refers to itself. // to avoid endless recursion when a named type refers to itself.
tree named_tree_; 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 // Whether this type is visible. This is false if this type was
// created because it was referenced by an imported object, but the // created because it was referenced by an imported object, but the
// type itself was not exported. This will always be true for types // type itself was not exported. This will always be true for types
...@@ -2654,6 +2681,12 @@ class Named_type : public Type ...@@ -2654,6 +2681,12 @@ class Named_type : public Type
bool is_visible_; bool is_visible_;
// Whether this type is erroneous. // Whether this type is erroneous.
bool is_error_; 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 // In a recursive operation such as has_hidden_fields, this flag is
// used to prevent infinite recursion when a type refers to itself. // used to prevent infinite recursion when a type refers to itself.
// This is mutable because it is always reset to false when the // This is mutable because it is always reset to false when the
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment