On Mon, Jul 15, 2013 at 12:36 AM, Kevin Klues wrote:

I'm currently in the process of porting go to a new OS for 386/amd64
and, in doing so, find myself writing go code that needs to be called
just curious, what's the target OS?
from c code under various circumstances. In doing so, I've come
across an error that may or may not be a compiler bug depending on
whether or not this type of operation is supported.

Glancing through the code base, I've found a few places where go
already gest called directly from c (most notably main·main() in
pkg/runtime/proc.c), but these calls appear to be far and few between.
Since this sort of operation doesn't seem to be documented anywhere
and its use is not very ubiquitous throughout the code base, it's
actually not clear to me whether this practice is encouraged or even
supported at all.
it's supported (in the sense that it's supported by the toolchain), 6c/8c
just can't get regular Go function return values, so you must define your
C-callable Go function like this:
func CCallableFunction(args uintptr /* or others, prefers pointer for
anything larger
than uintptr */, retval *uintptr) { /* blah blah */ }
That said, from what I can tell by looking at the x86 assembly
generated for go functions vs. 8c/6c functions, it seems that it
should be OK to just directly call go functions from c, so long as the
go function only returns a single value (or void), and I get the
function declaration right when I extern it in, e.g..
go: func go_func(n int32) int32 { return n }
c: extern int32 go_func(int32 n);
it won't always work, as C expects the return value in some register (AX
for 386/amd64,
R0 for ARM), Go always set return value on stack, so actually what you got
for the
n here is the last value that is stored into that register in the Go
function, and it might
not be the actual return value.
So long as I adhere to these guidelines, this has worked well for me
in almost every case I've encountered -- with one notable exception.
If I call a go function from within a c function and the c function
has the following properties, I get a page fault in my executing
page fault? you mean SIGSEGV/SIGBUS?

1) The c function does not take any arguments
2) The c function does not have any local variables
3) The c function makes a tail call to return the value of a go remember
function, rather than explicitly consuming the go functions return
value and then returning that,
return pkg·func();
// rather than ...
n = pkg.func();
return n;

Unlike in C, go functions appear to pass their return values both on
the stack (I assume to accommodate support for multiple return values)
as well as in eax in the case of having a single return value (as is
i think this is not guaranteed, it might just that the register allocator
to use AX to save the return value to stack.
so to be safe, you should treat the return value as an argument in the C
for example:
// in Go
func GoFunc(int) int
// in C
extern void GoFunc(intgo, intgo);

as i said above, in C you can't treat the GoFunc as returning one intgo
the common practice in standard c). So long as some stack space has
been reserved for ANY purpose within the body of the c function, a
tail call to a go function will benignly overwrite some (now unusable)
local variable, and the return value will be propagated to its caller
through eax (just as in standard c). Assembly output for such a
scenario can be seen below:
// Check if we need to grow our linked stack
mov %gs:0xffffffdc,%ecx
cmp (%ecx),%esp
ja <c_func+0x14>
xor %edi,%edi
xor %eax,%eax
call <runtime.morestack>
// Reserve some stack space for local operations
sub $0xc,%esp
// Do some local operations
// Make a tail call to return the value of go_func()
call <go_func>
// Restore esp to the value it had upon entering
add $0xc,%esp

However, if the conditions listed above are satisfied, then assembly
such as the following ends up being generated (on 32-bit x86):
mov %gs:0xffffffdc,%ecx
cmp (%ecx),%esp
ja <c_func+0x14>
xor %edi,%edi
xor %eax,%eax
call <runtime.morestack>
// No stack reservation
call <global_func_1>
call <global_func_2>
call <go_func>
// No stack restore

Since this c function takes no arguments and has no local variables,
then no stack space is reserved that is able to consume the return
value from the tail call to the go function, and instead, the return
value of the c function residing at 0(%esp) gets overwritten by the go
function, and the c function returns to some garbage location.

A full example can be constructed as follows:
extern int32 go_pkg·go_func();
static int32 global_data = 10;
static int32 change_global() { global_data += 1; }
static int32 buggy_func() {
return go_pkg·go_func();

Which generates the following assembly:
mov %gs:0xffffffdc,%ecx
cmp (%ecx),%esp
ja <buggy_func+0x14>
xor %edi,%edi
xor %eax,%eax
call <runtime.morestack>
call <change_global>
call <change_global>
call <change_global>
call <go_pkg.go_func>


As a side note, is there any particular reason that the preamble to
each function is of the form:
mov %gs:0xffffffdc,%ecx
cmp (%ecx),%esp
ja <func+0x14>
xor %edi,%edi
xor %eax,%eax
call <runtime.morestack>
// Actual function body at <func+0x14>

Rather than:
mov %gs:0xffffffdc,%ecx
cmp (%ecx),%esp
jnbe <stack_stuff>
// Actual function body
xor %edi,%edi
xor %eax,%eax
call <runtime.morestack>

The second one is slightly more efficient since (in the common case)
the linked stacks will not need to grow and a jump will be avoided
(saving 12 cycles per function call).
have you measured the difference? i think it might not be that big since
the pc difference is pretty small, and also that for the actual function
to execute, we must wait for the result for last cmp instruction, so i don't
think there could be that big difference for inverting the comparison

You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Search Discussions

Discussion Posts


Follow ups

Related Discussions

Discussion Navigation
viewthread | post
posts ‹ prev | 3 of 4 | next ›
Discussion Overview
groupgolang-nuts @
postedJul 14, '13 at 5:33p
activeJul 15, '13 at 2:11a

2 users in discussion

Kevin Klues: 3 posts Minux: 1 post



site design / logo © 2022 Grokbase