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
This commit is contained in:
Chris Manghane 2015-09-10 18:24:28 +00:00 committed by Ian Lance Taylor
parent 8b66114510
commit ec23e5b395
5 changed files with 81 additions and 19 deletions

View File

@ -1,3 +1,8 @@
2015-09-10 Chris Manghane <cmang@google.com>
* go-gcc.cc (Gcc_backend::type_size): Return -1 for
unrepresentable size.
2015-08-24 Marek Polacek <polacek@redhat.com> 2015-08-24 Marek Polacek <polacek@redhat.com>
PR tree-optimization/67284 PR tree-optimization/67284

View File

@ -1099,7 +1099,8 @@ Gcc_backend::type_size(Btype* btype)
gcc_assert(tree_fits_uhwi_p (t)); gcc_assert(tree_fits_uhwi_p (t));
unsigned HOST_WIDE_INT val_wide = TREE_INT_CST_LOW(t); unsigned HOST_WIDE_INT val_wide = TREE_INT_CST_LOW(t);
int64_t ret = static_cast<int64_t>(val_wide); int64_t ret = static_cast<int64_t>(val_wide);
gcc_assert(ret >= 0 && static_cast<unsigned HOST_WIDE_INT>(ret) == val_wide); if (ret < 0 || static_cast<unsigned HOST_WIDE_INT>(ret) != val_wide)
return -1;
return ret; return ret;
} }

View File

@ -1,4 +1,4 @@
913b47c957ea91db2f724491d88cb20e8f9be8c7 7ba569544420d1de0eb607707ced6d23f8865186
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.

View File

@ -3626,8 +3626,13 @@ Unary_expression::do_flatten(Gogo* gogo, Named_object*,
Type* ptype = this->expr_->type()->points_to(); Type* ptype = this->expr_->type()->points_to();
if (!ptype->is_void_type()) if (!ptype->is_void_type())
{ {
Btype* pbtype = ptype->get_backend(gogo); int64_t s;
int64_t s = gogo->backend()->type_size(pbtype); 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_) if (s >= 4096 || this->issue_nil_check_)
{ {
Temporary_statement* temp = Temporary_statement* temp =
@ -4131,7 +4136,13 @@ Unary_expression::do_get_backend(Translate_context* context)
Btype* pbtype = ptype->get_backend(gogo); Btype* pbtype = ptype->get_backend(gogo);
if (!ptype->is_void_type()) 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_) if (s >= 4096 || this->issue_nil_check_)
{ {
go_assert(this->expr_->is_variable()); 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); Expression::make_conditional(cond, arg1_len, arg2_len, location);
Type* element_type = at->element_type(); Type* element_type = at->element_type();
Btype* element_btype = element_type->get_backend(gogo); int64_t element_size;
int64_t element_size = gogo->backend()->type_size(element_btype); 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, Expression* size_expr = Expression::make_integer_int64(element_size,
length->type(), length->type(),
location); location);
@ -8381,8 +8398,12 @@ Builtin_call_expression::do_get_backend(Translate_context* context)
{ {
arg2_val = at->get_value_pointer(gogo, arg2); arg2_val = at->get_value_pointer(gogo, arg2);
arg2_len = at->get_length(gogo, arg2); arg2_len = at->get_length(gogo, arg2);
Btype* element_btype = element_type->get_backend(gogo); bool ok = element_type->backend_type_size(gogo, &size);
size = gogo->backend()->type_size(element_btype); if (!ok)
{
go_assert(saw_errors());
return gogo->backend()->error_expression();
}
} }
Expression* element_size = Expression* element_size =
Expression::make_integer_int64(size, NULL, location); Expression::make_integer_int64(size, NULL, location);
@ -11539,14 +11560,20 @@ Allocation_expression::do_get_backend(Translate_context* context)
Gogo* gogo = context->gogo(); Gogo* gogo = context->gogo();
Location loc = this->location(); Location loc = this->location();
Btype* btype = this->type_->get_backend(gogo);
if (this->allocate_on_stack_) 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); 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); gogo->allocate_memory(this->type_, loc)->get_backend(context);
Btype* pbtype = gogo->backend()->pointer_type(btype); Btype* pbtype = gogo->backend()->pointer_type(btype);
return gogo->backend()->convert_expression(pbtype, space, loc); return gogo->backend()->convert_expression(pbtype, space, loc);
@ -13731,23 +13758,28 @@ Type_info_expression::do_type()
Bexpression* Bexpression*
Type_info_expression::do_get_backend(Translate_context* context) Type_info_expression::do_get_backend(Translate_context* context)
{ {
Btype* btype = this->type_->get_backend(context->gogo());
Gogo* gogo = context->gogo(); Gogo* gogo = context->gogo();
bool ok = true;
int64_t val; int64_t val;
switch (this->type_info_) switch (this->type_info_)
{ {
case TYPE_INFO_SIZE: case TYPE_INFO_SIZE:
val = gogo->backend()->type_size(btype); ok = this->type_->backend_type_size(gogo, &val);
break; break;
case TYPE_INFO_ALIGNMENT: case TYPE_INFO_ALIGNMENT:
val = gogo->backend()->type_alignment(btype); ok = this->type_->backend_type_align(gogo, &val);
break; break;
case TYPE_INFO_FIELD_ALIGNMENT: case TYPE_INFO_FIELD_ALIGNMENT:
val = gogo->backend()->type_field_alignment(btype); ok = this->type_->backend_type_field_align(gogo, &val);
break; break;
default: default:
go_unreachable(); go_unreachable();
} }
if (!ok)
{
go_assert(saw_errors());
return gogo->backend()->error_expression();
}
Expression* e = Expression::make_integer_int64(val, this->type(), Expression* e = Expression::make_integer_int64(val, this->type(),
this->location()); this->location());
return e->get_backend(context); return e->get_backend(context);

View File

@ -2524,6 +2524,20 @@ Type::backend_type_size(Gogo* gogo, int64_t *psize)
return false; return false;
Btype* bt = this->get_backend_placeholder(gogo); Btype* bt = this->get_backend_placeholder(gogo);
*psize = gogo->backend()->type_size(bt); *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; 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. // Differentiate between slices with zero-length and non-zero-length values.
Type* element_type = this->element_type(); Type* element_type = this->element_type();
Btype* ebtype = element_type->get_backend(gogo); int64_t element_size;
int64_t element_size = gogo->backend()->type_size(ebtype); 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"); Type* uintptr_type = Type::lookup_integer_type("uintptr");
unsigned long opval = element_size == 0 ? GC_APTR : GC_SLICE; 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()); Btype* pbtype = gogo->backend()->pointer_type(gogo->backend()->void_type());
int64_t pwidth = gogo->backend()->type_size(pbtype); 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(); Type* element_type = this->element_type();
if (bound < 1 || !element_type->has_pointer()) if (bound < 1 || !element_type->has_pointer())