Is there any way to force Go to call asm function using register-based arguments?

738 views
Skip to first unread message

Richiise Nugraha

unread,
Mar 7, 2022, 3:37:26 PM3/7/22
to golang-nuts
Hi i wonder if there's option to use register-based arguments, maybe like compiler directive or something?

Expected result:
But this one wasting r9 as function address.
unknown.png


What i got so far:
But this is stack-based :/
unknown.png

Ian Lance Taylor

unread,
Mar 7, 2022, 3:56:43 PM3/7/22
to Richiise Nugraha, golang-nuts
Please always show text as plain text, not as images.  Plain text is much easier to read.  I'm not even going to try to read your images; sorry.

That said, there is no supported way to do this.  You can indicate that an assembly function uses the internal ABI, which is currently the register ABI, by changing "(SB)" to "<ABInternal>" in the TEXT directive introducing the function.  However, as you can guess from the name, the internal ABI is subject to change over time.  See https://go.googlesource.com/proposal/+/refs/heads/master/design/27539-internal-abi.md.  So while it is possible to write such an assembly function today, it may break in future releases.

Ian

drc...@google.com

unread,
Mar 8, 2022, 5:22:48 PM3/8/22
to golang-nuts
You could use build tags to write a portable implementation and a (very) version-specific implementation.
E.g.
//go:build go1.18 && !go1.19
// go1.18-specific
and
//go:build (go1.8 && !go1.18) || go1.19
// not go1.18

We have ideas about changing the ABI in the future -- possible changes include
- use the closure context pointer to pass the receiver to methods
- don't reserve stack space for spilling in the prologue
- perhaps reserve some registers for generational GC, if we ever do that

Jakob Thomsen

unread,
Aug 3, 2022, 8:44:53 AM8/3/22
to golang-nuts
Hi all!

Thanks for the pointer to using <ABIInternal> in the code. Unfortunately, it seems that it is only allowed for runtime* packages, as I get a 
ABI selector only permitted when compiling runtime, reference was to "\"\".__CompareNMask"
error, when using it. I'm trying to use it for this simple function (invoking some SIMD operations):

// func __CompareNMask(buf, mask unsafe.Pointer) (ret uint16)
TEXT ·__CompareNMask<ABIInternal>(SB), $0-24

    MOVQ buf+0(FP), DI
    MOVQ mask+8(FP), SI

    LONG $0xc66ef9c5             // vmovd    xmm0, esi
    LONG $0x7879e2c4; BYTE $0xc0 // vpbroadcastb    xmm0, xmm0
    LONG $0x0774f9c5             // vpcmpeqb    xmm0, xmm0, oword [rdi]
    LONG $0xc0d7f9c5             // vpmovmskb    eax, xmm0
    MOVW AX, ret+16(FP)
    RET


Is there any way to allow non-runtime packages to use the register-based calling convention (or open up for the ABIInternal)?

Best regards

Jakob



opennota

unread,
Jul 1, 2023, 11:46:03 AM7/1/23
to golang-nuts
Any update on this? I wanted to use the register-based calling convention as well and got "ABI selector only permitted when compiling runtime", too.

opennota

unread,
Jul 3, 2023, 1:44:20 AM7/3/23
to golang-nuts
Ok Google, so one can use `-asmflags=-compiling-runtime` to work around this limitation. The resulting speed-up can be well worth it.

Keith Randall

unread,
Jul 3, 2023, 10:02:09 PM7/3/23
to golang-nuts
There is still no way to do this in a supported manner.
We may at some future time freeze ABIInternal and call it ABI1, at which point you could use that. But we have no plans or schedule for that at the moment.

Reply all
Reply to author
Forward
0 new messages