compiler, runtime: harmonize types referenced by both C and Go

Compiling with LTO revealed a number of cases in the runtime and
standard library where C and Go disagreed about the type of an object or
function (or where Go and code generated by the compiler disagreed). In
all cases the underlying representation was the same (e.g., uintptr vs.
void*), so this wasn't causing actual problems, but it did result in a
number of annoying warnings when compiling with LTO.

Change-Id: I9dbb285c1d038e9fd28bc2fc4584b7c2064d7100
Reviewed-on: https://go-review.googlesource.com/c/160700
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/go/expressions.cc b/go/expressions.cc
index 40b9f18..d46c754 100644
--- a/go/expressions.cc
+++ b/go/expressions.cc
@@ -1344,7 +1344,7 @@
   if (Func_descriptor_expression::descriptor_type != NULL)
     return;
   Type* uintptr_type = Type::lookup_integer_type("uintptr");
-  Type* struct_type = Type::make_builtin_struct_type(1, "code", uintptr_type);
+  Type* struct_type = Type::make_builtin_struct_type(1, "fn", uintptr_type);
   Func_descriptor_expression::descriptor_type =
     Type::make_builtin_named_type("functionDescriptor", struct_type);
 }
@@ -3874,7 +3874,9 @@
 	      || et->integer_type() != NULL
               || et->is_nil_type());
   else if (et->is_unsafe_pointer_type())
-    go_assert(t->points_to() != NULL);
+    go_assert(t->points_to() != NULL
+	      || (t->integer_type() != NULL
+		  && t->integer_type() == Type::lookup_integer_type("uintptr")->real_type()));
   else if (t->interface_type() != NULL)
     {
       bool empty_iface = t->interface_type()->is_empty();
diff --git a/go/gogo.cc b/go/gogo.cc
index 79c3cc9..9bd25fa 100644
--- a/go/gogo.cc
+++ b/go/gogo.cc
@@ -4513,13 +4513,13 @@
     builtin_return_address =
       Gogo::declare_builtin_rf_address("__builtin_return_address");
 
+  Type* uintptr_type = Type::lookup_integer_type("uintptr");
   static Named_object* can_recover;
   if (can_recover == NULL)
     {
       const Location bloc = Linemap::predeclared_location();
       Typed_identifier_list* param_types = new Typed_identifier_list();
-      Type* voidptr_type = Type::make_pointer_type(Type::make_void_type());
-      param_types->push_back(Typed_identifier("a", voidptr_type, bloc));
+      param_types->push_back(Typed_identifier("a", uintptr_type, bloc));
       Type* boolean_type = Type::lookup_bool_type();
       Typed_identifier_list* results = new Typed_identifier_list();
       results->push_back(Typed_identifier("", boolean_type, bloc));
@@ -4539,6 +4539,7 @@
   args->push_back(zexpr);
 
   Expression* call = Expression::make_call(fn, args, false, location);
+  call = Expression::make_unsafe_cast(uintptr_type, call, location);
 
   args = new Expression_list();
   args->push_back(call);
diff --git a/go/runtime.cc b/go/runtime.cc
index bb30cc1..7ecbf68 100644
--- a/go/runtime.cc
+++ b/go/runtime.cc
@@ -60,8 +60,6 @@
   RFT_IFACE,
   // Go type interface{}, C type struct __go_empty_interface.
   RFT_EFACE,
-  // Go type func(unsafe.Pointer), C type void (*) (void *).
-  RFT_FUNC_PTR,
   // Pointer to Go type descriptor.
   RFT_TYPE,
   // [2]string.
@@ -176,15 +174,6 @@
 	  t = Type::make_empty_interface_type(bloc);
 	  break;
 
-	case RFT_FUNC_PTR:
-	  {
-	    Typed_identifier_list* param_types = new Typed_identifier_list();
-	    Type* ptrtype = runtime_function_type(RFT_POINTER);
-	    param_types->push_back(Typed_identifier("", ptrtype, bloc));
-	    t = Type::make_function_type(NULL, param_types, NULL, bloc);
-	  }
-	  break;
-
 	case RFT_TYPE:
 	  t = Type::make_type_descriptor_ptr_type();
 	  break;
@@ -265,7 +254,6 @@
     case RFT_COMPLEX128:
     case RFT_STRING:
     case RFT_POINTER:
-    case RFT_FUNC_PTR:
       {
 	Type* t = runtime_function_type(bft);
 	if (!Type::are_identical(t, e->type(), true, NULL))
diff --git a/go/runtime.def b/go/runtime.def
index ded6251..273c860 100644
--- a/go/runtime.def
+++ b/go/runtime.def
@@ -168,10 +168,10 @@
 DEF_GO_RUNTIME(DEFERREDRECOVER, "runtime.deferredrecover", P0(), R1(EFACE))
 
 // Decide whether this function can call recover.
-DEF_GO_RUNTIME(CANRECOVER, "runtime.canrecover", P1(POINTER), R1(BOOL))
+DEF_GO_RUNTIME(CANRECOVER, "runtime.canrecover", P1(UINTPTR), R1(BOOL))
 
 // Set the return address for defer in a defer thunk.
-DEF_GO_RUNTIME(SETDEFERRETADDR, "runtime.setdeferretaddr", P1(POINTER),
+DEF_GO_RUNTIME(SETDEFERRETADDR, "runtime.setdeferretaddr", P1(UINTPTR),
 	       R1(BOOL))
 
 // Check for a deferred function in an exception handler.
@@ -213,10 +213,10 @@
 DEF_GO_RUNTIME(NEW, "runtime.newobject", P1(TYPE), R1(POINTER))
 
 // Start a new goroutine.
-DEF_GO_RUNTIME(GO, "__go_go", P2(FUNC_PTR, POINTER), R0())
+DEF_GO_RUNTIME(GO, "__go_go", P2(UINTPTR, POINTER), R1(POINTER))
 
 // Defer a function.
-DEF_GO_RUNTIME(DEFERPROC, "runtime.deferproc", P3(BOOLPTR, FUNC_PTR, POINTER),
+DEF_GO_RUNTIME(DEFERPROC, "runtime.deferproc", P3(BOOLPTR, UINTPTR, POINTER),
 	       R0())
 
 
@@ -303,7 +303,7 @@
 
 // Set *dst = src where dst is a pointer to a pointer and src is a pointer.
 DEF_GO_RUNTIME(GCWRITEBARRIER, "runtime.gcWriteBarrier",
-	       P2(POINTER, POINTER), R0())
+	       P2(POINTER, UINTPTR), R0())
 
 // Set *dst = *src for an arbitrary type.
 DEF_GO_RUNTIME(TYPEDMEMMOVE, "runtime.typedmemmove",
diff --git a/go/wb.cc b/go/wb.cc
index 8620e40..04619d3 100644
--- a/go/wb.cc
+++ b/go/wb.cc
@@ -664,11 +664,19 @@
     {
       Location bloc = Linemap::predeclared_location();
 
-      // We pretend that writeBarrier is a uint32, so that we do a
-      // 32-bit load.  That is what the gc toolchain does.
-      Type* uint32_type = Type::lookup_integer_type("uint32");
-      Variable* var = new Variable(uint32_type, NULL, true, false, false,
-				   bloc);
+      Type* bool_type = Type::lookup_bool_type();
+      Array_type* pad_type = Type::make_array_type(this->lookup_global("byte")->type_value(),
+						   Expression::make_integer_ul(3, NULL, bloc));
+      Type* uint64_type = Type::lookup_integer_type("uint64");
+      Type* wb_type = Type::make_builtin_struct_type(5,
+						     "enabled", bool_type,
+						     "pad", pad_type,
+						     "needed", bool_type,
+						     "cgo", bool_type,
+						     "alignme", uint64_type);
+
+      Variable* var = new Variable(wb_type, NULL,
+				    true, false, false, bloc);
 
       bool add_to_globals;
       Package* package = this->add_imported_package("runtime", "_", false,
@@ -850,8 +858,12 @@
     case Type::TYPE_FUNCTION:
     case Type::TYPE_MAP:
     case Type::TYPE_CHANNEL:
-      // These types are all represented by a single pointer.
-      call = Runtime::make_call(Runtime::GCWRITEBARRIER, loc, 2, lhs, rhs);
+      {
+	// These types are all represented by a single pointer.
+	Type* uintptr_type = Type::lookup_integer_type("uintptr");
+	rhs = Expression::make_unsafe_cast(uintptr_type, rhs, loc);
+	call = Runtime::make_call(Runtime::GCWRITEBARRIER, loc, 2, lhs, rhs);
+      }
       break;
 
     case Type::TYPE_STRING:
@@ -882,7 +894,17 @@
 {
   Location loc = without->location();
   Named_object* wb = this->write_barrier_variable();
+  // We pretend that writeBarrier is a uint32, so that we do a
+  // 32-bit load.  That is what the gc toolchain does.
+  Type* void_type = Type::make_void_type();
+  Type* unsafe_pointer_type = Type::make_pointer_type(void_type);
+  Type* uint32_type = Type::lookup_integer_type("uint32");
+  Type* puint32_type = Type::make_pointer_type(uint32_type);
   Expression* ref = Expression::make_var_reference(wb, loc);
+  ref = Expression::make_unary(OPERATOR_AND, ref, loc);
+  ref = Expression::make_cast(unsafe_pointer_type, ref, loc);
+  ref = Expression::make_cast(puint32_type, ref, loc);
+  ref = Expression::make_unary(OPERATOR_MULT, ref, loc);
   Expression* zero = Expression::make_integer_ul(0, ref->type(), loc);
   Expression* cond = Expression::make_binary(OPERATOR_EQEQ, ref, zero, loc);
 
diff --git a/libgo/go/runtime/mgc.go b/libgo/go/runtime/mgc.go
index 0973f1d..b8c91ac 100644
--- a/libgo/go/runtime/mgc.go
+++ b/libgo/go/runtime/mgc.go
@@ -238,7 +238,7 @@
 var gcphase uint32
 
 // The compiler knows about this variable.
-// If you change it, you must change builtin/runtime.go, too.
+// If you change it, you must change gofrontend/wb.cc, too.
 // If you change the first four bytes, you must also change the write
 // barrier insertion code.
 var writeBarrier struct {
diff --git a/libgo/go/runtime/netpoll.go b/libgo/go/runtime/netpoll.go
index 6d39114..3515922 100644
--- a/libgo/go/runtime/netpoll.go
+++ b/libgo/go/runtime/netpoll.go
@@ -112,7 +112,7 @@
 }
 
 //go:linkname poll_runtime_pollOpen internal..z2fpoll.runtime_pollOpen
-func poll_runtime_pollOpen(fd uintptr) (*pollDesc, int) {
+func poll_runtime_pollOpen(fd uintptr) (uintptr, int) {
 	pd := pollcache.alloc()
 	lock(&pd.lock)
 	if pd.wg != 0 && pd.wg != pdReady {
@@ -133,11 +133,12 @@
 
 	var errno int32
 	errno = netpollopen(fd, pd)
-	return pd, int(errno)
+	return uintptr(unsafe.Pointer(pd)), int(errno)
 }
 
 //go:linkname poll_runtime_pollClose internal..z2fpoll.runtime_pollClose
-func poll_runtime_pollClose(pd *pollDesc) {
+func poll_runtime_pollClose(ctx uintptr) {
+	pd := (*pollDesc)(unsafe.Pointer(ctx))
 	if !pd.closing {
 		throw("runtime: close polldesc w/o unblock")
 	}
@@ -159,7 +160,8 @@
 }
 
 //go:linkname poll_runtime_pollReset internal..z2fpoll.runtime_pollReset
-func poll_runtime_pollReset(pd *pollDesc, mode int) int {
+func poll_runtime_pollReset(ctx uintptr, mode int) int {
+	pd := (*pollDesc)(unsafe.Pointer(ctx))
 	err := netpollcheckerr(pd, int32(mode))
 	if err != 0 {
 		return err
@@ -173,7 +175,8 @@
 }
 
 //go:linkname poll_runtime_pollWait internal..z2fpoll.runtime_pollWait
-func poll_runtime_pollWait(pd *pollDesc, mode int) int {
+func poll_runtime_pollWait(ctx uintptr, mode int) int {
+	pd := (*pollDesc)(unsafe.Pointer(ctx))
 	err := netpollcheckerr(pd, int32(mode))
 	if err != 0 {
 		return err
@@ -195,7 +198,8 @@
 }
 
 //go:linkname poll_runtime_pollWaitCanceled internal..z2fpoll.runtime_pollWaitCanceled
-func poll_runtime_pollWaitCanceled(pd *pollDesc, mode int) {
+func poll_runtime_pollWaitCanceled(ctx uintptr, mode int) {
+	pd := (*pollDesc)(unsafe.Pointer(ctx))
 	// This function is used only on windows after a failed attempt to cancel
 	// a pending async IO operation. Wait for ioready, ignore closing or timeouts.
 	for !netpollblock(pd, int32(mode), true) {
@@ -203,7 +207,8 @@
 }
 
 //go:linkname poll_runtime_pollSetDeadline internal..z2fpoll.runtime_pollSetDeadline
-func poll_runtime_pollSetDeadline(pd *pollDesc, d int64, mode int) {
+func poll_runtime_pollSetDeadline(ctx uintptr, d int64, mode int) {
+	pd := (*pollDesc)(unsafe.Pointer(ctx))
 	lock(&pd.lock)
 	if pd.closing {
 		unlock(&pd.lock)
@@ -288,7 +293,8 @@
 }
 
 //go:linkname poll_runtime_pollUnblock internal..z2fpoll.runtime_pollUnblock
-func poll_runtime_pollUnblock(pd *pollDesc) {
+func poll_runtime_pollUnblock(ctx uintptr) {
+	pd := (*pollDesc)(unsafe.Pointer(ctx))
 	lock(&pd.lock)
 	if pd.closing {
 		throw("runtime: unblock on closing polldesc")
diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go
index b4fa88f..e937563 100644
--- a/libgo/go/runtime/proc.go
+++ b/libgo/go/runtime/proc.go
@@ -153,7 +153,7 @@
 var initSigmask sigset
 
 // The main goroutine.
-func main() {
+func main(unsafe.Pointer) {
 	g := getg()
 
 	// Max stack size is 1 GB on 64-bit, 250 MB on 32-bit.
diff --git a/libgo/go/runtime/stubs.go b/libgo/go/runtime/stubs.go
index f2b0ee8..9f5191b 100644
--- a/libgo/go/runtime/stubs.go
+++ b/libgo/go/runtime/stubs.go
@@ -283,8 +283,7 @@
 // For gccgo this is in the C code.
 func osyield()
 
-// For gccgo this can be called directly.
-//extern syscall
+//extern __go_syscall6
 func syscall(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) uintptr
 
 // For gccgo, to communicate from the C code to the Go code.
diff --git a/libgo/go/syscall/syscall_unix.go b/libgo/go/syscall/syscall_unix.go
index 450173a..b786dc5 100644
--- a/libgo/go/syscall/syscall_unix.go
+++ b/libgo/go/syscall/syscall_unix.go
@@ -19,11 +19,8 @@
 	Stderr = 2
 )
 
-//extern syscall
-func c_syscall32(trap int32, a1, a2, a3, a4, a5, a6 int32) int32
-
-//extern syscall
-func c_syscall64(trap int64, a1, a2, a3, a4, a5, a6 int64) int64
+//extern __go_syscall6
+func syscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) uintptr
 
 const (
 	darwin64Bit    = runtime.GOOS == "darwin" && sizeofPtr == 8
@@ -38,14 +35,7 @@
 func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
 	Entersyscall()
 	SetErrno(0)
-	var r uintptr
-	if unsafe.Sizeof(r) == 4 {
-		r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0)
-		r = uintptr(r1)
-	} else {
-		r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0)
-		r = uintptr(r1)
-	}
+	r := syscall6(trap, a1, a2, a3, 0, 0, 0)
 	err = GetErrno()
 	Exitsyscall()
 	return r, 0, err
@@ -54,47 +44,22 @@
 func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
 	Entersyscall()
 	SetErrno(0)
-	var r uintptr
-	if unsafe.Sizeof(r) == 4 {
-		r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3),
-			int32(a4), int32(a5), int32(a6))
-		r = uintptr(r1)
-	} else {
-		r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3),
-			int64(a4), int64(a5), int64(a6))
-		r = uintptr(r1)
-	}
+	r := syscall6(trap, a1, a2, a3, a4, a5, a6)
 	err = GetErrno()
 	Exitsyscall()
 	return r, 0, err
 }
 
 func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) {
-	var r uintptr
 	SetErrno(0)
-	if unsafe.Sizeof(r) == 4 {
-		r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0)
-		r = uintptr(r1)
-	} else {
-		r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0)
-		r = uintptr(r1)
-	}
+	r := syscall6(trap, a1, a2, a3, 0, 0, 0)
 	err = GetErrno()
 	return r, 0, err
 }
 
 func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) {
-	var r uintptr
 	SetErrno(0)
-	if unsafe.Sizeof(r) == 4 {
-		r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3),
-			int32(a4), int32(a5), int32(a6))
-		r = uintptr(r1)
-	} else {
-		r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3),
-			int64(a4), int64(a5), int64(a6))
-		r = uintptr(r1)
-	}
+	r := syscall6(trap, a1, a2, a3, a4, a5, a6)
 	err = GetErrno()
 	return r, 0, err
 }
diff --git a/libgo/go/syscall/wait.c b/libgo/go/syscall/wait.c
index 9555a41..0b234d0 100644
--- a/libgo/go/syscall/wait.c
+++ b/libgo/go/syscall/wait.c
@@ -65,10 +65,10 @@
   return WCOREDUMP (*w) != 0;
 }
 
-extern int ExitStatus (uint32_t *w)
+extern intgo ExitStatus (uint32_t *w)
   __asm__ (GOSYM_PREFIX "syscall.WaitStatus.ExitStatus");
 
-int
+intgo
 ExitStatus (uint32_t *w)
 {
   if (!WIFEXITED (*w))
@@ -76,10 +76,10 @@
   return WEXITSTATUS (*w);
 }
 
-extern int Signal (uint32_t *w)
+extern intgo Signal (uint32_t *w)
   __asm__ (GOSYM_PREFIX "syscall.WaitStatus.Signal");
 
-int
+intgo
 Signal (uint32_t *w)
 {
   if (!WIFSIGNALED (*w))
@@ -87,10 +87,10 @@
   return WTERMSIG (*w);
 }
 
-extern int StopSignal (uint32_t *w)
+extern intgo StopSignal (uint32_t *w)
   __asm__ (GOSYM_PREFIX "syscall.WaitStatus.StopSignal");
 
-int
+intgo
 StopSignal (uint32_t *w)
 {
   if (!WIFSTOPPED (*w))
@@ -98,10 +98,10 @@
   return WSTOPSIG (*w);
 }
 
-extern int TrapCause (uint32_t *w)
+extern intgo TrapCause (uint32_t *w)
   __asm__ (GOSYM_PREFIX "syscall.WaitStatus.TrapCause");
 
-int
+intgo
 TrapCause (uint32_t *w __attribute__ ((unused)))
 {
 #ifndef __linux__
diff --git a/libgo/runtime/go-caller.c b/libgo/runtime/go-caller.c
index 6fe4340..2143446 100644
--- a/libgo/runtime/go-caller.c
+++ b/libgo/runtime/go-caller.c
@@ -192,12 +192,12 @@
   _Bool ok;
 };
 
-struct caller_ret Caller (int n) __asm__ (GOSYM_PREFIX "runtime.Caller");
+struct caller_ret Caller (intgo n) __asm__ (GOSYM_PREFIX "runtime.Caller");
 
 /* Implement runtime.Caller.  */
 
 struct caller_ret
-Caller (int skip)
+Caller (intgo skip)
 {
   struct caller_ret ret;
   Location loc;
diff --git a/libgo/runtime/go-callers.c b/libgo/runtime/go-callers.c
index 7ea7085..a72b4e8 100644
--- a/libgo/runtime/go-callers.c
+++ b/libgo/runtime/go-callers.c
@@ -236,11 +236,11 @@
   return data.index;
 }
 
-int Callers (int, struct __go_open_array)
+intgo Callers (intgo, struct __go_open_array)
   __asm__ (GOSYM_PREFIX "runtime.Callers");
 
-int
-Callers (int skip, struct __go_open_array pc)
+intgo
+Callers (intgo skip, struct __go_open_array pc)
 {
   Location *locbuf;
   int ret;
diff --git a/libgo/runtime/go-libmain.c b/libgo/runtime/go-libmain.c
index 4f47639..00a8e6b 100644
--- a/libgo/runtime/go-libmain.c
+++ b/libgo/runtime/go-libmain.c
@@ -231,7 +231,7 @@
   setpagesize (getpagesize ());
   runtime_sched = runtime_getsched();
   runtime_schedinit ();
-  __go_go (runtime_main, NULL);
+  __go_go ((uintptr)(runtime_main), NULL);
   runtime_mstart (runtime_m ());
   abort ();
 }
diff --git a/libgo/runtime/go-main.c b/libgo/runtime/go-main.c
index 1048161..301ac4e 100644
--- a/libgo/runtime/go-main.c
+++ b/libgo/runtime/go-main.c
@@ -55,7 +55,7 @@
   setpagesize (getpagesize ());
   runtime_sched = runtime_getsched();
   runtime_schedinit ();
-  __go_go (runtime_main, NULL);
+  __go_go ((uintptr)(runtime_main), NULL);
   runtime_mstart (runtime_m ());
   abort ();
 }
diff --git a/libgo/runtime/go-reflect-call.c b/libgo/runtime/go-reflect-call.c
index 6a9a7f3..abd598b 100644
--- a/libgo/runtime/go-reflect-call.c
+++ b/libgo/runtime/go-reflect-call.c
@@ -229,7 +229,8 @@
 
   call_result = (unsigned char *) malloc (go_results_size (func_type));
 
-  ffi_call_go (&cif, func_val->fn, call_result, params, func_val);
+  ffi_call_go (&cif, (void (*)(void)) func_val->fn, call_result, params,
+	       func_val);
 
   /* Some day we may need to free result values if RESULTS is
      NULL.  */
diff --git a/libgo/runtime/go-varargs.c b/libgo/runtime/go-varargs.c
index 691ee56..dda9959 100644
--- a/libgo/runtime/go-varargs.c
+++ b/libgo/runtime/go-varargs.c
@@ -89,3 +89,14 @@
 }
 
 #endif
+
+// __go_syscall6 is called by both the runtime and syscall packages.
+// We use uintptr_t to make sure that the types match, since the Go
+// and C "int" types are not the same.
+
+uintptr_t
+__go_syscall6(uintptr_t flag, uintptr_t a1, uintptr_t a2, uintptr_t a3,
+	      uintptr_t a4, uintptr_t a5, uintptr_t a6)
+{
+  return syscall (flag, a1, a2, a3, a4, a5, a6);
+}
diff --git a/libgo/runtime/panic.c b/libgo/runtime/panic.c
index 9cd69ee..9025505 100644
--- a/libgo/runtime/panic.c
+++ b/libgo/runtime/panic.c
@@ -34,7 +34,7 @@
 			runtime_throw("panic holding locks");
 		}
 	}
-	runtime_newErrorCString(s, &err);
+	runtime_newErrorCString((uintptr) s, &err);
 	runtime_panic(err);
 }
 
diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h
index 5da34fb..a6135b0 100644
--- a/libgo/runtime/runtime.h
+++ b/libgo/runtime/runtime.h
@@ -94,7 +94,7 @@
 
 struct FuncVal
 {
-	void	(*fn)(void);
+	uintptr_t fn;
 	// variable-size, fn-specific data here
 };
 
@@ -295,7 +295,7 @@
   __asm__ (GOSYM_PREFIX "runtime.entersyscall");
 void	runtime_entersyscallblock()
   __asm__ (GOSYM_PREFIX "runtime.entersyscallblock");
-G*	__go_go(void (*pfn)(void*), void*);
+G*	__go_go(uintptr, void*);
 int32	runtime_callers(int32, Location*, int32, bool keep_callers);
 int64	runtime_nanotime(void)	// monotonic time
   __asm__(GOSYM_PREFIX "runtime.nanotime");
@@ -389,7 +389,7 @@
 /*
  * runtime c-called (but written in Go)
  */
-void	runtime_newErrorCString(const char*, Eface*)
+void	runtime_newErrorCString(uintptr, Eface*)
      __asm__ (GOSYM_PREFIX "runtime.NewErrorCString");
 
 /*
diff --git a/libgo/runtime/stack.c b/libgo/runtime/stack.c
index 2d5d1e0..be5e523 100644
--- a/libgo/runtime/stack.c
+++ b/libgo/runtime/stack.c
@@ -20,7 +20,7 @@
 // tail call to doscanstack1.
 #pragma GCC optimize ("-fno-optimize-sibling-calls")
 
-extern void scanstackblock(void *addr, uintptr size, void *gcw)
+extern void scanstackblock(uintptr addr, uintptr size, void *gcw)
   __asm__("runtime.scanstackblock");
 
 static bool doscanstack1(G*, void*)
@@ -84,11 +84,11 @@
 		}
 	}
 	if(sp != nil) {
-		scanstackblock(sp, (uintptr)(spsize), gcw);
+		scanstackblock((uintptr)(sp), (uintptr)(spsize), gcw);
 		while((sp = __splitstack_find(next_segment, next_sp,
 					      &spsize, &next_segment,
 					      &next_sp, &initial_sp)) != nil)
-			scanstackblock(sp, (uintptr)(spsize), gcw);
+			scanstackblock((uintptr)(sp), (uintptr)(spsize), gcw);
 	}
 #else
 	byte* bottom;