def test_read_wat(): for text in (TEXT1, TEXT2): m = Module(text) m.to_string() b = m.to_bytes() assert isinstance(b, bytes)
def test_type1(): """ Test canoncocal form of import and func and inline typedefs. """ # The canonical form CODE0 = dedent(""" (module (type $0 (func (param i32))) (type $1 (func (param i32 i32) (result i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $0))) (start $main) (func $add (type $1) (get_local 0) (get_local 1) (i32.add) ) (func $main (type $2) (i32.const 4) (i32.const 3) (call $add) (call $print) ) ) """) # Test main code m0 = Module(CODE0) assert m0.to_string() == CODE0 b0 = m0.to_bytes() assert Module(b0).to_bytes() == b0 if has_node(): assert run_wasm_in_node(m0, True) == '7' # Abbreviation: inline typedefs CODE1 = """ (module (import "js" "print_ln" (func $print (param i32))) (start $main) (func $add (param i32 i32) (result i32) (get_local 0) (get_local 1) (i32.add) ) (func $main (i32.const 4) (i32.const 3) (call $add) (call $print) ) ) """ m1 = Module(CODE1) assert m1.to_string() == CODE0 assert m1.to_bytes() == b0
def test_export1(): # The canonical form CODE0 = dedent(""" (module (type $sig (func)) (table $t1 2 anyfunc) (memory $m1 1) (global $g1 i32 (i32.const 7)) (export "bar_table1" (table $t1)) (export "bar_mem1" (memory $m1)) (export "bar_global" (global $g1)) (export "bar_func1" (func $f1)) (export "bar_func2" (func $f1)) (func $f1 (type $sig) ) ) """) # Test main code m0 = Module(CODE0) print(m0.to_string()) assert m0.to_string() == CODE0 b0 = m0.to_bytes() assert Module(b0).to_bytes() == b0 # Export abbreviations: definitions of func/memory/table/global # that are really exports. CODE1 = dedent(""" (module (type $sig (func)) (table $t1 (export "bar_table1") 2 anyfunc) (memory $m1 (export "bar_mem1") 1) (global $g1 (export "bar_global") i32 (i32.const 7)) (func $f1 (export "bar_func1") (export "bar_func2") (type $sig) ) ) """) m1 = Module(CODE1) assert m1.to_string() == CODE0 assert m1.to_bytes() == b0
def test_import1(): # The canonical form CODE0 = dedent(""" (module (type $bar_func (func)) (import "foo" "bar_func" (func $bar_func (type $bar_func))) (import "foo" "bar_table1" (table $t1 2 funcref)) (import "foo" "bar_mem1" (memory $m1 1)) (import "foo" "bar_mem2" (memory $m2 1 2)) (import "foo" "bar_global" (global $bar_global i32)) ) """) # (import "foo" "bar_table" (table $bar_table (type $bar_func))) # Test main code m0 = Module(CODE0) print(m0.to_string()) assert m0.to_string() == CODE0 b0 = m0.to_bytes() assert Module(b0).to_bytes() == b0 # Import abbreviations: definitions of func/memory/table/global # that are really imports. CODE1 = dedent(""" (module (type $bar_func (func)) (func $bar_func (import "foo" "bar_func") (type $bar_func)) (table $t1 (import "foo" "bar_table1") 2 funcref) (memory $m1 (import "foo" "bar_mem1") 1) (memory $m2 (import "foo" "bar_mem2") 1 2) (global $bar_global (import "foo" "bar_global") i32) ) """) m1 = Module(CODE1) assert m1.to_string() == CODE0 assert m1.to_bytes() == b0
def test_global1(): CODE0 = dedent(r""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (global $foo i32 i32.const 7) (start $main) (func $main (type $2) global.get $foo call $print) ) """) # Test main code m0 = Module(CODE0) assert m0.to_string() == CODE0 b0 = m0.to_bytes() assert Module(b0).to_bytes() == b0 if has_node(): assert run_wasm_in_node(m0, True) == '7'
def test_table1(): # The canonical form CODE0 = dedent(r""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (table $0 2 2 funcref) (start $main) (elem i32.const 0 $f1 $f2) (func $f1 (type $2) i32.const 101 call $print) (func $f2 (type $2) i32.const 102 call $print) (func $main (type $2) i32.const 0 call_indirect (type $2) i32.const 1 call_indirect (type $2)) ) """) # Test main code m0 = Module(CODE0) assert m0.to_string() == CODE0 b0 = m0.to_bytes() assert Module(b0).to_bytes() == b0 html_report = 'table_and_element_compilation_report.html' with open(html_report, 'w') as f, HtmlReportGenerator(f) as reporter: printed_numbers = [] def print_ln(x: int) -> None: printed_numbers.append(x) imports = { 'js': { 'print_ln': print_ln, }, } instantiate(m0, imports, target='python', reporter=reporter) assert [101, 102] == printed_numbers if is_platform_supported(): printed_numbers = [] def print_ln(x: int) -> None: printed_numbers.append(x) imports = { 'js': { 'print_ln': print_ln, }, } instantiate(m0, imports, target='native', reporter=reporter) assert [101, 102] == printed_numbers if has_node(): assert run_wasm_in_node(m0, True) == '101\n102' # Abbreviation: imported table m3 = Module('(module (table $t1 (import "foo" "bar_table1") funcref) )') assert m3.to_string() == dedent(""" (module (import "foo" "bar_table1" (table $t1 funcref)) ) """) m3 = Module('(module (table (import "foo" "bar_table1") 2 3 funcref) )') assert m3.to_string() == dedent(""" (module (import "foo" "bar_table1" (table 2 3 funcref)) ) """) # Abbeviation: inline data and unspecified (default) alignment CODE1 = r""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (table funcref (elem $f1 $f2)) (start $main) (func $f1 (type $2) (i32.const 101) (call $print) ) (func $f2 (type $2) (i32.const 102) (call $print) ) (func $main (type $2) (i32.const 0) (call_indirect (type $2)) (i32.const 1) (call_indirect (type $2)) ) ) """ m1 = Module(CODE1) assert m1.to_string() == CODE0 assert m1.to_bytes() == b0
def test_func1(): # The canonical form CODE0 = dedent(""" (module (type $0 (func (param i32))) (type $1 (func (param i32 i32) (result i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $0))) (start $main) (func $add (type $1) (get_local 0) (get_local 1) (i32.add) ) (func $main (type $2) (local $foo i32) (i32.const 4) (i32.const 3) (call $add) (set_local $foo) (get_local $foo) (call $print) ) ) """) # Test main code m0 = Module(CODE0) assert m0.to_string() == CODE0 b0 = m0.to_bytes() assert Module(b0).to_bytes() == b0 # TODO: figure out what is wrong below: if False: printed_numbers = [] def print_ln(x: int) -> None: printed_numbers.append(x) imports = { 'js': { 'print_ln': print_ln, }, } instantiate(m0, imports, target='python') assert [7] == printed_numbers if has_node(): assert run_wasm_in_node(m0, True) == '7' # Abbreviation: inline typedefs CODE1 = """ (module (import "js" "print_ln" (func $print (param i32))) (start $main) (func $add (param i32 i32) (result i32) (get_local 0) (get_local 1) (i32.add) ) (func $main (local $foo i32) (set_local $foo (call $add (i32.const 4) (i32.const 3) ) ) (call $print (get_local $foo) ) ) ) """ m1 = Module(CODE1) assert m1.to_string() == CODE0 # look at the indentation! assert m1.to_bytes() == b0
def test_instructions1(): """ Test canoncocal form of import and func and inline typedefs. """ # The canonical form CODE0 = dedent(""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (start $main) (func $main (type $2) (i32.const 1) (if) (i32.const 4) (i32.const 3) (i32.add) (call $print) (else) (i32.const 5) (call $print) (end) ) ) """) # Test main code m0 = Module(CODE0) assert m0.to_string() == CODE0 b0 = m0.to_bytes() assert Module(b0).to_bytes() == b0 if has_node(): assert run_wasm_in_node(m0, True) == '7' # Variant 1 - no inentation, nested test for if CODE1 = dedent(""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (start $main) (func $main (type $2) (if (i32.const 1)) (i32.const 4) (i32.const 3) (i32.add) (call $print) (else) (i32.const 5) (call $print) (end) ) ) """) m1 = Module(CODE1) assert m1.to_string() == CODE0 assert m1.to_bytes() == b0 # Variant 2 - nesting all the way CODE2 = dedent(""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (start $main) (func $main (type $2) (if (i32.const 1) (i32.const 4) (i32.const 3) (i32.add) (call $print) (else) (i32.const 5) (call $print) ) ) ) """) m2 = Module(CODE2) assert m2.to_string() == CODE0 assert m2.to_bytes() == b0 # Variant 3 - leave out the else clause # This is described as an "abbreviation", but it seems that we don't # have to always output an else clause in binary form either. CODE3 = dedent(""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (start $main) (func $main (type $2) (if (i32.const 1) (i32.const 4) (i32.const 3) (i32.add) (call $print) ) ) ) """) m3 = Module(CODE3) assert m3.to_string() != CODE0 assert m3.to_bytes() != b0 if has_node(): assert run_wasm_in_node(m3, True) == '7'
(func $fac-f32 (export "fac-f32") (type $over-f32) (if (result f32) (f32.eq (local.get 0) (f32.const 0.0)) (then (f32.const 1.0)) (else (f32.mul (local.get 0) (call $fac-f32 (f32.sub (local.get 0) (f32.const 1.0)) ) ) ) ) ) ) """ m = Module(src) obj = api.wasmcompile(src, 'x86_64', opt_level=0) api.objcopy(obj, None, 'elf', 'fac_f32.o') print(m.to_string()) inst = instantiate(m, {}) inst2 = instantiate(m, {}, target='python') for number in [1.0, 5.0, 10.0]: print('number', number, 'fac', inst.exports['fac-f32'](number), 'fac_python', inst2.exports['fac-f32'](number))
def test_type2(): """ Test inline typedefs with various number of args and results. """ # Canonical form CODE0 = dedent(""" (module (type $0 (func (param i32))) (type $1 (func (param i32) (result i32))) (type $2 (func (result i32))) (type $3 (func)) (import "js" "print_ln" (func $print (type $0))) (start $main) (func $test_11 (type $1) (i32.const 111) (call $print) (i32.const 0) ) (func $test_10 (type $0) (i32.const 110) (call $print) ) (func $test_01 (type $2) (i32.const 101) (call $print) (i32.const 0) ) (func $test_00 (type $3) (i32.const 100) (call $print) ) (func $main (type $3) (i32.const 0) (call $test_11) (drop) (i32.const 0) (call $test_10) (call $test_01) (drop) (call $test_00) ) ) """) # Test main code m0 = Module(CODE0) assert m0.to_string() == CODE0 b0 = m0.to_bytes() if has_node(): assert run_wasm_in_node(m0, True) == '111\n110\n101\n100' # Abbreviated CODE1 = """ (module (import "js" "print_ln" (func $print (param i32))) (start $main) (func $test_11 (param i32) (result i32) (i32.const 111) (call $print) (i32.const 0) ) (func $test_10 (param i32) (i32.const 110) (call $print) ) (func $test_01 (result i32) (i32.const 101) (call $print) (i32.const 0) ) (func $test_00 (i32.const 100) (call $print) ) (func $main (i32.const 0) (call $test_11) (drop) (i32.const 0) (call $test_10) (call $test_01) (drop) (call $test_00) ) ) """ m1 = Module(CODE1) assert m1.to_string() == CODE0 assert m1.to_bytes() == b0
def test_memory1(): # The canonical form CODE0 = dedent(r""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (memory $0 1 1) (start $main) (func $main (type $2) i32.const 0 i32.load8_u call $print i32.const 1 i32.load8_u call $print) (data i32.const 0 "\04\03\02") ) """) # Test main code m0 = Module(CODE0) assert m0.to_string() == CODE0 b0 = m0.to_bytes() assert Module(b0).to_bytes() == b0 printed_numbers = [] def print_ln(x: int) -> None: printed_numbers.append(x) imports = { 'js': { 'print_ln': print_ln, } } instantiate(m0, imports=imports, target='python') assert [4, 3] == printed_numbers if has_node(): assert run_wasm_in_node(m0, True) == '4\n3' # Abbreviation: imported memory m3 = Module('(module (memory $m1 (import "foo" "bar_mem1") 1) )') assert m3.to_string() == dedent(""" (module (import "foo" "bar_mem1" (memory $m1 1)) ) """) m3 = Module('(module (memory (import "foo" "bar_mem1") 2 3) )') assert m3.to_string() == dedent(""" (module (import "foo" "bar_mem1" (memory 2 3)) ) """) # Abbeviation: inline data and unspecified (default) alignment CODE1 = r""" (module (type $print (func (param i32))) (type $2 (func)) (import "js" "print_ln" (func $print (type $print))) (memory (data "\04\03\02")) (start $main) (func $main (type $2) i32.const 0 i32.load8_u call $print i32.const 1 i32.load8_u call $print ) ) """ m1 = Module(CODE1) assert m1.to_string() == CODE0 assert m1.to_bytes() == b0