Use backend interface for function types.

Drop type_tree() functions for Float_type and Complex_type.
Don't define builtin functions until gogo is created.

	* go-gcc.cc (Gcc_backend::error_type): Implement.
	(Gcc_backend::string_type): Remove.
	(Gcc_backend::function_type): Change signature and implement.
	(Gcc_backend::struct_type): Change signature.
	(Gcc_backend::slice_type, Gcc_backend::map_type): Remove.
	(Gcc_backend::channel_type, Gcc_backend::interface_type): Remove.
	(Gcc_backend::pointer_type): Check for error.
	* Make-lang.in (go/types.o): Depend on go/gofrontend/backend.h.

From-SVN: r172932
This commit is contained in:
Ian Lance Taylor 2011-04-25 17:21:28 +00:00 committed by Ian Lance Taylor
parent 0aa5e7f22a
commit 482829acf2
10 changed files with 178 additions and 172 deletions

View File

@ -1,3 +1,14 @@
2011-04-25 Ian Lance Taylor <iant@google.com>
* go-gcc.cc (Gcc_backend::error_type): Implement.
(Gcc_backend::string_type): Remove.
(Gcc_backend::function_type): Change signature and implement.
(Gcc_backend::struct_type): Change signature.
(Gcc_backend::slice_type, Gcc_backend::map_type): Remove.
(Gcc_backend::channel_type, Gcc_backend::interface_type): Remove.
(Gcc_backend::pointer_type): Check for error.
* Make-lang.in (go/types.o): Depend on go/gofrontend/backend.h.
2011-04-25 Evan Shaw <edsrzf@gmail.com>
* go-gcc.c (class Gcc_tree): Make get_tree const.

View File

@ -287,6 +287,7 @@ go/statements.o: go/gofrontend/statements.cc $(GO_SYSTEM_H) \
go/types.o: go/gofrontend/types.cc $(GO_SYSTEM_H) $(TOPLEV_H) intl.h $(TREE_H) \
$(GIMPLE_H) $(REAL_H) convert.h $(GO_C_H) $(GO_GOGO_H) \
go/gofrontend/operator.h $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) \
go/gofrontend/export.h $(GO_IMPORT_H) $(GO_TYPES_H)
go/gofrontend/export.h $(GO_IMPORT_H) go/gofrontend/backend.h \
$(GO_TYPES_H)
go/unsafe.o: go/gofrontend/unsafe.cc $(GO_SYSTEM_H) $(GO_C_H) $(GO_TYPES_H) \
$(GO_GOGO_H)

View File

@ -129,7 +129,7 @@ class Gcc_backend : public Backend
Btype*
error_type()
{ gcc_unreachable(); }
{ return this->make_type(error_mark_node); }
Btype*
void_type()
@ -149,43 +149,22 @@ class Gcc_backend : public Backend
complex_type(int);
Btype*
string_type()
{ gcc_unreachable(); }
pointer_type(Btype*);
Btype*
pointer_type(const Btype*);
function_type(const Btyped_identifier&,
const std::vector<Btyped_identifier>&,
const std::vector<Btyped_identifier>&,
source_location);
Btype*
function_type(const Function_type*, Btype* /* receiver */,
const Btypes* /* parameters */,
const Btypes* /* results */)
{ gcc_unreachable(); }
Btype*
struct_type(const Struct_type*, const Btypes* /* field_types */)
struct_type(const std::vector<Btyped_identifier>&)
{ gcc_unreachable(); }
Btype*
array_type(const Btype* /* element_type */, const Bexpression* /* length */)
{ gcc_unreachable(); }
Btype*
slice_type(const Btype* /* element_type */)
{ gcc_unreachable(); }
Btype*
map_type(const Btype* /* key_type */, const Btype* /* value_type */,
source_location)
{ gcc_unreachable(); }
Btype*
channel_type(const Btype* /* element_type */)
{ gcc_unreachable(); }
Btype*
interface_type(const Interface_type*, const Btypes* /* method_types */)
{ gcc_unreachable(); }
// Statements.
Bstatement*
@ -387,12 +366,89 @@ Gcc_backend::complex_type(int bits)
// Get a pointer type.
Btype*
Gcc_backend::pointer_type(const Btype* to_type)
Gcc_backend::pointer_type(Btype* to_type)
{
tree type = build_pointer_type(to_type->get_tree());
tree to_type_tree = to_type->get_tree();
if (to_type_tree == error_mark_node)
return this->error_type();
tree type = build_pointer_type(to_type_tree);
return this->make_type(type);
}
// Make a function type.
Btype*
Gcc_backend::function_type(const Btyped_identifier& receiver,
const std::vector<Btyped_identifier>& parameters,
const std::vector<Btyped_identifier>& results,
source_location location)
{
tree args = NULL_TREE;
tree* pp = &args;
if (receiver.btype != NULL)
{
tree t = receiver.btype->get_tree();
if (t == error_mark_node)
return this->error_type();
*pp = tree_cons(NULL_TREE, t, NULL_TREE);
pp = &TREE_CHAIN(*pp);
}
for (std::vector<Btyped_identifier>::const_iterator p = parameters.begin();
p != parameters.end();
++p)
{
tree t = p->btype->get_tree();
if (t == error_mark_node)
return this->error_type();
*pp = tree_cons(NULL_TREE, t, NULL_TREE);
pp = &TREE_CHAIN(*pp);
}
// Varargs is handled entirely at the Go level. When converted to
// GENERIC functions are not varargs.
*pp = void_list_node;
tree result;
if (results.empty())
result = void_type_node;
else if (results.size() == 1)
result = results.front().btype->get_tree();
else
{
result = make_node(RECORD_TYPE);
tree field_trees = NULL_TREE;
pp = &field_trees;
for (std::vector<Btyped_identifier>::const_iterator p = results.begin();
p != results.end();
++p)
{
const std::string name = (p->name.empty()
? "UNNAMED"
: p->name);
tree name_tree = get_identifier_from_string(name);
tree field_type_tree = p->btype->get_tree();
if (field_type_tree == error_mark_node)
return this->error_type();
tree field = build_decl(location, FIELD_DECL, name_tree,
field_type_tree);
DECL_CONTEXT(field) = result;
*pp = field;
pp = &DECL_CHAIN(field);
}
TYPE_FIELDS(result) = field_trees;
layout_type(result);
}
if (result == error_mark_node)
return this->error_type();
tree fntype = build_function_type(result, args);
if (fntype == error_mark_node)
return this->error_type();
return this->make_type(build_pointer_type(fntype));
}
// An expression as a statement.
Bstatement*

View File

@ -7,10 +7,6 @@
#ifndef GO_BACKEND_H
#define GO_BACKEND_H
class Function_type;
class Struct_type;
class Interface_type;
// Pointers to these types are created by the backend, passed to the
// frontend, and passed back to the backend. The types must be
// defined by the backend using these names.
@ -36,9 +32,6 @@ class Bvariable;
// The backend representation of a label.
class Blabel;
// A list of backend types.
typedef std::vector<Btype*> Btypes;
// The backend interface. This is a pure abstract class that a
// specific backend will implement.
@ -47,6 +40,24 @@ class Backend
public:
virtual ~Backend() { }
// Name/type/location. Used for function parameters, struct fields,
// interface methods.
struct Btyped_identifier
{
std::string name;
Btype* btype;
source_location location;
Btyped_identifier()
: name(), btype(NULL), location(UNKNOWN_LOCATION)
{ }
Btyped_identifier(const std::string& a_name, Btype* a_btype,
source_location a_location)
: name(a_name), btype(a_btype), location(a_location)
{ }
};
// Types.
// Produce an error type. Actually the backend could probably just
@ -69,56 +80,36 @@ class Backend
virtual Btype*
integer_type(bool is_unsigned, int bits) = 0;
// Get an unnamed floating point type with the given number of bits.
// Get an unnamed floating point type with the given number of bits
// (32 or 64).
virtual Btype*
float_type(int bits) = 0;
// Get an unnamed complex type with the given number of bits.
// Get an unnamed complex type with the given number of bits (64 or 128).
virtual Btype*
complex_type(int bits) = 0;
// Get the unnamed string type.
virtual Btype*
string_type() = 0;
// Get a pointer type.
virtual Btype*
pointer_type(const Btype* to_type) = 0;
pointer_type(Btype* to_type) = 0;
// Get a function type. The receiver, parameter, and results are
// generated from the types in the Function_type. The Function_type
// is provided so that the names are available.
virtual Btype*
function_type(const Function_type*, Btype* receiver,
const Btypes* parameters,
const Btypes* results) = 0;
function_type(const Btyped_identifier& receiver,
const std::vector<Btyped_identifier>& parameters,
const std::vector<Btyped_identifier>& results,
source_location location) = 0;
// Get a struct type. The Struct_type is provided to get the field
// names.
// Get a struct type.
virtual Btype*
struct_type(const Struct_type*, const Btypes* field_types) = 0;
struct_type(const std::vector<Btyped_identifier>& fields) = 0;
// Get an array type.
virtual Btype*
array_type(const Btype* element_type, const Bexpression* length) = 0;
// Get a slice type.
virtual Btype*
slice_type(const Btype* element_type) = 0;
// Get a map type.
virtual Btype*
map_type(const Btype* key_type, const Btype* value_type, source_location) = 0;
// Get a channel type.
virtual Btype*
channel_type(const Btype* element_type) = 0;
// Get an interface type. The Interface_type is provided to get the
// method names.
virtual Btype*
interface_type(const Interface_type*, const Btypes* method_types) = 0;
// Statements.
// Create an error statement. This is used for cases which should

View File

@ -31,6 +31,9 @@ go_create_gogo(int int_type_size, int pointer_size)
::gogo = new Gogo(go_get_backend(), int_type_size, pointer_size);
if (!unique_prefix.empty())
::gogo->set_unique_prefix(unique_prefix);
// FIXME: This should be in the gcc dependent code.
::gogo->define_builtin_function_trees();
}
// Set the unique prefix we use for exported symbols.

View File

@ -1743,7 +1743,7 @@ go_type_for_mode(enum machine_mode mode, int unsignedp)
return long_double_type_node;
return NULL_TREE;
}
return type->float_type()->type_tree();
return type->get_tree(go_get_gogo());
}
else if (mc == MODE_COMPLEX_FLOAT)
{
@ -1763,7 +1763,7 @@ go_type_for_mode(enum machine_mode mode, int unsignedp)
return complex_long_double_type_node;
return NULL_TREE;
}
return type->complex_type()->type_tree();
return type->get_tree(go_get_gogo());
}
else
return NULL_TREE;

View File

@ -203,8 +203,6 @@ Gogo::Gogo(Backend* backend, int int_type_size, int pointer_size)
imag_type->set_is_varargs();
imag_type->set_is_builtin();
this->globals_->add_function_declaration("imag", NULL, imag_type, loc);
this->define_builtin_function_trees();
}
// Munge name for use in an error message.

View File

@ -439,6 +439,10 @@ class Gogo
void
write_globals();
// Create trees for implicit builtin functions.
void
define_builtin_function_trees();
// Build a call to a builtin function. PDECL should point to a NULL
// initialized static pointer which will hold the fndecl. NAME is
// the name of the function. NARGS is the number of arguments.
@ -558,10 +562,6 @@ class Gogo
// The stack of functions.
typedef std::vector<Open_function> Open_functions;
// Create trees for implicit builtin functions.
void
define_builtin_function_trees();
// Set up the built-in unsafe package.
void
import_unsafe(const std::string&, bool is_exported, source_location);

View File

@ -850,10 +850,10 @@ Type::get_tree(Gogo* gogo)
if (this->is_error_type())
return error_mark_node;
// To avoid confusing GIMPLE, we need to translate all identical Go
// types to the same GIMPLE type. We use a hash table to do that.
// There is no need to use the hash table for named types, as named
// types are only identical to themselves.
// To avoid confusing the backend, translate all identical Go types
// to the same backend type. We use a hash table to do that. There
// is no need to use the hash table for named types, as named types
// are only identical to themselves.
std::pair<Type*, tree> val(this, NULL);
std::pair<Type_trees::iterator, bool> ins =
@ -1802,10 +1802,10 @@ Integer_type::do_hash_for_method(Gogo*) const
+ ((this->is_abstract_ ? 1 : 0) << 9));
}
// Get the tree for an Integer_type.
// Convert an Integer_type to the backend representation.
tree
Integer_type::do_get_tree(Gogo*)
Integer_type::do_get_tree(Gogo* gogo)
{
if (this->is_abstract_)
{
@ -1813,9 +1813,8 @@ Integer_type::do_get_tree(Gogo*)
return error_mark_node;
}
// FIXME: GOGO can be NULL when called from go_type_for_size, so call
// go_get_backend() instead of gogo->backend().
Btype* btype = go_get_backend()->integer_type(this->is_unsigned_, this->bits_);
Btype* btype = gogo->backend()->integer_type(this->is_unsigned_,
this->bits_);
return type_to_tree(btype);
}
@ -1944,23 +1943,15 @@ Float_type::do_hash_for_method(Gogo*) const
return (this->bits_ << 4) + ((this->is_abstract_ ? 1 : 0) << 8);
}
// Get a tree without using a Gogo*.
// Convert to the backend representation.
tree
Float_type::type_tree() const
Float_type::do_get_tree(Gogo* gogo)
{
Btype* btype = go_get_backend()->float_type(this->bits_);
Btype* btype = gogo->backend()->float_type(this->bits_);
return type_to_tree(btype);
}
// Get a tree.
tree
Float_type::do_get_tree(Gogo*)
{
return this->type_tree();
}
tree
Float_type::do_get_init_tree(Gogo*, tree type_tree, bool is_clear)
{
@ -2089,21 +2080,12 @@ Complex_type::do_hash_for_method(Gogo*) const
return (this->bits_ << 4) + ((this->is_abstract_ ? 1 : 0) << 8);
}
// Get a tree without using a Gogo*.
// Convert to the backend representation.
tree
Complex_type::type_tree() const
Complex_type::do_get_tree(Gogo* gogo)
{
Btype* btype = go_get_backend()->complex_type(this->bits_);
return type_to_tree(btype);
}
// Get a tree.
tree
Complex_type::do_get_tree(Gogo*)
{
return this->type_tree();
return type_to_tree(gogo->backend()->complex_type(this->bits_));
}
// Zero initializer.
@ -2175,8 +2157,8 @@ Type::lookup_complex_type(const char* name)
// Class String_type.
// Return the tree for String_type. A string is a struct with two
// fields: a pointer to the characters and a length.
// Convert String_type to the backend representation. A string is a
// struct with two fields: a pointer to the characters and a length.
tree
String_type::do_get_tree(Gogo*)
@ -2608,83 +2590,55 @@ Function_type::do_hash_for_method(Gogo* gogo) const
tree
Function_type::do_get_tree(Gogo* gogo)
{
tree args = NULL_TREE;
tree* pp = &args;
Backend::Btyped_identifier breceiver;
if (this->receiver_ != NULL)
{
Type* rtype = this->receiver_->type();
tree ptype = rtype->get_tree(gogo);
if (ptype == error_mark_node)
return error_mark_node;
breceiver.name = this->receiver_->name();
// We always pass the address of the receiver parameter, in
// order to make interface calls work with unknown types.
Type* rtype = this->receiver_->type();
if (rtype->points_to() == NULL)
ptype = build_pointer_type(ptype);
*pp = tree_cons (NULL_TREE, ptype, NULL_TREE);
pp = &TREE_CHAIN (*pp);
rtype = Type::make_pointer_type(rtype);
breceiver.btype = tree_to_type(rtype->get_tree(gogo));
breceiver.location = this->receiver_->location();
}
std::vector<Backend::Btyped_identifier> bparameters;
if (this->parameters_ != NULL)
{
bparameters.resize(this->parameters_->size());
size_t i = 0;
for (Typed_identifier_list::const_iterator p = this->parameters_->begin();
p != this->parameters_->end();
++p)
++p, ++i)
{
tree ptype = p->type()->get_tree(gogo);
if (ptype == error_mark_node)
return error_mark_node;
*pp = tree_cons (NULL_TREE, ptype, NULL_TREE);
pp = &TREE_CHAIN (*pp);
bparameters[i].name = p->name();
bparameters[i].btype = tree_to_type(p->type()->get_tree(gogo));
bparameters[i].location = p->location();
}
gcc_assert(i == bparameters.size());
}
// Varargs is handled entirely at the Go level. At the tree level,
// functions are not varargs.
*pp = void_list_node;
tree result;
if (this->results_ == NULL)
result = void_type_node;
else if (this->results_->size() == 1)
result = this->results_->begin()->type()->get_tree(gogo);
else
std::vector<Backend::Btyped_identifier> bresults;
if (this->results_ != NULL)
{
result = make_node(RECORD_TYPE);
tree field_trees = NULL_TREE;
tree* pp = &field_trees;
bresults.resize(this->results_->size());
size_t i = 0;
for (Typed_identifier_list::const_iterator p = this->results_->begin();
p != this->results_->end();
++p)
++p, ++i)
{
const std::string name = (p->name().empty()
? "UNNAMED"
: Gogo::unpack_hidden_name(p->name()));
tree name_tree = get_identifier_with_length(name.data(),
name.length());
tree field_type_tree = p->type()->get_tree(gogo);
if (field_type_tree == error_mark_node)
return error_mark_node;
tree field = build_decl(this->location_, FIELD_DECL, name_tree,
field_type_tree);
DECL_CONTEXT(field) = result;
*pp = field;
pp = &DECL_CHAIN(field);
bresults[i].name = p->name();
bresults[i].btype = tree_to_type(p->type()->get_tree(gogo));
bresults[i].location = p->location();
}
TYPE_FIELDS(result) = field_trees;
layout_type(result);
gcc_assert(i == bresults.size());
}
if (result == error_mark_node)
return error_mark_node;
tree fntype = build_function_type(result, args);
if (fntype == error_mark_node)
return fntype;
return build_pointer_type(fntype);
Btype* fntype = gogo->backend()->function_type(breceiver, bparameters,
bresults, this->location());
return type_to_tree(fntype);
}
// Functions are initialized to NULL.

View File

@ -1396,10 +1396,6 @@ class Float_type : public Type
bool
is_identical(const Float_type* t) const;
// Return a tree for this type without using a Gogo*.
tree
type_tree() const;
protected:
unsigned int
do_hash_for_method(Gogo*) const;
@ -1468,10 +1464,6 @@ class Complex_type : public Type
bool
is_identical(const Complex_type* t) const;
// Return a tree for this type without using a Gogo*.
tree
type_tree() const;
protected:
unsigned int
do_hash_for_method(Gogo*) const;