mirror of
https://github.com/golang/go
synced 2024-09-29 20:55:07 +00:00
cmd/asm: fix assembling return jump
In RET instruction, the operand is the return jump's target, which should be put in Prog.To. Add an action "buildrundir" to the test driver, which builds (compile+assemble+link) the code in a directory and runs the resulting binary. Fixes #23838. Change-Id: I7ebe7eda49024b40a69a24857322c5ca9c67babb Reviewed-on: https://go-review.googlesource.com/94175 Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
This commit is contained in:
parent
213a75171d
commit
2baed3856d
|
@ -486,7 +486,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
|
|||
case 0:
|
||||
// Nothing to do.
|
||||
case 1:
|
||||
if p.arch.UnaryDst[op] {
|
||||
if p.arch.UnaryDst[op] || op == obj.ARET {
|
||||
// prog.From is no address.
|
||||
prog.To = a[0]
|
||||
} else {
|
||||
|
|
1
src/cmd/asm/internal/asm/testdata/386.s
vendored
1
src/cmd/asm/internal/asm/testdata/386.s
vendored
|
@ -91,3 +91,4 @@ loop:
|
|||
|
||||
// LTYPE0 nonnon { outcode(int($1), &$2); }
|
||||
RET
|
||||
RET foo(SB)
|
||||
|
|
1
src/cmd/asm/internal/asm/testdata/amd64.s
vendored
1
src/cmd/asm/internal/asm/testdata/amd64.s
vendored
|
@ -145,3 +145,4 @@ loop:
|
|||
|
||||
// LTYPE0 nonnon { outcode($1, &$2); }
|
||||
RET // c3
|
||||
RET foo(SB)
|
||||
|
|
2
src/cmd/asm/internal/asm/testdata/arm.s
vendored
2
src/cmd/asm/internal/asm/testdata/arm.s
vendored
|
@ -1579,6 +1579,8 @@ jmp_label_3:
|
|||
MOVHU R5@>16, R1 // 7518ffe6
|
||||
MOVHU R5@>24, R1 // 751cffe6
|
||||
|
||||
RET foo(SB)
|
||||
|
||||
//
|
||||
// END
|
||||
//
|
||||
|
|
1
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
1
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
|
@ -426,6 +426,7 @@ again:
|
|||
// }
|
||||
BEQ 2(PC)
|
||||
RET
|
||||
RET foo(SB)
|
||||
|
||||
// More B/BL cases, and canonical names JMP, CALL.
|
||||
|
||||
|
|
1
src/cmd/asm/internal/asm/testdata/mips.s
vendored
1
src/cmd/asm/internal/asm/testdata/mips.s
vendored
|
@ -422,6 +422,7 @@ label4:
|
|||
BEQ R1, 2(PC)
|
||||
JMP foo(SB)
|
||||
CALL foo(SB)
|
||||
RET foo(SB)
|
||||
|
||||
NEGW R1, R2 // 00011023
|
||||
|
||||
|
|
1
src/cmd/asm/internal/asm/testdata/mips64.s
vendored
1
src/cmd/asm/internal/asm/testdata/mips64.s
vendored
|
@ -402,6 +402,7 @@ label4:
|
|||
BEQ R1, 2(PC)
|
||||
JMP foo(SB)
|
||||
CALL foo(SB)
|
||||
RET foo(SB)
|
||||
|
||||
NEGW R1, R2 // 00011023
|
||||
NEGV R1, R2 // 0001102f
|
||||
|
|
1
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
1
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
|
@ -1197,6 +1197,7 @@ label1:
|
|||
BEQ 2(PC)
|
||||
JMP foo(SB)
|
||||
CALL foo(SB)
|
||||
RET foo(SB)
|
||||
|
||||
// END
|
||||
//
|
||||
|
|
1
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
1
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
|
@ -365,6 +365,7 @@ TEXT main·foo(SB),DUPOK|NOSPLIT,$16-0 // TEXT main.foo(SB), DUPOK|NOSPLIT, $16-
|
|||
VSTEB $15, V29, 4094(R12) // e7d0cffef808
|
||||
|
||||
RET
|
||||
RET foo(SB)
|
||||
|
||||
TEXT main·init(SB),DUPOK|NOSPLIT,$0 // TEXT main.init(SB), DUPOK|NOSPLIT, $0
|
||||
RET
|
||||
|
|
12
test/retjmp.dir/a.s
Normal file
12
test/retjmp.dir/a.s
Normal file
|
@ -0,0 +1,12 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
TEXT ·f(SB), 4, $8-0
|
||||
CALL ·f1(SB)
|
||||
RET ·f2(SB)
|
||||
CALL ·unreachable(SB)
|
||||
|
||||
TEXT ·leaf(SB), 4, $0-0
|
||||
RET ·f3(SB)
|
||||
JMP ·unreachable(SB)
|
32
test/retjmp.dir/main.go
Normal file
32
test/retjmp.dir/main.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
func f()
|
||||
func leaf()
|
||||
|
||||
var f1called, f2called, f3called bool
|
||||
|
||||
func main() {
|
||||
f()
|
||||
if !f1called {
|
||||
panic("f1 not called")
|
||||
}
|
||||
if !f2called {
|
||||
panic("f2 not called")
|
||||
}
|
||||
leaf()
|
||||
if !f3called {
|
||||
panic("f3 not called")
|
||||
}
|
||||
}
|
||||
|
||||
func f1() { f1called = true }
|
||||
func f2() { f2called = true }
|
||||
func f3() { f3called = true }
|
||||
|
||||
func unreachable() {
|
||||
panic("unreachable function called")
|
||||
}
|
9
test/retjmp.go
Normal file
9
test/retjmp.go
Normal file
|
@ -0,0 +1,9 @@
|
|||
// buildrundir
|
||||
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Test that return jump works correctly in assembly code.
|
||||
|
||||
package ignored
|
17
test/run.go
17
test/run.go
|
@ -488,7 +488,7 @@ func (t *test) run() {
|
|||
action = "rundir"
|
||||
case "cmpout":
|
||||
action = "run" // the run case already looks for <dir>/<test>.out files
|
||||
case "compile", "compiledir", "build", "builddir", "run", "buildrun", "runoutput", "rundir", "asmcheck":
|
||||
case "compile", "compiledir", "build", "builddir", "buildrundir", "run", "buildrun", "runoutput", "rundir", "asmcheck":
|
||||
// nothing to do
|
||||
case "errorcheckandrundir":
|
||||
wantError = false // should be no error if also will run
|
||||
|
@ -735,7 +735,7 @@ func (t *test) run() {
|
|||
t.err = err
|
||||
}
|
||||
|
||||
case "builddir":
|
||||
case "builddir", "buildrundir":
|
||||
// Build an executable from all the .go and .s files in a subdirectory.
|
||||
useTmp = true
|
||||
longdir := filepath.Join(cwd, t.goDirName())
|
||||
|
@ -788,12 +788,23 @@ func (t *test) run() {
|
|||
t.err = err
|
||||
break
|
||||
}
|
||||
cmd = []string{"go", "tool", "link", "all.a"}
|
||||
cmd = []string{"go", "tool", "link", "-o", "a.exe", "all.a"}
|
||||
_, err = runcmd(cmd...)
|
||||
if err != nil {
|
||||
t.err = err
|
||||
break
|
||||
}
|
||||
if action == "buildrundir" {
|
||||
cmd = append(findExecCmd(), filepath.Join(t.tempDir, "a.exe"))
|
||||
out, err := runcmd(cmd...)
|
||||
if err != nil {
|
||||
t.err = err
|
||||
break
|
||||
}
|
||||
if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() {
|
||||
t.err = fmt.Errorf("incorrect output\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
case "buildrun": // build binary, then run binary, instead of go run. Useful for timeout tests where failure mode is infinite loop.
|
||||
// TODO: not supported on NaCl
|
||||
|
|
Loading…
Reference in a new issue