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
+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.
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)
Btype*
error_type()
- { gcc_unreachable(); }
+ { return this->make_type(error_mark_node); }
Btype*
void_type()
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<Btyped_identifier>&,
+ const std::vector<Btyped_identifier>&,
+ source_location);
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*
// 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*
#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.
// 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.
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
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
::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.
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)
{
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;
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.
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.
// 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);
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 =
+ ((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_)
{
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);
}
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)
{
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.
// 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*)
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.
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;
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;