diff options
author | Ian Lance Taylor <iant@google.com> | 2011-06-14 05:53:10 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-06-14 05:53:10 +0000 |
commit | 3b8dffe701e9a1f6641f3ff1f08899614ce38ae0 (patch) | |
tree | 075a60d271b289fa96fb47546b7be74d188590e1 /gcc | |
parent | 8365a060e613196d31719832af2a4cb2b9886a30 (diff) | |
download | gcc-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')
-rw-r--r-- | gcc/go/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/go/Make-lang.in | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 352 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.h | 15 | ||||
-rw-r--r-- | gcc/go/gofrontend/runtime.cc | 11 | ||||
-rw-r--r-- | gcc/go/gofrontend/runtime.def | 10 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.cc | 395 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.h | 65 |
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*); |