Commit 7fc2f86b by Ian Lance Taylor Committed by Ian Lance Taylor

Use backend interface for named types and array types.

	* go-gcc.cc (Gcc_backend::struct_type): Call fill_in_struct.
	(Gcc_backend::fill_in_struct): New function.
	(Gcc_backend::array_type): Implement.
	(Gcc_backend::fill_in_array): New function.
	(Gcc_backend::placeholder_pointer_type): New function.
	(Gcc_backend::set_placeholder_pointer_type): New function.
	(Gcc_backend::set_placeholder_function_type): New function.
	(Gcc_backend::placeholder_struct_type): New function.
	(Gcc_backend::set_placeholder_struct_type): New function.
	(Gcc_backend::placeholder_array_type): New function.
	(Gcc_backend::set_placeholder_array_type): New function.
	(Gcc_backend::named_type): New function.
	(Gcc_backend::circular_pointer_type): New function.
	(Gcc_backend::is_circular_pointer_type): New function.

From-SVN: r173380
parent f81b1a3d
2011-05-04 Ian Lance Taylor <iant@google.com>
* go-gcc.cc (Gcc_backend::struct_type): Call fill_in_struct.
(Gcc_backend::fill_in_struct): New function.
(Gcc_backend::array_type): Implement.
(Gcc_backend::fill_in_array): New function.
(Gcc_backend::placeholder_pointer_type): New function.
(Gcc_backend::set_placeholder_pointer_type): New function.
(Gcc_backend::set_placeholder_function_type): New function.
(Gcc_backend::placeholder_struct_type): New function.
(Gcc_backend::set_placeholder_struct_type): New function.
(Gcc_backend::placeholder_array_type): New function.
(Gcc_backend::set_placeholder_array_type): New function.
(Gcc_backend::named_type): New function.
(Gcc_backend::circular_pointer_type): New function.
(Gcc_backend::is_circular_pointer_type): New function.
2011-04-26 Ian Lance Taylor <iant@google.com>
* go-gcc.cc (Gcc_backend::struct_type): Implement.
......
......@@ -161,8 +161,38 @@ class Gcc_backend : public Backend
struct_type(const std::vector<Btyped_identifier>&);
Btype*
array_type(const Btype* /* element_type */, const Bexpression* /* length */)
{ gcc_unreachable(); }
array_type(Btype*, Bexpression*);
Btype*
placeholder_pointer_type(const std::string&, source_location, bool);
bool
set_placeholder_pointer_type(Btype*, Btype*);
bool
set_placeholder_function_type(Btype*, Btype*);
Btype*
placeholder_struct_type(const std::string&, source_location);
bool
set_placeholder_struct_type(Btype* placeholder,
const std::vector<Btyped_identifier>&);
Btype*
placeholder_array_type(const std::string&, source_location);
bool
set_placeholder_array_type(Btype*, Btype*, Bexpression*);
Btype*
named_type(const std::string&, Btype*, source_location);
Btype*
circular_pointer_type(Btype*, bool);
bool
is_circular_pointer_type(Btype*);
// Statements.
......@@ -270,6 +300,12 @@ class Gcc_backend : public Backend
Btype*
make_type(tree t)
{ return new Btype(t); }
Btype*
fill_in_struct(Btype*, const std::vector<Btyped_identifier>&);
Btype*
fill_in_array(Btype*, Btype*, Bexpression*);
};
// A helper function.
......@@ -453,7 +489,16 @@ Gcc_backend::function_type(const Btyped_identifier& receiver,
Btype*
Gcc_backend::struct_type(const std::vector<Btyped_identifier>& fields)
{
tree ret = make_node(RECORD_TYPE);
return this->fill_in_struct(this->make_type(make_node(RECORD_TYPE)), fields);
}
// Fill in the fields of a struct type.
Btype*
Gcc_backend::fill_in_struct(Btype* fill,
const std::vector<Btyped_identifier>& fields)
{
tree fill_tree = fill->get_tree();
tree field_trees = NULL_TREE;
tree* pp = &field_trees;
for (std::vector<Btyped_identifier>::const_iterator p = fields.begin();
......@@ -465,15 +510,192 @@ Gcc_backend::struct_type(const std::vector<Btyped_identifier>& fields)
if (type_tree == error_mark_node)
return this->error_type();
tree field = build_decl(p->location, FIELD_DECL, name_tree, type_tree);
DECL_CONTEXT(field) = ret;
DECL_CONTEXT(field) = fill_tree;
*pp = field;
pp = &DECL_CHAIN(field);
}
TYPE_FIELDS(ret) = field_trees;
layout_type(ret);
TYPE_FIELDS(fill_tree) = field_trees;
layout_type(fill_tree);
return fill;
}
// Make an array type.
Btype*
Gcc_backend::array_type(Btype* element_btype, Bexpression* length)
{
return this->fill_in_array(this->make_type(make_node(ARRAY_TYPE)),
element_btype, length);
}
// Fill in an array type.
Btype*
Gcc_backend::fill_in_array(Btype* fill, Btype* element_type,
Bexpression* length)
{
tree element_type_tree = element_type->get_tree();
tree length_tree = length->get_tree();
if (element_type_tree == error_mark_node || length_tree == error_mark_node)
return this->error_type();
gcc_assert(TYPE_SIZE(element_type_tree) != NULL_TREE);
length_tree = fold_convert(sizetype, length_tree);
// build_index_type takes the maximum index, which is one less than
// the length.
tree index_type_tree = build_index_type(fold_build2(MINUS_EXPR, sizetype,
length_tree,
size_one_node));
tree fill_tree = fill->get_tree();
TREE_TYPE(fill_tree) = element_type_tree;
TYPE_DOMAIN(fill_tree) = index_type_tree;
TYPE_ADDR_SPACE(fill_tree) = TYPE_ADDR_SPACE(element_type_tree);
layout_type(fill_tree);
if (TYPE_STRUCTURAL_EQUALITY_P(element_type_tree))
SET_TYPE_STRUCTURAL_EQUALITY(fill_tree);
else if (TYPE_CANONICAL(element_type_tree) != element_type_tree
|| TYPE_CANONICAL(index_type_tree) != index_type_tree)
TYPE_CANONICAL(fill_tree) =
build_array_type(TYPE_CANONICAL(element_type_tree),
TYPE_CANONICAL(index_type_tree));
return fill;
}
// Create a placeholder for a pointer type.
Btype*
Gcc_backend::placeholder_pointer_type(const std::string& name,
source_location location, bool)
{
tree ret = build_variant_type_copy(ptr_type_node);
tree decl = build_decl(location, TYPE_DECL,
get_identifier_from_string(name),
ret);
TYPE_NAME(ret) = decl;
return this->make_type(ret);
}
// Set the real target type for a placeholder pointer type.
bool
Gcc_backend::set_placeholder_pointer_type(Btype* placeholder,
Btype* to_type)
{
tree pt = placeholder->get_tree();
if (pt == error_mark_node)
return false;
gcc_assert(TREE_CODE(pt) == POINTER_TYPE);
tree tt = to_type->get_tree();
if (tt == error_mark_node)
{
TREE_TYPE(pt) = tt;
return false;
}
gcc_assert(TREE_CODE(tt) == POINTER_TYPE);
TREE_TYPE(pt) = TREE_TYPE(tt);
return true;
}
// Set the real values for a placeholder function type.
bool
Gcc_backend::set_placeholder_function_type(Btype* placeholder, Btype* ft)
{
return this->set_placeholder_pointer_type(placeholder, ft);
}
// Create a placeholder for a struct type.
Btype*
Gcc_backend::placeholder_struct_type(const std::string& name,
source_location location)
{
tree ret = make_node(RECORD_TYPE);
tree decl = build_decl(location, TYPE_DECL,
get_identifier_from_string(name),
ret);
TYPE_NAME(ret) = decl;
return this->make_type(ret);
}
// Fill in the fields of a placeholder struct type.
bool
Gcc_backend::set_placeholder_struct_type(
Btype* placeholder,
const std::vector<Btyped_identifier>& fields)
{
tree t = placeholder->get_tree();
gcc_assert(TREE_CODE(t) == RECORD_TYPE && TYPE_FIELDS(t) == NULL_TREE);
Btype* r = this->fill_in_struct(placeholder, fields);
return r->get_tree() != error_mark_node;
}
// Create a placeholder for an array type.
Btype*
Gcc_backend::placeholder_array_type(const std::string& name,
source_location location)
{
tree ret = make_node(ARRAY_TYPE);
tree decl = build_decl(location, TYPE_DECL,
get_identifier_from_string(name),
ret);
TYPE_NAME(ret) = decl;
return this->make_type(ret);
}
// Fill in the fields of a placeholder array type.
bool
Gcc_backend::set_placeholder_array_type(Btype* placeholder,
Btype* element_btype,
Bexpression* length)
{
tree t = placeholder->get_tree();
gcc_assert(TREE_CODE(t) == ARRAY_TYPE && TREE_TYPE(t) == NULL_TREE);
Btype* r = this->fill_in_array(placeholder, element_btype, length);
return r->get_tree() != error_mark_node;
}
// Return a named version of a type.
Btype*
Gcc_backend::named_type(const std::string& name, Btype* btype,
source_location location)
{
tree type = btype->get_tree();
if (type == error_mark_node)
return this->error_type();
type = build_variant_type_copy(type);
tree decl = build_decl(location, TYPE_DECL,
get_identifier_from_string(name),
type);
TYPE_NAME(type) = decl;
return this->make_type(type);
}
// Return a pointer type used as a marker for a circular type.
Btype*
Gcc_backend::circular_pointer_type(Btype*, bool)
{
return this->make_type(ptr_type_node);
}
// Return whether we might be looking at a circular type.
bool
Gcc_backend::is_circular_pointer_type(Btype* btype)
{
return btype->get_tree() == ptr_type_node;
}
// An expression as a statement.
Bstatement*
......
......@@ -108,7 +108,93 @@ class Backend
// Get an array type.
virtual Btype*
array_type(const Btype* element_type, const Bexpression* length) = 0;
array_type(Btype* element_type, Bexpression* length) = 0;
// Create a placeholder pointer type. This is used for a named
// pointer type, since in Go a pointer type may refer to itself.
// NAME is the name of the type, and the location is where the named
// type is defined. FOR_FUNCTION is true if this is for a Go
// function type, which corresponds to a C/C++ pointer to function
// type. The return value will later be passed as the first
// parameter to set_placeholder_pointer_type or
// set_placeholder_function_type.
virtual Btype*
placeholder_pointer_type(const std::string& name, source_location,
bool for_function) = 0;
// Fill in a placeholder pointer type as a pointer. This takes a
// type returned by placeholder_pointer_type and arranges for it to
// point to to_type. Returns true on success, false on failure.
virtual bool
set_placeholder_pointer_type(Btype* placeholder, Btype* to_type) = 0;
// Fill in a placeholder pointer type as a function. This takes a
// type returned by placeholder_pointer_type and arranges for it to
// become a real Go function type (which corresponds to a C/C++
// pointer to function type). FT will be something returned by the
// function_type method. Returns true on success, false on failure.
virtual bool
set_placeholder_function_type(Btype* placeholder, Btype* ft) = 0;
// Create a placeholder struct type. This is used for a named
// struct type, as with placeholder_pointer_type.
virtual Btype*
placeholder_struct_type(const std::string& name, source_location) = 0;
// Fill in a placeholder struct type. This takes a type returned by
// placeholder_struct_type and arranges for it to become a real
// struct type. The parameter is as for struct_type. Returns true
// on success, false on failure.
virtual bool
set_placeholder_struct_type(Btype* placeholder,
const std::vector<Btyped_identifier>& fields)
= 0;
// Create a placeholder array type. This is used for a named array
// type, as with placeholder_pointer_type, to handle cases like
// type A []*A.
virtual Btype*
placeholder_array_type(const std::string& name, source_location) = 0;
// Fill in a placeholder array type. This takes a type returned by
// placeholder_array_type and arranges for it to become a real array
// type. The parameters are as for array_type. Returns true on
// success, false on failure.
virtual bool
set_placeholder_array_type(Btype* placeholder, Btype* element_type,
Bexpression* length) = 0;
// Return a named version of a type. The location is the location
// of the type definition. This will not be called for a type
// created via placeholder_pointer_type, placeholder_struct_type, or
// placeholder_array_type.. (It may be called for a pointer,
// struct, or array type in a case like "type P *byte; type Q P".)
virtual Btype*
named_type(const std::string& name, Btype*, source_location) = 0;
// Create a marker for a circular pointer type. Go pointer and
// function types can refer to themselves in ways that are not
// permitted in C/C++. When a circular type is found, this function
// is called for the circular reference. This permits the backend
// to decide how to handle such a type. PLACEHOLDER is the
// placeholder type which has already been created; if the backend
// is prepared to handle a circular pointer type, it may simply
// return PLACEHOLDER. FOR_FUNCTION is true if this is for a
// function type.
//
// For "type P *P" the sequence of calls will be
// bt1 = placeholder_pointer_type();
// bt2 = circular_pointer_type(bt1, false);
// set_placeholder_pointer_type(bt1, bt2);
virtual Btype*
circular_pointer_type(Btype* placeholder, bool for_function) = 0;
// Return whether the argument could be a special type created by
// circular_pointer_type. This is used to introduce explicit type
// conversions where needed. If circular_pointer_type returns its
// PLACEHOLDER parameter, this may safely always return false.
virtual bool
is_circular_pointer_type(Btype*) = 0;
// Statements.
......
......@@ -42,6 +42,8 @@ class Function;
class Translate_context;
class Export;
class Import;
class Btype;
class Bexpression;
// Type codes used in type descriptors. These must match the values
// in libgo/runtime/go-type.h. They also match the values in the gc
......@@ -973,10 +975,11 @@ class Type
static unsigned int
hash_string(const std::string&, unsigned int);
// Return a tree for the underlying type of a named type.
static tree
get_named_type_tree(Gogo* gogo, Type* base_type)
{ return base_type->get_tree_without_hash(gogo); }
// Return the backend representation for the underlying type of a
// named type.
static Btype*
get_named_base_btype(Gogo* gogo, Type* base_type)
{ return base_type->get_btype_without_hash(gogo); }
private:
// Convert to the desired type classification, or return NULL. This
......@@ -1100,6 +1103,11 @@ class Type
tree
get_tree_without_hash(Gogo*);
// Get the backend representation for a type without looking in the
// hash table for identical types.
Btype*
get_btype_without_hash(Gogo*);
// A mapping from Type to tree, used to ensure that the GIMPLE
// representation of identical types is identical.
typedef Unordered_map_hash(const Type*, tree, Type_hash_identical,
......@@ -1952,10 +1960,6 @@ class Struct_type : public Type
static Struct_type*
do_import(Import*);
// Fill in the fields for a named struct type.
tree
fill_in_tree(Gogo*, tree);
static Type*
make_struct_type_descriptor_type();
......@@ -2056,9 +2060,13 @@ class Array_type : public Type
static Array_type*
do_import(Import*);
// Fill in the fields for a named array type.
tree
fill_in_array_tree(Gogo*, tree);
// Return the backend representation of the element type.
Btype*
get_backend_element(Gogo*);
// Return the backend representation of the length.
Bexpression*
get_backend_length(Gogo*);
// Fill in the fields for a named slice type.
tree
......@@ -2430,7 +2438,7 @@ 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), dependencies_(),
location_(location), named_btype_(NULL), dependencies_(),
is_visible_(true), is_error_(false), is_converted_(false),
is_circular_(false), seen_(0)
{ }
......@@ -2676,9 +2684,10 @@ class Named_type : public Type
Interface_method_tables* pointer_interface_method_tables_;
// The location where this type was defined.
source_location location_;
// 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_;
// The backend representation of this type during backend
// conversion. This is used to avoid endless recursion when a named
// type refers to itself.
Btype* named_btype_;
// A list of types which must be converted to the backend
// representation before this type can be converted. This is for
// cases like
......
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