Skip to content

Commit

Permalink
compiler: Report errors from very large types.
Browse files Browse the repository at this point in the history
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.

Change-Id: Ic9a606472688d8f5bf3fdc38907d86c50755ee12
Reviewed-on: https://go-review.googlesource.com/13684
Reviewed-by: Ian Lance Taylor <[email protected]>
  • Loading branch information
Chris Manghane authored and ianlancetaylor committed Sep 10, 2015
1 parent 913b47c commit 7ba5695
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 17 deletions.
60 changes: 46 additions & 14 deletions go/expressions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
30 changes: 27 additions & 3 deletions go/types.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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())
Expand Down

0 comments on commit 7ba5695

Please sign in to comment.