package main import ( "bytes" "crypto/rand" "encoding/binary" "os" "time" ) func (p *Process) getInt32(addr int32) int32 { mem := p.vm.Memory()[addr : addr+4] var result int32 err := binary.Read(bytes.NewReader(mem), binary.LittleEndian, &result) if err != nil { panic(err) } return result } func (p *Process) setInt32(addr int32, val int32) { data := make([]byte, 4) buf := bytes.NewBuffer(data) err := binary.Write(buf, binary.LittleEndian, val) if err != nil { panic(err) } _, err := p.writeMem(addr, data) if err != nil { panic(err) } } func (p *Process) getInt64(addr int32) int64 { mem := p.vm.Memory()[addr : addr+8] var result int64 err := binary.Read(bytes.NewReader(mem), binary.LittleEndian, &result) if err != nil { panic(err) } return result } func (p *Process) setInt64(addr int32, val int64) { data := make([]byte, 8) buf := bytes.NewBuffer(data) err := binary.Write(buf, binary.LittleEndian, val) if err != nil { panic(err) } _, err := p.writeMem(addr, data) if err != nil { panic(err) } } // goRuntimeWasmExit implements the go runtime function runtime.wasmExit. It uses // the Go abi. // // This has the effective type of: // // func (p *Process) goRuntimeWasmExit(code int32) func (p *Process) goRuntimeWasmExit(sp int32) { exitCode := p.getInt32(sp + 8) os.Exit(int(exitCode)) } // goRuntimeWasmWrite wraps the write function. // // This has the effective type of: // // func (p *Process) goRuntimeWasmWrite(fd int64, ptr int64, n int32) func (p *Process) goRuntimeWasmWrite(sp int32) { fd := p.getInt64(sp + 8) ptr := p.getInt64(sp + 16) n := p.getInt32(sp + 24) result := p.write(int32(fd), int32(ptr), n) // TODO: write result to wasmWrite? _ = result } // goRuntimeNanotime implements the go runtime function runtime.nanotime. It uses // the Go abi. // // This has the effective type of: // // func (p *Process) goRuntimeNanotime() int64 func (p *Process) goRuntimeNanotime(sp int32) { p.setInt64(sp+8, int64(time.Now().UnixNano())) } // goRuntimeWalltime implements the go runtime function runtime.walltime. It uses // the Go abi. // // This has the effective type of: // // func (p *Process) goRuntimeWalltime() (int64, int32) func (p *Process) goRuntimeWalltime(sp int32) { now := time.Now() p.setInt64(sp+8, now.Unix()) p.setInt32(sp+16, int32(now.Nanosecond())) } // goRuntimeScheduleCallback implements the go runtime function runtime.scheduleCallback. // It uses the Go abi and is not implemented yet. func (p *Process) goRuntimeScheduleCallback(sp int32) { p.setInt32(sp+16, -1) } func (p *Process) goRuntimeClearScheduledCallback(sp int32) {} // goLoadSlice loads a Go slice out of wasm memory. It uses the the Go abi. func (p *Process) goLoadSlice(sp int32) []byte { arr := p.getInt64(sp) len := p.getInt64(sp + 8) return p.vm.Memory()[arr : arr+len] } func (p *Process) goRuntimeGetRandomData(sp int32) { data := p.goLoadSlice(sp + 8) _, err := rand.Read(data) if err != nil { panic(err) } p.writeMem(sp+8, data) }