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:
Cherry Zhang 2018-02-14 19:35:03 -05:00
parent 213a75171d
commit 2baed3856d
13 changed files with 77 additions and 4 deletions

View File

@ -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 {

View File

@ -91,3 +91,4 @@ loop:
// LTYPE0 nonnon { outcode(int($1), &$2); }
RET
RET foo(SB)

View File

@ -145,3 +145,4 @@ loop:
// LTYPE0 nonnon { outcode($1, &$2); }
RET // c3
RET foo(SB)

View File

@ -1579,6 +1579,8 @@ jmp_label_3:
MOVHU R5@>16, R1 // 7518ffe6
MOVHU R5@>24, R1 // 751cffe6
RET foo(SB)
//
// END
//

View File

@ -426,6 +426,7 @@ again:
// }
BEQ 2(PC)
RET
RET foo(SB)
// More B/BL cases, and canonical names JMP, CALL.

View File

@ -422,6 +422,7 @@ label4:
BEQ R1, 2(PC)
JMP foo(SB)
CALL foo(SB)
RET foo(SB)
NEGW R1, R2 // 00011023

View File

@ -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

View File

@ -1197,6 +1197,7 @@ label1:
BEQ 2(PC)
JMP foo(SB)
CALL foo(SB)
RET foo(SB)
// END
//

View File

@ -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
View 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
View 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
View 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

View File

@ -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