forked from TrueCloudLab/neoneo-go
compiler: copy locals slice during inline
Consider function call `f(1, g(2, 3))` when both `f` and `g` are inlined. If `f` contains some locals, inlining `g` will replace them with it's another locals map, because slices in Go reuse storage on `append`. Thus scope needs to be copied.
This commit is contained in:
parent
b66b853285
commit
7577bbef22
3 changed files with 31 additions and 1 deletions
|
@ -39,7 +39,8 @@ func (c *codegen) inlineCall(f *funcScope, n *ast.CallExpr) {
|
||||||
// while stored in the new.
|
// while stored in the new.
|
||||||
oldScope := c.scope.vars.locals
|
oldScope := c.scope.vars.locals
|
||||||
c.scope.vars.newScope()
|
c.scope.vars.newScope()
|
||||||
newScope := c.scope.vars.locals
|
newScope := make([]map[string]varInfo, len(c.scope.vars.locals))
|
||||||
|
copy(newScope, c.scope.vars.locals)
|
||||||
defer c.scope.vars.dropScope()
|
defer c.scope.vars.dropScope()
|
||||||
|
|
||||||
hasVarArgs := !n.Ellipsis.IsValid()
|
hasVarArgs := !n.Ellipsis.IsValid()
|
||||||
|
|
|
@ -131,6 +131,21 @@ func TestInlineInLoop(t *testing.T) {
|
||||||
}`
|
}`
|
||||||
eval(t, src, big.NewInt(20))
|
eval(t, src, big.NewInt(20))
|
||||||
})
|
})
|
||||||
|
t.Run("inlined argument", func(t *testing.T) {
|
||||||
|
src := `package foo
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/interop/binary"
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/inline"
|
||||||
|
func Main() int {
|
||||||
|
sum := 0
|
||||||
|
values := []int{10, 11}
|
||||||
|
for _, v := range values {
|
||||||
|
binary.Itoa(v, 10)
|
||||||
|
sum += inline.VarSum(1, 2, 3, binary.Atoi("4", 10))
|
||||||
|
}
|
||||||
|
return sum
|
||||||
|
}`
|
||||||
|
eval(t, src, big.NewInt(20))
|
||||||
|
})
|
||||||
t.Run("check clean stack on return", func(t *testing.T) {
|
t.Run("check clean stack on return", func(t *testing.T) {
|
||||||
src := `package foo
|
src := `package foo
|
||||||
import "github.com/nspcc-dev/neo-go/pkg/interop/binary"
|
import "github.com/nspcc-dev/neo-go/pkg/interop/binary"
|
||||||
|
|
|
@ -3,6 +3,8 @@ package compiler_test
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -107,6 +109,7 @@ func newStoragePlugin() *storagePlugin {
|
||||||
s.interops[interopnames.ToID([]byte(interopnames.SystemStoragePut))] = s.Put
|
s.interops[interopnames.ToID([]byte(interopnames.SystemStoragePut))] = s.Put
|
||||||
s.interops[interopnames.ToID([]byte(interopnames.SystemStorageGetContext))] = s.GetContext
|
s.interops[interopnames.ToID([]byte(interopnames.SystemStorageGetContext))] = s.GetContext
|
||||||
s.interops[interopnames.ToID([]byte(interopnames.SystemRuntimeNotify))] = s.Notify
|
s.interops[interopnames.ToID([]byte(interopnames.SystemRuntimeNotify))] = s.Notify
|
||||||
|
s.interops[interopnames.ToID([]byte(interopnames.SystemBinaryAtoi))] = s.Atoi
|
||||||
s.interops[interopnames.ToID([]byte(interopnames.SystemBinaryItoa))] = s.Itoa
|
s.interops[interopnames.ToID([]byte(interopnames.SystemBinaryItoa))] = s.Itoa
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
@ -123,6 +126,17 @@ func (s *storagePlugin) syscallHandler(v *vm.VM, id uint32) error {
|
||||||
return errors.New("syscall not found")
|
return errors.New("syscall not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *storagePlugin) Atoi(v *vm.VM) error {
|
||||||
|
str := v.Estack().Pop().String()
|
||||||
|
base := v.Estack().Pop().BigInt().Int64()
|
||||||
|
n, err := strconv.ParseInt(str, int(base), 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
v.Estack().PushVal(big.NewInt(n))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *storagePlugin) Itoa(v *vm.VM) error {
|
func (s *storagePlugin) Itoa(v *vm.VM) error {
|
||||||
n := v.Estack().Pop().BigInt()
|
n := v.Estack().Pop().BigInt()
|
||||||
base := v.Estack().Pop().BigInt()
|
base := v.Estack().Pop().BigInt()
|
||||||
|
|
Loading…
Reference in a new issue