Here's a little program:
$ cat /tmp/x.go
package main
type T struct { x int }
func do(t *T) {do(t) }
func alloc() *T { return &T{42} }
func f() {
x := alloc()
do(x)
do(x)
}
GOARCH=amd64 go tool compile -S on amd64 produces:
main.f STEXT size=71 args=0x0 locals=0x18 funcid=0x0 align=0x0
0x0000 00000 (/tmp/x.go:9) TEXT main.f(SB), ABIInternal, $24-0
0x0000 00000 (/tmp/x.go:9) CMPQ SP, 16(R14)
0x0004 00004 (/tmp/x.go:9) PCDATA $0, $-2
0x0004 00004 (/tmp/x.go:9) JLS 59
0x0006 00006 (/tmp/x.go:9) PCDATA $0, $-1
0x0006 00006 (/tmp/x.go:9) PUSHQ BP
0x0007 00007 (/tmp/x.go:9) MOVQ SP, BP
0x000a 00010 (/tmp/x.go:9) SUBQ $16, SP
0x000e 00014 (/tmp/x.go:9) FUNCDATA $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
0x000e 00014 (/tmp/x.go:9) FUNCDATA $1, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
0x000e 00014 (/tmp/x.go:10) XCHGL AX, AX
0x000f 00015 (/tmp/x.go:7) MOVQ $0, main..autotmp_3+8(SP)
0x0018 00024 (/tmp/x.go:7) MOVQ $42, main..autotmp_3+8(SP)
0x0021 00033 (/tmp/x.go:11) LEAQ main..autotmp_3+8(SP), AX
0x0026 00038 (/tmp/x.go:11) PCDATA $1, $0
0x0026 00038 (/tmp/x.go:11) CALL main.do(SB)
0x002b 00043 (/tmp/x.go:12) LEAQ main..autotmp_3+8(SP), AX
0x0030 00048 (/tmp/x.go:12) CALL main.do(SB)
0x0035 00053 (/tmp/x.go:13) ADDQ $16, SP
0x0039 00057 (/tmp/x.go:13) POPQ BP
0x003a 00058 (/tmp/x.go:13) RET
0x003b 00059 (/tmp/x.go:13) NOP
0x003b 00059 (/tmp/x.go:9) PCDATA $1, $-1
0x003b 00059 (/tmp/x.go:9) PCDATA $0, $-2
0x003b 00059 (/tmp/x.go:9) NOP
0x0040 00064 (/tmp/x.go:9) CALL runtime.morestack_noctxt(SB)
0x0045 00069 (/tmp/x.go:9) PCDATA $0, $-1
0x0045 00069 (/tmp/x.go:9) JMP 0
Note the inlined call to alloc at 0x000f (line 7) with the inlining mark (XCHGL AX, AX) above it.
No other inlining here.
Note in particular that between the two CALL main.do at 0x002b there is a reload of x from main..autotmp_3 and it is attributed to line 12, because it is the setup for the next call on line 12.
GOARCH=386 go tool compile -S produces:
main.f STEXT size=73 args=0x0 locals=0x8 funcid=0x0 align=0x0
0x0000 00000 (/tmp/x.go:9) TEXT main.f(SB), NOFRAME|ABIInternal, $8-0
0x0000 00000 (/tmp/x.go:9) MOVL TLS, CX
0x0007 00007 (/tmp/x.go:9) PCDATA $0, $-2
0x0007 00007 (/tmp/x.go:9) MOVL (CX)(TLS*2), CX
0x000d 00013 (/tmp/x.go:9) PCDATA $0, $-1
0x000d 00013 (/tmp/x.go:9) CMPL SP, 8(CX)
0x0010 00016 (/tmp/x.go:9) PCDATA $0, $-2
0x0010 00016 (/tmp/x.go:9) JLS 66
0x0012 00018 (/tmp/x.go:9) PCDATA $0, $-1
0x0012 00018 (/tmp/x.go:9) SUBL $8, SP
0x0015 00021 (/tmp/x.go:9) FUNCDATA $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
0x0015 00021 (/tmp/x.go:9) FUNCDATA $1, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
0x0015 00021 (/tmp/x.go:10) XCHGL AX, AX
0x0016 00022 (/tmp/x.go:7) MOVL $0, main..autotmp_3+4(SP)
0x001e 00030 (/tmp/x.go:7) MOVL $42, main..autotmp_3+4(SP)
0x0026 00038 (/tmp/x.go:7) LEAL main..autotmp_3+4(SP), AX
0x002a 00042 (/tmp/x.go:7) MOVL AX, (SP)
0x002d 00045 (/tmp/x.go:11) PCDATA $1, $0
0x002d 00045 (/tmp/x.go:11) CALL main.do(SB)
0x0032 00050 (/tmp/x.go:7) LEAL main..autotmp_3+4(SP), AX
0x0036 00054 (/tmp/x.go:7) MOVL AX, (SP)
0x0039 00057 (/tmp/x.go:12) CALL main.do(SB)
0x003e 00062 (/tmp/x.go:13) ADDL $8, SP
0x0041 00065 (/tmp/x.go:13) RET
0x0042 00066 (/tmp/x.go:13) NOP
0x0042 00066 (/tmp/x.go:9) PCDATA $1, $-1
0x0042 00066 (/tmp/x.go:9) PCDATA $0, $-2
0x0042 00066 (/tmp/x.go:9) CALL runtime.morestack_noctxt(SB)
0x0047 00071 (/tmp/x.go:9) PCDATA $0, $-1
0x0047 00071 (/tmp/x.go:9) JMP 0
Note the same inlining at 0x0016. But then note the LEAL/MOVL reloading x at 0x0032. It is attributed to line 7, the implementation of alloc, instead of to the setup for the next call. It says x.go:7 instead of x.go:12 like the GOARCH=amd64 one.
This inconsistency is part of a problem I'm seeing with runtime.CallersFrames applied to the result of runtime.Callers.
It's not the most direct problem, though: using runtime.CallersFrames on runtime.Callers should not care about the line number of that instruction at all!
Here's a little program:
GOARCH=amd64 go tool compile -Son amd64 produces:Note the inlined call to alloc at 0x000f (line 7) with the inlining mark (XCHGL AX, AX) above it.
No other inlining here.
Note in particular that between the two
CALL main.doat 0x002b there is a reload ofxfrommain..autotmp_3and it is attributed to line 12, because it is the setup for the next call on line 12.GOARCH=386 go tool compile -Sproduces:Note the same inlining at 0x0016. But then note the LEAL/MOVL reloading
xat 0x0032. It is attributed to line 7, the implementation of alloc, instead of to the setup for the next call. It says x.go:7 instead of x.go:12 like the GOARCH=amd64 one.This inconsistency is part of a problem I'm seeing with runtime.CallersFrames applied to the result of runtime.Callers.
It's not the most direct problem, though: using runtime.CallersFrames on runtime.Callers should not care about the line number of that instruction at all!