From 21a7f3d76005e45763fed4df4574b605c295fe41 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Mon, 5 Apr 2021 22:56:59 +0300 Subject: [PATCH 1/2] compiler: keep traversing after c.countLocalsCall() Some arguments can be inlined functions themselves thus requiring additional attention. Otherwise we can get less local variables than really used by STLOCs (and subsequent program crash). --- pkg/compiler/func_scope.go | 1 - pkg/compiler/inline_test.go | 9 +++++++++ pkg/compiler/testdata/inline/inline.go | 4 ++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/pkg/compiler/func_scope.go b/pkg/compiler/func_scope.go index 5e2534287..672b839ef 100644 --- a/pkg/compiler/func_scope.go +++ b/pkg/compiler/func_scope.go @@ -162,7 +162,6 @@ func (c *codegen) countLocalsInline(decl *ast.FuncDecl, pkg *types.Package, f *f switch n := n.(type) { case *ast.CallExpr: size += c.countLocalsCall(n, pkg) - return false case *ast.FuncType: num := n.Results.NumFields() if num != 0 && len(n.Results.List[0].Names) != 0 { diff --git a/pkg/compiler/inline_test.go b/pkg/compiler/inline_test.go index eeb9bfe3a..4c814cf26 100644 --- a/pkg/compiler/inline_test.go +++ b/pkg/compiler/inline_test.go @@ -209,6 +209,15 @@ func TestInlineGlobalVariable(t *testing.T) { }) } +func TestInlineVariadicInInlinedCall(t *testing.T) { + src := `package foo + import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/inline" + func Main() int { + return inline.SumSquared(inline.SumVar(3, 4) - 2, 3) + }` + eval(t, src, big.NewInt(64)) +} + func TestInlineConversion(t *testing.T) { src1 := `package foo import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/inline" diff --git a/pkg/compiler/testdata/inline/inline.go b/pkg/compiler/testdata/inline/inline.go index c319c6b1d..62aaf2c79 100644 --- a/pkg/compiler/testdata/inline/inline.go +++ b/pkg/compiler/testdata/inline/inline.go @@ -39,6 +39,10 @@ func VarSum(a int, b ...int) int { return sum } +func SumVar(a, b int) int { + return VarSum(a, b) +} + func Concat(n int) int { return n*100 + b.A*10 + A } From 7e9f8e03c24d05fb9cca3188fe4ad7ecf7d826a2 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Mon, 5 Apr 2021 23:03:10 +0300 Subject: [PATCH 2/2] compiler: add a test for inlined selector statements Selector here is either a struct field access or global package variable/constant. While technically none of these require an additional local, inlining actually uses one, so add a test for it. --- pkg/compiler/inline_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg/compiler/inline_test.go b/pkg/compiler/inline_test.go index 4c814cf26..bf62e65a3 100644 --- a/pkg/compiler/inline_test.go +++ b/pkg/compiler/inline_test.go @@ -264,3 +264,13 @@ func TestInlineConversionQualified(t *testing.T) { require.NoError(t, err) require.Equal(t, b2, b1) } + +func TestPackageVarsInInlinedCalls(t *testing.T) { + src := `package foo + import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/inline" + import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/inline/b" + func Main() int { + return inline.Sum(inline.A, b.A) + }` + eval(t, src, big.NewInt(13)) +}