4ad / go.arm64 Goto Github PK
View Code? Open in Web Editor NEWGo development tree for the arm64 port (historical).
License: BSD 3-Clause "New" or "Revised" License
Go development tree for the arm64 port (historical).
License: BSD 3-Clause "New" or "Revised" License
AFAICT, 7g fails on any code that contains a comparison, for example:
mwhudson@narsil:tmp$ cat t.go
package p
func f(x, y int) bool {
return x > y
}
mwhudson@narsil:tmp$ GOARCH=arm64 go tool 7g ./t.go
00016 (./t.go:4) CMP R9,R10
00016 (./t.go:4) CMP R9,R10
./t.go:5: illegal combination CMP R1 R0 R1
mwhudson@narsil:tmp$ cp t.go ~/tmp
The problem as I see it is that 7g's code generation generates an ACMP Prog with from and to filled out but the assembler in liblink only handles a ACMP with from and reg filled out (which is also what 7a produces when parsing a .s file with a CMP in). Not sure whether the correct fix is to change 7g or liblink...
I guess we all know this already. But it seems worth having an issue for too.
math.normalize: math.Abs: not defined
TEXT foo(SB),7,$-8
MOV $bar(SB), R4
MOV $baz(SB), R4
B (R4)
TEXT cow(SB),7,$-8
MOV $moo(SB), R4
B (R4)
cd /tmp/1 && GOARCH=arm64 go tool 7a -S a.s
foo t=1 dupok nosplit size=32 value=0 args=0xffffffff80000000 locals=0xfffffffffffffff8 leaf
0x0000 00000 (a.s:2) TEXT foo+0(SB),7,$-8--1
0x0000 00000 (a.s:2) MOV $bar+0(SB),R4
0x0004 00004 (a.s:3) MOV $baz+0(SB),R4
0x0008 00008 (a.s:4) B ,0(R4)
0x000c 00012 (<unknown line number>) B ,0(APC)
0x0010 00016 (<unknown line number>) DWORD ,$bar+0(SB)
0x0018 00024 (<unknown line number>) DWORD ,$baz+0(SB)
0x0000 84 00 00 58 a4 00 00 58 80 00 1f d6 00 00 00 14 ...X...X........
0x0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
rel 8+0 t=8 +0
rel 16+8 t=1 bar+0
rel 24+8 t=1 baz+0
cow t=1 dupok nosplit size=36 value=0 args=0xffffffff80000000 locals=0xfffffffffffffff8 leaf
0x0000 00000 (a.s:7) TEXT cow+0(SB),7,$-8--1
0x0000 00000 (a.s:7) MOV $moo+0(SB),R4
0x0004 00004 (a.s:8) B ,0(R4)
0x0008 00008 (<unknown line number>) B ,0(APC)
0x0010 00016 (<unknown line number>) DWORD ,$moo+0(SB)
0x0000 00 00 00 00 00 00 00 00 00 00 00 14 00 00 00 00 ................
0x0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0020 00 00 00 00 ....
rel 4+0 t=8 +0
rel 16+8 t=1 moo+0
: xgene:1;
The first function is correctly assembled, the second one is not.
mwhudson@narsil:go-test-cases$ cat exp.go
package p
func e(k int) float64 {
return float64(k)
}
mwhudson@narsil:go-test-cases$ GOARCH=arm64 /opt/opensource/go/pkg/tool/linux_amd64/7g exp.go 00024 (exp.go:4) SCVTFS F7,F7
00024 (exp.go:4) SCVTFS F7,F7
exp.go:5: illegal combination 00024 (exp.go:4) SCVTFS F7,F7 FREG NONE FREG, 16 16
I have a fairly terrible script (http://pastebin.ubuntu.com/9481723/) that lets me compare the assembly of files like this http://pastebin.ubuntu.com/9521747/ to the disassembly provided by binutils. In this specific case, the disassembly is http://pastebin.ubuntu.com/9521771/, which shows that certain values are being misassembled (1,2,3,4,6,7,8,12,14,15,16,24,28,30,31,32 below 40 -- no obvious pattern to me!).
My best guess is that this is aclass returning the wrong thing for these values for some reason.
This also fails when there is an implicit init function, but this seems simplest:
mwhudson@narsil:shared-lib-stuff$ cat init.go
package main
func init() {
}
mwhudson@narsil:shared-lib-stuff$ GOARCH=arm64 go tool 7g init.go
init.go:4: address constant needs DWORD
00116 (<unknown line number>) WORD ,"".initdone·+0(SB)
TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
MOV addr+0(FP), R0
MOV val+8(FP), R1
STLR R1, (R0)
RETURN
Becomes
(gdb) disassemble /r
Dump of assembler code for function runtime.atomicstore64:
0x0000000000124740 <+0>: e0 07 40 f9 ldr x0, [sp,#8]
0x0000000000124744 <+4>: e1 0b 40 f9 ldr x1, [sp,#16]
=> 0x0000000000124748 <+8>: 01 fc a0 c8 .inst 0xc8a0fc01 ; undefined
0x000000000012474c <+12>: c0 03 5f d6 ret
End of assembler dump.
And results in a delightful SIGILL
os/signal.loop: call to external function os/signal.signal_recv
os/signal.loop: os/signal.signal_recv: not defined
os/signal.init·1: os/signal.signal_enable: not defined
os/signal.enableSignal: os/signal.signal_enable: not defined
Haven't dug into this at all yet:
$ cat wrappermethod.go
package p
type embedded struct {
}
type embeds struct {
embedded
}
func (r *embedded) method() {
}
$ GOARCH=arm64 go tool 7g wrappermethod.go
00040 (<autogenerated>:1) RET ,"".(*embedded).method+0(SB)(R30)
00040 (<autogenerated>:1) RET ,"".(*embedded).method+0(SB)(R30)
<autogenerated>:1: illegal combination 00040 (<autogenerated>:1) RET ,"".(*embedded).method+0(SB)(R30) NONE NONE ADDR, 1 7
This example:
package foo
type s struct {
f1 uintptr
f2 uintptr
}
var globl s
func mallocsetfields(arg uintptr) {
globl.f1 = arg
globl.f2 = arg
}
compiles to this by default:
0x0000 00000 (regoptboom.go:10) TEXT "".mallocsetfields+0(SB),$-8-8
0x0000 00000 (regoptboom.go:10) MOV "".arg+0(FP),R1
0x0004 00004 (regoptboom.go:10) FUNCDATA $0,gclocals·5d05a78f811f5c3f62710534cdce0004+0(SB)
0x0004 00004 (regoptboom.go:10) FUNCDATA $1,gclocals·3280bececceccd33cb74587feedb1f9f+0(SB)
0x0004 00004 (regoptboom.go:11) MOV R1,R7
0x0008 00008 (regoptboom.go:11) MOV R7,"".globl+0(SB)
0x0010 00016 (regoptboom.go:12) MOV R1,R7
0x0014 00020 (regoptboom.go:12) MOV R7,"".globl+8(SB)
0x001c 00028 (regoptboom.go:13) RET ,0(R30)
0x0020 00032 (regoptboom.go:13) B ,0(PC)
The problem with this is that it stores the function argument in R1, which is REGTMP, and so liblink turns "MOV R7,"".globl+0(SB)" into "ldr x1, $constant; str x7, [x1]". Turning off optimizations with -N "fixes" this, maybe it should be the default for now?
0x0000 00000 (a.s:2) TEXT foo+0(SB),7,$-8--2147483648
0x0000 00000 (a.s:2) MOV $-1,R7
0x0004 00004 (a.s:3) MOV $4294967295,R7
0x0008 00008 (<unknown line number>) RET ,0(R30)
0x0000 07 00 80 92 e7 7f 00 b2 c0 03 5f d6 00 00 00 00 .........._.....
rel 8+0 t=7 +0
e7 7f 00 b2 is an undefined instruction. Note that 4294967295 is 0xffffffff.
rugby(~/go.arm64/src) % ./make.bash ##### Building C bootstrap tool.
cmd/dist
##### Building compilers and Go bootstrap tool for host, linux/arm64.
lib9
libbio
liblink
cmd/gc
cmd/7l
cmd/7a
cmd/7g
runtime
00492 (/home/dfc/go.arm64/src/runtime/cpuprof.go:154) NEG ,R11
00616 (/home/dfc/go.arm64/src/runtime/cpuprof.go:158) MOVBU R10,3211324(R9)
00684 (/home/dfc/go.arm64/src/runtime/cpuprof.go:160) MOVBU R10,3211325(R9)
00716 (/home/dfc/go.arm64/src/runtime/cpuprof.go:161) MOVBU R10,3211326(R9)
01384 (<unknown line number>) DWORD ,$2162728(R9)
00492 (/home/dfc/go.arm64/src/runtime/cpuprof.go:154) NEG ,R11
00616 (/home/dfc/go.arm64/src/runtime/cpuprof.go:158) MOVBU R10,3211324(R9)
00684 (/home/dfc/go.arm64/src/runtime/cpuprof.go:160) MOVBU R10,3211325(R9)
00716 (/home/dfc/go.arm64/src/runtime/cpuprof.go:161) MOVBU R10,3211326(R9)
/home/dfc/go.arm64/src/runtime/alg.go:1: illegal combination 00492 (/home/dfc/go.arm64/src/runtime/cpuprof.go:154) NEG ,R11 NONE =
0 NONE = 0 REG, 1 14
/home/dfc/go.arm64/src/runtime/alg.go:1: illegal combination 00616 (/home/dfc/go.arm64/src/runtime/cpuprof.go:158) MOVBU R10,3211324(R9) REG NONE=
0 LOREG, 14 7
/home/dfc/go.arm64/src/runtime/alg.go:1: illegal combination 00684 (/home/dfc/go.arm64/src/runtime/cpuprof.go:160) MOVBU R10,3211325(R9) REG NONE=
0 LOREG, 14 7
/home/dfc/go.arm64/src/runtime/alg.go:1: illegal combination 00716 (/home/dfc/go.arm64/src/runtime/cpuprof.go:161) MOVBU R10,3211326(R9) REG NONE=
0 LOREG, 14 7
/home/dfc/go.arm64/src/runtime/alg.go:1: illegal combination 01384 (<unknown line number>) DWORD ,$2162728(R9) NONE = 0 NONE =
0 LACON, 1 10
/home/dfc/go.arm64/src/runtime/alg.go:1: illegal combination 00492 (/home/dfc/go.arm64/src/runtime/cpuprof.go:154) NEG ,R11 NONE =
0 NONE = 0 REG, 1 14
/home/dfc/go.arm64/src/runtime/alg.go:1: illegal combination 00616 (/home/dfc/go.arm64/src/runtime/cpuprof.go:158) MOVBU R10,3211324(R9) REG NONE=
0 LOREG, 14 7
/home/dfc/go.arm64/src/runtime/alg.go:1: illegal combination 00684 (/home/dfc/go.arm64/src/runtime/cpuprof.go:160) MOVBU R10,3211325(R9) REG NONE=
0 LOREG, 14 7
/home/dfc/go.arm64/src/runtime/alg.go:1: illegal combination 00716 (/home/dfc/go.arm64/src/runtime/cpuprof.go:161) MOVBU R10,3211326(R9) REG NONE=
0 LOREG, 14 7
/home/dfc/go.arm64/src/runtime/alg.go:1: illegal combination 01384 (<unknown line number>) DWORD ,$2162728(R9) NONE = 0 NONE =
0 LACON, 1 10
/home/dfc/go.arm64/src/runtime/alg.go:1: too many errors
These are all autogenerated functions, so why are they not there?
: xgene:1; cd /tmp/1 && GOARCH=arm64 go tool 7l a.7
runtime.interequal: runtime.p: not defined
runtime.interequal: runtime.q: not defined
runtime.nilinterequal: runtime.p: not defined
runtime.nilinterequal: runtime.q: not defined
runtime.init·1: runtime.r: not defined
runtime.cgocallbackg1: runtime.reflectcall: not defined
runtime.cgocallbackg1: runtime.s: not defined
runtime.unwindm: runtime.s: not defined
runtime.chansend: runtime.reason: not defined
runtime.chansend: runtime.s: not defined
runtime.chansend: runtime.reason: not defined
runtime.chanrecv: runtime.reason: not defined
runtime.chanrecv: runtime.s: not defined
runtime.chanrecv: runtime.reason: not defined
runtime.cpuproftick: runtime.pc: not defined
runtime.(*cpuProfile).flushlog: runtime.f: not defined
runtime.(*cpuProfile).getprofile: runtime.p: not defined
runtime.(*TypeAssertionError).Error: runtime.src·2: not defined
runtime.printany: runtime.i1·2: not defined
runtime.printany: runtime.iface·3: not defined
runtime.panicwrap: runtime.src·2: not defined
too many errors
: xgene:1;
Is the error real, or is it just some artefact of something else missing?
mwhudson@narsil:shared-lib-stuff$ cat gvar64.go
package p
var i int64 = 1111111
func g() int64 {
return i
}
mwhudson@narsil:shared-lib-stuff$ GOARCH=arm64 go tool 7g gvar64.go
00004 (gvar64.go:6) MOV "".i+0(SB),R9
00004 (gvar64.go:6) MOV "".i+0(SB),R9
gvar64.go:7: illegal combination 00004 (gvar64.go:6) MOV "".i+0(SB),R9 ADDR NONE = 0 REG, 7 14
mwhudson@narsil:shared-lib-stuff$ cat gvar32.go
package p
var i int32 = 1111111
func g() int32 {
return i
}
mwhudson@narsil:shared-lib-stuff$ GOARCH=arm64 go tool 7g gvar32.go
gvar32.go:7: address constant needs DWORD
00028 (<unknown line number>) WORD ,"".i+0(SB)
I think the gvar32.go problem is more or less the same as issue 10. The problem with the 64 bit variable seems to be a missing entry from optab but maybe not...
Applying #52 makes the compiler unhappy
01008 (<unknown line number>) DWORD ,$"".wd+0(FP)
01016 (<unknown line number>) DWORD ,$"".err+16(FP)
01032 (<unknown line number>) DWORD ,$"".autotmp_0511-24(SP)
01056 (<unknown line number>) DWORD ,$"".autotmp_0516-48(SP)
01080 (<unknown line number>) DWORD ,$"".autotmp_0510-80(SP)
01112 (<unknown line number>) DWORD ,$"".autotmp_0506-64(SP)
01008 (<unknown line number>) DWORD ,$"".wd+0(FP)
01016 (<unknown line number>) DWORD ,$"".err+16(FP)
01032 (<unknown line number>) DWORD ,$"".autotmp_0511-24(SP)
/home/dfc/go.arm64/src/syscall/env_unix.go:1: illegal combination 01008 (<unknown line number>) DWORD ,$"".wd+0(FP) NONE NONE LACON, 1 10
/home/dfc/go.arm64/src/syscall/env_unix.go:1: illegal combination 01016 (<unknown line number>) DWORD ,$"".err+16(FP) NONE NONE LACON, 1 10
/home/dfc/go.arm64/src/syscall/env_unix.go:1: illegal combination 01032 (<unknown line number>) DWORD ,$"".autotmp_0511-24(SP) NONE NONE LACON, 1 10
/home/dfc/go.arm64/src/syscall/env_unix.go:1: illegal combination 01056 (<unknown line number>) DWORD ,$"".autotmp_0516-48(SP) NONE NONE LACON, 1 10
/home/dfc/go.arm64/src/syscall/env_unix.go:1: illegal combination 01080 (<unknown line number>) DWORD ,$"".autotmp_0510-80(SP) NONE NONE LACON, 1 10
/home/dfc/go.arm64/src/syscall/env_unix.go:1: illegal combination 01112 (<unknown line number>) DWORD ,$"".autotmp_0506-64(SP) NONE NONE LACON, 1 10
/home/dfc/go.arm64/src/syscall/env_unix.go:1: illegal combination 01008 (<unknown line number>) DWORD ,$"".wd+0(FP) NONE NONE LACON, 1 10
/home/dfc/go.arm64/src/syscall/env_unix.go:1: illegal combination 01016 (<unknown line number>) DWORD ,$"".err+16(FP) NONE NONE LACON, 1 10
/home/dfc/go.arm64/src/syscall/env_unix.go:1: illegal combination 01032 (<unknown line number>) DWORD ,$"".autotmp_0511-24(SP) NONE NONE LACON, 1 10
/home/dfc/go.arm64/src/syscall/env_unix.go:1: illegal combination 01056 (<unknown line number>) DWORD ,$"".autotmp_0516-48(SP) NONE NONE LACON, 1 10
/home/dfc/go.arm64/src/syscall/env_unix.go:1: too many errors
Something seems to still be generating the wrong form of CMP:
mwhudson@narsil:shared-lib-stuff$ cat cmpsp.go
package p
type T struct{}
func deref(q *T) T {
return *q
}
mwhudson@narsil:shared-lib-stuff$ GOARCH=arm64 go tool 7g cmpsp.go
00020 (cmpsp.go:6) CMP R9,R31
00020 (cmpsp.go:6) CMP R9,R31
cmpsp.go:7: illegal combination 00020 (cmpsp.go:6) CMP R9,R31 REG NONE = 0 REG, 14 14
rugby(~/src) % ../go.arm64/pkg/tool/linux_arm64/7l x.7
runtime.xadd: call to external function runtime.cas
runtime.atomicstorep1: call to external function runtime.casp1
runtime.cas64: call to external function runtime.systemstack
runtime.deferproc: call to external function runtime.getcallersp
runtime.freedefer: call to external function runtime.duffzero
runtime.deferreturn: call to external function runtime.jmpdefer
runtime.dopanic: call to external function runtime.getcallerpc
runtime.Gosched: call to external function runtime.mcall
runtime.gostringnocopy: call to external function runtime.casuintptr
runtime.strequal: call to external function runtime.eqstring
runtime.chanrecv: call to external function runtime.atomicloaduint
runtime.newosproc: call to external function runtime.clone
runtime.recovery: call to external function runtime.gogo
runtime.strequal: runtime.eqstring: not defined
runtime.interequal: runtime.p: not defined
runtime.interequal: runtime.q: not defined
runtime.nilinterequal: runtime.p: not defined
runtime.nilinterequal: runtime.q: not defined
runtime.init·1: runtime.r: not defined
runtime.xadd: runtime.cas: not defined
runtime.xchg: runtime.cas: not defined
too many errors
... and more errors
The linux headers are extremely confusing on this point, but e.g. this:
is the call for the "compat32" mmap sycall, not the actual arm64 one (which seems to be 222). Four of the syscalls we currently define (open, select, epoll_create, epoll_wait) don't actually exist for the aarch64 mode so we need to find what the modern version of them is (I know from prior experience that epoll_wait can be implemented in terms of epoll_pwait). Will do this after lunch.
Actually 64-bit atomics are implemented in sync/atomic, but in runtime there's a really lame fallback (in Go even!) that uses 32-bit CAS to implement all the other atomics. Gross.
Let's get rid of that.
For example:
mwhudson@narsil:shared-lib-stuff$ cat duff.go
package p
type s struct {
a [4]uintptr
}
func f() uintptr {
var s s
return s.a[0]
}
mwhudson@narsil:shared-lib-stuff$ GOARCH=arm64 go tool 7g duff.go
00024 (duff.go:8) DUFFZERO ,runtime.duffzero+496(APC)
duff.go:10: bad bra DUFFZERO
It's pretty easy to see which code is responsible, it's the q>= 4 case in ggen.c:clearfat.
syscall
/home/dfc/go.arm64/src/syscall/flock.go:16: undefined: Flock_t
/home/dfc/go.arm64/src/syscall/lsf_linux.go:13: undefined: SockFilter
/home/dfc/go.arm64/src/syscall/lsf_linux.go:17: undefined: SockFilter
/home/dfc/go.arm64/src/syscall/lsf_linux.go:40: undefined: IFNAMSIZ
/home/dfc/go.arm64/src/syscall/lsf_linux.go:40: invalid array bound IFNAMSIZ
Probably missing {z,}linux_arm64.go
Various compilation tests fail with missing runtime symbols: http://paste.ubuntu.com/9758979/
TEXT foo0(SB),7,$0
is different than TEXT foo00(SB),7,$0-0
TEXT foo0(SB),7,$0
BL foo-8(SB)
RETURN
TEXT foo00(SB),7,$0-0
BL foo-8(SB)
RETURN
Yields:
foo0 t=1 dupok nosplit size=16 value=0 args=0xffffffff80000000 locals=0x0 leaf
0x0000 00000 (a.s:5) TEXT foo0+0(SB),7,$-8--1
0x0000 00000 (a.s:5) BL ,foo+-8(APC)
0x0004 00004 (a.s:7) RET ,0(R30)
0x0000 00 00 00 94 c0 03 5f d6 00 00 00 00 00 00 00 00 ......_.........
rel 0+4 t=7 foo+-1744830466
rel 4+0 t=8 +0
foo00 t=1 dupok nosplit size=16 value=0 args=0x0 locals=0x0
0x0000 00000 (a.s:8) TEXT foo00+0(SB),7,$8-0
0x0000 00000 (a.s:8) MOV R30,-16(R31)!
0x0004 00004 (a.s:9) BL ,foo+-8(APC)
0x0008 00008 (a.s:11) MOV (R31)16!,R30
0x000c 00012 (a.s:11) RET ,0(R30)
0x0000 fe 0f 1f f8 00 00 00 94 fe 07 41 f8 c0 03 5f d6 ..........A..._.
rel 4+4 t=7 foo+-1744830466
rel 12+0 t=8 +0
Notice $-8--1
vs. $8-0
. A $0
is not a leaf, and should save LR
.
I am not sure if logical operations using C_BITCON work.
518837e added a slow version of IndexBytes that calls back to the bytes
package. We could do this better.
Ignore the DWORD
errors,
00616 (/home/dfc/go.arm64/src/runtime/cpuprof.go:158) MOVBU R10,3211324(R9)
00684 (/home/dfc/go.arm64/src/runtime/cpuprof.go:160) MOVBU R10,3211325(R9)
00716 (/home/dfc/go.arm64/src/runtime/cpuprof.go:161) MOVBU R10,3211326(R9)
01384 (<unknown line number>) DWORD ,$2162728(R9)
01064 (<unknown line number>) DWORD ,$2162728(R9)
/home/dfc/go.arm64/src/runtime/alg.go:1: illegal combination 00616 (/home/dfc/go.arm64/src/runtime/cpuprof.go:158) MOVBU R10,3211324(R9) REG NONE= 0 LOREG, 14 7
/home/dfc/go.arm64/src/runtime/alg.go:1: illegal combination 00684 (/home/dfc/go.arm64/src/runtime/cpuprof.go:160) MOVBU R10,3211325(R9) REG NONE= 0 LOREG, 14 7
/home/dfc/go.arm64/src/runtime/alg.go:1: illegal combination 00716 (/home/dfc/go.arm64/src/runtime/cpuprof.go:161) MOVBU R10,3211326(R9) REG NONE= 0 LOREG, 14 7
src/runtime/asm.s has this.
$ cat ret.s
TEXT _main(SB), $0
RET
$ GOARCH=arm64 go tool 7a ret.s
illegal combination 00000 (<unknown line number>) RET , NONE NONE NONE, 1 1
00000 (<unknown line number>) RET ,
illegal combination 00000 (<unknown line number>) RET , NONE NONE NONE, 1 1
00000 (<unknown line number>) RET ,
(FWIW, ken-cc fails in the same way)
rugby(~/go.arm64/src) % ../pkg/tool/linux_arm64/7l -w x.7
entry not text: _rt0_arm64_linux
/home/dfc/go.arm64/src/runtime/asm_arm64.s:15 syntax error, last name: g
Did we ever sort out which register we were going to devote to g
?
b6533a2 added a slow version of Index and Equals, we need to go back and make these call back into the runtime versions (when we have them).
"CMP $0,R13" in a .s file ends up being assembled as:
1c: eb2001bf cmp x13, w0, uxtb
which is not at all the right thing (gnu as assembles "cmp x13, #0" as "f10001bf cmp x13, #0x0")
This is the limiting package when building the standard library -- all other packages either build or (transitively) depend on it.
This sort of thing:
00020 (/opt/opensource/go/src/math/nextafter.go:15) FCVTSD "".x+0(FP),F7
../go/src/math/abs.go:1: illegal combination 00020 (/opt/opensource/go/src/math/nextafter.go:15) FCVTSD"".x+0(FP),F7 PSAUTO NONE FREG, 7 16
reflect.methodValueCall·f: reflect.methodValueCall: not defined
REGENV is zero, that's what causes the runtime to fail ATM. Fix should be simple.
Compiling this noddy code (with -l):
package e
var s = "xxx"
func e() {
f(s)
}
func f(s string) {
}
generates rather broken code:
"".e t=1 size=80 value=0 args=0x0 locals=0x10
0x0000 00000 (stringarg.go:5) TEXT "".e+0(SB),$24-0
0x0000 00000 (stringarg.go:5) MOV R30,-32(R31)!
0x0004 00004 (stringarg.go:5) FUNCDATA $0,gclocals·3280bececceccd33cb74587feedb1f9f+0(SB)
0x0004 00004 (stringarg.go:5) FUNCDATA $1,gclocals·3280bececceccd33cb74587feedb1f9f+0(SB)
0x0004 00004 (stringarg.go:6) MOV $"".s+0(SB),R7
0x0008 00008 (stringarg.go:6) MOV R7,R7
0x000c 00012 (stringarg.go:6) MOV R7,R8
0x0010 00016 (stringarg.go:6) MOV $8,R7
0x0014 00020 (stringarg.go:6) MOV R7,R7
0x0018 00024 (stringarg.go:6) SUB $8,R8
0x001c 00028 (stringarg.go:6) SUB $8,R7
0x0020 00032 (stringarg.go:6) MOV 8(R8),R9
0x0024 00036 (stringarg.go:6) MOV R9,8(R7)
0x0028 00040 (stringarg.go:6) MOV 8(R8),R9
0x002c 00044 (stringarg.go:6) MOV R9,8(R7)
0x0030 00048 (stringarg.go:6) PCDATA $0,$0
0x0030 00048 (stringarg.go:6) BL ,"".f+0(PC)
0x0034 00052 (stringarg.go:7) MOV (R31)32!,R30
0x0038 00056 (stringarg.go:7) RET ,0(R30)
0x003c 00060 (stringarg.go:7) B ,0(PC)
0x0040 00064 (stringarg.go:7) DWORD ,$"".s+0(SB)
0x0000 fe 0f 1e f8 e7 01 00 58 e7 03 07 aa e8 03 07 aa .......X........
0x0010 07 01 80 d2 e7 03 07 aa 08 21 00 d1 e7 20 00 d1 .........!... ..
0x0020 09 05 40 f9 e9 04 00 f9 09 05 40 f9 e9 04 00 f9 ..@.......@.....
0x0030 00 00 00 94 fe 07 42 f8 c0 03 5f d6 00 00 00 14 ......B..._.....
0x0040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
rel 48+4 t=6 "".f+2483027968
rel 56+0 t=7 +0
rel 64+8 t=1 "".s+0
In particular, the code at offset 0x10 puts a small integer into R7 and (unless I'm blind) R7 is still a small integer (in fact, 0) when the code at offset 0x24 treats it as a pointer.
@4ad and I hit this today.
getoutarg (t=t@entry=0x0) at /home/dfc/go.arm64/src/cmd/gc/subr.c:1936
1936 if(t->etype != TFUNC)
(gdb) bt
#0 getoutarg (t=t@entry=0x0) at /home/dfc/go.arm64/src/cmd/gc/subr.c:1936
#1 0x00000000004143f0 in argsize (t=0x0) at /home/dfc/go.arm64/src/cmd/gc/align.c:655
#2 0x000000000040c8a8 in ginscall (f=0x7fb1c9af18, proc=proc@entry=0) at /home/dfc/go.arm64/src/cmd/7g/ggen.c:201
#3 0x000000000040c514 in cgen_ret (n=n@entry=0x0) at /home/dfc/go.arm64/src/cmd/7g/ggen.c:467
#4 0x000000000040c730 in ginscall (f=<optimized out>, proc=proc@entry=2) at /home/dfc/go.arm64/src/cmd/7g/ggen.c:263
#5 0x000000000040cbf8 in cgen_call (n=0x7fb7871010, proc=2) at /home/dfc/go.arm64/src/cmd/7g/ggen.c:385
#6 0x000000000041e99c in cgen_proc (proc=proc@entry=2, n=0x7fb78711a8) at /home/dfc/go.arm64/src/cmd/gc/gen.c:561
#7 0x000000000041f318 in gen (n=0x7fb78711a8) at /home/dfc/go.arm64/src/cmd/gc/gen.c:487
#8 0x000000000041f4f8 in genlist (l=0x7fb1ae85b8) at /home/dfc/go.arm64/src/cmd/gc/gen.c:253
#9 0x0000000000402fb4 in compile (fn=fn@entry=0x7fb7869920) at /home/dfc/go.arm64/src/cmd/7g/../gc/pgen.c:275
#10 0x000000000041a444 in funccompile (n=0x7fb7869920, isclosure=isclosure@entry=0) at /home/dfc/go.arm64/src/cmd/gc/dcl.c:1473
#11 0x0000000000425864 in p9main (argc=85, argv=0x7fffffe470) at /home/dfc/go.arm64/src/cmd/gc/lex.c:506
#12 0x000000000040196c in main (argc=<optimized out>, argv=<optimized out>) at /home/dfc/go.arm64/src/lib9/main.c:57
We might want to investigate a R_ADDRARM64 relocation that would not
require pool literals.
Right now MOV g(SB), R
is
MOV pool(PC), TMP
MOV (TMP), R
...
DWORD g(SB)
So it uses 8 bytes of instructions and 8 bytes of pool. Note that the
pool literals are not coalesced (perhaps this can be implemented). We
can say that the cost of using R_ADDR is:
Cost(n * R_ADDR) = {2n+2n bytes, 2n loads}
A potential R_ADDRARM64 might do this instead:
ADRP g(SB), TMP
MOV off(TMP), R
The ADRP instruction calculates the 4k page which holds g(SB), the final
MOV can just encode an immediate offset since it's in C_ADDCON0 class.
For MOV g(SB), R
the generated code is:
ADRP g(SB), R
ADR g(SB), R
Note that we don't even need the temporary register, and we don't even do any loads.
In both cases we don't need pool literals at all, and they only do one
or zero loads!
Cost(n * R_ADDRARM64) = {2n bytes, 0.5n loads}
It might be worth doing this. This will affect #49.
The summary is a bit of a guess I suppose. This is what currently kills runtime initialization.
Compiling this code:
package mheap
type mspan struct {
foo uintptr
bar uintptr
}
type mheap struct {
free [10]mspan
}
func mHeap_Init(h *mheap, j int32) {
mSpanList_Init(&h.free[j])
}
func mSpanList_Init(s *mspan) {
s.foo = 0
}
Results in this:
0x0000 00000 (mheap.go:12) TEXT "".mHeap_Init+0(SB),$24-16
0x0000 00000 (mheap.go:12) MOV R30,-32(R31)!
0x0004 00004 (mheap.go:12) FUNCDATA $0,gclocals·cd30d2bcfdea04ed7c49639580b4bd08+0(SB)
0x0004 00004 (mheap.go:12) FUNCDATA $1,gclocals·3280bececceccd33cb74587feedb1f9f+0(SB)
0x0004 00004 (mheap.go:13) MOV "".h+0(FP),R0
0x0008 00008 (mheap.go:13) CMP R0,R31,
0x000c 00012 (mheap.go:13) BNE ,00014(BRANCH)
0x0010 00016 (mheap.go:13) MOV R0,0(R31)
0x0014 00020 (mheap.go:13) MOV $0,R1
0x0018 00024 (mheap.go:13) MOV R1,R1
0x001c 00028 (mheap.go:13) MOVW "".j+8(FP),R0
0x0020 00032 (mheap.go:13) MOVW R0,R2
0x0024 00036 (mheap.go:13) MOV R2,"".autotmp_0000-8(SP)
0x0028 00040 (mheap.go:13) MOV "".autotmp_0000-8(SP),R0
0x002c 00044 (mheap.go:13) MOV R0,R0
0x0030 00048 (mheap.go:13) MOV $16,R2
0x0034 00052 (mheap.go:13) UMULL R2,R0
0x0038 00056 (mheap.go:13) ADD R0,R1
0x003c 00060 (mheap.go:13) MOV R1,8(R31)
0x0040 00064 (mheap.go:13) PCDATA $0,$0
0x0040 00064 (mheap.go:13) BL ,"".mSpanList_Init+0(PC)
0x0044 00068 (mheap.go:14) MOV (R31)32!,R30
0x0048 00072 (mheap.go:14) RET ,0(R30)
Chasing this through, the brokenness is that the UMULL at offset 0x34 stomps over R0, which contains h. Maybe it's supposed to write to R1?
Disabled in the assemblers for now. Possible LDXP is also broken.
We need to use the register pair form.
runtime
illegal combination 00012 (/home/dfc/go.arm64/src/runtime/asm_arm64.s:57) LDAXRW 0(R1),R0 NONE NONE REG, 7 14
00012 (/home/dfc/go.arm64/src/runtime/asm_arm64.s:57) LDAXRW 0(R1),R0
illegal combination 00024 (/home/dfc/go.arm64/src/runtime/asm_arm64.s:60) STLXRW R3,R0,0(R1) NONE REG ZOREG, 14 7
00024 (/home/dfc/go.arm64/src/runtime/asm_arm64.s:60) STLXRW R3,R0,0(R1)
illegal combination 00012 (/home/dfc/go.arm64/src/runtime/asm_arm64.s:57) LDAXRW 0(R1),R0 NONE NONE REG, 7 14
00012 (/home/dfc/go.arm64/src/runtime/asm_arm64.s:57) LDAXRW 0(R1),R0
illegal combination 00024 (/home/dfc/go.arm64/src/runtime/asm_arm64.s:60) STLXRW R3,R0,0(R1) NONE REG ZOREG, 14 7
00024 (/home/dfc/go.arm64/src/runtime/asm_arm64.s:60) STLXRW R3,R0,0(R1)
Looks like MOV _cgo_init(SB), R12
is actually doing MOV $_cgo_init(SB), R12
: xgene:1; gdb 7.out
GNU gdb (Ubuntu 7.8-1ubuntu4) 7.8.0.20141001-cvs
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "aarch64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from 7.out...done.
(gdb) b runtime.rt0_go
Breakpoint 1 at 0x67ba4: file /home/aram/go/src/runtime/asm_arm64.s, line 174.
(gdb) r
Starting program: /tmp/1/7.out
Breakpoint 1, runtime.rt0_go () at /home/aram/go/src/runtime/asm_arm64.s:174
174 BL runtime·reginit(SB)
(gdb) n
runtime.reginit () at /home/aram/go/src/runtime/asm_arm64.s:22
22 FMOVD $4503601774854144.0, F27
(gdb)
23 FMOVD $0.5, F29
(gdb)
24 FSUBD F29, F29, F28
(gdb)
25 FADDD F29, F29, F30
(gdb)
26 FADDD F30, F30, F31
(gdb)
28
(gdb)
runtime.rt0_go () at /home/aram/go/src/runtime/asm_arm64.s:177
177 MOVW R0, 8(SP) // argc
(gdb)
runtime.rt0_go () at /home/aram/go/src/runtime/asm_arm64.s:178
178 MOV R1, 16(SP) // argv
(gdb)
179
(gdb)
182 MOV $runtime·g0(SB), g
(gdb)
183 MOV $(-64*1024), R7
(gdb)
184 ADD R7, SP, R0
(gdb)
186 MOV R0, g_stackguard1(g)
(gdb)
187 MOV R0, (g_stack+stack_lo)(g)
(gdb)
188 MOV SP, R7
(gdb)
190
(gdb)
192 MOV _cgo_init(SB), R12
(gdb)
194 BEQ nocgo
(gdb)
195
(gdb) disas
Dump of assembler code for function runtime.rt0_go:
0x0000000000067ba0 <+0>: str x30, [sp,#-16]!
0x0000000000067ba4 <+4>: bl 0x679a0 <runtime.reginit>
0x0000000000067ba8 <+8>: sub sp, sp, #0x20
0x0000000000067bac <+12>: str w0, [sp,#24]
0x0000000000067bb0 <+16>: str x1, [sp,#32]
0x0000000000067bb4 <+20>: ldr x29, 0x67c48 <runtime.rt0_go+168>
0x0000000000067bb8 <+24>: mov x7, #0xffffffffffff0000 // #-65536
0x0000000000067bbc <+28>: add x0, xzr, x7
0x0000000000067bc0 <+32>: str x0, [x29,#16]
0x0000000000067bc4 <+36>: str x0, [x29,#24]
0x0000000000067bc8 <+40>: str x0, [x29]
0x0000000000067bcc <+44>: mov x7, sp
0x0000000000067bd0 <+48>: str x7, [x29,#8]
0x0000000000067bd4 <+52>: ldr x12, 0x67c50 <runtime.rt0_go+176>
0x0000000000067bd8 <+56>: cmp x12, xzr
=> 0x0000000000067bdc <+60>: b.eq 0x67be4 <runtime.rt0_go+68>
0x0000000000067be0 <+64>: bl 0x67e30 <runtime.abort>
0x0000000000067be4 <+68>: ldr x0, [x29]
0x0000000000067be8 <+72>: add x0, x0, #0x280
0x0000000000067bec <+76>: str x0, [x29,#16]
0x0000000000067bf0 <+80>: str x0, [x29,#24]
0x0000000000067bf4 <+84>: ldr x0, 0x67c58 <runtime.rt0_go+184>
---Type <return> to continue, or q <return> to quit---q
Quit
(gdb) info reg x12
x12 0xb68e0 747744
(gdb) p/x _cgo_init
$1 = 0x0
(gdb) p/x &_cgo_init
$2 = 0xb68e0
(gdb) �quit
A debugging session is active.
Inferior 1 [process 7377] will be killed.
Quit anyway? (y or n) y
: xgene:1;
Small reproducer:
package p
type I interface {
F()
}
gives error:
00020 (<autogenerated>:1) BL ,R7
00020 (<autogenerated>:1) BL ,R7
<autogenerated>:1: illegal combination 00020 (<autogenerated>:1) BL ,R7 NONE = 0 NONE = 0 REG, 1 14
This looks very similar to the problem with an explicit indirect call fixed in d032caa and I imagine the fix will be similar too.
rugby(~/go.arm64/src) % ../pkg/tool/linux_arm64/7g ~/src/x.go
rugby(~/go.arm64/src) % ll x.7
-rw-r--r-- 1 dfc warthogs 1420 Jan 8 00:53 x.7
rugby(~/go.arm64/src) % ../pkg/tool/linux_arm64/7l x.7
Segmentation fault (core dumped)
rugby(~/go.arm64/src) % gdb --args ../pkg/tool/linux_arm64/7l x.7
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "aarch64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ../pkg/tool/linux_arm64/7l...done.
(gdb) r
Starting program: /home/dfc/go.arm64/pkg/tool/linux_arm64/7l x.7
Program received signal SIGSEGV, Segmentation fault.
writelines () at /home/dfc/go.arm64/src/cmd/7l/../ld/dwarf.c:1564
1564 newattr(dwinfo, DW_AT_low_pc, DW_CLS_ADDRESS, s->value, (char*)s);
(gdb) bt
#0 writelines () at /home/dfc/go.arm64/src/cmd/7l/../ld/dwarf.c:1564
#1 0x0000000000408d3c in dwarfemitdebugsections () at /home/dfc/go.arm64/src/cmd/7l/../ld/dwarf.c:2077
#2 0x000000000041a36c in asmb () at /home/dfc/go.arm64/src/cmd/7l/asm.c:251
#3 0x0000000000418d0c in p9main (argc=1, argv=0x7ffffff560) at /home/dfc/go.arm64/src/cmd/7l/../ld/pobj.c:195
#4 0x0000000000401cb4 in main (argc=<optimized out>, argv=<optimized out>) at /home/dfc/go.arm64/src/lib9/main.c:57
/home/dfc/go.arm64/src/runtime/sys_linux_arm64.s:184 syntax error, last name: ok
/home/dfc/go.arm64/src/runtime/sys_linux_arm64.s:253 syntax error, last name: ok
/home/dfc/go.arm64/src/runtime/sys_linux_arm64.s:255 redeclaration of ok
/home/dfc/go.arm64/src/runtime/sys_linux_arm64.s:348 redeclaration of ok
The rest of the assemblers grew this ability a while ago, https://codereview.appspot.com/159670043/
The c2go changes are landing in the dev.cc and master branches upstream and work is well underway to integrate those changes into our branch.
This is a tracking bug to assert that this work is completed, tentatively assigned to the all.bash milestone.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.