go/analysis/passes/asmdecl: permit return jump without writing to results

RET f(SB) is a tail call. It is okay to not write the results,
as it has not returned to the caller at this point.

Change-Id: I670486d02285c3a346cbc93e91be3b9e61ab77bd
Reviewed-on: https://go-review.googlesource.com/c/tools/+/264319
Trust: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Austin Clements <austin@google.com>
diff --git a/go/analysis/passes/asmdecl/asmdecl.go b/go/analysis/passes/asmdecl/asmdecl.go
index d63855b..eb0016b 100644
--- a/go/analysis/passes/asmdecl/asmdecl.go
+++ b/go/analysis/passes/asmdecl/asmdecl.go
@@ -308,7 +308,8 @@
 				continue
 			}
 
-			if strings.Contains(line, "RET") {
+			if strings.Contains(line, "RET") && !strings.Contains(line, "(SB)") {
+				// RET f(SB) is a tail call. It is okay to not write the results.
 				retLine = append(retLine, lineno)
 			}
 
diff --git a/go/analysis/passes/asmdecl/testdata/src/a/asm.go b/go/analysis/passes/asmdecl/testdata/src/a/asm.go
index 27470c5..6bcfb2f 100644
--- a/go/analysis/passes/asmdecl/testdata/src/a/asm.go
+++ b/go/analysis/passes/asmdecl/testdata/src/a/asm.go
@@ -51,3 +51,5 @@
 func pickStableABI(x int)
 func pickInternalABI(x int)
 func pickFutureABI(x int)
+
+func retjmp() int
diff --git a/go/analysis/passes/asmdecl/testdata/src/a/asm1.s b/go/analysis/passes/asmdecl/testdata/src/a/asm1.s
index 8fa0401..8c43223 100644
--- a/go/analysis/passes/asmdecl/testdata/src/a/asm1.s
+++ b/go/analysis/passes/asmdecl/testdata/src/a/asm1.s
@@ -345,3 +345,7 @@
 TEXT ·pickFutureABI<ABISomethingNotyetInvented>(SB), NOSPLIT, $32
 	MOVQ	x+0(FP), AX
 	RET
+
+// return jump
+TEXT ·retjmp(SB), NOSPLIT, $0-8
+	RET	retjmp1(SB) // It's okay to not write results if there's a tail call.