]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: try to preserve IsStmt marks from OpConvert
authorDavid Chase <drchase@google.com>
Tue, 23 Nov 2021 18:29:13 +0000 (13:29 -0500)
committerDavid Chase <drchase@google.com>
Wed, 8 Dec 2021 18:30:00 +0000 (18:30 +0000)
Note when a statement mark was not consumed during Prog
generation, and try to use it on a subsequent opcode so
that the statement marker will not be lost.

And a test.

Fixes #49628.

Change-Id: I03f7782a9809cc4a0a5870df92b3e182cf124554
Reviewed-on: https://go-review.googlesource.com/c/go/+/366694
Trust: David Chase <drchase@google.com>
Run-TryBot: David Chase <drchase@google.com>
Trust: Dan Scales <danscales@google.com>
Reviewed-by: Dan Scales <danscales@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/cmd/compile/internal/ssa/debug_lines_test.go
src/cmd/compile/internal/ssa/testdata/convertline.go [new file with mode: 0644]
src/cmd/compile/internal/ssagen/ssa.go

index 0df56f5d4bfe96eb85fa0d3867ea9298fdf983e1..c0ccdb1c93e32281fa41479546ff237d60831189 100644 (file)
@@ -82,6 +82,25 @@ func TestDebugLinesPushback(t *testing.T) {
        }
 }
 
+func TestDebugLinesConvert(t *testing.T) {
+       if runtime.GOOS != "linux" && runtime.GOOS != "darwin" { // in particular, it could be windows.
+               t.Skip("this test depends on creating a file with a wonky name, only works for sure on Linux and Darwin")
+       }
+
+       switch testGoArch() {
+       default:
+               t.Skip("skipped for many architectures")
+
+       case "arm64", "amd64": // register ABI
+               fn := "G[go.shape.int_0]"
+               if buildcfg.Experiment.Unified {
+                       // Unified mangles differently
+                       fn = "G[int]"
+               }
+               testDebugLines(t, "-N -l -G=3", "convertline.go", fn, []int{9, 10, 11}, true)
+       }
+}
+
 func TestInlineLines(t *testing.T) {
        if runtime.GOARCH != "amd64" && *testGoArchFlag == "" {
                // As of september 2021, works for everything except mips64, but still potentially fragile
diff --git a/src/cmd/compile/internal/ssa/testdata/convertline.go b/src/cmd/compile/internal/ssa/testdata/convertline.go
new file mode 100644 (file)
index 0000000..08f3ae8
--- /dev/null
@@ -0,0 +1,16 @@
+package main
+
+import "fmt"
+
+func F[T any](n T) {
+       fmt.Printf("called\n")
+}
+
+func G[T any](n T) {
+       F(n)
+       fmt.Printf("after\n")
+}
+
+func main() {
+       G(3)
+}
index d6407af334b01e3c063ea70b1a3206af1ed3109d..265ef1aab32e5fcc213168123c6e4a7c4fb87e55 100644 (file)
@@ -6577,6 +6577,22 @@ func (s *State) DebugFriendlySetPosFrom(v *ssa.Value) {
                        // explicit statement boundaries should appear
                        // in the generated code.
                        if p.IsStmt() != src.PosIsStmt {
+                               if s.pp.Pos.IsStmt() == src.PosIsStmt && s.pp.Pos.SameFileAndLine(p) {
+                                       // If s.pp.Pos already has a statement mark, then it was set here (below) for
+                                       // the previous value.  If an actual instruction had been emitted for that
+                                       // value, then the statement mark would have been reset.  Since the statement
+                                       // mark of s.pp.Pos was not reset, this position (file/line) still needs a
+                                       // statement mark on an instruction.  If file and line for this value are
+                                       // the same as the previous value, then the first instruction for this
+                                       // value will work to take the statement mark.  Return early to avoid
+                                       // resetting the statement mark.
+                                       //
+                                       // The reset of s.pp.Pos occurs in (*Progs).Prog() -- if it emits
+                                       // an instruction, and the instruction's statement mark was set,
+                                       // and it is not one of the LosesStmtMark instructions,
+                                       // then Prog() resets the statement mark on the (*Progs).Pos.
+                                       return
+                               }
                                p = p.WithNotStmt()
                                // Calls use the pos attached to v, but copy the statement mark from State
                        }
@@ -6818,6 +6834,7 @@ func genssa(f *ssa.Func, pp *objw.Progs) {
        for i, b := range f.Blocks {
                s.bstart[b.ID] = s.pp.Next
                s.lineRunStart = nil
+               s.SetPos(s.pp.Pos.WithNotStmt()) // It needs a non-empty Pos, but cannot be a statement boundary (yet).
 
                // Attach a "default" liveness info. Normally this will be
                // overwritten in the Values loop below for each Value. But