From 34840250650ddc3a4008380504e14593dbffbfcf Mon Sep 17 00:00:00 2001 From: Evgeniy Stratonikov Date: Fri, 5 Feb 2021 16:15:26 +0300 Subject: [PATCH] compiler: load constants directly on inline --- pkg/compiler/codegen.go | 25 +++++++++++++++---------- pkg/compiler/inline.go | 9 +++++++-- pkg/compiler/inline_test.go | 3 +-- pkg/compiler/vars.go | 21 ++++++++++++++++----- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 992b9c49b..ea96ef834 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -194,20 +194,21 @@ func (c *codegen) emitStoreStructField(i int) { // getVarIndex returns variable type and position in corresponding slot, // according to current scope. -func (c *codegen) getVarIndex(pkg string, name string) (varType, int) { +func (c *codegen) getVarIndex(pkg string, name string) *varInfo { if pkg == "" { if c.scope != nil { - vt, val := c.scope.vars.getVarIndex(name) - if val >= 0 { - return vt, val + vi := c.scope.vars.getVarInfo(name) + if vi != nil { + return vi } } } if i, ok := c.globals[c.getIdentName(pkg, name)]; ok { - return varGlobal, i + return &varInfo{refType: varGlobal, index: i} } - return varLocal, c.scope.newVariable(varLocal, name) + c.scope.newVariable(varLocal, name) + return c.scope.vars.getVarInfo(name) } func getBaseOpcode(t varType) (opcode.Opcode, opcode.Opcode) { @@ -225,8 +226,12 @@ func getBaseOpcode(t varType) (opcode.Opcode, opcode.Opcode) { // emitLoadVar loads specified variable to the evaluation stack. func (c *codegen) emitLoadVar(pkg string, name string) { - t, i := c.getVarIndex(pkg, name) - c.emitLoadByIndex(t, i) + vi := c.getVarIndex(pkg, name) + if vi.tv.Value != nil { + c.emitLoadConst(vi.tv) + return + } + c.emitLoadByIndex(vi.refType, vi.index) } // emitLoadByIndex loads specified variable type with index i. @@ -245,8 +250,8 @@ func (c *codegen) emitStoreVar(pkg string, name string) { emit.Opcodes(c.prog.BinWriter, opcode.DROP) return } - t, i := c.getVarIndex(pkg, name) - c.emitStoreByIndex(t, i) + vi := c.getVarIndex(pkg, name) + c.emitStoreByIndex(vi.refType, vi.index) } // emitLoadByIndex stores top value in the specified variable type with index i. diff --git a/pkg/compiler/inline.go b/pkg/compiler/inline.go index 39ba8ef7e..417e5b857 100644 --- a/pkg/compiler/inline.go +++ b/pkg/compiler/inline.go @@ -28,13 +28,18 @@ func (c *codegen) inlineCall(f *funcScope, n *ast.CallExpr) { for i := range n.Args { c.scope.vars.locals = oldScope name := sig.Params().At(i).Name() + if tv := c.typeAndValueOf(n.Args[i]); tv.Value != nil { + c.scope.vars.locals = newScope + c.scope.vars.addAlias(name, varLocal, unspecifiedVarIndex, tv) + continue + } if arg, ok := n.Args[i].(*ast.Ident); ok { // When function argument is variable or const, we may avoid // introducing additional variables for parameters. // This is done by providing additional alias to variable. - if vt, index := c.scope.vars.getVarIndex(arg.Name); index != -1 { + if vi := c.scope.vars.getVarInfo(arg.Name); vi != nil { c.scope.vars.locals = newScope - c.scope.vars.addAlias(name, vt, index) + c.scope.vars.addAlias(name, vi.refType, vi.index, vi.tv) continue } } diff --git a/pkg/compiler/inline_test.go b/pkg/compiler/inline_test.go index fa14c31bf..8870f1a47 100644 --- a/pkg/compiler/inline_test.go +++ b/pkg/compiler/inline_test.go @@ -110,8 +110,7 @@ func TestInlineConversion(t *testing.T) { func Main() int { a := 2 { - b := 1 - return (b + a) * (b + a) + return (1 + a) * (1 + a) } }` b2, err := compiler.Compile("foo.go", strings.NewReader(src2)) diff --git a/pkg/compiler/vars.go b/pkg/compiler/vars.go index f8a3fc481..4753d56f8 100644 --- a/pkg/compiler/vars.go +++ b/pkg/compiler/vars.go @@ -1,5 +1,9 @@ package compiler +import ( + "go/types" +) + type varScope struct { localsCnt int argCnt int @@ -10,8 +14,11 @@ type varScope struct { type varInfo struct { refType varType index int + tv types.TypeAndValue } +const unspecifiedVarIndex = -1 + func newVarScope() varScope { return varScope{ arguments: make(map[string]int), @@ -26,23 +33,27 @@ func (c *varScope) dropScope() { c.locals = c.locals[:len(c.locals)-1] } -func (c *varScope) addAlias(name string, vt varType, index int) { +func (c *varScope) addAlias(name string, vt varType, index int, tv types.TypeAndValue) { c.locals[len(c.locals)-1][name] = varInfo{ refType: vt, index: index, + tv: tv, } } -func (c *varScope) getVarIndex(name string) (varType, int) { +func (c *varScope) getVarInfo(name string) *varInfo { for i := len(c.locals) - 1; i >= 0; i-- { if vi, ok := c.locals[i][name]; ok { - return vi.refType, vi.index + return &vi } } if i, ok := c.arguments[name]; ok { - return varArgument, i + return &varInfo{ + refType: varArgument, + index: i, + } } - return 0, -1 + return nil } // newVariable creates a new local variable or argument in the scope of the function.