aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2011-06-14 05:53:10 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-06-14 05:53:10 +0000
commit3b8dffe701e9a1f6641f3ff1f08899614ce38ae0 (patch)
tree075a60d271b289fa96fb47546b7be74d188590e1 /gcc/go
parent8365a060e613196d31719832af2a4cb2b9886a30 (diff)
downloadgcc-3b8dffe701e9a1f6641f3ff1f08899614ce38ae0.zip
gcc-3b8dffe701e9a1f6641f3ff1f08899614ce38ae0.tar.gz
gcc-3b8dffe701e9a1f6641f3ff1f08899614ce38ae0.tar.bz2
Change builtin make to runtime call at lowering time.
Use kindNoPointers as 6g does. * Make-lang.in (go/expressions.o): Depend on $(GO_RUNTIME_H). From-SVN: r175008
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/ChangeLog4
-rw-r--r--gcc/go/Make-lang.in2
-rw-r--r--gcc/go/gofrontend/expressions.cc352
-rw-r--r--gcc/go/gofrontend/expressions.h15
-rw-r--r--gcc/go/gofrontend/runtime.cc11
-rw-r--r--gcc/go/gofrontend/runtime.def10
-rw-r--r--gcc/go/gofrontend/types.cc395
-rw-r--r--gcc/go/gofrontend/types.h65
8 files changed, 256 insertions, 598 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index 11abbbc..a5e56b1 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,7 @@
+2011-06-13 Ian Lance Taylor <iant@google.com>
+
+ * Make-lang.in (go/expressions.o): Depend on $(GO_RUNTIME_H).
+
2011-06-10 Ian Lance Taylor <iant@google.com>
* go-gcc.cc: Include "toplev.h".
diff --git a/gcc/go/Make-lang.in b/gcc/go/Make-lang.in
index 61a0f3c..51760bf 100644
--- a/gcc/go/Make-lang.in
+++ b/gcc/go/Make-lang.in
@@ -255,7 +255,7 @@ go/expressions.o: go/gofrontend/expressions.cc $(GO_SYSTEM_H) $(TOPLEV_H) \
intl.h $(TREE_H) $(GIMPLE_H) tree-iterator.h convert.h $(REAL_H) \
realmpfr.h $(GO_C_H) $(GO_GOGO_H) $(GO_TYPES_H) \
go/gofrontend/export.h $(GO_IMPORT_H) $(GO_STATEMENTS_H) $(GO_LEX_H) \
- go/gofrontend/backend.h $(GO_EXPRESSIONS_H)
+ $(GO_RUNTIME_H) go/gofrontend/backend.h $(GO_EXPRESSIONS_H)
go/go.o: go/gofrontend/go.cc $(GO_SYSTEM_H) $(GO_C_H) $(GO_LEX_H) \
$(GO_PARSE_H) go/gofrontend/backend.h $(GO_GOGO_H)
go/go-dump.o: go/gofrontend/go-dump.cc $(GO_SYSTEM_H) $(GO_C_H) \
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 9c6af0b..bd437c4 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -33,6 +33,7 @@ extern "C"
#include "import.h"
#include "statements.h"
#include "lex.h"
+#include "runtime.h"
#include "backend.h"
#include "expressions.h"
@@ -3592,7 +3593,7 @@ class Unsafe_type_conversion_expression : public Expression
void
do_determine_type(const Type_context*)
- { }
+ { this->expr_->determine_type_no_context(); }
Expression*
do_copy()
@@ -6739,6 +6740,12 @@ class Builtin_call_expression : public Call_expression
static Type*
complex_type(Type*);
+ Expression*
+ lower_make();
+
+ bool
+ check_int_value(Expression*);
+
// A pointer back to the general IR structure. This avoids a global
// variable, or passing it around everywhere.
Gogo* gogo_;
@@ -6859,6 +6866,9 @@ Find_call_expression::expression(Expression** pexpr)
Expression*
Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function, int)
{
+ if (this->classification() == EXPRESSION_ERROR)
+ return this;
+
if (this->is_varargs() && this->code_ != BUILTIN_APPEND)
{
this->report_error(_("invalid use of %<...%> with builtin function"));
@@ -6885,36 +6895,7 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function, int)
}
}
else if (this->code_ == BUILTIN_MAKE)
- {
- const Expression_list* args = this->args();
- if (args == NULL || args->size() < 1)
- this->report_error(_("not enough arguments"));
- else
- {
- Expression* arg = args->front();
- if (!arg->is_type_expression())
- {
- error_at(arg->location(), "expected type");
- this->set_is_error();
- }
- else
- {
- Expression_list* newargs;
- if (args->size() == 1)
- newargs = NULL;
- else
- {
- newargs = new Expression_list();
- Expression_list::const_iterator p = args->begin();
- ++p;
- for (; p != args->end(); ++p)
- newargs->push_back(*p);
- }
- return Expression::make_make(arg->type(), newargs,
- this->location());
- }
- }
- }
+ return this->lower_make();
else if (this->is_constant())
{
// We can only lower len and cap if there are no function calls
@@ -6999,6 +6980,170 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function, int)
return this;
}
+// Lower a make expression.
+
+Expression*
+Builtin_call_expression::lower_make()
+{
+ source_location loc = this->location();
+
+ const Expression_list* args = this->args();
+ if (args == NULL || args->size() < 1)
+ {
+ this->report_error(_("not enough arguments"));
+ return Expression::make_error(this->location());
+ }
+
+ Expression_list::const_iterator parg = args->begin();
+
+ Expression* first_arg = *parg;
+ if (!first_arg->is_type_expression())
+ {
+ error_at(first_arg->location(), "expected type");
+ this->set_is_error();
+ return Expression::make_error(this->location());
+ }
+ Type* type = first_arg->type();
+
+ bool is_slice = false;
+ bool is_map = false;
+ bool is_chan = false;
+ if (type->is_open_array_type())
+ is_slice = true;
+ else if (type->map_type() != NULL)
+ is_map = true;
+ else if (type->channel_type() != NULL)
+ is_chan = true;
+ else
+ {
+ this->report_error(_("invalid type for make function"));
+ return Expression::make_error(this->location());
+ }
+
+ ++parg;
+ Expression* len_arg;
+ if (parg == args->end())
+ {
+ if (is_slice)
+ {
+ this->report_error(_("length required when allocating a slice"));
+ return Expression::make_error(this->location());
+ }
+
+ mpz_t zval;
+ mpz_init_set_ui(zval, 0);
+ len_arg = Expression::make_integer(&zval, NULL, loc);
+ mpz_clear(zval);
+ }
+ else
+ {
+ len_arg = *parg;
+ if (!this->check_int_value(len_arg))
+ {
+ this->report_error(_("bad size for make"));
+ return Expression::make_error(this->location());
+ }
+ ++parg;
+ }
+
+ Expression* cap_arg = NULL;
+ if (is_slice && parg != args->end())
+ {
+ cap_arg = *parg;
+ if (!this->check_int_value(cap_arg))
+ {
+ this->report_error(_("bad capacity when making slice"));
+ return Expression::make_error(this->location());
+ }
+ ++parg;
+ }
+
+ if (parg != args->end())
+ {
+ this->report_error(_("too many arguments to make"));
+ return Expression::make_error(this->location());
+ }
+
+ source_location type_loc = first_arg->location();
+ Expression* type_arg;
+ if (is_slice || is_chan)
+ type_arg = Expression::make_type_descriptor(type, type_loc);
+ else if (is_map)
+ type_arg = Expression::make_map_descriptor(type->map_type(), type_loc);
+ else
+ go_unreachable();
+
+ Expression* call;
+ if (is_slice)
+ {
+ if (cap_arg == NULL)
+ call = Runtime::make_call(Runtime::MAKESLICE1, loc, 2, type_arg,
+ len_arg);
+ else
+ call = Runtime::make_call(Runtime::MAKESLICE2, loc, 3, type_arg,
+ len_arg, cap_arg);
+ }
+ else if (is_map)
+ call = Runtime::make_call(Runtime::MAKEMAP, loc, 2, type_arg, len_arg);
+ else if (is_chan)
+ call = Runtime::make_call(Runtime::MAKECHAN, loc, 2, type_arg, len_arg);
+ else
+ go_unreachable();
+
+ return Expression::make_unsafe_cast(type, call, loc);
+}
+
+// Return whether an expression has an integer value. Report an error
+// if not. This is used when handling calls to the predeclared make
+// function.
+
+bool
+Builtin_call_expression::check_int_value(Expression* e)
+{
+ if (e->type()->integer_type() != NULL)
+ return true;
+
+ // Check for a floating point constant with integer value.
+ mpfr_t fval;
+ mpfr_init(fval);
+
+ Type* dummy;
+ if (e->float_constant_value(fval, &dummy) && mpfr_integer_p(fval))
+ {
+ mpz_t ival;
+ mpz_init(ival);
+
+ bool ok = false;
+
+ mpfr_clear_overflow();
+ mpfr_clear_erangeflag();
+ mpfr_get_z(ival, fval, GMP_RNDN);
+ if (!mpfr_overflow_p()
+ && !mpfr_erangeflag_p()
+ && mpz_sgn(ival) >= 0)
+ {
+ Named_type* ntype = Type::lookup_integer_type("int");
+ Integer_type* inttype = ntype->integer_type();
+ mpz_t max;
+ mpz_init_set_ui(max, 1);
+ mpz_mul_2exp(max, max, inttype->bits() - 1);
+ ok = mpz_cmp(ival, max) < 0;
+ mpz_clear(max);
+ }
+ mpz_clear(ival);
+
+ if (ok)
+ {
+ mpfr_clear(fval);
+ return true;
+ }
+ }
+
+ mpfr_clear(fval);
+
+ return false;
+}
+
// Return the type of the real or imag functions, given the type of
// the argument. We need to map complex to float, complex64 to
// float32, and complex128 to float64, so it has to be done by name.
@@ -10684,107 +10829,6 @@ Expression::make_allocation(Type* type, source_location location)
return new Allocation_expression(type, location);
}
-// Implement the builtin function make.
-
-class Make_expression : public Expression
-{
- public:
- Make_expression(Type* type, Expression_list* args, source_location location)
- : Expression(EXPRESSION_MAKE, location),
- type_(type), args_(args)
- { }
-
- protected:
- int
- do_traverse(Traverse* traverse);
-
- Type*
- do_type()
- { return this->type_; }
-
- void
- do_determine_type(const Type_context*);
-
- void
- do_check_types(Gogo*);
-
- Expression*
- do_copy()
- {
- return new Make_expression(this->type_, this->args_->copy(),
- this->location());
- }
-
- tree
- do_get_tree(Translate_context*);
-
- private:
- // The type we are making.
- Type* type_;
- // The arguments to pass to the make routine.
- Expression_list* args_;
-};
-
-// Traversal.
-
-int
-Make_expression::do_traverse(Traverse* traverse)
-{
- if (this->args_ != NULL
- && this->args_->traverse(traverse) == TRAVERSE_EXIT)
- return TRAVERSE_EXIT;
- if (Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
- return TRAVERSE_EXIT;
- return TRAVERSE_CONTINUE;
-}
-
-// Set types of arguments.
-
-void
-Make_expression::do_determine_type(const Type_context*)
-{
- if (this->args_ != NULL)
- {
- Type_context context(Type::lookup_integer_type("int"), false);
- for (Expression_list::const_iterator pe = this->args_->begin();
- pe != this->args_->end();
- ++pe)
- (*pe)->determine_type(&context);
- }
-}
-
-// Check types for a make expression.
-
-void
-Make_expression::do_check_types(Gogo*)
-{
- if (this->type_->channel_type() == NULL
- && this->type_->map_type() == NULL
- && (this->type_->array_type() == NULL
- || this->type_->array_type()->length() != NULL))
- this->report_error(_("invalid type for make function"));
- else if (!this->type_->check_make_expression(this->args_, this->location()))
- this->set_is_error();
-}
-
-// Return a tree for a make expression.
-
-tree
-Make_expression::do_get_tree(Translate_context* context)
-{
- return this->type_->make_expression_tree(context, this->args_,
- this->location());
-}
-
-// Make a make expression.
-
-Expression*
-Expression::make_make(Type* type, Expression_list* args,
- source_location location)
-{
- return new Make_expression(type, args, location);
-}
-
// Construct a struct.
class Struct_construction_expression : public Expression
@@ -12771,6 +12815,50 @@ Expression::make_struct_field_offset(Struct_type* type,
return new Struct_field_offset_expression(type, field);
}
+// An expression which evaluates to a pointer to the map descriptor of
+// a map type.
+
+class Map_descriptor_expression : public Expression
+{
+ public:
+ Map_descriptor_expression(Map_type* type, source_location location)
+ : Expression(EXPRESSION_MAP_DESCRIPTOR, location),
+ type_(type)
+ { }
+
+ protected:
+ Type*
+ do_type()
+ { return Type::make_pointer_type(Map_type::make_map_descriptor_type()); }
+
+ void
+ do_determine_type(const Type_context*)
+ { }
+
+ Expression*
+ do_copy()
+ { return this; }
+
+ tree
+ do_get_tree(Translate_context* context)
+ {
+ return this->type_->map_descriptor_pointer(context->gogo(),
+ this->location());
+ }
+
+ private:
+ // The type for which this is the descriptor.
+ Map_type* type_;
+};
+
+// Make a map descriptor expression.
+
+Expression*
+Expression::make_map_descriptor(Map_type* type, source_location location)
+{
+ return new Map_descriptor_expression(type, location);
+}
+
// An expression which evaluates to the address of an unnamed label.
class Label_addr_expression : public Expression
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 13f4fb4..271b1bb 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -78,7 +78,6 @@ class Expression
EXPRESSION_FIELD_REFERENCE,
EXPRESSION_INTERFACE_FIELD_REFERENCE,
EXPRESSION_ALLOCATION,
- EXPRESSION_MAKE,
EXPRESSION_TYPE_GUARD,
EXPRESSION_CONVERSION,
EXPRESSION_UNSAFE_CONVERSION,
@@ -92,6 +91,7 @@ class Expression
EXPRESSION_TYPE_DESCRIPTOR,
EXPRESSION_TYPE_INFO,
EXPRESSION_STRUCT_FIELD_OFFSET,
+ EXPRESSION_MAP_DESCRIPTOR,
EXPRESSION_LABEL_ADDR
};
@@ -236,10 +236,6 @@ class Expression
static Expression*
make_allocation(Type*, source_location);
- // Make a call to the builtin function make.
- static Expression*
- make_make(Type*, Expression_list*, source_location);
-
// Make a type guard expression.
static Expression*
make_type_guard(Expression*, Type*, source_location);
@@ -276,8 +272,8 @@ class Expression
static Receive_expression*
make_receive(Expression* channel, source_location);
- // Make an expression which evaluates to the type descriptor of a
- // type.
+ // Make an expression which evaluates to the address of the type
+ // descriptor for TYPE.
static Expression*
make_type_descriptor(Type* type, source_location);
@@ -304,6 +300,11 @@ class Expression
static Expression*
make_struct_field_offset(Struct_type*, const Struct_field*);
+ // Make an expression which evaluates to the address of the map
+ // descriptor for TYPE.
+ static Expression*
+ make_map_descriptor(Map_type* type, source_location);
+
// Make an expression which evaluates to the address of an unnamed
// label.
static Expression*
diff --git a/gcc/go/gofrontend/runtime.cc b/gcc/go/gofrontend/runtime.cc
index 204f147..2ecfbf5 100644
--- a/gcc/go/gofrontend/runtime.cc
+++ b/gcc/go/gofrontend/runtime.cc
@@ -64,6 +64,8 @@ enum Runtime_function_type
RFT_FUNC_PTR,
// Pointer to Go type descriptor.
RFT_TYPE,
+ // Pointer to map descriptor.
+ RFT_MAPDESCRIPTOR,
NUMBER_OF_RUNTIME_FUNCTION_TYPES
};
@@ -175,6 +177,10 @@ runtime_function_type(Runtime_function_type bft)
case RFT_TYPE:
t = Type::make_type_descriptor_ptr_type();
break;
+
+ case RFT_MAPDESCRIPTOR:
+ t = Type::make_pointer_type(Map_type::make_map_descriptor_type());
+ break;
}
runtime_function_types[bft] = t;
@@ -225,6 +231,11 @@ convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
case RFT_TYPE:
go_assert(e->type() == Type::make_type_descriptor_ptr_type());
return e;
+
+ case RFT_MAPDESCRIPTOR:
+ go_assert(e->type()->points_to()
+ == Map_type::make_map_descriptor_type());
+ return e;
}
}
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index 6e7a807..219ccb8 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -65,8 +65,14 @@ DEF_GO_RUNTIME(STRING_TO_INT_ARRAY, "__go_string_to_int_array",
P1(STRING), R1(SLICE))
+// Make a slice.
+DEF_GO_RUNTIME(MAKESLICE1, "__go_make_slice1", P2(TYPE, UINTPTR), R1(SLICE))
+DEF_GO_RUNTIME(MAKESLICE2, "__go_make_slice2", P3(TYPE, UINTPTR, UINTPTR),
+ R1(SLICE))
+
+
// Make a map.
-DEF_GO_RUNTIME(NEW_MAP, "__go_new_map", P2(TYPE, UINTPTR), R1(MAP))
+DEF_GO_RUNTIME(MAKEMAP, "__go_new_map", P2(MAPDESCRIPTOR, UINTPTR), R1(MAP))
// Build a map from a composite literal.
DEF_GO_RUNTIME(CONSTRUCT_MAP, "__go_construct_map",
@@ -103,7 +109,7 @@ DEF_GO_RUNTIME(MAPITERNEXT, "runtime.mapiternext", P1(MAPITER), R0())
// Make a channel.
-DEF_GO_RUNTIME(NEW_CHANNEL, "__go_new_channel", P2(UINTPTR, UINTPTR), R1(CHAN))
+DEF_GO_RUNTIME(MAKECHAN, "__go_new_channel", P2(TYPE, UINTPTR), R1(CHAN))
// Get the length of a channel (the number of unread values).
DEF_GO_RUNTIME(CHAN_LEN, "__go_chan_len", P1(CHAN), R1(INT))
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index e19d4f2..4b2ceeb 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -768,68 +768,6 @@ Type::hash_string(const std::string& s, unsigned int h)
return h;
}
-// Default check for the expression passed to make. Any type which
-// may be used with make implements its own version of this.
-
-bool
-Type::do_check_make_expression(Expression_list*, source_location)
-{
- go_unreachable();
-}
-
-// Return whether an expression has an integer value. Report an error
-// if not. This is used when handling calls to the predeclared make
-// function.
-
-bool
-Type::check_int_value(Expression* e, const char* errmsg,
- source_location location)
-{
- if (e->type()->integer_type() != NULL)
- return true;
-
- // Check for a floating point constant with integer value.
- mpfr_t fval;
- mpfr_init(fval);
-
- Type* dummy;
- if (e->float_constant_value(fval, &dummy) && mpfr_integer_p(fval))
- {
- mpz_t ival;
- mpz_init(ival);
-
- bool ok = false;
-
- mpfr_clear_overflow();
- mpfr_clear_erangeflag();
- mpfr_get_z(ival, fval, GMP_RNDN);
- if (!mpfr_overflow_p()
- && !mpfr_erangeflag_p()
- && mpz_sgn(ival) >= 0)
- {
- Named_type* ntype = Type::lookup_integer_type("int");
- Integer_type* inttype = ntype->integer_type();
- mpz_t max;
- mpz_init_set_ui(max, 1);
- mpz_mul_2exp(max, max, inttype->bits() - 1);
- ok = mpz_cmp(ival, max) < 0;
- mpz_clear(max);
- }
- mpz_clear(ival);
-
- if (ok)
- {
- mpfr_clear(fval);
- return true;
- }
- }
-
- mpfr_clear(fval);
-
- error_at(location, "%s", errmsg);
- return false;
-}
-
// A hash table mapping unnamed types to the backend representation of
// those types.
@@ -912,16 +850,6 @@ Type::get_btype_without_hash(Gogo* gogo)
return this->btype_;
}
-// Any type which supports the builtin make function must implement
-// this.
-
-tree
-Type::do_make_expression_tree(Translate_context*, Expression_list*,
- source_location)
-{
- go_unreachable();
-}
-
// Return a pointer to the type descriptor for this type.
tree
@@ -1366,6 +1294,8 @@ Type::type_descriptor_constructor(Gogo* gogo, int runtime_type_kind,
Expression_list* vals = new Expression_list();
vals->reserve(9);
+ if (!this->has_pointer())
+ runtime_type_kind |= RUNTIME_TYPE_KIND_NO_POINTERS;
Struct_field_list::const_iterator p = fields->begin();
go_assert(p->field_name() == "Kind");
mpz_t iv;
@@ -4341,43 +4271,6 @@ Array_type::do_hash_for_method(Gogo* gogo) const
return this->element_type_->hash_for_method(gogo) + 1;
}
-// See if the expression passed to make is suitable. The first
-// argument is required, and gives the length. An optional second
-// argument is permitted for the capacity.
-
-bool
-Array_type::do_check_make_expression(Expression_list* args,
- source_location location)
-{
- go_assert(this->length_ == NULL);
- if (args == NULL || args->empty())
- {
- error_at(location, "length required when allocating a slice");
- return false;
- }
- else if (args->size() > 2)
- {
- error_at(location, "too many expressions passed to make");
- return false;
- }
- else
- {
- if (!Type::check_int_value(args->front(),
- _("bad length when making slice"), location))
- return false;
-
- if (args->size() > 1)
- {
- if (!Type::check_int_value(args->back(),
- _("bad capacity when making slice"),
- location))
- return false;
- }
-
- return true;
- }
-}
-
// Get a tree for the length of a fixed array. The length may be
// computed using a function call, so we must only evaluate it once.
@@ -4491,129 +4384,6 @@ Array_type::get_backend_length(Gogo* gogo)
return tree_to_expr(this->get_length_tree(gogo));
}
-// Handle the builtin make function for a slice.
-
-tree
-Array_type::do_make_expression_tree(Translate_context* context,
- Expression_list* args,
- source_location location)
-{
- go_assert(this->length_ == NULL);
-
- Gogo* gogo = context->gogo();
- tree type_tree = type_to_tree(this->get_backend(gogo));
- if (type_tree == error_mark_node)
- return error_mark_node;
-
- tree values_field = TYPE_FIELDS(type_tree);
- go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(values_field)),
- "__values") == 0);
-
- tree count_field = DECL_CHAIN(values_field);
- go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(count_field)),
- "__count") == 0);
-
- tree element_type_tree = type_to_tree(this->element_type_->get_backend(gogo));
- if (element_type_tree == error_mark_node)
- return error_mark_node;
- tree element_size_tree = TYPE_SIZE_UNIT(element_type_tree);
-
- // The first argument is the number of elements, the optional second
- // argument is the capacity.
- go_assert(args != NULL && args->size() >= 1 && args->size() <= 2);
-
- tree length_tree = args->front()->get_tree(context);
- if (length_tree == error_mark_node)
- return error_mark_node;
- if (!DECL_P(length_tree))
- length_tree = save_expr(length_tree);
- if (!INTEGRAL_TYPE_P(TREE_TYPE(length_tree)))
- length_tree = convert_to_integer(TREE_TYPE(count_field), length_tree);
-
- tree bad_index = Expression::check_bounds(length_tree,
- TREE_TYPE(count_field),
- NULL_TREE, location);
-
- length_tree = fold_convert_loc(location, TREE_TYPE(count_field), length_tree);
- tree capacity_tree;
- if (args->size() == 1)
- capacity_tree = length_tree;
- else
- {
- capacity_tree = args->back()->get_tree(context);
- if (capacity_tree == error_mark_node)
- return error_mark_node;
- if (!DECL_P(capacity_tree))
- capacity_tree = save_expr(capacity_tree);
- if (!INTEGRAL_TYPE_P(TREE_TYPE(capacity_tree)))
- capacity_tree = convert_to_integer(TREE_TYPE(count_field),
- capacity_tree);
-
- bad_index = Expression::check_bounds(capacity_tree,
- TREE_TYPE(count_field),
- bad_index, location);
-
- tree chktype = (((TYPE_SIZE(TREE_TYPE(capacity_tree))
- > TYPE_SIZE(TREE_TYPE(length_tree)))
- || ((TYPE_SIZE(TREE_TYPE(capacity_tree))
- == TYPE_SIZE(TREE_TYPE(length_tree)))
- && TYPE_UNSIGNED(TREE_TYPE(capacity_tree))))
- ? TREE_TYPE(capacity_tree)
- : TREE_TYPE(length_tree));
- tree chk = fold_build2_loc(location, LT_EXPR, boolean_type_node,
- fold_convert_loc(location, chktype,
- capacity_tree),
- fold_convert_loc(location, chktype,
- length_tree));
- if (bad_index == NULL_TREE)
- bad_index = chk;
- else
- bad_index = fold_build2_loc(location, TRUTH_OR_EXPR, boolean_type_node,
- bad_index, chk);
-
- capacity_tree = fold_convert_loc(location, TREE_TYPE(count_field),
- capacity_tree);
- }
-
- tree size_tree = fold_build2_loc(location, MULT_EXPR, sizetype,
- element_size_tree,
- fold_convert_loc(location, sizetype,
- capacity_tree));
-
- tree chk = fold_build2_loc(location, TRUTH_AND_EXPR, boolean_type_node,
- fold_build2_loc(location, GT_EXPR,
- boolean_type_node,
- fold_convert_loc(location,
- sizetype,
- capacity_tree),
- size_zero_node),
- fold_build2_loc(location, LT_EXPR,
- boolean_type_node,
- size_tree, element_size_tree));
- if (bad_index == NULL_TREE)
- bad_index = chk;
- else
- bad_index = fold_build2_loc(location, TRUTH_OR_EXPR, boolean_type_node,
- bad_index, chk);
-
- tree space = context->gogo()->allocate_memory(this->element_type_,
- size_tree, location);
-
- space = fold_convert(TREE_TYPE(values_field), space);
-
- if (bad_index != NULL_TREE && bad_index != boolean_false_node)
- {
- tree crash = Gogo::runtime_error(RUNTIME_ERROR_MAKE_SLICE_OUT_OF_BOUNDS,
- location);
- space = build2(COMPOUND_EXPR, TREE_TYPE(space),
- build3(COND_EXPR, void_type_node,
- bad_index, crash, NULL_TREE),
- space);
- }
-
- return gogo->slice_constructor(type_tree, space, length_tree, capacity_tree);
-}
-
// Return a tree for a pointer to the values in ARRAY.
tree
@@ -4962,28 +4732,6 @@ Map_type::do_hash_for_method(Gogo* gogo) const
+ 2);
}
-// Check that a call to the builtin make function is valid. For a map
-// the optional argument is the number of spaces to preallocate for
-// values.
-
-bool
-Map_type::do_check_make_expression(Expression_list* args,
- source_location location)
-{
- if (args != NULL && !args->empty())
- {
- if (!Type::check_int_value(args->front(), _("bad size when making map"),
- location))
- return false;
- else if (args->size() > 1)
- {
- error_at(location, "too many arguments when making map");
- return false;
- }
- }
- return true;
-}
-
// Get the backend representation for a map type. A map type is
// represented as a pointer to a struct. The struct is __go_map in
// libgo/map.h.
@@ -5024,62 +4772,6 @@ Map_type::do_get_backend(Gogo* gogo)
return backend_map_type;
}
-// Return an expression for a newly allocated map.
-
-tree
-Map_type::do_make_expression_tree(Translate_context* context,
- Expression_list* args,
- source_location location)
-{
- tree bad_index = NULL_TREE;
-
- tree expr_tree;
- if (args == NULL || args->empty())
- expr_tree = size_zero_node;
- else
- {
- expr_tree = args->front()->get_tree(context);
- if (expr_tree == error_mark_node)
- return error_mark_node;
- if (!DECL_P(expr_tree))
- expr_tree = save_expr(expr_tree);
- if (!INTEGRAL_TYPE_P(TREE_TYPE(expr_tree)))
- expr_tree = convert_to_integer(sizetype, expr_tree);
- bad_index = Expression::check_bounds(expr_tree, sizetype, bad_index,
- location);
- }
-
- Gogo* gogo = context->gogo();
- tree map_type = type_to_tree(this->get_backend(gogo));
-
- static tree new_map_fndecl;
- tree ret = Gogo::call_builtin(&new_map_fndecl,
- location,
- "__go_new_map",
- 2,
- map_type,
- TREE_TYPE(TYPE_FIELDS(TREE_TYPE(map_type))),
- this->map_descriptor_pointer(gogo, location),
- sizetype,
- expr_tree);
- if (ret == error_mark_node)
- return error_mark_node;
- // This can panic if the capacity is out of range.
- TREE_NOTHROW(new_map_fndecl) = 0;
-
- if (bad_index == NULL_TREE)
- return ret;
- else
- {
- tree crash = Gogo::runtime_error(RUNTIME_ERROR_MAKE_MAP_OUT_OF_BOUNDS,
- location);
- return build2(COMPOUND_EXPR, TREE_TYPE(ret),
- build3(COND_EXPR, void_type_node,
- bad_index, crash, NULL_TREE),
- ret);
- }
-}
-
// The type of a map type descriptor.
Type*
@@ -5343,29 +5035,6 @@ Channel_type::is_identical(const Channel_type* t,
&& this->may_receive_ == t->may_receive_);
}
-// Check whether the parameters for a call to the builtin function
-// make are OK for a channel. A channel can take an optional single
-// parameter which is the buffer size.
-
-bool
-Channel_type::do_check_make_expression(Expression_list* args,
- source_location location)
-{
- if (args != NULL && !args->empty())
- {
- if (!Type::check_int_value(args->front(),
- _("bad buffer size when making channel"),
- location))
- return false;
- else if (args->size() > 1)
- {
- error_at(location, "too many arguments when making channel");
- return false;
- }
- }
- return true;
-}
-
// Return the tree for a channel type. A channel is a pointer to a
// __go_channel struct. The __go_channel struct is defined in
// libgo/runtime/channel.h.
@@ -5384,66 +5053,6 @@ Channel_type::do_get_backend(Gogo* gogo)
return backend_channel_type;
}
-// Handle the builtin function make for a channel.
-
-tree
-Channel_type::do_make_expression_tree(Translate_context* context,
- Expression_list* args,
- source_location location)
-{
- Gogo* gogo = context->gogo();
- tree channel_type = type_to_tree(this->get_backend(gogo));
-
- Type* ptdt = Type::make_type_descriptor_ptr_type();
- tree element_type_descriptor =
- this->element_type_->type_descriptor_pointer(gogo, location);
-
- tree bad_index = NULL_TREE;
-
- tree expr_tree;
- if (args == NULL || args->empty())
- expr_tree = size_zero_node;
- else
- {
- expr_tree = args->front()->get_tree(context);
- if (expr_tree == error_mark_node)
- return error_mark_node;
- if (!DECL_P(expr_tree))
- expr_tree = save_expr(expr_tree);
- if (!INTEGRAL_TYPE_P(TREE_TYPE(expr_tree)))
- expr_tree = convert_to_integer(sizetype, expr_tree);
- bad_index = Expression::check_bounds(expr_tree, sizetype, bad_index,
- location);
- }
-
- static tree new_channel_fndecl;
- tree ret = Gogo::call_builtin(&new_channel_fndecl,
- location,
- "__go_new_channel",
- 2,
- channel_type,
- type_to_tree(ptdt->get_backend(gogo)),
- element_type_descriptor,
- sizetype,
- expr_tree);
- if (ret == error_mark_node)
- return error_mark_node;
- // This can panic if the capacity is out of range.
- TREE_NOTHROW(new_channel_fndecl) = 0;
-
- if (bad_index == NULL_TREE)
- return ret;
- else
- {
- tree crash = Gogo::runtime_error(RUNTIME_ERROR_MAKE_CHAN_OUT_OF_BOUNDS,
- location);
- return build2(COMPOUND_EXPR, TREE_TYPE(ret),
- build3(COND_EXPR, void_type_node,
- bad_index, crash, NULL_TREE),
- ret);
- }
-}
-
// Build a type descriptor for a channel type.
Type*
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index 2ee80a4..9947a2c 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -78,6 +78,8 @@ static const int RUNTIME_TYPE_KIND_STRING = 24;
static const int RUNTIME_TYPE_KIND_STRUCT = 25;
static const int RUNTIME_TYPE_KIND_UNSAFE_POINTER = 26;
+static const int RUNTIME_TYPE_KIND_NO_POINTERS = (1 << 7);
+
// To build the complete list of methods for a named type we need to
// gather all methods from anonymous fields. Those methods may
// require an arbitrary set of indirections and field offsets. There
@@ -811,13 +813,6 @@ class Type
is_unexported_field_or_method(Gogo*, const Type*, const std::string&,
std::vector<const Named_type*>*);
- // This type was passed to the builtin function make. ARGS are the
- // arguments passed to make after the type; this may be NULL if
- // there were none. Issue any required errors.
- bool
- check_make_expression(Expression_list* args, source_location location)
- { return this->do_check_make_expression(args, location); }
-
// Convert the builtin named types.
static void
convert_builtin_named_types(Gogo*);
@@ -826,12 +821,6 @@ class Type
Btype*
get_backend(Gogo*);
- // Return a tree for a make expression applied to this type.
- tree
- make_expression_tree(Translate_context* context, Expression_list* args,
- source_location location)
- { return this->do_make_expression_tree(context, args, location); }
-
// Build a type descriptor entry for this type. Return a pointer to
// it. The location is the location which causes us to need the
// entry.
@@ -878,16 +867,9 @@ class Type
virtual unsigned int
do_hash_for_method(Gogo*) const;
- virtual bool
- do_check_make_expression(Expression_list* args, source_location);
-
virtual Btype*
do_get_backend(Gogo*) = 0;
- virtual tree
- do_make_expression_tree(Translate_context*, Expression_list*,
- source_location);
-
virtual Expression*
do_type_descriptor(Gogo*, Named_type* name) = 0;
@@ -901,10 +883,6 @@ class Type
virtual void
do_export(Export*) const;
- // Return whether an expression is an integer.
- static bool
- check_int_value(Expression*, const char*, source_location);
-
// Return whether a method expects a pointer as the receiver.
static bool
method_expects_pointer(const Named_object*);
@@ -2083,16 +2061,9 @@ class Array_type : public Type
unsigned int
do_hash_for_method(Gogo*) const;
- bool
- do_check_make_expression(Expression_list*, source_location);
-
Btype*
do_get_backend(Gogo*);
- tree
- do_make_expression_tree(Translate_context*, Expression_list*,
- source_location);
-
Expression*
do_type_descriptor(Gogo*, Named_type*);
@@ -2180,16 +2151,9 @@ class Map_type : public Type
unsigned int
do_hash_for_method(Gogo*) const;
- bool
- do_check_make_expression(Expression_list*, source_location);
-
Btype*
do_get_backend(Gogo*);
- tree
- do_make_expression_tree(Translate_context*, Expression_list*,
- source_location);
-
Expression*
do_type_descriptor(Gogo*, Named_type*);
@@ -2269,16 +2233,9 @@ class Channel_type : public Type
unsigned int
do_hash_for_method(Gogo*) const;
- bool
- do_check_make_expression(Expression_list*, source_location);
-
Btype*
do_get_backend(Gogo*);
- tree
- do_make_expression_tree(Translate_context*, Expression_list*,
- source_location);
-
Expression*
do_type_descriptor(Gogo*, Named_type*);
@@ -2611,18 +2568,9 @@ class Named_type : public Type
unsigned int
do_hash_for_method(Gogo*) const;
- bool
- do_check_make_expression(Expression_list* args, source_location location)
- { return this->type_->check_make_expression(args, location); }
-
Btype*
do_get_backend(Gogo*);
- tree
- do_make_expression_tree(Translate_context* context, Expression_list* args,
- source_location location)
- { return this->type_->make_expression_tree(context, args, location); }
-
Expression*
do_type_descriptor(Gogo*, Named_type*);
@@ -2751,18 +2699,9 @@ class Forward_declaration_type : public Type
do_hash_for_method(Gogo* gogo) const
{ return this->real_type()->hash_for_method(gogo); }
- bool
- do_check_make_expression(Expression_list* args, source_location location)
- { return this->base()->check_make_expression(args, location); }
-
Btype*
do_get_backend(Gogo* gogo);
- tree
- do_make_expression_tree(Translate_context* context, Expression_list* args,
- source_location location)
- { return this->base()->make_expression_tree(context, args, location); }
-
Expression*
do_type_descriptor(Gogo*, Named_type*);