Index: gcc/go/Make-lang.in =================================================================== --- gcc/go/Make-lang.in (revision 172743) +++ gcc/go/Make-lang.in (working copy) @@ -287,6 +287,7 @@ go/statements.o: go/gofrontend/statement 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) Index: gcc/go/go-gcc.cc =================================================================== --- gcc/go/go-gcc.cc (revision 172931) +++ gcc/go/go-gcc.cc (working copy) @@ -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*); - - Btype* - function_type(const Function_type*, Btype* /* receiver */, - const Btypes* /* parameters */, - const Btypes* /* results */) - { gcc_unreachable(); } + function_type(const Btyped_identifier&, + const std::vector&, + const std::vector&, + source_location); Btype* - struct_type(const Struct_type*, const Btypes* /* field_types */) + struct_type(const std::vector&) { 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& parameters, + const std::vector& 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::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::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* Index: gcc/go/gofrontend/gogo.cc =================================================================== --- gcc/go/gofrontend/gogo.cc (revision 172882) +++ gcc/go/gofrontend/gogo.cc (working copy) @@ -203,8 +203,6 @@ Gogo::Gogo(Backend* backend, int int_typ 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. Index: gcc/go/gofrontend/gogo.h =================================================================== --- gcc/go/gofrontend/gogo.h (revision 172846) +++ gcc/go/gofrontend/gogo.h (working copy) @@ -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_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); Index: gcc/go/gofrontend/go.cc =================================================================== --- gcc/go/gofrontend/go.cc (revision 172846) +++ gcc/go/gofrontend/go.cc (working copy) @@ -31,6 +31,9 @@ go_create_gogo(int int_type_size, int po ::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. Index: gcc/go/gofrontend/types.h =================================================================== --- gcc/go/gofrontend/types.h (revision 172882) +++ gcc/go/gofrontend/types.h (working copy) @@ -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; Index: gcc/go/gofrontend/gogo-tree.cc =================================================================== --- gcc/go/gofrontend/gogo-tree.cc (revision 172882) +++ gcc/go/gofrontend/gogo-tree.cc (working copy) @@ -1743,7 +1743,7 @@ go_type_for_mode(enum machine_mode mode, 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, 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; Index: gcc/go/gofrontend/backend.h =================================================================== --- gcc/go/gofrontend/backend.h (revision 172931) +++ gcc/go/gofrontend/backend.h (working copy) @@ -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 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& parameters, + const std::vector& 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& 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 Index: gcc/go/gofrontend/types.cc =================================================================== --- gcc/go/gofrontend/types.cc (revision 172931) +++ gcc/go/gofrontend/types.cc (working copy) @@ -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 val(this, NULL); std::pair ins = @@ -1802,10 +1802,10 @@ Integer_type::do_hash_for_method(Gogo*) + ((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*) co 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*) 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* na // 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* 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 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 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.