Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/compile: bad debug_line stmt selection for if statement involving string comparison #31138

Open
aarzilli opened this Issue Mar 29, 2019 · 2 comments

Comments

Projects
None yet
3 participants
@aarzilli
Copy link
Contributor

aarzilli commented Mar 29, 2019

$ go version
go version devel +ddef157813 Fri Mar 29 07:17:49 2019 +0000 linux/amd64

Given the following program:

package main

type Struct struct {
	Name string
	Func func()
}

func NewStruct(name string) Struct {
	return Struct{Name:name}
}

func FindIndex2(structs []Struct, s string) int {
	for i, st := range structs { // breakpoint here, then step
		// fmt.Println(i) // uncomment this and it will work
		if st.Name == s { // starts with i = 3
			return i
		}
	}
	return -1
}

func main() {
	structs := []Struct{
		NewStruct("a"),
		NewStruct("b"),
		NewStruct("c"),
		NewStruct("dddddddd1"),
		NewStruct("dddddddd2"),
	}

	FindIndex2(structs, "dddddddd2")
}

for line 15 (if st.Name == s) the generated code is:

test.go:15 |   | 0x450bea | 48894c2440 | MOVQ CX, 0x40(SP)
test.go:15 |   | 0x450bef | 4889542448 | MOVQ DX, 0x48(SP)
test.go:15 |   | 0x450bf4 | 48399424c8000000 | CMPQ DX, 0xc8(SP)
test.go:15 |   | 0x450bfc | 7405 | JE 0x450c03
test.go:15 |   | 0x450bfe | e98c000000 | JMP 0x450c8f
test.go:15 | S | 0x450c03 | 48890c24 | MOVQ CX, 0(SP)
test.go:15 |   | 0x450c07 | 488b8424c0000000 | MOVQ 0xc0(SP), AX
test.go:15 |   | 0x450c0f | 4889442408 | MOVQ AX, 0x8(SP)
test.go:15 |   | 0x450c14 | 4889542410 | MOVQ DX, 0x10(SP)
test.go:15 | S | 0x450c19 | e8f215fbff | CALL runtime.memequal(SB)
test.go:15 |   | 0x450c1e | 807c241800 | CMPB $0x0, 0x18(SP)
test.go:15 |   | 0x450c23 | 7502 | JNE 0x450c27
test.go:15 |   | 0x450c25 | eb1d | JMP 0x450c44

Both instructions selected as statements (0x450c03 and 0x450c19) happen after a check on string length, something like 0x450bea or 0x450bf4 would be more appropriate.

Original report: go-delve/delve#1527
cc @heschik @dr2chase
@gopherbot please add label Debugging

@gopherbot gopherbot added the Debugging label Mar 29, 2019

@cuonglm

This comment has been minimized.

Copy link
Contributor

cuonglm commented Apr 3, 2019

It's only happen if you disable optimization, which dlv debug does by default. In this case, the compiler seems to be smart enough to ignore element, which has len(Name) != len(s).

If you move NewStruct("dddddddd1") to first, you got i == 0, second, got i == 1.

For me, the compiler does reverse logic here. I expect the behavior of non-optimization happens in optimization mode.

@cuonglm

This comment has been minimized.

Copy link
Contributor

cuonglm commented Apr 3, 2019

git bisect points to 2578ac5

It seems to be reasonable, because with optimization, NewStruct is inlined:

go build -gcflags "-m -m"      
# _/home/cuonglm/bin/go/31138
./main.go:8:6: can inline NewStruct as: func(string) Struct { return Struct literal }
./main.go:12:6: cannot inline FindIndex2: unhandled op RANGE
./main.go:22:6: cannot inline main: function too complex: cost 102 exceeds budget 80
./main.go:24:12: inlining call to NewStruct func(string) Struct { return Struct literal }
./main.go:25:12: inlining call to NewStruct func(string) Struct { return Struct literal }
./main.go:26:12: inlining call to NewStruct func(string) Struct { return Struct literal }
./main.go:27:12: inlining call to NewStruct func(string) Struct { return Struct literal }
./main.go:28:12: inlining call to NewStruct func(string) Struct { return Struct literal }
./main.go:8:16: leaking param: name to result ~r1 level=0
./main.go:8:16: 	from Struct literal (struct literal element) at ./main.go:9:15
./main.go:8:16: 	from ~r1 (return) at ./main.go:9:2
./main.go:12:17: FindIndex2 structs does not escape
./main.go:12:35: FindIndex2 s does not escape
./main.go:23:21: main []Struct literal does not escape

What should we do in this case? cc @josharian

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.