From 1f2d76a1c2b690e310644b664e60979f0671fca1 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 14 Oct 2020 14:34:53 +0300 Subject: [PATCH] compiler: fix manifest method offset While optimizing jumps, old offsets should be compared with the method offset before optimization, not with the constantly changing value. --- pkg/compiler/codegen.go | 9 ++++++--- pkg/compiler/function_call_test.go | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 5a9bbebf9..764830d7e 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -1951,18 +1951,21 @@ func (c *codegen) writeJumps(b []byte) ([]byte, error) { // Correct function ip range. // Note: indices are sorted in increasing order. for _, f := range c.funcs { + start, end := f.rng.Start, f.rng.End loop: for _, ind := range offsets { switch { case ind > int(f.rng.End): break loop case ind < int(f.rng.Start): - f.rng.Start -= longToShortRemoveCount - f.rng.End -= longToShortRemoveCount + start -= longToShortRemoveCount + end -= longToShortRemoveCount case ind >= int(f.rng.Start): - f.rng.End -= longToShortRemoveCount + end -= longToShortRemoveCount } } + f.rng.Start = start + f.rng.End = end } return shortenJumps(b, offsets), nil } diff --git a/pkg/compiler/function_call_test.go b/pkg/compiler/function_call_test.go index 4c7732f66..1de9f3ae4 100644 --- a/pkg/compiler/function_call_test.go +++ b/pkg/compiler/function_call_test.go @@ -3,7 +3,12 @@ package compiler_test import ( "fmt" "math/big" + "strings" "testing" + + "github.com/nspcc-dev/neo-go/pkg/compiler" + "github.com/nspcc-dev/neo-go/pkg/vm/opcode" + "github.com/stretchr/testify/require" ) func TestSimpleFunctionCall(t *testing.T) { @@ -269,3 +274,19 @@ func TestVariadicMethod(t *testing.T) { }` eval(t, src, big.NewInt(42)) } + +func TestJumpOptimize(t *testing.T) { + src := `package foo + func Get1() int { return 1 } + func Get2() int { Get1(); Get1(); Get1(); Get1(); return Get1() } + func Get3() int { return Get2() } + func Main() int { + return Get3() + }` + b, di, err := compiler.CompileWithDebugInfo("", strings.NewReader(src)) + require.NoError(t, err) + for _, mi := range di.Methods { + require.Equal(t, b[mi.Range.Start], byte(opcode.INITSLOT)) + require.Equal(t, b[mi.Range.End], byte(opcode.RET)) + } +}