From ec23e5b3950ab5a907aecdb0860340b86702ed13 Mon Sep 17 00:00:00 2001 From: Chris Manghane Date: Thu, 10 Sep 2015 18:24:28 +0000 Subject: [PATCH] compiler: Report errors from very large types. The gcc backend throws an internal error when trying to get the size of a type which is larger than the amount of address space on the machine. This patch catches this error and reports it in a user friendly way. Fixes golang/go#11554. Reviewed-on: https://go-review.googlesource.com/13684 * go-gcc.cc (Gcc_backend::type_size): Return -1 for unrepresentable size. From-SVN: r227656 --- gcc/go/ChangeLog | 5 +++ gcc/go/go-gcc.cc | 3 +- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/expressions.cc | 60 ++++++++++++++++++++++++-------- gcc/go/gofrontend/types.cc | 30 ++++++++++++++-- 5 files changed, 81 insertions(+), 19 deletions(-) diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index 90520ded455..2fa56ab0ac0 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,8 @@ +2015-09-10 Chris Manghane + + * go-gcc.cc (Gcc_backend::type_size): Return -1 for + unrepresentable size. + 2015-08-24 Marek Polacek PR tree-optimization/67284 diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index cb4c2e5c73a..13143440761 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -1099,7 +1099,8 @@ Gcc_backend::type_size(Btype* btype) gcc_assert(tree_fits_uhwi_p (t)); unsigned HOST_WIDE_INT val_wide = TREE_INT_CST_LOW(t); int64_t ret = static_cast(val_wide); - gcc_assert(ret >= 0 && static_cast(ret) == val_wide); + if (ret < 0 || static_cast(ret) != val_wide) + return -1; return ret; } diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index a4ec9249bf7..ddf4637a775 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -913b47c957ea91db2f724491d88cb20e8f9be8c7 +7ba569544420d1de0eb607707ced6d23f8865186 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 21b4f143b77..dc37cf0b01e 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -3626,8 +3626,13 @@ Unary_expression::do_flatten(Gogo* gogo, Named_object*, Type* ptype = this->expr_->type()->points_to(); if (!ptype->is_void_type()) { - Btype* pbtype = ptype->get_backend(gogo); - int64_t s = gogo->backend()->type_size(pbtype); + int64_t s; + bool ok = ptype->backend_type_size(gogo, &s); + if (!ok) + { + go_assert(saw_errors()); + return Expression::make_error(this->location()); + } if (s >= 4096 || this->issue_nil_check_) { Temporary_statement* temp = @@ -4131,7 +4136,13 @@ Unary_expression::do_get_backend(Translate_context* context) Btype* pbtype = ptype->get_backend(gogo); if (!ptype->is_void_type()) { - int64_t s = gogo->backend()->type_size(pbtype); + int64_t s; + bool ok = ptype->backend_type_size(gogo, &s); + if (!ok) + { + go_assert(saw_errors()); + return gogo->backend()->error_expression(); + } if (s >= 4096 || this->issue_nil_check_) { go_assert(this->expr_->is_variable()); @@ -8339,8 +8350,14 @@ Builtin_call_expression::do_get_backend(Translate_context* context) Expression::make_conditional(cond, arg1_len, arg2_len, location); Type* element_type = at->element_type(); - Btype* element_btype = element_type->get_backend(gogo); - int64_t element_size = gogo->backend()->type_size(element_btype); + int64_t element_size; + bool ok = element_type->backend_type_size(gogo, &element_size); + if (!ok) + { + go_assert(saw_errors()); + return gogo->backend()->error_expression(); + } + Expression* size_expr = Expression::make_integer_int64(element_size, length->type(), location); @@ -8381,8 +8398,12 @@ Builtin_call_expression::do_get_backend(Translate_context* context) { arg2_val = at->get_value_pointer(gogo, arg2); arg2_len = at->get_length(gogo, arg2); - Btype* element_btype = element_type->get_backend(gogo); - size = gogo->backend()->type_size(element_btype); + bool ok = element_type->backend_type_size(gogo, &size); + if (!ok) + { + go_assert(saw_errors()); + return gogo->backend()->error_expression(); + } } Expression* element_size = Expression::make_integer_int64(size, NULL, location); @@ -11539,14 +11560,20 @@ Allocation_expression::do_get_backend(Translate_context* context) Gogo* gogo = context->gogo(); Location loc = this->location(); - Btype* btype = this->type_->get_backend(gogo); if (this->allocate_on_stack_) { - int64_t size = gogo->backend()->type_size(btype); + int64_t size; + bool ok = this->type_->backend_type_size(gogo, &size); + if (!ok) + { + go_assert(saw_errors()); + return gogo->backend()->error_expression(); + } return gogo->backend()->stack_allocation_expression(size, loc); } - Bexpression* space = + Btype* btype = this->type_->get_backend(gogo); + Bexpression* space = gogo->allocate_memory(this->type_, loc)->get_backend(context); Btype* pbtype = gogo->backend()->pointer_type(btype); return gogo->backend()->convert_expression(pbtype, space, loc); @@ -13731,23 +13758,28 @@ Type_info_expression::do_type() Bexpression* Type_info_expression::do_get_backend(Translate_context* context) { - Btype* btype = this->type_->get_backend(context->gogo()); Gogo* gogo = context->gogo(); + bool ok = true; int64_t val; switch (this->type_info_) { case TYPE_INFO_SIZE: - val = gogo->backend()->type_size(btype); + ok = this->type_->backend_type_size(gogo, &val); break; case TYPE_INFO_ALIGNMENT: - val = gogo->backend()->type_alignment(btype); + ok = this->type_->backend_type_align(gogo, &val); break; case TYPE_INFO_FIELD_ALIGNMENT: - val = gogo->backend()->type_field_alignment(btype); + ok = this->type_->backend_type_field_align(gogo, &val); break; default: go_unreachable(); } + if (!ok) + { + go_assert(saw_errors()); + return gogo->backend()->error_expression(); + } Expression* e = Expression::make_integer_int64(val, this->type(), this->location()); return e->get_backend(context); diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 8331678578d..dcc6bc829c6 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -2524,6 +2524,20 @@ Type::backend_type_size(Gogo* gogo, int64_t *psize) return false; Btype* bt = this->get_backend_placeholder(gogo); *psize = gogo->backend()->type_size(bt); + if (*psize == -1) + { + if (this->named_type() != NULL) + error_at(this->named_type()->location(), + "type %s larger than address space", + Gogo::message_name(this->named_type()->name()).c_str()); + else + error("type %s larger than address space", + this->reflection(gogo).c_str()); + + // Make this an error type to avoid knock-on errors. + this->classification_ = TYPE_ERROR; + return false; + } return true; } @@ -6400,8 +6414,12 @@ Array_type::slice_gc_symbol(Gogo* gogo, Expression_list** vals, // Differentiate between slices with zero-length and non-zero-length values. Type* element_type = this->element_type(); - Btype* ebtype = element_type->get_backend(gogo); - int64_t element_size = gogo->backend()->type_size(ebtype); + int64_t element_size; + bool ok = element_type->backend_type_size(gogo, &element_size); + if (!ok) { + go_assert(saw_errors()); + element_size = 4; + } Type* uintptr_type = Type::lookup_integer_type("uintptr"); unsigned long opval = element_size == 0 ? GC_APTR : GC_SLICE; @@ -6432,7 +6450,13 @@ Array_type::array_gc_symbol(Gogo* gogo, Expression_list** vals, Btype* pbtype = gogo->backend()->pointer_type(gogo->backend()->void_type()); int64_t pwidth = gogo->backend()->type_size(pbtype); - int64_t iwidth = gogo->backend()->type_size(this->get_backend(gogo)); + int64_t iwidth; + bool ok = this->backend_type_size(gogo, &iwidth); + if (!ok) + { + go_assert(saw_errors()); + iwidth = 4; + } Type* element_type = this->element_type(); if (bound < 1 || !element_type->has_pointer()) -- 2.30.2