
Things I Learned Writing a JIT in Go - ConceitedCode
http://nelhagedebugsshit.tumblr.com/post/84342207533/things-i-learned-writing-a-jit-in-go
======
ridiculous_fish
The ABI (all registers caller-saved, parameters and return values
unconditionally passed on the stack) is quite simple compared to C. Is it
still in flux, or is it considered done?

Of course the Go team is aware of this, but once you support dynamic linking,
ABIs become very hard to change. A bad one will weigh you down for a long
time! Apple famously used PC-relative addressing on PowerPC, which has no
program counter register. It was, let's say, measurably suboptimal, but they
were stuck with it until the Intel transition (or technically the PPC64 one).

------
CyberShadow
The ABI seems to sacrifice performance for the sake of simplicity, which IMHO
has little value at such a low level. There's a reason why the x86-64 ABI
passes 6 (4 for the MS variant) machine words via registers! Disappointing.

Both D and Go use an unusual convention. The GCC maintainers raised issues
over D's ABI during discussions regarding integrating the GCC-based D
compiler. I wonder how did this apply to Go's inclusion? Or did GCC support
the Plan9 ABI before Go's inclusion?

~~~
pjmlp
One of the Go developers is part of the GCC project, maybe that helps?

------
kyrra
The author next a small comment that dynamic linking will be making its way
into Go sometime soon. Right now, with go being fully staticly link you always
know all of the code that you link against, making it easier to dive into.
Does anyone know what the Golang team is thinking about when it comes to
dynamic linking?

~~~
mitchellh
I don't know the full extent of the issue, but the issue right now is two
ways. I don't know which they're tackling, or maybe both:

* Go can't dynamically link to C libraries (.so). It can, however, dynamically link to DLLs, which is interesting.

* C can't dynamically link things built with Go

If I were to guess, they're trying to tackle the first problem.

~~~
misframer
Cgo can link to dynamic (.so) and static (.a) libraries.

~~~
mitchellh
I know, I said "Go" can't. Sorry if that isn't clear.

~~~
e12e
I was recently surprised by this, when I tried to run a simple go web server
in a chroot -- Apparently go defaults to dynamically linking to the host c
libraries for domain lookups (partly this has to do with it being hard to do
this with static code on OS X apparently).

The upshot is that while "go build" might be expected to create a static
binary (that should be easy to run in a chroot) -- in practice it won't unless
you manually rebuild your go toolchain, passing in a parameter to avoid
cgo/linking to c libraries for name lookup.

~~~
f2f
if you build with CGO_ENABLED=0 then you'll have fully static go binaries on
osx (but TLS won't work)

~~~
e12e
It's my understanding that you have to do this on Linux as well, and it isn't
enough to just build _your_ project with CGO_ENABLED=0, you'll also have to
rebuild the go-toolchain with CGO_ENABLED=0 for it to work. But perhaps this
has changed in recent versions of go?

Eg:

    
    
        cd /tmp
        git clone git@github.com:apg/wipes.git wipes.git
        cd wipes.git/
        go get github.com/gorilla/websocket
        go get github.com/gorilla/websocket
        go build
        ldd wipes.git
        # > libc.so.6 among others
        export CGO_ENABLED=0
        go build  # makes no difference, produces identical binary
    

Afaik, in this case it's 'net/http' that pulls in a dependency on cgo (again,
unless we rebuild the whole go toolchain with cgo_enabled=0).

Not that this is terrible as such, but it's a gotcha if you want to run the
resulting binary in a chroot, or on a host with a different version of libc...

~~~
stock_toaster

      > Afaik, in this case it's 'net/http' that pulls in a 
      > dependency on cgo (again, unless we rebuild the whole
      > go toolchain with cgo_enabled=0).
    

You can also build with '-tags netgo'[1], and use go for name resolution, but
still use cgo for when else you may need it.

[1]: [http://dominik.honnef.co/go-
tip/2013-09-07/#netgo](http://dominik.honnef.co/go-tip/2013-09-07/#netgo)

~~~
e12e
Indeed:

    
    
        go install -a -tags netgo std
        go build -tags netgo
        ldd wipes.git
            not a dynamic executable
    

Thanks for the tip :)

------
4ad
A few small nits:

The Go calling convention is described correctly, but the runtime is largely C
(compiled by a modified Plan 9 C compiler), and C compilers return values in a
register, not on the stack.

The Plan 9 ABI is significantly different. Yes, the compilers come from Plan 9
(Inferno, actually), but the calling convention was modified. E.g. on Plan 9
first argument is usually passed in register.

------
AsmMAn
What register allocation algorithm did you used?

