mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-25 23:42:23 +00:00
compiler: load constants directly on inline
This commit is contained in:
parent
27e60455c7
commit
3484025065
4 changed files with 39 additions and 19 deletions
|
@ -194,20 +194,21 @@ func (c *codegen) emitStoreStructField(i int) {
|
||||||
|
|
||||||
// getVarIndex returns variable type and position in corresponding slot,
|
// getVarIndex returns variable type and position in corresponding slot,
|
||||||
// according to current scope.
|
// 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 pkg == "" {
|
||||||
if c.scope != nil {
|
if c.scope != nil {
|
||||||
vt, val := c.scope.vars.getVarIndex(name)
|
vi := c.scope.vars.getVarInfo(name)
|
||||||
if val >= 0 {
|
if vi != nil {
|
||||||
return vt, val
|
return vi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if i, ok := c.globals[c.getIdentName(pkg, name)]; ok {
|
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) {
|
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.
|
// emitLoadVar loads specified variable to the evaluation stack.
|
||||||
func (c *codegen) emitLoadVar(pkg string, name string) {
|
func (c *codegen) emitLoadVar(pkg string, name string) {
|
||||||
t, i := c.getVarIndex(pkg, name)
|
vi := c.getVarIndex(pkg, name)
|
||||||
c.emitLoadByIndex(t, i)
|
if vi.tv.Value != nil {
|
||||||
|
c.emitLoadConst(vi.tv)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.emitLoadByIndex(vi.refType, vi.index)
|
||||||
}
|
}
|
||||||
|
|
||||||
// emitLoadByIndex loads specified variable type with index i.
|
// 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)
|
emit.Opcodes(c.prog.BinWriter, opcode.DROP)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t, i := c.getVarIndex(pkg, name)
|
vi := c.getVarIndex(pkg, name)
|
||||||
c.emitStoreByIndex(t, i)
|
c.emitStoreByIndex(vi.refType, vi.index)
|
||||||
}
|
}
|
||||||
|
|
||||||
// emitLoadByIndex stores top value in the specified variable type with index i.
|
// emitLoadByIndex stores top value in the specified variable type with index i.
|
||||||
|
|
|
@ -28,13 +28,18 @@ func (c *codegen) inlineCall(f *funcScope, n *ast.CallExpr) {
|
||||||
for i := range n.Args {
|
for i := range n.Args {
|
||||||
c.scope.vars.locals = oldScope
|
c.scope.vars.locals = oldScope
|
||||||
name := sig.Params().At(i).Name()
|
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 {
|
if arg, ok := n.Args[i].(*ast.Ident); ok {
|
||||||
// When function argument is variable or const, we may avoid
|
// When function argument is variable or const, we may avoid
|
||||||
// introducing additional variables for parameters.
|
// introducing additional variables for parameters.
|
||||||
// This is done by providing additional alias to variable.
|
// 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.locals = newScope
|
||||||
c.scope.vars.addAlias(name, vt, index)
|
c.scope.vars.addAlias(name, vi.refType, vi.index, vi.tv)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,8 +110,7 @@ func TestInlineConversion(t *testing.T) {
|
||||||
func Main() int {
|
func Main() int {
|
||||||
a := 2
|
a := 2
|
||||||
{
|
{
|
||||||
b := 1
|
return (1 + a) * (1 + a)
|
||||||
return (b + a) * (b + a)
|
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
b2, err := compiler.Compile("foo.go", strings.NewReader(src2))
|
b2, err := compiler.Compile("foo.go", strings.NewReader(src2))
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
package compiler
|
package compiler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
type varScope struct {
|
type varScope struct {
|
||||||
localsCnt int
|
localsCnt int
|
||||||
argCnt int
|
argCnt int
|
||||||
|
@ -10,8 +14,11 @@ type varScope struct {
|
||||||
type varInfo struct {
|
type varInfo struct {
|
||||||
refType varType
|
refType varType
|
||||||
index int
|
index int
|
||||||
|
tv types.TypeAndValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const unspecifiedVarIndex = -1
|
||||||
|
|
||||||
func newVarScope() varScope {
|
func newVarScope() varScope {
|
||||||
return varScope{
|
return varScope{
|
||||||
arguments: make(map[string]int),
|
arguments: make(map[string]int),
|
||||||
|
@ -26,23 +33,27 @@ func (c *varScope) dropScope() {
|
||||||
c.locals = c.locals[:len(c.locals)-1]
|
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{
|
c.locals[len(c.locals)-1][name] = varInfo{
|
||||||
refType: vt,
|
refType: vt,
|
||||||
index: index,
|
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-- {
|
for i := len(c.locals) - 1; i >= 0; i-- {
|
||||||
if vi, ok := c.locals[i][name]; ok {
|
if vi, ok := c.locals[i][name]; ok {
|
||||||
return vi.refType, vi.index
|
return &vi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if i, ok := c.arguments[name]; ok {
|
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.
|
// newVariable creates a new local variable or argument in the scope of the function.
|
||||||
|
|
Loading…
Reference in a new issue