-4a6f2bb2c8d3f00966f001a5b03c57cb4a278265
+03e28273a4fcb114f5204d52ed107591404002f4
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
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);
}
|| 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();
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));
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);
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.
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;
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))
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.
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())
// 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",
{
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,
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:
{
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);
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 {
}
//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 {
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")
}
}
//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
}
//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
}
//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) {
}
//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)
}
//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")
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.
// 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.
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
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
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
}
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))
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))
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))
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__
_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;
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;
setpagesize (getpagesize ());
runtime_sched = runtime_getsched();
runtime_schedinit ();
- __go_go (runtime_main, NULL);
+ __go_go ((uintptr)(runtime_main), NULL);
runtime_mstart (runtime_m ());
abort ();
}
setpagesize (getpagesize ());
runtime_sched = runtime_getsched();
runtime_schedinit ();
- __go_go (runtime_main, NULL);
+ __go_go ((uintptr)(runtime_main), NULL);
runtime_mstart (runtime_m ());
abort ();
}
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. */
}
#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);
+}
runtime_throw("panic holding locks");
}
}
- runtime_newErrorCString(s, &err);
+ runtime_newErrorCString((uintptr) s, &err);
runtime_panic(err);
}
struct FuncVal
{
- void (*fn)(void);
+ uintptr_t fn;
// variable-size, fn-specific data here
};
__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");
/*
* runtime c-called (but written in Go)
*/
-void runtime_newErrorCString(const char*, Eface*)
+void runtime_newErrorCString(uintptr, Eface*)
__asm__ (GOSYM_PREFIX "runtime.NewErrorCString");
/*
// 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*)
}
}
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;