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>
PR tree-optimization/67284

View File

@ -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<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;
}

View File

@ -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.

View File

@ -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);

View File

@ -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())