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,
return false;
if (arg_type->is_abstract())
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_);
if (arg_type_tree == error_mark_node)
return false;
......@@ -7057,6 +7059,8 @@ Builtin_call_expression::do_integer_constant_value(bool iota_is_constant,
Type* st = struct_expr->type();
if (st->struct_type() == NULL)
return false;
if (st->named_type() != NULL)
st->named_type()->convert(this->gogo_);
tree struct_tree = st->get_tree(this->gogo_);
gcc_assert(TREE_CODE(struct_tree) == RECORD_TYPE);
tree field = TYPE_FIELDS(struct_tree);
......@@ -8793,10 +8797,21 @@ Call_expression::do_get_tree(Translate_context* context)
return error_mark_node;
}
// This is to support builtin math functions when using 80387 math.
tree fndecl = fn;
if (TREE_CODE(fndecl) == ADDR_EXPR)
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;
if (DECL_P(fndecl)
&& DECL_IS_BUILTIN(fndecl)
......@@ -8842,7 +8857,7 @@ Call_expression::do_get_tree(Translate_context* context)
// to the correct type.
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);
}
......
......@@ -118,9 +118,6 @@ go_parse_input_files(const char** filenames, unsigned int filename_count,
// Export global identifiers as appropriate.
::gogo->do_exports();
// Build required interface method tables.
::gogo->build_interface_method_tables();
// Turn short-cut operators (&&, ||) into explicit if statements.
::gogo->remove_shortcuts();
......
......@@ -640,6 +640,9 @@ sort_var_inits(Var_inits* var_inits)
void
Gogo::write_globals()
{
this->convert_named_types();
this->build_interface_method_tables();
Bindings* bindings = this->current_bindings();
size_t count = bindings->size_definitions();
......
......@@ -34,7 +34,8 @@ Gogo::Gogo(int int_type_size, int pointer_size)
imported_init_fns_(),
unique_prefix_(),
unique_prefix_specified_(false),
interface_types_()
interface_types_(),
named_types_are_converted_(false)
{
const source_location loc = BUILTINS_LOCATION;
......@@ -1119,11 +1120,6 @@ class Verify_types : public Traverse
int
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())
return TRAVERSE_SKIP_COMPONENTS;
return TRAVERSE_CONTINUE;
......@@ -2520,6 +2516,83 @@ Gogo::do_exports()
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.
Function::Function(Function_type* type, Function* enclosing, Block* block,
......
......@@ -405,6 +405,20 @@ class Gogo
void
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.
void
write_globals();
......@@ -661,6 +675,8 @@ class Gogo
bool unique_prefix_specified_;
// A list of interface types defined while parsing.
std::vector<Interface_type*> interface_types_;
// Whether named types have been converted.
bool named_types_are_converted_;
};
// A block of statements.
......
......@@ -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
......@@ -1992,25 +1990,12 @@ class Struct_type : public Type
source_location, Saw_named_type*,
unsigned int* depth) const;
static Type*
make_struct_type_descriptor_type();
// The fields of the struct.
Struct_field_list* fields_;
// The place where the struct was declared.
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.
......@@ -2066,6 +2051,12 @@ class Array_type : public Type
tree
fill_in_slice_tree(Gogo*, tree);
static Type*
make_array_type_descriptor_type();
static Type*
make_slice_type_descriptor_type();
protected:
int
do_traverse(Traverse* traverse);
......@@ -2114,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*);
......@@ -2162,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*);
......@@ -2202,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.
......@@ -2248,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)
......@@ -2286,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.
......@@ -2308,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
......@@ -2361,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*);
......@@ -2395,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_;
......@@ -2419,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.
......@@ -2493,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();
......@@ -2567,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;
......@@ -2575,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)
......@@ -2618,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,
......@@ -2647,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
......@@ -2654,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
......
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