gcc/libgo/runtime/go-trampoline.c
Ian Lance Taylor b39c10b813 Unify handling of runtime support functions.
This introduces the new approach, and rewrites the lowering
code which uses runtime functions.  The code which calls
runtime functions at GENERIC conversion time is not yet
rewritten.

From-SVN: r172396
2011-04-13 21:00:59 +00:00

54 lines
1.4 KiB
C

/* go-trampoline.c -- allocate a trampoline for a nested function.
Copyright 2009 The Go Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file. */
#include "config.h"
#include <stddef.h>
#include <stdint.h>
#include <unistd.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#include "go-alloc.h"
#include "go-assert.h"
/* In order to build a trampoline we need space which is both writable
and executable. We currently just allocate a whole page. This
needs to be more system dependent. */
void *
__go_allocate_trampoline (uintptr_t size, void *closure)
{
unsigned int page_size;
void *ret;
size_t off;
page_size = getpagesize ();
__go_assert (page_size >= size);
ret = __go_alloc (2 * page_size - 1);
ret = (void *) (((uintptr_t) ret + page_size - 1)
& ~ ((uintptr_t) page_size - 1));
/* Because the garbage collector only looks at correct address
offsets, we need to ensure that it will see the closure
address. */
off = ((size + sizeof (void *) - 1) / sizeof (void *)) * sizeof (void *);
__go_assert (size + off + sizeof (void *) <= page_size);
__builtin_memcpy (ret + off, &closure, sizeof (void *));
#ifdef HAVE_SYS_MMAN_H
{
int i;
i = mprotect (ret, size, PROT_READ | PROT_WRITE | PROT_EXEC);
__go_assert (i == 0);
}
#endif
return ret;
}