diff mbox

Go patch committed: Fix 32-bit host to 64-bit target cross-compilation

Message ID CAOyqgcVfivyKQYhMjfPObTaedF+aXqkt64UfTi-k6Jjb54aNTQ@mail.gmail.com
State New
Headers show

Commit Message

Ian Lance Taylor Feb. 3, 2015, 3:33 a.m. UTC
In the backend interface for the Go frontend, I foolishly used size_t
for the size of a type.  That usually works, but fails when compiling
on a 32-bit host for a 64-bit target and compiling code that uses very
large types.  The maximum type size for any Go target is a signed
64-bit number, so for simplicity I changed the type size and alignment
routines to all return int64_t.  The rest of this patch adjusts the Go
frontend to deal with that correctly, and to fix the overflow checks
when dealing with types whose size does not fit into a host unsigned
long.  This is PRs 64836 and 64838.  Bootstrapped and ran Go testsuite
on x86_64-unknown-linux-gnu.  Committed to mainline.

Ian


2015-02-02  Ian Lance Taylor  <iant@google.com>

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.
diff mbox

Patch

Index: gcc/go/go-gcc.cc
===================================================================
--- gcc/go/go-gcc.cc	(revision 219876)
+++ gcc/go/go-gcc.cc	(working copy)
@@ -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(Bt
 
 // 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<size_t>(val_wide);
-  gcc_assert(ret == val_wide);
+  int64_t ret = static_cast<int64_t>(val_wide);
+  gcc_assert(ret >= 0 && static_cast<unsigned HOST_WIDE_INT>(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*
 
 // 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* bt
       gcc_assert(field != NULL_TREE);
     }
   HOST_WIDE_INT offset_wide = int_byte_position(field);
-  gcc_assert(offset_wide >= 0);
-  size_t ret = static_cast<size_t>(offset_wide);
-  gcc_assert(ret == static_cast<unsigned HOST_WIDE_INT>(offset_wide));
+  int64_t ret = static_cast<int64_t>(offset_wide);
+  gcc_assert(ret == offset_wide);
   return ret;
 }
 
@@ -2609,7 +2608,7 @@  Gcc_backend::temporary_variable(Bfunctio
 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)
Index: gcc/go/gofrontend/backend.h
===================================================================
--- gcc/go/gofrontend/backend.h	(revision 219876)
+++ gcc/go/gofrontend/backend.h	(working copy)
@@ -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.
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 219984)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -181,8 +181,10 @@  Expression::convert_for_assignment(Gogo*
       // 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, Ty
   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<unsigned long>(val);
+      if (static_cast<int64_t>(ul) == val)
+	{
+	  mpz_init_set_ui(*zval, ul);
+	  return;
+	}
+    }
+  uint64_t uv;
+  if (val >= 0)
+    uv = static_cast<uint64_t>(val);
+  else
+    uv = static_cast<uint64_t>(- val);
+  unsigned long ul = uv & 0xffffffffUL;
+  mpz_init_set_ui(*zval, ul);
+  mpz_t hval;
+  mpz_init_set_ui(hval, static_cast<unsigned long>(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,
       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(Transla
         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_cons
       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_cons
       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_cons
       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_cons
             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_cons
             }
           break;
         }
-      nc->set_unsigned_long(Type::lookup_integer_type("uintptr"),
-			    static_cast<unsigned long>(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(
 
 	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(
         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(
 	    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(Tra
 {
   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(Tra
     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_b
   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);
 }
 
Index: gcc/go/gofrontend/expressions.h
===================================================================
--- gcc/go/gofrontend/expressions.h	(revision 219876)
+++ gcc/go/gofrontend/expressions.h	(working copy)
@@ -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*
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 220291)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -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);
 
Index: gcc/go/gofrontend/gogo.h
===================================================================
--- gcc/go/gofrontend/gogo.h	(revision 220268)
+++ gcc/go/gofrontend/gogo.h	(working copy)
@@ -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.
Index: gcc/go/gofrontend/types.cc
===================================================================
--- gcc/go/gofrontend/types.cc	(revision 219876)
+++ gcc/go/gofrontend/types.cc	(working copy)
@@ -2533,15 +2533,12 @@  Type::is_backend_type_size_known(Gogo* g
 // 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<unsigned long>(size);
-  if (*psize != size)
-    return false;
+  *psize = gogo->backend()->type_size(bt);
   return true;
 }
 
@@ -2549,15 +2546,12 @@  Type::backend_type_size(Gogo* gogo, unsi
 // 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<unsigned long>(align);
-  if (*palign != align)
-    return false;
+  *palign = gogo->backend()->type_alignment(bt);
   return true;
 }
 
@@ -2565,15 +2559,12 @@  Type::backend_type_align(Gogo* gogo, uns
 // 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<unsigned long>(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
   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
       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
 	  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,
 
 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<unsigned int>(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*
     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,
   // 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,
     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())
Index: gcc/go/gofrontend/types.h
===================================================================
--- gcc/go/gofrontend/types.h	(revision 219876)
+++ gcc/go/gofrontend/types.h	(working copy)
@@ -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