mohanson / pywasm

A WebAssembly interpreter written in pure Python
MIT License
443 stars 39 forks source link

Results seem to be different from wasmer #52

Open taylorh140 opened 1 year ago

taylorh140 commented 1 year ago

I was playing around with wasmer and saw this implmentation I like portable stuff so i tried it. but for some reason it doesnt behave quite the same as wasmer. I get different images.

image

image

pikchrNoImp.zip

wasmer setup

#this uses python-wasmer
from wasmer import FunctionType,Buffer,Memory,MemoryType, engine, Store, Module, Instance, Function,Value,Type
from pathlib import Path
store = Store()
module=Module(store, open('pikchrNoImp.wasm', 'rb').read())

for i in module.imports:
    print(i.name)

instance = Instance(module)#, import_object)
memory = instance.exports.memory

def write_c_string(instance,bstring:bytearray):
  ptr=instance.exports.stackAlloc(len(bstring)+1)
  mem=instance.exports.memory.int8_view()
  ptrcnt=ptr
  for c in bstring:
    mem[ptrcnt]=c
    ptrcnt+=1
  return ptr

def get_c_string(instance,ptr):
  mem = bytearray(instance.exports.memory.buffer)
  result_str = mem[ptr:].partition(b"\x00")[0] #get c string
  return str(result_str, 'UTF-8') 

in1=write_c_string(instance,b""" 
   arrow right 200% "Markdown" "Source"
   box rad 10px "Markdown" "Formatter" "(markdown.c)" fit
   arrow right 200% "HTML+SVG" "Output"
   arrow <-> down 70% from last box.s
   box same "Pikchr" "Formatter" "(pikchr.c)" fit
""")
result = instance.exports.pikchr(in1,0,0,0,0)
print(get_c_string(instance,result))

Path("wasmTest.svg").write_text(get_c_string(instance,result))

pywasm setup

#This uses python-wasmer
import pywasm
from pathlib import Path

option = pywasm.Option()
runtime = pywasm.load('PikchrNoImp.wasm')

def write_c_string(runtime,bstring:bytearray):
  ptr=runtime.exec("stackAlloc",[(len(bstring)+1)])
  mem=runtime.machine.store.mems[0].data
  ptrcnt=ptr
  for c in bstring:
    mem[ptrcnt]=c
    ptrcnt+=1
  mem[ptrcnt]=0
  return ptr

def get_c_string(runtime,ptr):
  mem = runtime.machine.store.mems[0].data
  result_str = mem[ptr:].partition(b"\x00")[0] #get c string
  return str(result_str, 'UTF-8') 

print(get_c_string(runtime,5268992))

in1=write_c_string(runtime,b""" 
   arrow right 200% "Markdown" "Source"
   box rad 10px "Markdown" "Formatter" "(markdown.c)" fit
   arrow right 200% "HTML+SVG" "Output"
   arrow <-> down 70% from last box.s
   box same "Pikchr" "Formatter" "(pikchr.c)" fit
""")

#print(dir(runtime.machine.store.mems.index()))
print(in1)
print(get_c_string(runtime,in1))

r = runtime.exec('pikchr', [in1,0,0,0,0])
print(r)
print(get_c_string(runtime,r))

Path("wasmTest.svg").write_text(get_c_string(runtime,r))

I have no idea why they would have different results? maybe math issue?

mohanson commented 1 year ago

You are right. I reproduced this issue with nodejs, but I'm not yet able to identify the cause of the problem.

const fs = require('fs')

const wasmBuffer = fs.readFileSync('/tmp/pikchrNoImp.wasm')
WebAssembly.instantiate(wasmBuffer).then(wasmModule => {
    const { stackAlloc, pikchr, memory } = wasmModule.instance.exports
    const dataView = new Uint8Array(memory.buffer)

    write_c_string = (s) => {
        let ptr = stackAlloc(s.length + 1)
        let idx = ptr
        for (let i in s.slice()) {
            dataView[idx] = s[i].charCodeAt(0)
            idx += 1
        }
        dataView[idx] = 0
        return ptr
    }

    get_c_string = (ptr) => {
        let idx = ptr
        let buf = []
        while (dataView[idx] !== undefined && dataView[idx] !== 0) {
            buf.push(String.fromCharCode(dataView[idx]))
            idx += 1
        }
        return buf.join('')
    }

    in1 = write_c_string(`arrow right 200% "Markdown" "Source"
box rad 10px "Markdown" "Formatter" "(markdown.c)" fit
arrow right 200% "HTML+SVG" "Output"
arrow <-> down 70% from last box.s
box same "Pikchr" "Formatter" "(pikchr.c)" fit`)

    console.log('in1 =', in1)
    console.log('raw =', get_c_string(in1))
    let in2 = pikchr(in1, 0, 0, 0, 0)
    console.log('in2 =', in2)
    console.log('out =', get_c_string(in2))
});