Example #1
0
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
Example #2
0
def test_read_wat():

    for text in (TEXT1, TEXT2):
        m = Module(text)
        m.to_string()
        b = m.to_bytes()
        assert isinstance(b, bytes)
Example #3
0
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
Example #4
0
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
Example #5
0
    def parse_module(self, s_expr):
        if 'binary' in s_expr:
            # We have (module binary "")

            # Iterate:
            elems = iter(s_expr)

            # Skip to binary tag:
            while next(elems) != 'binary':
                pass

            # fetch data from last tuple elements:
            parts = []
            for elem in elems:
                data = datastring2bytes(elem)
                parts.append(data)
            data = reduce(add, parts)

            # Load module from binary data:
            m1 = Module(data)

            # Go back
            data2 = m1.to_bytes()

            # Wont always be the same, e.g. some tests use non-minimal LEB ints
            # assert data == data2

            data3 = Module(data2).to_bytes()

            # Check that reading it in result in the same module ...
            assert data2 == data3

        else:
            # Load module from tuples:
            m1 = Module(s_expr)

            # # Convert module to text form and parse again
            # # This should yield the same binary form:
            # m2 = Module(m1.to_string())
            # assert m1.to_bytes() == m2.to_bytes()

            # NOTE: going to string format and back does not
            # guarantee that parsing was correct.

            self.reporter.dump_wasm(m1)

        self.logger.debug('loaded wasm module %s (id=%s)', m1, m1.id)
        return m1
Example #6
0
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'
Example #7
0
def do_func(fname):
    """ Test parsing on a single test file.
    Its great to call this at the botton during dev!
    """

    print('Testing {} - "{}"'.format(fname,
                                     os.path.join(get_spec_suite_dir(),
                                                  fname)))

    for text in get_test_script_parts(fname):
        sexpr = parse_sexpr(text)

        # Assert that the toplevel expression makes sense
        assert sexpr[0] in (
            'module',
            'invoke',
            'register',
            'assert_return',
            'assert_invalid',
            'assert_trap',
            'assert_malformed',
            'assert_exhaustion',
            'assert_unlinkable',
            'assert_return_canonical_nan',
            'assert_return_arithmetic_nan',
            'func',
            'memory',  # inline-module.wast
        ), '{}: unexpected expression in'.format(fname)

        # But in this script we only do modules
        if sexpr[0] != 'module':
            continue
        if 'binary' in sexpr:
            continue

        # todo: skipping a few here, for now
        if fname in (
                'names.wast',
                'comments.wast',  # because sending Unicode over Pipes seems to go wrong
        ):
            continue

        wasm_bin0 = wabt.wat2wasm(text)

        m1 = Module(wasm_bin0)
        m2 = Module(text)
        m3 = Module(sexpr)

        wasm_bin1 = m1.to_bytes()
        wasm_bin2 = m2.to_bytes()
        wasm_bin3 = m3.to_bytes()

        assert wasm_bin0 == wasm_bin1, '{}: our binary parsing is broken'.format(
            fname)
        assert wasm_bin2 == wasm_bin3, '{}: our text/tuple paring differs'.format(
            fname)
        assert wasm_bin0 == wasm_bin2, '{}: our text parsing is broken'.format(
            fname)

        if False:  # debug helpers
            print(len(wasm_bin1), len(wasm_bin2))
            print(len(m1.definitions), len(m2.definitions))
            hexdump(wasm_bin1)
            print()
            hexdump(wasm_bin2)
Example #8
0
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
Example #9
0
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
Example #10
0
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'
Example #11
0
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
Example #12
0
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
Example #13
0
    def load_module(self, s_expr):
        if 'binary' in s_expr:
            # We have (module binary "")

            # Iterate:
            elems = iter(s_expr)

            # Skip to binary tag:
            while next(elems) != 'binary':
                pass

            # fetch data from last tuple elements:
            parts = []
            for elem in elems:
                data = datastring2bytes(elem)
                parts.append(data)
            data = reduce(add, parts)

            # Load module from binary data:
            m1 = Module(data)

            # Go back
            data2 = m1.to_bytes()

            # Wont always be the same, e.g. some tests use non-minimal LEB ints
            # assert data == data2

            data3 = Module(data2).to_bytes()

            # Check that reading it in result in the same module ...
            assert data2 == data3

        else:
            # Load module from tuples:
            m1 = Module(s_expr)

            # # Convert module to text form and parse again
            # # This should yield the same binary form:
            # m2 = Module(m1.to_string())
            # assert m1.to_bytes() == m2.to_bytes()

            # NOTE: going to string format and back does not
            # guarantee that parsing was correct.

            self.reporter.dump_wasm(m1)

        self.logger.debug('loaded wasm module %s', m1)

        # Next step: Instantiate:
        if self.target:
            def my_print() -> None:
                pass

            def print_i32(x: int) -> None:
                pass

            imports = {
               'spectest': {
                   'print_i32': print_i32,
                   'print': my_print,
               }
            }
            self.mod_instance = instantiate(
                m1, imports, target=self.target, reporter=self.reporter)
            self.logger.debug('Instantiated wasm module %s', self.mod_instance)
        else:
            self.mod_instance = None