Full test (which fails)
This commit is contained in:
@@ -27,4 +27,8 @@ functions:
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if state.GlobalMemory().MustReadUnsigned(0) != 3 {
|
||||||
|
t.Fatalf("Expected 3, found %d\n", state.GlobalMemory().MustReadUnsigned(0))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,12 +41,5 @@ func NewInstructionsFromByteCode(byteCode []byte) ([]*Instruction, error) {
|
|||||||
instrs = append(instrs, instr)
|
instrs = append(instrs, instr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(instrs) == 0 || instrs[len(instrs)-1].OpCode != OpReturn {
|
|
||||||
// Add implicit return at the end of each function
|
|
||||||
instrs = append(instrs, &Instruction{
|
|
||||||
OpCode: OpReturn,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return instrs, nil
|
return instrs, nil
|
||||||
}
|
}
|
||||||
|
|||||||
14
vm/memory.go
14
vm/memory.go
@@ -2,17 +2,17 @@ package vm
|
|||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
type memory struct {
|
type Memory struct {
|
||||||
entries []uint64
|
entries []uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMemory(size uint64) *memory {
|
func NewMemory(size uint64) *Memory {
|
||||||
return &memory{
|
return &Memory{
|
||||||
entries: make([]uint64, size),
|
entries: make([]uint64, size),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mem *memory) readUnsigned(index uint64) (uint64, error) {
|
func (mem *Memory) ReadUnsigned(index uint64) (uint64, error) {
|
||||||
if index >= uint64(len(mem.entries)) {
|
if index >= uint64(len(mem.entries)) {
|
||||||
return 0, fmt.Errorf("Invalid memory index: %016x", index)
|
return 0, fmt.Errorf("Invalid memory index: %016x", index)
|
||||||
}
|
}
|
||||||
@@ -20,15 +20,15 @@ func (mem *memory) readUnsigned(index uint64) (uint64, error) {
|
|||||||
return mem.entries[index], nil
|
return mem.entries[index], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mem *memory) mustReadUnsigned(index uint64) uint64 {
|
func (mem *Memory) MustReadUnsigned(index uint64) uint64 {
|
||||||
value, err := mem.readUnsigned(index)
|
value, err := mem.ReadUnsigned(index)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mem *memory) writeUnsigned(index uint64, value uint64) error {
|
func (mem *Memory) WriteUnsigned(index uint64, value uint64) error {
|
||||||
if index >= uint64(len(mem.entries)) {
|
if index >= uint64(len(mem.entries)) {
|
||||||
return fmt.Errorf("Invalid memory index: %016x", index)
|
return fmt.Errorf("Invalid memory index: %016x", index)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ package vm
|
|||||||
type stackFrame struct {
|
type stackFrame struct {
|
||||||
previousFunctionIndex int64
|
previousFunctionIndex int64
|
||||||
previousInstructionIndex int64
|
previousInstructionIndex int64
|
||||||
functionMemory *memory
|
functionMemory *Memory
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStackFrame(state *State) *stackFrame {
|
func newStackFrame(state *State) *stackFrame {
|
||||||
return &stackFrame{
|
return &stackFrame{
|
||||||
previousFunctionIndex: state.functionIndex,
|
previousFunctionIndex: state.functionIndex,
|
||||||
previousInstructionIndex: state.instructionIndex,
|
previousInstructionIndex: state.instructionIndex,
|
||||||
functionMemory: newMemory(16),
|
functionMemory: NewMemory(16),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
20
vm/state.go
20
vm/state.go
@@ -13,14 +13,14 @@ type State struct {
|
|||||||
instructionIndex int64
|
instructionIndex int64
|
||||||
|
|
||||||
comparisonResult bool
|
comparisonResult bool
|
||||||
globalMemory *memory
|
globalMemory *Memory
|
||||||
stack []*stackFrame
|
stack []*stackFrame
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewState(functions [][]*Instruction) (*State, error) {
|
func NewState(functions [][]*Instruction) (*State, error) {
|
||||||
return &State{
|
return &State{
|
||||||
functions: functions,
|
functions: functions,
|
||||||
globalMemory: newMemory(16),
|
globalMemory: NewMemory(16),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +51,10 @@ func (state *State) Execute() error {
|
|||||||
return state.err
|
return state.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (state *State) GlobalMemory() *Memory {
|
||||||
|
return state.globalMemory
|
||||||
|
}
|
||||||
|
|
||||||
func (state *State) stackFrame() *stackFrame {
|
func (state *State) stackFrame() *stackFrame {
|
||||||
return state.stack[len(state.stack)-1]
|
return state.stack[len(state.stack)-1]
|
||||||
}
|
}
|
||||||
@@ -83,6 +87,10 @@ func (state *State) processInstruction() {
|
|||||||
instr := fnc[state.instructionIndex]
|
instr := fnc[state.instructionIndex]
|
||||||
state.instructionIndex += 1
|
state.instructionIndex += 1
|
||||||
instr.opHandler(state, instr)
|
instr.opHandler(state, instr)
|
||||||
|
|
||||||
|
if state.instructionIndex >= int64(len(fnc)) {
|
||||||
|
state.ret()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (state *State) readUnsigned(op *Operand) uint64 {
|
func (state *State) readUnsigned(op *Operand) uint64 {
|
||||||
@@ -91,14 +99,14 @@ func (state *State) readUnsigned(op *Operand) uint64 {
|
|||||||
return op.Value
|
return op.Value
|
||||||
|
|
||||||
case FunctionMemoryIndex:
|
case FunctionMemoryIndex:
|
||||||
value, err := state.stackFrame().functionMemory.readUnsigned(op.Value)
|
value, err := state.stackFrame().functionMemory.ReadUnsigned(op.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.setError(err)
|
state.setError(err)
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
|
|
||||||
case GlobalMemoryIndex:
|
case GlobalMemoryIndex:
|
||||||
value, err := state.globalMemory.readUnsigned(op.Value)
|
value, err := state.globalMemory.ReadUnsigned(op.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.setError(err)
|
state.setError(err)
|
||||||
}
|
}
|
||||||
@@ -120,13 +128,13 @@ func (state *State) writeUnsigned(op *Operand, value uint64) {
|
|||||||
state.setError(fmt.Errorf("Write to literal operand"))
|
state.setError(fmt.Errorf("Write to literal operand"))
|
||||||
|
|
||||||
case FunctionMemoryIndex:
|
case FunctionMemoryIndex:
|
||||||
err := state.stackFrame().functionMemory.writeUnsigned(op.Value, value)
|
err := state.stackFrame().functionMemory.WriteUnsigned(op.Value, value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.setError(err)
|
state.setError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
case GlobalMemoryIndex:
|
case GlobalMemoryIndex:
|
||||||
err := state.globalMemory.writeUnsigned(op.Value, value)
|
err := state.globalMemory.WriteUnsigned(op.Value, value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
state.setError(err)
|
state.setError(err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user