move generator to its own package

This commit is contained in:
Ömer Faruk IRMAK 2025-07-25 11:12:53 +03:00
parent ae63a92d08
commit df14a86947
2 changed files with 42 additions and 13 deletions

View file

@ -1,4 +1,4 @@
package vm package main
import ( import (
"fmt" "fmt"
@ -10,10 +10,22 @@ import (
"reflect" "reflect"
"runtime" "runtime"
"strings" "strings"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
) )
var fSet = token.NewFileSet() var fSet = token.NewFileSet()
type OpcodeImpl interface {
MemoryFunc() any
GasFunc() any
ExecuteFunc() any
ConstantGas() uint64
MinStack() uint64
MaxStack() uint64
}
type opFuncNames struct { type opFuncNames struct {
memory string memory string
gas string gas string
@ -35,13 +47,14 @@ func functionName(f any) string {
return arr[len(arr)-1] return arr[len(arr)-1]
} }
func collectFuncNames(jt JumpTable) [256]opFuncNames { func collectFuncNames(jt vm.JumpTable) [256]opFuncNames {
var funcNames [256]opFuncNames var funcNames [256]opFuncNames
for opCode, entry := range jt { for opCode, entry := range jt {
impl := (OpcodeImpl)(entry)
funcNames[opCode] = opFuncNames{ funcNames[opCode] = opFuncNames{
memory: functionName(entry.memorySize), memory: functionName(impl.MemoryFunc()),
gas: functionName(entry.dynamicGas), gas: functionName(impl.GasFunc()),
execution: functionName(entry.execute), execution: functionName(impl.ExecuteFunc()),
} }
} }
return funcNames return funcNames
@ -81,7 +94,7 @@ func extractBody(funcDef string) string {
} }
func collectFuncDefinitions(funcNames [256]opFuncNames) [256]opFuncDefs { func collectFuncDefinitions(funcNames [256]opFuncNames) [256]opFuncDefs {
pkgs, err := parser.ParseDir(fSet, ".", nil, 0) pkgs, err := parser.ParseDir(fSet, "..", nil, 0)
if err != nil { if err != nil {
panic(fmt.Sprint("failed to parse vm package", err)) panic(fmt.Sprint("failed to parse vm package", err))
} }
@ -165,12 +178,18 @@ func outputExecution(w io.Writer, op *funcDef) {
`, extractBody(op.source)) `, extractBody(op.source))
} }
func GenerateRun() { func main() {
set := newLondonInstructionSet() set, err := vm.LookupInstructionSet(params.Rules{
IsLondon: true,
})
if err != nil {
panic("failed to get instruction set")
}
funcNames := collectFuncNames(set) funcNames := collectFuncNames(set)
funcDefinitions := collectFuncDefinitions(funcNames) funcDefinitions := collectFuncDefinitions(funcNames)
output, _ := os.Create("out.go") output, _ := os.Create("../out.go")
fmt.Fprintln(output, `package vm fmt.Fprintln(output, `package vm
func Run(interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error) { func Run(interpreter *EVMInterpreter, callContext *ScopeContext) ([]byte, error) {
@ -181,6 +200,8 @@ func GenerateRun() {
switch op { switch op {
`) `)
for opCode := range funcDefinitions { for opCode := range funcDefinitions {
impl := (OpcodeImpl)(set[opCode])
fmt.Fprintf(output, `case %d: fmt.Fprintf(output, `case %d:
if !callContext.Contract.UseGas(%d, nil, tracing.GasChangeIgnored) { if !callContext.Contract.UseGas(%d, nil, tracing.GasChangeIgnored) {
return nil, ErrOutOfGas return nil, ErrOutOfGas
@ -191,23 +212,23 @@ func GenerateRun() {
} else if sLen > %d { } else if sLen > %d {
return nil, &ErrStackOverflow{stackLen: sLen, limit: %d} return nil, &ErrStackOverflow{stackLen: sLen, limit: %d}
} }
`, opCode, set[opCode].constantGas, set[opCode].minStack, set[opCode].minStack, set[opCode].maxStack, set[opCode].maxStack) `, opCode, impl.ConstantGas(), impl.MinStack(), impl.MinStack(), impl.MaxStack(), impl.MaxStack())
if funcDefinitions[opCode].memory.decl != nil { if funcDefinitions[opCode].memory.decl != nil {
outputMemoryCalc(output, &funcDefinitions[opCode].memory) outputMemoryCalc(output, &funcDefinitions[opCode].memory)
} else if len(funcNames[opCode].memory) > 0 { } else if len(funcNames[opCode].memory) > 0 {
panic(fmt.Sprint("failed to get memory handler definition for ", opCodeToString[opCode])) panic(fmt.Sprint("failed to get memory handler definition for ", opCode))
} }
if funcDefinitions[opCode].gas.decl != nil { if funcDefinitions[opCode].gas.decl != nil {
outputDynamicGas(output, &funcDefinitions[opCode].gas, funcDefinitions[opCode].memory.decl != nil) outputDynamicGas(output, &funcDefinitions[opCode].gas, funcDefinitions[opCode].memory.decl != nil)
} else if len(funcNames[opCode].gas) > 0 { } else if len(funcNames[opCode].gas) > 0 {
panic(fmt.Sprint("failed to get gas handler definition for ", opCodeToString[opCode])) panic(fmt.Sprint("failed to get gas handler definition for ", opCode))
} }
if funcDefinitions[opCode].execution.decl != nil { if funcDefinitions[opCode].execution.decl != nil {
outputExecution(output, &funcDefinitions[opCode].execution) outputExecution(output, &funcDefinitions[opCode].execution)
} else if len(funcNames[opCode].execution) > 0 { } else if len(funcNames[opCode].execution) > 0 {
panic(fmt.Sprint("failed to get exec handler definition for ", opCodeToString[opCode])) panic(fmt.Sprint("failed to get exec handler definition for ", opCode))
} }
} }
fmt.Fprintln(output, `} fmt.Fprintln(output, `}

View file

@ -47,6 +47,14 @@ type operation struct {
undefined bool undefined bool
} }
// Generator interface
func (o *operation) MemoryFunc() any { return o.memorySize }
func (o *operation) GasFunc() any { return o.dynamicGas }
func (o *operation) ExecuteFunc() any { return o.execute }
func (o *operation) ConstantGas() uint64 { return o.constantGas }
func (o *operation) MinStack() uint64 { return uint64(o.minStack) }
func (o *operation) MaxStack() uint64 { return uint64(o.minStack) }
var ( var (
frontierInstructionSet = newFrontierInstructionSet() frontierInstructionSet = newFrontierInstructionSet()
homesteadInstructionSet = newHomesteadInstructionSet() homesteadInstructionSet = newHomesteadInstructionSet()