Commit 482829ac by Ian Lance Taylor Committed by Ian Lance Taylor

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
parent 0aa5e7f2
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> 2011-04-25 Evan Shaw <edsrzf@gmail.com>
* go-gcc.c (class Gcc_tree): Make get_tree const. * go-gcc.c (class Gcc_tree): Make get_tree const.
......
...@@ -287,6 +287,7 @@ go/statements.o: go/gofrontend/statements.cc $(GO_SYSTEM_H) \ ...@@ -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) \ 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) \ $(GIMPLE_H) $(REAL_H) convert.h $(GO_C_H) $(GO_GOGO_H) \
go/gofrontend/operator.h $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_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/unsafe.o: go/gofrontend/unsafe.cc $(GO_SYSTEM_H) $(GO_C_H) $(GO_TYPES_H) \
$(GO_GOGO_H) $(GO_GOGO_H)
...@@ -129,7 +129,7 @@ class Gcc_backend : public Backend ...@@ -129,7 +129,7 @@ class Gcc_backend : public Backend
Btype* Btype*
error_type() error_type()
{ gcc_unreachable(); } { return this->make_type(error_mark_node); }
Btype* Btype*
void_type() void_type()
...@@ -149,43 +149,22 @@ class Gcc_backend : public Backend ...@@ -149,43 +149,22 @@ class Gcc_backend : public Backend
complex_type(int); complex_type(int);
Btype* Btype*
string_type() pointer_type(Btype*);
{ gcc_unreachable(); }
Btype* Btype*
pointer_type(const Btype*); function_type(const Btyped_identifier&,
const std::vector<Btyped_identifier>&,
Btype* const std::vector<Btyped_identifier>&,
function_type(const Function_type*, Btype* /* receiver */, source_location);
const Btypes* /* parameters */,
const Btypes* /* results */)
{ gcc_unreachable(); }
Btype* Btype*
struct_type(const Struct_type*, const Btypes* /* field_types */) struct_type(const std::vector<Btyped_identifier>&)
{ gcc_unreachable(); } { gcc_unreachable(); }
Btype* Btype*
array_type(const Btype* /* element_type */, const Bexpression* /* length */) array_type(const Btype* /* element_type */, const Bexpression* /* length */)
{ gcc_unreachable(); } { 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. // Statements.
Bstatement* Bstatement*
...@@ -387,12 +366,89 @@ Gcc_backend::complex_type(int bits) ...@@ -387,12 +366,89 @@ Gcc_backend::complex_type(int bits)
// Get a pointer type. // Get a pointer type.
Btype* 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); 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. // An expression as a statement.
Bstatement* Bstatement*
......
...@@ -7,10 +7,6 @@ ...@@ -7,10 +7,6 @@
#ifndef GO_BACKEND_H #ifndef GO_BACKEND_H
#define 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 // Pointers to these types are created by the backend, passed to the
// frontend, and passed back to the backend. The types must be // frontend, and passed back to the backend. The types must be
// defined by the backend using these names. // defined by the backend using these names.
...@@ -36,9 +32,6 @@ class Bvariable; ...@@ -36,9 +32,6 @@ class Bvariable;
// The backend representation of a label. // The backend representation of a label.
class Blabel; class Blabel;
// A list of backend types.
typedef std::vector<Btype*> Btypes;
// The backend interface. This is a pure abstract class that a // The backend interface. This is a pure abstract class that a
// specific backend will implement. // specific backend will implement.
...@@ -47,6 +40,24 @@ class Backend ...@@ -47,6 +40,24 @@ class Backend
public: public:
virtual ~Backend() { } 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. // Types.
// Produce an error type. Actually the backend could probably just // Produce an error type. Actually the backend could probably just
...@@ -69,56 +80,36 @@ class Backend ...@@ -69,56 +80,36 @@ class Backend
virtual Btype* virtual Btype*
integer_type(bool is_unsigned, int bits) = 0; 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* virtual Btype*
float_type(int bits) = 0; 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* virtual Btype*
complex_type(int bits) = 0; complex_type(int bits) = 0;
// Get the unnamed string type.
virtual Btype*
string_type() = 0;
// Get a pointer type. // Get a pointer type.
virtual Btype* 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 // Get a function type. The receiver, parameter, and results are
// generated from the types in the Function_type. The Function_type // generated from the types in the Function_type. The Function_type
// is provided so that the names are available. // is provided so that the names are available.
virtual Btype* virtual Btype*
function_type(const Function_type*, Btype* receiver, function_type(const Btyped_identifier& receiver,
const Btypes* parameters, const std::vector<Btyped_identifier>& parameters,
const Btypes* results) = 0; const std::vector<Btyped_identifier>& results,
source_location location) = 0;
// Get a struct type. The Struct_type is provided to get the field // Get a struct type.
// names.
virtual Btype* 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. // Get an array type.
virtual Btype* virtual Btype*
array_type(const Btype* element_type, const Bexpression* length) = 0; 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. // Statements.
// Create an error statement. This is used for cases which should // Create an error statement. This is used for cases which should
......
...@@ -31,6 +31,9 @@ go_create_gogo(int int_type_size, int pointer_size) ...@@ -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); ::gogo = new Gogo(go_get_backend(), int_type_size, pointer_size);
if (!unique_prefix.empty()) if (!unique_prefix.empty())
::gogo->set_unique_prefix(unique_prefix); ::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. // Set the unique prefix we use for exported symbols.
......
...@@ -1743,7 +1743,7 @@ go_type_for_mode(enum machine_mode mode, int unsignedp) ...@@ -1743,7 +1743,7 @@ go_type_for_mode(enum machine_mode mode, int unsignedp)
return long_double_type_node; return long_double_type_node;
return NULL_TREE; return NULL_TREE;
} }
return type->float_type()->type_tree(); return type->get_tree(go_get_gogo());
} }
else if (mc == MODE_COMPLEX_FLOAT) else if (mc == MODE_COMPLEX_FLOAT)
{ {
...@@ -1763,7 +1763,7 @@ go_type_for_mode(enum machine_mode mode, int unsignedp) ...@@ -1763,7 +1763,7 @@ go_type_for_mode(enum machine_mode mode, int unsignedp)
return complex_long_double_type_node; return complex_long_double_type_node;
return NULL_TREE; return NULL_TREE;
} }
return type->complex_type()->type_tree(); return type->get_tree(go_get_gogo());
} }
else else
return NULL_TREE; return NULL_TREE;
......
...@@ -203,8 +203,6 @@ Gogo::Gogo(Backend* backend, int int_type_size, int pointer_size) ...@@ -203,8 +203,6 @@ Gogo::Gogo(Backend* backend, int int_type_size, int pointer_size)
imag_type->set_is_varargs(); imag_type->set_is_varargs();
imag_type->set_is_builtin(); imag_type->set_is_builtin();
this->globals_->add_function_declaration("imag", NULL, imag_type, loc); this->globals_->add_function_declaration("imag", NULL, imag_type, loc);
this->define_builtin_function_trees();
} }
// Munge name for use in an error message. // Munge name for use in an error message.
......
...@@ -439,6 +439,10 @@ class Gogo ...@@ -439,6 +439,10 @@ class Gogo
void void
write_globals(); 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 // Build a call to a builtin function. PDECL should point to a NULL
// initialized static pointer which will hold the fndecl. NAME is // initialized static pointer which will hold the fndecl. NAME is
// the name of the function. NARGS is the number of arguments. // the name of the function. NARGS is the number of arguments.
...@@ -558,10 +562,6 @@ class Gogo ...@@ -558,10 +562,6 @@ class Gogo
// The stack of functions. // The stack of functions.
typedef std::vector<Open_function> Open_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. // Set up the built-in unsafe package.
void void
import_unsafe(const std::string&, bool is_exported, source_location); import_unsafe(const std::string&, bool is_exported, source_location);
......
...@@ -850,10 +850,10 @@ Type::get_tree(Gogo* gogo) ...@@ -850,10 +850,10 @@ Type::get_tree(Gogo* gogo)
if (this->is_error_type()) if (this->is_error_type())
return error_mark_node; return error_mark_node;
// To avoid confusing GIMPLE, we need to translate all identical Go // To avoid confusing the backend, translate all identical Go types
// types to the same GIMPLE type. We use a hash table to do that. // to the same backend type. We use a hash table to do that. There
// There is no need to use the hash table for named types, as named // is no need to use the hash table for named types, as named types
// types are only identical to themselves. // are only identical to themselves.
std::pair<Type*, tree> val(this, NULL); std::pair<Type*, tree> val(this, NULL);
std::pair<Type_trees::iterator, bool> ins = std::pair<Type_trees::iterator, bool> ins =
...@@ -1802,10 +1802,10 @@ Integer_type::do_hash_for_method(Gogo*) const ...@@ -1802,10 +1802,10 @@ Integer_type::do_hash_for_method(Gogo*) const
+ ((this->is_abstract_ ? 1 : 0) << 9)); + ((this->is_abstract_ ? 1 : 0) << 9));
} }
// Get the tree for an Integer_type. // Convert an Integer_type to the backend representation.
tree tree
Integer_type::do_get_tree(Gogo*) Integer_type::do_get_tree(Gogo* gogo)
{ {
if (this->is_abstract_) if (this->is_abstract_)
{ {
...@@ -1813,9 +1813,8 @@ Integer_type::do_get_tree(Gogo*) ...@@ -1813,9 +1813,8 @@ Integer_type::do_get_tree(Gogo*)
return error_mark_node; return error_mark_node;
} }
// FIXME: GOGO can be NULL when called from go_type_for_size, so call Btype* btype = gogo->backend()->integer_type(this->is_unsigned_,
// go_get_backend() instead of gogo->backend(). this->bits_);
Btype* btype = go_get_backend()->integer_type(this->is_unsigned_, this->bits_);
return type_to_tree(btype); return type_to_tree(btype);
} }
...@@ -1944,23 +1943,15 @@ Float_type::do_hash_for_method(Gogo*) const ...@@ -1944,23 +1943,15 @@ Float_type::do_hash_for_method(Gogo*) const
return (this->bits_ << 4) + ((this->is_abstract_ ? 1 : 0) << 8); return (this->bits_ << 4) + ((this->is_abstract_ ? 1 : 0) << 8);
} }
// Get a tree without using a Gogo*. // Convert to the backend representation.
tree 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); return type_to_tree(btype);
} }
// Get a tree.
tree
Float_type::do_get_tree(Gogo*)
{
return this->type_tree();
}
tree tree
Float_type::do_get_init_tree(Gogo*, tree type_tree, bool is_clear) 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 ...@@ -2089,21 +2080,12 @@ Complex_type::do_hash_for_method(Gogo*) const
return (this->bits_ << 4) + ((this->is_abstract_ ? 1 : 0) << 8); return (this->bits_ << 4) + ((this->is_abstract_ ? 1 : 0) << 8);
} }
// Get a tree without using a Gogo*. // Convert to the backend representation.
tree 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(gogo->backend()->complex_type(this->bits_));
return type_to_tree(btype);
}
// Get a tree.
tree
Complex_type::do_get_tree(Gogo*)
{
return this->type_tree();
} }
// Zero initializer. // Zero initializer.
...@@ -2175,8 +2157,8 @@ Type::lookup_complex_type(const char* name) ...@@ -2175,8 +2157,8 @@ Type::lookup_complex_type(const char* name)
// Class String_type. // Class String_type.
// Return the tree for String_type. A string is a struct with two // Convert String_type to the backend representation. A string is a
// fields: a pointer to the characters and a length. // struct with two fields: a pointer to the characters and a length.
tree tree
String_type::do_get_tree(Gogo*) String_type::do_get_tree(Gogo*)
...@@ -2608,83 +2590,55 @@ Function_type::do_hash_for_method(Gogo* gogo) const ...@@ -2608,83 +2590,55 @@ Function_type::do_hash_for_method(Gogo* gogo) const
tree tree
Function_type::do_get_tree(Gogo* gogo) Function_type::do_get_tree(Gogo* gogo)
{ {
tree args = NULL_TREE; Backend::Btyped_identifier breceiver;
tree* pp = &args;
if (this->receiver_ != NULL) if (this->receiver_ != NULL)
{ {
Type* rtype = this->receiver_->type(); breceiver.name = this->receiver_->name();
tree ptype = rtype->get_tree(gogo);
if (ptype == error_mark_node)
return error_mark_node;
// We always pass the address of the receiver parameter, in // We always pass the address of the receiver parameter, in
// order to make interface calls work with unknown types. // order to make interface calls work with unknown types.
Type* rtype = this->receiver_->type();
if (rtype->points_to() == NULL) if (rtype->points_to() == NULL)
ptype = build_pointer_type(ptype); rtype = Type::make_pointer_type(rtype);
breceiver.btype = tree_to_type(rtype->get_tree(gogo));
*pp = tree_cons (NULL_TREE, ptype, NULL_TREE); breceiver.location = this->receiver_->location();
pp = &TREE_CHAIN (*pp);
} }
std::vector<Backend::Btyped_identifier> bparameters;
if (this->parameters_ != NULL) if (this->parameters_ != NULL)
{ {
bparameters.resize(this->parameters_->size());
size_t i = 0;
for (Typed_identifier_list::const_iterator p = this->parameters_->begin(); for (Typed_identifier_list::const_iterator p = this->parameters_->begin();
p != this->parameters_->end(); p != this->parameters_->end();
++p) ++p, ++i)
{ {
tree ptype = p->type()->get_tree(gogo); bparameters[i].name = p->name();
if (ptype == error_mark_node) bparameters[i].btype = tree_to_type(p->type()->get_tree(gogo));
return error_mark_node; bparameters[i].location = p->location();
*pp = tree_cons (NULL_TREE, ptype, NULL_TREE);
pp = &TREE_CHAIN (*pp);
} }
gcc_assert(i == bparameters.size());
} }
// Varargs is handled entirely at the Go level. At the tree level, std::vector<Backend::Btyped_identifier> bresults;
// functions are not varargs. if (this->results_ != NULL)
*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
{ {
result = make_node(RECORD_TYPE); bresults.resize(this->results_->size());
tree field_trees = NULL_TREE; size_t i = 0;
tree* pp = &field_trees;
for (Typed_identifier_list::const_iterator p = this->results_->begin(); for (Typed_identifier_list::const_iterator p = this->results_->begin();
p != this->results_->end(); p != this->results_->end();
++p) ++p, ++i)
{ {
const std::string name = (p->name().empty() bresults[i].name = p->name();
? "UNNAMED" bresults[i].btype = tree_to_type(p->type()->get_tree(gogo));
: Gogo::unpack_hidden_name(p->name())); bresults[i].location = p->location();
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);
} }
TYPE_FIELDS(result) = field_trees; gcc_assert(i == bresults.size());
layout_type(result);
} }
if (result == error_mark_node) Btype* fntype = gogo->backend()->function_type(breceiver, bparameters,
return error_mark_node; bresults, this->location());
return type_to_tree(fntype);
tree fntype = build_function_type(result, args);
if (fntype == error_mark_node)
return fntype;
return build_pointer_type(fntype);
} }
// Functions are initialized to NULL. // Functions are initialized to NULL.
......
...@@ -1396,10 +1396,6 @@ class Float_type : public Type ...@@ -1396,10 +1396,6 @@ class Float_type : public Type
bool bool
is_identical(const Float_type* t) const; is_identical(const Float_type* t) const;
// Return a tree for this type without using a Gogo*.
tree
type_tree() const;
protected: protected:
unsigned int unsigned int
do_hash_for_method(Gogo*) const; do_hash_for_method(Gogo*) const;
...@@ -1468,10 +1464,6 @@ class Complex_type : public Type ...@@ -1468,10 +1464,6 @@ class Complex_type : public Type
bool bool
is_identical(const Complex_type* t) const; is_identical(const Complex_type* t) const;
// Return a tree for this type without using a Gogo*.
tree
type_tree() const;
protected: protected:
unsigned int unsigned int
do_hash_for_method(Gogo*) const; do_hash_for_method(Gogo*) const;
......
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