golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.72k stars 17.62k forks source link

cmd/compile: switch to a register-based calling convention for Go functions #40724

Open aclements opened 4 years ago

aclements commented 4 years ago

I propose that we switch the Go internal ABI (used between Go functions) from stack-based to register-based argument and result passing for Go ~1.16~ 1.17.

I lay out the details of our proposal and the work required in this document.

The ABI specification can be found here.

This was previously proposed in #18597, where @dr2chase did some excellent prototyping work that our new proposal builds on. With multiple ABI support, we’re now in a much better position to execute on this without breaking compatibility with the existing body of Go assembly code. I’ve opened this new issue to focus on discussion of our new proposal.

/cc @dr2chase @danscales @thanm @cherrymui @mknyszek @prattmic @randall77

An incomplete and evolving list of tasks:

High-priority non-critical path

Enabling steps

Testing

Post-MVP

Cleanup (can be done later)

gopherbot commented 3 years ago

Change https://golang.org/cl/305330 mentions this issue: runtime: add GC testing helpers for regabi signature fuzzer

gopherbot commented 3 years ago

Change https://golang.org/cl/305669 mentions this issue: runtime: use ABIInternal for closure calls from assembly

gopherbot commented 3 years ago

Change https://golang.org/cl/305671 mentions this issue: cmd/compile: emit writebarriers in specified ABI

aclements commented 3 years ago

One example is to interface with the Core Audio APIs. In this specific case, the support for callbacks with floating point argument is needed.

@emarj, are you saying that there's already Go code that calls these, or just giving a theoretical example? Unless I'm completely misunderstanding the Windows calling convention, it has never worked for a Go callback to accept floating-point arguments. As of Go 1.16 NewCallback will actually panic, but before that it would simply do the wrong thing. If it's a theoretical example, it would great if you could open a new issue about adding support for floating-point Windows callback arguments so we can track that separately.

gopherbot commented 3 years ago

Change https://golang.org/cl/305672 mentions this issue: cmd/compile: make expandCalls preserve types of pointer stores

gopherbot commented 3 years ago

Change https://golang.org/cl/305550 mentions this issue: cmd/compile: wrap defer/go call with results

gopherbot commented 3 years ago

Change https://golang.org/cl/304771 mentions this issue: cmd/compile: be sure to wrap defer/go calls with arguments

gopherbot commented 3 years ago

Change https://golang.org/cl/305549 mentions this issue: cmd/compile: check deferred nil interface call before wrapping it

emarj commented 3 years ago

@emarj, are you saying that there's already Go code that calls these, or just giving a theoretical example? Unless I'm completely misunderstanding the Windows calling convention, it has never worked for a Go callback to accept floating-point arguments. As of Go 1.16 NewCallback will actually panic, but before that it would simply do the wrong thing. If it's a theoretical example, it would great if you could open a new issue about adding support for floating-point Windows callback arguments so we can track that separately.

@aclements I'm sorry for the confusion. There are pure Go libraries that implements these Windows APIs, but they are incomplete for this reason (i.e. they cannot implement callbacks). There is no (afaik) actual code that does that, because, as you said, it is not possible at the moment. I discover that myself trying to improve one of those libraries (https://github.com/moutend/go-wca for reference).

I commented here since I saw there is work being done in the "calling conventions area" and maybe this could be addressed. But now I understand it is better to open a new issue, since this is a feature request.

gopherbot commented 3 years ago

Change https://golang.org/cl/305829 mentions this issue: cmd/compile: make amd64 version of zerorange regabi-friendly

gopherbot commented 3 years ago

Change https://golang.org/cl/305849 mentions this issue: dashboard: add windows- and darwin- amd64-regabi builders

aclements commented 3 years ago

@emarj , thanks for opening the issue! You're right that they're related issues. We're in a much better place to support floating-point arguments to callbacks now. Previously NewCallback could sort of pretend that the Windows calling convention and Go calling convention were close enough that it didn't need to do any complicated translation, and adding floating-point to that would have been really hard. With Go switching to a register-based calling convention, it has to really understand both calling conventions and translate between them, so adding floating-point support now is actually much easier.

gopherbot commented 3 years ago

Change https://golang.org/cl/306009 mentions this issue: runtime: check that defer/go frames are empty

gopherbot commented 3 years ago

Change https://golang.org/cl/306010 mentions this issue: runtime: replace reflectcall of defers with direct call

gopherbot commented 3 years ago

Change https://golang.org/cl/306109 mentions this issue: reflect: undo register count increments on register assignment failure

gopherbot commented 3 years ago

Change https://golang.org/cl/306409 mentions this issue: cmd/compile: fix incoming ABI with GOEXPERIMENT=regabiargs

gopherbot commented 3 years ago

Change https://golang.org/cl/306410 mentions this issue: cmd/compile: fix outgoing calls with GOEXPERIMENT=regabiargs

aclements commented 3 years ago

As of tip:

$ cat hello.go
package main

func main() {
    println("hello with registers")
}
$ GOEXPERIMENT=regabi,regabiargs go run hello.go
hello with registers

This means the full register ABI is running well enough to bring up the whole runtime (including the scheduler, GC, starting lots of threads and goroutines, allocating a bunch, etc) and get to main.main.

gopherbot commented 3 years ago

Change https://golang.org/cl/306469 mentions this issue: cmd/compile: fix register/offset calculation for trailing empty field case.

gopherbot commented 3 years ago

Change https://golang.org/cl/306571 mentions this issue: reflect,runtime: assume register ABI with GOEXPERIMENT=regabiargs

gopherbot commented 3 years ago

Change https://golang.org/cl/306869 mentions this issue: cmd/compile: mark unused values as invalid to prevent problems in expandCalls

gopherbot commented 3 years ago

Change https://golang.org/cl/306929 mentions this issue: reflect: remove short-circuits for zero-sized types in ABI algorithm

gopherbot commented 3 years ago

Change https://golang.org/cl/306910 mentions this issue: runtime: make concatstring{2,3,4,5} consistent w/ compiler's use

gopherbot commented 3 years ago

Change https://golang.org/cl/306931 mentions this issue: runtime: make reflectcall ABI0 on amd64

gopherbot commented 3 years ago

Change https://golang.org/cl/307009 mentions this issue: cmd/internal/obj: use REGENTRYTMP* in a few more places

gopherbot commented 3 years ago

Change https://golang.org/cl/304470 mentions this issue: cmd/compile, runtime: add metadata for argument printing in traceback

gopherbot commented 3 years ago

Change https://golang.org/cl/307309 mentions this issue: cmd/compile: add "surprised by IData of Arg" case for register args

gopherbot commented 3 years ago

Change https://golang.org/cl/307229 mentions this issue: cmd/link: mangle function name with ABI on Mach-O

gopherbot commented 3 years ago

Change https://golang.org/cl/307232 mentions this issue: cmd/compile, runtime: use ABI-aware function converting float to interface

gopherbot commented 3 years ago

Change https://golang.org/cl/307231 mentions this issue: cmd/compile: load results into registers on open defer return path

gopherbot commented 3 years ago

Change https://golang.org/cl/307235 mentions this issue: cmd/compile: untangle Wrapper and ABIWrapper flags

gopherbot commented 3 years ago

Change https://golang.org/cl/307234 mentions this issue: cmd/compile: disable tail call for method wrappers when RegabiArgs is enabled

gopherbot commented 3 years ago

Change https://golang.org/cl/307233 mentions this issue: cmd/compile: reference ABIInternal memequal_varlen

gopherbot commented 3 years ago

Change https://golang.org/cl/307390 mentions this issue: runtime: mark abort as ABIInternal on amd64

gopherbot commented 3 years ago

Change https://golang.org/cl/307391 mentions this issue: runtime: use funcID to identify abort in isAbortPC

gopherbot commented 3 years ago

Change https://golang.org/cl/307236 mentions this issue: cmd/compile: enable panic+recover adjustment for some ABI wrappers

gopherbot commented 3 years ago

Change https://golang.org/cl/307237 mentions this issue: reflect: call ABI0 callReflect/callMethod

gopherbot commented 3 years ago

Change https://golang.org/cl/307529 mentions this issue: cmd/compile: check for unused OpArg* and mark invalid (again)

gopherbot commented 3 years ago

Change https://golang.org/cl/307829 mentions this issue: cmd/compile/internal/amd64: follow-on regabi fix for amd64 zerorange

gopherbot commented 3 years ago

Change https://golang.org/cl/307869 mentions this issue: reflect: refactor funcLayout tests

gopherbot commented 3 years ago

Change https://golang.org/cl/307909 mentions this issue: cmd/compile: pre-spill pointers in aggregate-typed register args

gopherbot commented 3 years ago

Change https://golang.org/cl/307872 mentions this issue: runtime: set up read-only dummy TLS space for needm on Windows

gopherbot commented 3 years ago

Change https://golang.org/cl/308189 mentions this issue: reflect: fix typo in result-in-registers case

gopherbot commented 3 years ago

Change https://golang.org/cl/308309 mentions this issue: cmd/compile: sanitize before/after expansion OpSelectN references

gopherbot commented 3 years ago

Change https://golang.org/cl/308510 mentions this issue: cmd/compile: ensure spills of int/float reg args land in abi slots

gopherbot commented 3 years ago

Change https://golang.org/cl/308069 mentions this issue: cmd/compile: fix buglet in walk convert phase relating to convT64

gopherbot commented 3 years ago

Change https://golang.org/cl/308589 mentions this issue: cmd/compile: add recursive-invalidate Value method, use in expand_calls

gopherbot commented 3 years ago

Change https://golang.org/cl/308590 mentions this issue: test/abi: clean up test to fix builders

gopherbot commented 3 years ago

Change https://golang.org/cl/308689 mentions this issue: cmd/compile: fix buglet in walk convert phase relating to convF32/64

gopherbot commented 3 years ago

Change https://golang.org/cl/308889 mentions this issue: test/abi: disable test on windows for now