From 18fbd1ecf1440151236c388933b1541784f4f8c2 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 3 Feb 2015 03:33:21 +0000 Subject: [PATCH] re PR go/64836 (go.test/test/fixedbugs/issue4348.go FAILs) PR go/64836 PR go/64838 compiler: Use int64_t for backend type size and alignment. Fixes 32-bit host 64-bit target cross-compilation. * go-gcc.cc (Gcc_backend::type_size): Change return type to int64_t. (Gcc_backend::type_alignment): Likewise. (Gcc_backend::type_field_alignment): Likewise. (Gcc_backend::type_field_offset): Likewise. (Gcc_backend::implicit_variable): Change alignment parameter type to int64_t. From-SVN: r220364 --- gcc/go/ChangeLog | 12 ++++ gcc/go/go-gcc.cc | 29 +++++----- gcc/go/gofrontend/backend.h | 10 ++-- gcc/go/gofrontend/expressions.cc | 99 +++++++++++++++++++++++--------- gcc/go/gofrontend/expressions.h | 5 ++ gcc/go/gofrontend/gogo.cc | 15 +++-- gcc/go/gofrontend/gogo.h | 4 +- gcc/go/gofrontend/types.cc | 77 ++++++++++++------------- gcc/go/gofrontend/types.h | 8 +-- 9 files changed, 158 insertions(+), 101 deletions(-) diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index 7a624c7de33..1cee68cb76f 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,15 @@ +2015-02-02 Ian Lance Taylor + + PR go/64836 + PR go/64838 + * go-gcc.cc (Gcc_backend::type_size): Change return type to + int64_t. + (Gcc_backend::type_alignment): Likewise. + (Gcc_backend::type_field_alignment): Likewise. + (Gcc_backend::type_field_offset): Likewise. + (Gcc_backend::implicit_variable): Change alignment parameter type + to int64_t. + 2015-01-23 Ian Lance Taylor PR go/63565 diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index 1ce1ff2f79b..08f014fa02e 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -223,16 +223,16 @@ class Gcc_backend : public Backend bool is_circular_pointer_type(Btype*); - size_t + int64_t type_size(Btype*); - size_t + int64_t type_alignment(Btype*); - size_t + int64_t type_field_alignment(Btype*); - size_t + int64_t type_field_offset(Btype*, size_t index); // Expressions. @@ -411,7 +411,7 @@ class Gcc_backend : public Backend Bvariable* implicit_variable(const std::string&, Btype*, bool, bool, bool, - size_t); + int64_t); void implicit_variable_set_init(Bvariable*, const std::string&, Btype*, @@ -1097,7 +1097,7 @@ Gcc_backend::is_circular_pointer_type(Btype* btype) // Return the size of a type. -size_t +int64_t Gcc_backend::type_size(Btype* btype) { tree t = btype->get_tree(); @@ -1106,14 +1106,14 @@ Gcc_backend::type_size(Btype* btype) t = TYPE_SIZE_UNIT(t); gcc_assert(tree_fits_uhwi_p (t)); unsigned HOST_WIDE_INT val_wide = TREE_INT_CST_LOW(t); - size_t ret = static_cast(val_wide); - gcc_assert(ret == val_wide); + int64_t ret = static_cast(val_wide); + gcc_assert(ret >= 0 && static_cast(ret) == val_wide); return ret; } // Return the alignment of a type. -size_t +int64_t Gcc_backend::type_alignment(Btype* btype) { tree t = btype->get_tree(); @@ -1124,7 +1124,7 @@ Gcc_backend::type_alignment(Btype* btype) // Return the alignment of a struct field of type BTYPE. -size_t +int64_t Gcc_backend::type_field_alignment(Btype* btype) { tree t = btype->get_tree(); @@ -1135,7 +1135,7 @@ Gcc_backend::type_field_alignment(Btype* btype) // Return the offset of a field in a struct. -size_t +int64_t Gcc_backend::type_field_offset(Btype* btype, size_t index) { tree struct_tree = btype->get_tree(); @@ -1149,9 +1149,8 @@ Gcc_backend::type_field_offset(Btype* btype, size_t index) gcc_assert(field != NULL_TREE); } HOST_WIDE_INT offset_wide = int_byte_position(field); - gcc_assert(offset_wide >= 0); - size_t ret = static_cast(offset_wide); - gcc_assert(ret == static_cast(offset_wide)); + int64_t ret = static_cast(offset_wide); + gcc_assert(ret == offset_wide); return ret; } @@ -2609,7 +2608,7 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock, Bvariable* Gcc_backend::implicit_variable(const std::string& name, Btype* type, bool is_hidden, bool is_constant, - bool is_common, size_t alignment) + bool is_common, int64_t alignment) { tree type_tree = type->get_tree(); if (type_tree == error_mark_node) diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h index 31ed8dff0a6..b5071ae67c5 100644 --- a/gcc/go/gofrontend/backend.h +++ b/gcc/go/gofrontend/backend.h @@ -216,22 +216,22 @@ class Backend is_circular_pointer_type(Btype*) = 0; // Return the size of a type. - virtual size_t + virtual int64_t type_size(Btype*) = 0; // Return the alignment of a type. - virtual size_t + virtual int64_t type_alignment(Btype*) = 0; // Return the alignment of a struct field of this type. This is // normally the same as type_alignment, but not always. - virtual size_t + virtual int64_t type_field_alignment(Btype*) = 0; // Return the offset of field INDEX in a struct type. INDEX is the // entry in the FIELDS std::vector parameter of struct_type or // set_placeholder_struct_type. - virtual size_t + virtual int64_t type_field_offset(Btype*, size_t index) = 0; // Expressions. @@ -575,7 +575,7 @@ class Backend // If ALIGNMENT is not zero, it is the desired alignment of the variable. virtual Bvariable* implicit_variable(const std::string& name, Btype* type, bool is_hidden, - bool is_constant, bool is_common, size_t alignment) = 0; + bool is_constant, bool is_common, int64_t alignment) = 0; // Set the initial value of a variable created by implicit_variable. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index a8bed0b66e1..0cb0938fda1 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -181,8 +181,10 @@ Expression::convert_for_assignment(Gogo* gogo, Type* lhs_type, // represented as non-zero-sized. // TODO(cmang): This check is for a GCC-specific issue, and should be // removed from the frontend. FIXME. - size_t lhs_size = gogo->backend()->type_size(lhs_type->get_backend(gogo)); - size_t rhs_size = gogo->backend()->type_size(rhs_type->get_backend(gogo)); + int64_t lhs_size = + gogo->backend()->type_size(lhs_type->get_backend(gogo)); + int64_t rhs_size = + gogo->backend()->type_size(rhs_type->get_backend(gogo)); if (rhs_size == 0 || lhs_size == 0) return rhs; @@ -2112,6 +2114,48 @@ Expression::make_integer_sl(long val, Type *type, Location location) return ret; } +// Store an int64_t in an uninitialized mpz_t. + +static void +set_mpz_from_int64(mpz_t* zval, int64_t val) +{ + if (val >= 0) + { + unsigned long ul = static_cast(val); + if (static_cast(ul) == val) + { + mpz_init_set_ui(*zval, ul); + return; + } + } + uint64_t uv; + if (val >= 0) + uv = static_cast(val); + else + uv = static_cast(- val); + unsigned long ul = uv & 0xffffffffUL; + mpz_init_set_ui(*zval, ul); + mpz_t hval; + mpz_init_set_ui(hval, static_cast(uv >> 32)); + mpz_mul_2exp(hval, hval, 32); + mpz_add(*zval, *zval, hval); + mpz_clear(hval); + if (val < 0) + mpz_neg(*zval, *zval); +} + +// Build a new integer value from an int64_t. + +Expression* +Expression::make_integer_int64(int64_t val, Type* type, Location location) +{ + mpz_t zval; + set_mpz_from_int64(&zval, val); + Expression* ret = Expression::make_integer_z(&zval, type, location); + mpz_clear(zval); + return ret; +} + // Build a new character constant value. Expression* @@ -3694,7 +3738,7 @@ Unary_expression::do_flatten(Gogo* gogo, Named_object*, if (!ptype->is_void_type()) { Btype* pbtype = ptype->get_backend(gogo); - size_t s = gogo->backend()->type_size(pbtype); + int64_t s = gogo->backend()->type_size(pbtype); if (s >= 4096 || this->issue_nil_check_) { Temporary_statement* temp = @@ -4182,7 +4226,7 @@ Unary_expression::do_get_backend(Translate_context* context) Btype* pbtype = ptype->get_backend(gogo); if (!ptype->is_void_type()) { - size_t s = gogo->backend()->type_size(pbtype); + int64_t s = gogo->backend()->type_size(pbtype); if (s >= 4096 || this->issue_nil_check_) { go_assert(this->expr_->is_variable()); @@ -7361,7 +7405,7 @@ Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const if (this->seen_) return false; - unsigned long ret; + int64_t ret; if (this->code_ == BUILTIN_SIZEOF) { this->seen_ = true; @@ -7389,7 +7433,10 @@ Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const else go_unreachable(); - nc->set_unsigned_long(Type::lookup_integer_type("uintptr"), ret); + mpz_t zval; + set_mpz_from_int64(&zval, ret); + nc->set_int(Type::lookup_integer_type("uintptr"), zval); + mpz_clear(zval); return true; } else if (this->code_ == BUILTIN_OFFSETOF) @@ -7403,7 +7450,7 @@ Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const if (this->seen_) return false; - unsigned int total_offset = 0; + int64_t total_offset = 0; while (true) { Expression* struct_expr = farg->expr(); @@ -7412,7 +7459,7 @@ Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const return false; if (st->named_type() != NULL) st->named_type()->convert(this->gogo_); - unsigned int offset; + int64_t offset; this->seen_ = true; bool ok = st->struct_type()->backend_field_offset(this->gogo_, farg->field_index(), @@ -7429,8 +7476,10 @@ Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const } break; } - nc->set_unsigned_long(Type::lookup_integer_type("uintptr"), - static_cast(total_offset)); + mpz_t zval; + set_mpz_from_int64(&zval, total_offset); + nc->set_int(Type::lookup_integer_type("uintptr"), zval); + mpz_clear(zval); return true; } else if (this->code_ == BUILTIN_REAL || this->code_ == BUILTIN_IMAG) @@ -8329,10 +8378,10 @@ Builtin_call_expression::do_get_backend(Translate_context* context) Type* element_type = at->element_type(); Btype* element_btype = element_type->get_backend(gogo); - size_t element_size = gogo->backend()->type_size(element_btype); - Expression* size_expr = Expression::make_integer_ul(element_size, - length->type(), - location); + int64_t element_size = gogo->backend()->type_size(element_btype); + Expression* size_expr = Expression::make_integer_int64(element_size, + length->type(), + location); Expression* bytecount = Expression::make_binary(OPERATOR_MULT, size_expr, length, location); Expression* copy = Runtime::make_call(Runtime::COPY, location, 3, @@ -8355,7 +8404,7 @@ Builtin_call_expression::do_get_backend(Translate_context* context) go_assert(arg2->is_variable()); Expression* arg2_val; Expression* arg2_len; - unsigned long size; + int64_t size; if (arg2->type()->is_string_type() && element_type->integer_type() != NULL && element_type->integer_type()->is_byte()) @@ -8374,7 +8423,7 @@ Builtin_call_expression::do_get_backend(Translate_context* context) size = gogo->backend()->type_size(element_btype); } Expression* element_size = - Expression::make_integer_ul(size, NULL, location); + Expression::make_integer_int64(size, NULL, location); Expression* append = Runtime::make_call(Runtime::APPEND, location, 4, arg1, arg2_val, arg2_len, @@ -14028,7 +14077,7 @@ Type_info_expression::do_get_backend(Translate_context* context) { Btype* btype = this->type_->get_backend(context->gogo()); Gogo* gogo = context->gogo(); - size_t val; + int64_t val; switch (this->type_info_) { case TYPE_INFO_SIZE: @@ -14043,13 +14092,9 @@ Type_info_expression::do_get_backend(Translate_context* context) default: go_unreachable(); } - mpz_t cst; - mpz_init_set_ui(cst, val); - Btype* int_btype = this->type()->get_backend(gogo); - Bexpression* ret = - gogo->backend()->integer_constant_expression(int_btype, cst); - mpz_clear(cst); - return ret; + Expression* e = Expression::make_integer_int64(val, this->type(), + this->location()); + return e->get_backend(context); } // Dump ast representation for a type info expression. @@ -14780,11 +14825,11 @@ Struct_field_offset_expression::do_get_backend(Translate_context* context) Gogo* gogo = context->gogo(); Btype* btype = this->type_->get_backend(gogo); - size_t offset = gogo->backend()->type_field_offset(btype, i); + int64_t offset = gogo->backend()->type_field_offset(btype, i); Type* uptr_type = Type::lookup_integer_type("uintptr"); Expression* ret = - Expression::make_integer_ul(offset, uptr_type, - Linemap::predeclared_location()); + Expression::make_integer_int64(offset, uptr_type, + Linemap::predeclared_location()); return ret->get_backend(context); } diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index a2346c8c63e..fbccdf04c1c 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -233,6 +233,11 @@ class Expression static Expression* make_integer_sl(long, Type*, Location); + // Make a constant integer expression from an int64_t. TYPE should + // be NULL for an abstract type. + static Expression* + make_integer_int64(int64_t, Type*, Location); + // Make a constant float expression. TYPE should be NULL for an // abstract type. static Expression* diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 6196f03ae2c..ab305cf2741 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -602,7 +602,7 @@ Gogo::zero_value(Type *type) } // The zero value will be the maximum required size. - unsigned long size; + int64_t size; bool ok = type->backend_type_size(this, &size); if (!ok) { go_assert(saw_errors()); @@ -611,7 +611,7 @@ Gogo::zero_value(Type *type) if (size > this->zero_value_size_) this->zero_value_size_ = size; - unsigned long align; + int64_t align; ok = type->backend_type_align(this, &align); if (!ok) { go_assert(saw_errors()); @@ -644,13 +644,12 @@ Gogo::backend_zero_value() Btype* bbtype_type = byte_type->get_backend(this); Type* int_type = this->lookup_global("int")->type_value(); - Btype* bint_type = int_type->get_backend(this); - mpz_t val; - mpz_init_set_ui(val, this->zero_value_size_); - Bexpression* blength = - this->backend()->integer_constant_expression(bint_type, val); - mpz_clear(val); + Expression* e = Expression::make_integer_int64(this->zero_value_size_, + int_type, + Linemap::unknown_location()); + Translate_context context(this, NULL, NULL, NULL); + Bexpression* blength = e->get_backend(&context); Btype* barray_type = this->backend()->array_type(bbtype_type, blength); diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index c5a71abea94..6d082367928 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -746,9 +746,9 @@ class Gogo // The special zero value variable. Named_object* zero_value_; // The size of the zero value variable. - unsigned long zero_value_size_; + int64_t zero_value_size_; // The alignment of the zero value variable, in bytes. - unsigned long zero_value_align_; + int64_t zero_value_align_; // Whether pkgpath_ has been set. bool pkgpath_set_; // Whether an explicit package path was set by -fgo-pkgpath. diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index d3047575750..785889fb5c8 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -2533,15 +2533,12 @@ Type::is_backend_type_size_known(Gogo* gogo) // the backend. bool -Type::backend_type_size(Gogo* gogo, unsigned long *psize) +Type::backend_type_size(Gogo* gogo, int64_t *psize) { if (!this->is_backend_type_size_known(gogo)) return false; Btype* bt = this->get_backend_placeholder(gogo); - size_t size = gogo->backend()->type_size(bt); - *psize = static_cast(size); - if (*psize != size) - return false; + *psize = gogo->backend()->type_size(bt); return true; } @@ -2549,15 +2546,12 @@ Type::backend_type_size(Gogo* gogo, unsigned long *psize) // the alignment in bytes and return true. Otherwise, return false. bool -Type::backend_type_align(Gogo* gogo, unsigned long *palign) +Type::backend_type_align(Gogo* gogo, int64_t *palign) { if (!this->is_backend_type_size_known(gogo)) return false; Btype* bt = this->get_backend_placeholder(gogo); - size_t align = gogo->backend()->type_alignment(bt); - *palign = static_cast(align); - if (*palign != align) - return false; + *palign = gogo->backend()->type_alignment(bt); return true; } @@ -2565,15 +2559,12 @@ Type::backend_type_align(Gogo* gogo, unsigned long *palign) // field. bool -Type::backend_type_field_align(Gogo* gogo, unsigned long *palign) +Type::backend_type_field_align(Gogo* gogo, int64_t *palign) { if (!this->is_backend_type_size_known(gogo)) return false; Btype* bt = this->get_backend_placeholder(gogo); - size_t a = gogo->backend()->type_field_alignment(bt); - *palign = static_cast(a); - if (*palign != a) - return false; + *palign = gogo->backend()->type_field_alignment(bt); return true; } @@ -4780,7 +4771,7 @@ Struct_type::do_compare_is_identity(Gogo* gogo) const Struct_field_list* fields = this->fields_; if (fields == NULL) return true; - unsigned long offset = 0; + int64_t offset = 0; for (Struct_field_list::const_iterator pf = fields->begin(); pf != fields->end(); ++pf) @@ -4791,7 +4782,7 @@ Struct_type::do_compare_is_identity(Gogo* gogo) if (!pf->type()->compare_is_identity(gogo)) return false; - unsigned long field_align; + int64_t field_align; if (!pf->type()->backend_type_align(gogo, &field_align)) return false; if ((offset & (field_align - 1)) != 0) @@ -4802,13 +4793,13 @@ Struct_type::do_compare_is_identity(Gogo* gogo) return false; } - unsigned long field_size; + int64_t field_size; if (!pf->type()->backend_type_size(gogo, &field_size)) return false; offset += field_size; } - unsigned long struct_size; + int64_t struct_size; if (!this->backend_type_size(gogo, &struct_size)) return false; if (offset != struct_size) @@ -5571,15 +5562,12 @@ Struct_type::do_mangled_name(Gogo* gogo, std::string* ret) const bool Struct_type::backend_field_offset(Gogo* gogo, unsigned int index, - unsigned int* poffset) + int64_t* poffset) { if (!this->is_backend_type_size_known(gogo)) return false; Btype* bt = this->get_backend_placeholder(gogo); - size_t offset = gogo->backend()->type_field_offset(bt, index); - *poffset = static_cast(offset); - if (*poffset != offset) - return false; + *poffset = gogo->backend()->type_field_offset(bt, index); return true; } @@ -5764,10 +5752,17 @@ Array_type::verify_length() return false; } + Type* int_type = Type::lookup_integer_type("int"); + unsigned int tbits = int_type->integer_type()->bits(); unsigned long val; switch (nc.to_unsigned_long(&val)) { case Numeric_constant::NC_UL_VALID: + if (sizeof(val) >= tbits / 8 && val >> (tbits - 1) != 0) + { + error_at(this->length_->location(), "array bound overflows"); + return false; + } break; case Numeric_constant::NC_UL_NOTINT: error_at(this->length_->location(), "array bound truncated to integer"); @@ -5776,21 +5771,23 @@ Array_type::verify_length() error_at(this->length_->location(), "negative array bound"); return false; case Numeric_constant::NC_UL_BIG: - error_at(this->length_->location(), "array bound overflows"); - return false; + { + mpz_t val; + if (!nc.to_int(&val)) + go_unreachable(); + unsigned int bits = mpz_sizeinbase(val, 2); + mpz_clear(val); + if (bits >= tbits) + { + error_at(this->length_->location(), "array bound overflows"); + return false; + } + } + break; default: go_unreachable(); } - Type* int_type = Type::lookup_integer_type("int"); - unsigned int tbits = int_type->integer_type()->bits(); - if (sizeof(val) <= tbits * 8 - && val >> (tbits - 1) != 0) - { - error_at(this->length_->location(), "array bound overflows"); - return false; - } - return true; } @@ -5820,8 +5817,8 @@ Array_type::do_compare_is_identity(Gogo* gogo) return false; // If there is any padding, then we can't use memcmp. - unsigned long size; - unsigned long align; + int64_t size; + int64_t align; if (!this->element_type_->backend_type_size(gogo, &size) || !this->element_type_->backend_type_align(gogo, &align)) return false; @@ -6417,7 +6414,7 @@ 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); - size_t element_size = gogo->backend()->type_size(ebtype); + int64_t element_size = gogo->backend()->type_size(ebtype); Type* uintptr_type = Type::lookup_integer_type("uintptr"); unsigned long opval = element_size == 0 ? GC_APTR : GC_SLICE; @@ -6444,8 +6441,8 @@ Array_type::array_gc_symbol(Gogo* gogo, Expression_list** vals, go_assert(saw_errors()); Btype* pbtype = gogo->backend()->pointer_type(gogo->backend()->void_type()); - size_t pwidth = gogo->backend()->type_size(pbtype); - size_t iwidth = gogo->backend()->type_size(this->get_backend(gogo)); + int64_t pwidth = gogo->backend()->type_size(pbtype); + int64_t iwidth = gogo->backend()->type_size(this->get_backend(gogo)); Type* element_type = this->element_type(); if (bound < 1 || !element_type->has_pointer()) diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index acc8af5df03..82d50812228 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -942,18 +942,18 @@ class Type // in bytes and return true. Otherwise, return false. This queries // the backend. bool - backend_type_size(Gogo*, unsigned long* psize); + backend_type_size(Gogo*, int64_t* psize); // If the alignment of the type can be determined, set *PALIGN to // the alignment in bytes and return true. Otherwise, return false. bool - backend_type_align(Gogo*, unsigned long* palign); + backend_type_align(Gogo*, int64_t* palign); // If the alignment of a struct field of this type can be // determined, set *PALIGN to the alignment in bytes and return // true. Otherwise, return false. bool - backend_type_field_align(Gogo*, unsigned long* palign); + backend_type_field_align(Gogo*, int64_t* palign); // Whether the backend size is known. bool @@ -2263,7 +2263,7 @@ class Struct_type : public Type // determined, set *POFFSET to the offset in bytes and return true. // Otherwise, return false. bool - backend_field_offset(Gogo*, unsigned int index, unsigned int* poffset); + backend_field_offset(Gogo*, unsigned int index, int64_t* poffset); // Finish the backend representation of all the fields. void -- 2.30.2