Example #1
0
def test_s2wasm():
    print '\n[ checking .s testcases... ]\n'

    for dot_s_dir in ['dot_s', 'llvm_autogenerated']:
        dot_s_path = os.path.join(options.binaryen_test, dot_s_dir)
        for s in sorted(os.listdir(dot_s_path)):
            if not s.endswith('.s'):
                continue
            print '..', s
            wasm = s.replace('.s', '.wast')
            full = os.path.join(options.binaryen_test, dot_s_dir, s)
            stack_alloc = (['--allocate-stack=1024']
                           if dot_s_dir == 'llvm_autogenerated' else [])
            cmd = S2WASM + [full, '--emscripten-glue'] + stack_alloc
            if s.startswith('start_'):
                cmd.append('--start')
            actual = run_command(cmd)

            # verify output
            expected_file = os.path.join(options.binaryen_test, dot_s_dir,
                                         wasm)
            if not os.path.exists(expected_file):
                print actual
                fail_with_error('output ' + expected_file + ' does not exist')
            expected = open(expected_file, 'rb').read()
            if actual != expected:
                fail(actual, expected)

            # verify with options
            cmd = S2WASM + [full, '--global-base=1024'] + stack_alloc
            run_command(cmd)

            # run wasm-shell on the .wast to verify that it parses
            cmd = WASM_SHELL + [expected_file]
            run_command(cmd)
Example #2
0
def test_s2wasm():
  print '\n[ checking .s testcases... ]\n'

  for dot_s_dir in ['dot_s', 'llvm_autogenerated']:
    dot_s_path = os.path.join(options.binaryen_test, dot_s_dir)
    for s in sorted(os.listdir(dot_s_path)):
      if not s.endswith('.s'):
        continue
      print '..', s
      wasm = s.replace('.s', '.wast')
      full = os.path.join(options.binaryen_test, dot_s_dir, s)
      stack_alloc = (['--allocate-stack=1024']
                     if dot_s_dir == 'llvm_autogenerated'
                     else [])
      cmd = S2WASM + [full, '--emscripten-glue'] + stack_alloc
      if s.startswith('start_'):
        cmd.append('--start')
      actual = run_command(cmd)

      # verify output
      expected_file = os.path.join(options.binaryen_test, dot_s_dir, wasm)
      if not os.path.exists(expected_file):
        print actual
        fail_with_error('output ' + expected_file + ' does not exist')
      expected = open(expected_file, 'rb').read()
      if actual != expected:
        fail(actual, expected)

      # verify with options
      cmd = S2WASM + [full, '--global-base=1024'] + stack_alloc
      run_command(cmd)

      # run wasm-shell on the .wast to verify that it parses
      cmd = WASM_SHELL + [expected_file]
      run_command(cmd)
Example #3
0
def generate_wast_files(lld_bin):
    print '\n[ linking wasm files from object files... ]\n'

    lld_path = os.path.join(shared.options.binaryen_test, 'lld')
    for obj_file, ext in files_with_extensions(lld_path, ['.o']):
        print '..', obj_file
        wasm_file = obj_file.replace(ext, '.wasm')
        wast_file = obj_file.replace(ext, '.wast')

        obj_path = os.path.join(lld_path, obj_file)
        wasm_path = os.path.join(lld_path, wasm_file)
        wast_path = os.path.join(lld_path, wast_file)
        run_command([
            lld_bin,
            '-flavor',
            'wasm',
            '-z',
            '-stack-size=1048576',
            obj_path,
            '-o',
            wasm_path,
            '--entry=main',
            '--allow-undefined',
            '--export',
            '__wasm_call_ctors',
        ])
        try:
            run_command(shared.WASM_DIS + [wasm_path, '-o', wast_path])
        finally:
            # Don't need the .wasm file, don't leave it around
            shared.delete_from_orbit(wasm_path)
Example #4
0
def generate_object_files(clang_bin):
    print '\n[ building object files from C sources... ]\n'

    lld_path = os.path.join(shared.options.binaryen_test, 'lld')
    for src_file, ext in files_with_extensions(lld_path, ['.c', '.cpp']):
        print '..', src_file
        obj_file = src_file.replace(ext, '.o')

        src_path = os.path.join(lld_path, src_file)
        obj_path = os.path.join(lld_path, obj_file)
        run_command([
            clang_bin,
            src_path,
            '-o',
            obj_path,
            '--target=wasm32-unknown-unknown-wasm',
            '-c',
            '-nostdinc',
            '-Xclang',
            '-nobuiltininc',
            '-Xclang',
            '-nostdsysteminc',
            '-Xclang',
            '-I/s/work/emscripten/system/include',
            '-O1',
        ])
Example #5
0
def test_wasm2js_output():
  for wasm in tests + spec_tests + extra_wasm2js_tests:
    if not wasm.endswith('.wast'):
      continue
    basename = os.path.basename(wasm)
    if basename in wasm2js_blacklist:
      continue

    asm = basename.replace('.wast', '.2asm.js')
    expected_file = os.path.join(wasm2js_dir, asm)

    if not os.path.exists(expected_file):
      continue

    print '..', wasm

    t = os.path.join(options.binaryen_test, wasm)

    all_out = []

    for module, asserts in split_wast(t):
      with open('split.wast', 'w') as o:
        o.write(module + '\n'.join(asserts))

      cmd = WASM2JS + ['split.wast', '-O']
      if 'emscripten' in wasm:
        cmd += ['--emscripten']
      out = run_command(cmd)
      all_out.append(out)

      if not NODEJS and not MOZJS:
        print 'No JS interpreters. Skipping spec tests.'
        continue

      open('a.2asm.mjs', 'w').write(out)

      cmd += ['--allow-asserts']
      out = run_command(cmd)
      # also verify it passes pass-debug verifications
      with_pass_debug(lambda: run_command(cmd))

      open('a.2asm.asserts.mjs', 'w').write(out)

      # verify asm.js is valid js, note that we're using --experimental-modules
      # to enable ESM syntax and we're also passing a custom loader to handle the
      # `spectest` and `env` modules in our tests.
      if NODEJS:
        node = [NODEJS, '--experimental-modules', '--loader', './scripts/test/node-esm-loader.mjs']
        cmd = node[:]
        cmd.append('a.2asm.mjs')
        out = run_command(cmd)
        fail_if_not_identical(out, '')
        cmd = node[:]
        cmd.append('a.2asm.asserts.mjs')
        out = run_command(cmd, expected_err='', err_ignore='The ESM module loader is experimental')
        fail_if_not_identical(out, '')

    fail_if_not_identical_to_file(''.join(all_out), expected_file)
Example #6
0
def test_linker():
    print '\n[ running linker tests... ]\n'
    # The {main,foo,bar,baz}.s files were created by running clang over the
    # respective c files. The foobar.bar archive was created by running:
    # llvm-ar -format=gnu rc foobar.a quux.s foo.s bar.s baz.s
    cmd = S2WASM + [
        os.path.join(options.binaryen_test, 'linker', 'main.s'), '-l',
        os.path.join(options.binaryen_test, 'linker', 'archive', 'foobar.a')
    ]
    output = run_command(cmd)
    # foo should come from main.s and return 42
    fail_if_not_contained(output, '(func $foo')
    fail_if_not_contained(output, '(i32.const 42)')
    # bar should be linked in from bar.s
    fail_if_not_contained(output, '(func $bar')
    # quux should be linked in from bar.s even though it comes before bar.s in
    # the archive
    fail_if_not_contained(output, '(func $quux')
    # baz should not be linked in at all
    if 'baz' in output:
        fail_with_error('output should not contain "baz": ' + output)

    # Test an archive using a string table
    cmd = S2WASM + [
        os.path.join(options.binaryen_test, 'linker', 'main.s'), '-l',
        os.path.join(options.binaryen_test, 'linker', 'archive', 'barlong.a')
    ]
    output = run_command(cmd)
    # bar should be linked from the archive
    fail_if_not_contained(output, '(func $bar')

    # Test exporting memory growth function and emscripten runtime functions
    cmd = S2WASM + [
        os.path.join(options.binaryen_test, 'linker', 'main.s'),
        '--emscripten-glue', '--allow-memory-growth'
    ]
    output = run_command(cmd)
    expected_funcs = [
        ('__growWasmMemory', '(param $newSize i32)'),
        ('stackSave', '(result i32)'),
        ('stackAlloc', '(param $0 i32) (result i32)'),
        ('stackRestore', '(param $0 i32)'),
    ]
    for name, extra in expected_funcs:
        space = ' ' if extra else ''
        fail_if_not_contained(output,
                              '(export "{0}" (func ${0}))'.format(name))
        for line in output.split('\n'):
            if '(func ${0}'.format(name + space) in line:
                # we found the relevant line for the function definition. remove
                # a (; X ;) comment with its index
                start = line.find('(; ')
                if start >= 0:
                    end = line.find(' ;)')
                    line = line[:start] + line[end + 4:]
                fail_if_not_contained(
                    line, '(func ${0}'.format(name + space + extra))
Example #7
0
def update_wasm2js_tests():
  print '\n[ checking wasm2js ]\n'

  for wasm in tests + spec_tests + extra_wasm2js_tests:
    if not wasm.endswith('.wast'):
      continue

    if os.path.basename(wasm) in wasm2js_blacklist:
      continue

    asm = os.path.basename(wasm).replace('.wast', '.2asm.js')
    expected_file = os.path.join(wasm2js_dir, asm)

    # we run wasm2js on tests and spec tests only if the output
    # exists - only some work so far. the tests in extra are in
    # the test/wasm2js dir and so are specific to wasm2js, and
    # we run all of those.
    if wasm not in extra_wasm2js_tests and not os.path.exists(expected_file):
      continue

    print '..', wasm

    t = os.path.join(options.binaryen_test, wasm)

    all_out = []

    for module, asserts in split_wast(t):
      with open('split.wast', 'w') as o:
        o.write(module + '\n'.join(asserts))

      cmd = WASM2JS + ['split.wast', '-O']
      if 'emscripten' in wasm:
        cmd += ['--emscripten']
      out = run_command(cmd)
      all_out.append(out)

    with open(expected_file, 'w') as o:
      o.write(''.join(all_out))

  for wasm in assert_tests:
    print '..', wasm

    asserts = os.path.basename(wasm).replace('.wast.asserts', '.asserts.js')
    traps = os.path.basename(wasm).replace('.wast.asserts', '.traps.js')
    asserts_expected_file = os.path.join('test', asserts)
    traps_expected_file = os.path.join('test', traps)

    cmd = WASM2JS + [os.path.join(wasm2js_dir, wasm), '--allow-asserts']
    out = run_command(cmd)
    with open(asserts_expected_file, 'w') as o:
      o.write(out)

    cmd += ['--pedantic']
    out = run_command(cmd)
    with open(traps_expected_file, 'w') as o:
      o.write(out)
Example #8
0
def test_asm2wasm_binary():
  print '\n[ checking asm2wasm binary reading/writing... ]\n'

  asmjs = os.path.join(options.binaryen_test, 'hello_world.asm.js')
  delete_from_orbit('a.wasm')
  delete_from_orbit('b.wast')
  run_command(ASM2WASM + [asmjs, '-o', 'a.wasm'])
  assert open('a.wasm', 'rb').read()[0] == '\0', 'we emit binary by default'
  run_command(ASM2WASM + [asmjs, '-o', 'b.wast', '-S'])
  assert open('b.wast', 'rb').read()[0] != '\0', 'we emit text with -S'
Example #9
0
def test_asm2wasm_binary():
  print '\n[ checking asm2wasm binary reading/writing... ]\n'

  asmjs = os.path.join(options.binaryen_test, 'hello_world.asm.js')
  delete_from_orbit('a.wasm')
  delete_from_orbit('b.wast')
  run_command(ASM2WASM + [asmjs, '-o', 'a.wasm'])
  assert open('a.wasm', 'rb').read()[0] == '\0', 'we emit binary by default'
  run_command(ASM2WASM + [asmjs, '-o', 'b.wast', '-S'])
  assert open('b.wast', 'rb').read()[0] != '\0', 'we emit text with -S'
Example #10
0
def test_wasm2js_output():
    for wasm in tests + spec_tests + extra_wasm2js_tests:
        if not wasm.endswith('.wast'):
            continue
        basename = os.path.basename(wasm)
        if basename in wasm2js_blacklist:
            continue

        asm = basename.replace('.wast', '.2asm.js')
        expected_file = os.path.join(wasm2js_dir, asm)

        if not os.path.exists(expected_file):
            continue

        print '..', wasm

        cmd = WASM2JS + [os.path.join(options.binaryen_test, wasm)]
        out = run_command(cmd)
        fail_if_not_identical_to_file(out, expected_file)

        if not NODEJS and not MOZJS:
            print 'No JS interpreters. Skipping spec tests.'
            continue

        open('a.2asm.mjs', 'w').write(out)

        cmd += ['--allow-asserts']
        out = run_command(cmd)

        open('a.2asm.asserts.mjs', 'w').write(out)

        # verify asm.js is valid js, note that we're using --experimental-modules
        # to enable ESM syntax and we're also passing a custom loader to handle the
        # `spectest` module in our tests.
        if NODEJS:
            node = [
                NODEJS, '--experimental-modules', '--loader',
                './scripts/test/node-esm-loader.mjs'
            ]
            cmd = node[:]
            cmd.append('a.2asm.mjs')
            out = run_command(cmd)
            fail_if_not_identical(out, '')
            cmd = node[:]
            cmd.append('a.2asm.asserts.mjs')
            out = run_command(
                cmd,
                expected_err='',
                err_ignore='The ESM module loader is experimental')
            fail_if_not_identical(out, '')
Example #11
0
 def test(engine):
     cmd = [engine, 'a.js']
     if 'fatal' not in s:
         out = run_command(cmd, stderr=subprocess.STDOUT)
     else:
         # expect an error - the specific error code will depend on the vm
         out = run_command(cmd,
                           stderr=subprocess.STDOUT,
                           expected_status=None)
     expected = open(
         os.path.join(options.binaryen_test, 'binaryen.js',
                      s + '.txt')).read()
     if expected not in out:
         fail(out, expected)
Example #12
0
def test_wasm_emscripten_finalize():
  print '\n[ checking wasm-emscripten-finalize testcases... ]\n'

  for wast_path in files_with_pattern(options.binaryen_test, 'lld', '*.wast'):
    print '..', wast_path
    mem_file = wast_path + '.mem'
    extension_arg_map = {
      '.out': [],
      '.mem.out': ['--separate-data-segments', mem_file],
    }
    for ext, ext_args in extension_arg_map.items():
      expected_file = wast_path + ext
      if ext != '.out' and not os.path.exists(expected_file):
        continue

      cmd = WASM_EMSCRIPTEN_FINALIZE + [wast_path, '-S'] + ext_args
      cmd += args_for_finalize(os.path.basename(wast_path))
      actual = run_command(cmd)

      if not os.path.exists(expected_file):
        print actual
        fail_with_error('output ' + expected_file + ' does not exist')
      fail_if_not_identical_to_file(actual, expected_file)
      if ext == '.mem.out':
        with open(mem_file) as mf:
          mem = mf.read()
          fail_if_not_identical_to_file(mem, wast_path + '.mem.mem')
        os.remove(mem_file)
Example #13
0
def test_wasm_emscripten_finalize():
    print '\n[ checking wasm-emscripten-finalize testcases... ]\n'

    for wast_path in files_with_pattern(options.binaryen_test, 'lld',
                                        '*.wast'):
        print '..', wast_path
        mem_file = wast_path + '.mem'
        extension_arg_map = {
            '.out': [],
            '.mem.out': ['--separate-data-segments', mem_file],
        }
        for ext, ext_args in extension_arg_map.items():
            expected_file = wast_path + ext
            if ext != '.out' and not os.path.exists(expected_file):
                continue

            cmd = WASM_EMSCRIPTEN_FINALIZE + [wast_path, '-S'] + ext_args
            cmd += args_for_finalize(os.path.basename(wast_path))
            actual = run_command(cmd)

            if not os.path.exists(expected_file):
                print actual
                fail_with_error('output ' + expected_file + ' does not exist')
            fail_if_not_identical_to_file(actual, expected_file)
            if ext == '.mem.out':
                with open(mem_file) as mf:
                    mem = mf.read()
                    fail_if_not_identical_to_file(mem, wast_path + '.mem.mem')
                os.remove(mem_file)
Example #14
0
def test_wasm_emscripten_finalize():
    print '\n[ checking wasm-emscripten-finalize testcases... ]\n'

    extension_arg_map = {
        '.out': [],
        '.jscall.out': ['--emscripten-reserved-function-pointers=3'],
    }

    for wast_path in files_with_pattern(options.binaryen_test, 'lld',
                                        '*.wast'):
        print '..', wast_path
        for ext, ext_args in extension_arg_map.items():
            expected_file = wast_path + ext
            if ext != '.out' and not os.path.exists(expected_file):
                continue

            cmd = (WASM_EMSCRIPTEN_FINALIZE +
                   [wast_path, '-S', '--global-base=568'] + ext_args)
            actual = run_command(cmd)

            if not os.path.exists(expected_file):
                print actual
                fail_with_error('output ' + expected_file + ' does not exist')
            expected = open(expected_file, 'rb').read()
            if actual != expected:
                fail(actual, expected)
Example #15
0
def update_wasm2js_tests():
    print '\n[ checking wasm2js ]\n'

    for wasm in tests + spec_tests + extra_wasm2js_tests:
        if not wasm.endswith('.wast'):
            continue

        if os.path.basename(wasm) in wasm2js_blacklist:
            continue

        asm = os.path.basename(wasm).replace('.wast', '.2asm.js')
        expected_file = os.path.join(wasm2js_dir, asm)

        # we run wasm2js on tests and spec tests only if the output
        # exists - only some work so far. the tests in extra are in
        # the test/wasm2js dir and so are specific to wasm2js, and
        # we run all of those.
        if wasm not in extra_wasm2js_tests and not os.path.exists(
                expected_file):
            continue

        print '..', wasm

        cmd = WASM2JS + [os.path.join('test', wasm)]
        out = run_command(cmd)
        with open(expected_file, 'w') as o:
            o.write(out)

    for wasm in assert_tests:
        print '..', wasm

        asserts = os.path.basename(wasm).replace('.wast.asserts',
                                                 '.asserts.js')
        traps = os.path.basename(wasm).replace('.wast.asserts', '.traps.js')
        asserts_expected_file = os.path.join('test', asserts)
        traps_expected_file = os.path.join('test', traps)

        cmd = WASM2JS + [os.path.join(wasm2js_dir, wasm), '--allow-asserts']
        out = run_command(cmd)
        with open(asserts_expected_file, 'w') as o:
            o.write(out)

        cmd += ['--pedantic']
        out = run_command(cmd)
        with open(traps_expected_file, 'w') as o:
            o.write(out)
Example #16
0
def test_asserts_output():
  for wasm in assert_tests:
    print '..', wasm

    asserts = os.path.basename(wasm).replace('.wast.asserts', '.asserts.js')
    traps = os.path.basename(wasm).replace('.wast.asserts', '.traps.js')
    asserts_expected_file = os.path.join(options.binaryen_test, asserts)
    traps_expected_file = os.path.join(options.binaryen_test, traps)

    wasm = os.path.join(wasm2js_dir, wasm)
    cmd = WASM2JS + [wasm, '--allow-asserts']
    out = run_command(cmd)
    fail_if_not_identical_to_file(out, asserts_expected_file)

    cmd += ['--pedantic']
    out = run_command(cmd)
    fail_if_not_identical_to_file(out, traps_expected_file)
Example #17
0
        def do_asm2wasm_test():
          actual = run_command(cmd)

          # verify output
          if not os.path.exists(wasm):
            fail_with_error('output .wast file %s does not exist' % wasm)
          fail_if_not_identical_to_file(actual, wasm)

          binary_format_check(wasm, verify_final_result=False)
Example #18
0
def test_asserts_output():
    for wasm in assert_tests:
        print '..', wasm

        asserts = os.path.basename(wasm).replace('.wast.asserts',
                                                 '.asserts.js')
        traps = os.path.basename(wasm).replace('.wast.asserts', '.traps.js')
        asserts_expected_file = os.path.join(options.binaryen_test, asserts)
        traps_expected_file = os.path.join(options.binaryen_test, traps)

        wasm = os.path.join(wasm2asm_dir, wasm)
        cmd = WASM2ASM + [wasm, '--allow-asserts']
        out = run_command(cmd)
        fail_if_not_identical_to_file(out, asserts_expected_file)

        cmd += ['--pedantic']
        out = run_command(cmd)
        fail_if_not_identical_to_file(out, traps_expected_file)
Example #19
0
        def do_asm2wasm_test():
          actual = run_command(cmd)

          # verify output
          if not os.path.exists(wasm):
            fail_with_error('output .wast file %s does not exist' % wasm)
          fail_if_not_identical_to_file(actual, wasm)

          binary_format_check(wasm, verify_final_result=False)
Example #20
0
def test_asserts_output():
    for wasm in assert_tests:
        print '..', wasm

        asserts = os.path.basename(wasm).replace('.wast.asserts',
                                                 '.asserts.js')
        traps = os.path.basename(wasm).replace('.wast.asserts', '.traps.js')
        asserts_expected_file = os.path.join('test', asserts)
        traps_expected_file = os.path.join('test', traps)

        cmd = WASM2ASM + [os.path.join('test', wasm), '--allow-asserts']
        out = run_command(cmd)
        expected = open(asserts_expected_file).read()
        fail_if_not_identical(out, expected)

        cmd += ['--pedantic']
        out = run_command(cmd)
        expected = open(traps_expected_file).read()
        fail_if_not_identical(out, expected)
Example #21
0
def test_linker():
    print '\n[ running linker tests... ]\n'
    # The {main,foo,bar,baz}.s files were created by running clang over the
    # respective c files. The foobar.bar archive was created by running:
    # llvm-ar -format=gnu rc foobar.a quux.s foo.s bar.s baz.s
    cmd = S2WASM + [
        os.path.join(options.binaryen_test, 'linker', 'main.s'), '-l',
        os.path.join(options.binaryen_test, 'linker', 'archive', 'foobar.a')
    ]
    output = run_command(cmd)
    # foo should come from main.s and return 42
    fail_if_not_contained(output, '(func $foo')
    fail_if_not_contained(output, '(i32.const 42)')
    # bar should be linked in from bar.s
    fail_if_not_contained(output, '(func $bar')
    # quux should be linked in from bar.s even though it comes before bar.s in
    # the archive
    fail_if_not_contained(output, '(func $quux')
    # baz should not be linked in at all
    if 'baz' in output:
        fail_with_error('output should not contain "baz": ' + output)

    # Test an archive using a string table
    cmd = S2WASM + [
        os.path.join(options.binaryen_test, 'linker', 'main.s'), '-l',
        os.path.join(options.binaryen_test, 'linker', 'archive', 'barlong.a')
    ]
    output = run_command(cmd)
    # bar should be linked from the archive
    fail_if_not_contained(output, '(func $bar')

    # Test exporting memory growth function
    cmd = S2WASM + [
        os.path.join(options.binaryen_test, 'linker', 'main.s'),
        '--emscripten-glue', '--allow-memory-growth'
    ]
    output = run_command(cmd)
    fail_if_not_contained(
        output, '(export "__growWasmMemory" (func $__growWasmMemory))')
    fail_if_not_contained(output,
                          '(func $__growWasmMemory (param $newSize i32)')
Example #22
0
def test_wasm2asm():
    print '\n[ checking wasm2asm testcases... ]\n'

    # tests with i64s, invokes, etc.
    blacklist = ['atomics.wast', 'address.wast']
    spec_tests = [
        os.path.join('spec', t)
        for t in sorted(os.listdir(os.path.join('test', 'spec')))
    ]
    for wasm in tests + spec_tests:
        if not wasm.endswith('.wast') or os.path.basename(wasm) in blacklist:
            continue

        asm = os.path.basename(wasm).replace('.wast', '.2asm.js')
        expected_file = os.path.join('test', asm)
        if not os.path.exists(expected_file):
            continue

        print '..', wasm

        cmd = WASM2ASM + [os.path.join('test', wasm)]
        out = run_command(cmd)

        # verify output
        expected = open(expected_file).read()
        fail_if_not_identical(out, expected)

        open('a.2asm.js', 'w').write(out)

        if NODEJS:
            # verify asm.js is valid js
            out = run_command([NODEJS, 'a.2asm.js'])
            fail_if_not_identical(out, '')

        if MOZJS:
            # verify asm.js validates
            # check only subset of err because mozjs emits timing info
            out = run_command([MOZJS, '-w', 'a.2asm.js'],
                              expected_err='Successfully compiled asm.js code',
                              err_contains=True)
            fail_if_not_identical(out, '')
Example #23
0
                def do_asm2wasm_test():
                    actual = run_command(cmd)

                    # verify output
                    if not os.path.exists(wasm):
                        fail_with_error('output .wast file %s does not exist' %
                                        wasm)
                    expected = open(wasm, 'rb').read()
                    if actual != expected:
                        fail(actual, expected)

                    binary_format_check(wasm, verify_final_result=False)
def generate_wat_files(llvm_bin, emscripten_root):
    print('\n[ building wat files from C sources... ]\n')

    lld_path = os.path.join(shared.options.binaryen_test, 'lld')
    for src_file, ext in files_with_extensions(lld_path, ['.c', '.cpp', '.s']):
        print('..', src_file)
        obj_file = src_file.replace(ext, '.o')

        src_path = os.path.join(lld_path, src_file)
        obj_path = os.path.join(lld_path, obj_file)

        wasm_file = src_file.replace(ext, '.wasm')
        wat_file = src_file.replace(ext, '.wat')

        obj_path = os.path.join(lld_path, obj_file)
        wasm_path = os.path.join(lld_path, wasm_file)
        wat_path = os.path.join(lld_path, wat_file)
        is_shared = 'shared' in src_file

        compile_cmd = [
            os.path.join(llvm_bin, 'clang'), src_path, '-o', obj_path,
            '--target=wasm32-emscripten',
            '-mllvm', '-enable-emscripten-sjlj',
            '-c',
            '-nostdinc',
            '-Xclang', '-nobuiltininc',
            '-Xclang', '-nostdsysteminc',
            '-Xclang', '-I%s/system/include' % emscripten_root,
            '-O1',
        ]

        link_cmd = [
            os.path.join(llvm_bin, 'wasm-ld'), '-flavor', 'wasm',
            '-z', '-stack-size=1048576',
            obj_path, '-o', wasm_path,
            '--allow-undefined',
            '--export', '__wasm_call_ctors',
            '--export', '__data_end',
            '--global-base=568',
        ]
        # We had a regression where this test only worked if debug names
        # were included.
        if 'longjmp' in src_file:
            link_cmd.append('--strip-debug')
        if is_shared:
            compile_cmd.append('-fPIC')
            compile_cmd.append('-fvisibility=default')
            link_cmd.append('-shared')
            link_cmd.append('--experimental-pic')
        else:
            link_cmd.append('--entry=main')

        try:
            support.run_command(compile_cmd)
            support.run_command(link_cmd)
            support.run_command(shared.WASM_DIS + [wasm_path, '-o', wat_path])
        finally:
            # Don't need the .o or .wasm files, don't leave them around
            shared.delete_from_orbit(obj_path)
            shared.delete_from_orbit(wasm_path)
Example #25
0
def test_linker():
  print '\n[ running linker tests... ]\n'
  # The {main,foo,bar,baz}.s files were created by running clang over the
  # respective c files. The foobar.bar archive was created by running:
  # llvm-ar -format=gnu rc foobar.a quux.s foo.s bar.s baz.s
  cmd = S2WASM + [
      os.path.join(options.binaryen_test, 'linker', 'main.s'), '-l',
      os.path.join(options.binaryen_test, 'linker', 'archive', 'foobar.a')]
  output = run_command(cmd)
  # foo should come from main.s and return 42
  fail_if_not_contained(output, '(func $foo')
  fail_if_not_contained(output, '(i32.const 42)')
  # bar should be linked in from bar.s
  fail_if_not_contained(output, '(func $bar')
  # quux should be linked in from bar.s even though it comes before bar.s in
  # the archive
  fail_if_not_contained(output, '(func $quux')
  # baz should not be linked in at all
  if 'baz' in output:
    fail_with_error('output should not contain "baz": ' + output)

  # Test an archive using a string table
  cmd = S2WASM + [
      os.path.join(options.binaryen_test, 'linker', 'main.s'), '-l',
      os.path.join(options.binaryen_test, 'linker', 'archive', 'barlong.a')]
  output = run_command(cmd)
  # bar should be linked from the archive
  fail_if_not_contained(output, '(func $bar')

  # Test exporting memory growth function
  cmd = S2WASM + [
      os.path.join(options.binaryen_test, 'linker', 'main.s'),
      '--emscripten-glue', '--allow-memory-growth']
  output = run_command(cmd)
  fail_if_not_contained(
      output, '(export "__growWasmMemory" (func $__growWasmMemory))')
  fail_if_not_contained(output, '(func $__growWasmMemory (param $newSize i32)')
Example #26
0
def test_wasm_emscripten_finalize():
  print '\n[ checking wasm-emscripten-finalize testcases... ]\n'

  for wast_path in files_with_pattern(options.binaryen_test, 'lld', '*.wast'):
    print '..', wast_path
    expected_file = wast_path + '.out'
    cmd = WASM_EMSCRIPTEN_FINALIZE + [wast_path, '-S']
    actual = run_command(cmd)

    if not os.path.exists(expected_file):
      print actual
      fail_with_error('output ' + expected_file + ' does not exist')
    expected = open(expected_file, 'rb').read()
    if actual != expected:
      fail(actual, expected)
Example #27
0
def test_wasm_link_metadata():
  print '\n[ checking wasm-link-metadata testcases... ]\n'

  for obj_path in files_with_pattern(options.binaryen_test, 'lld', '*.o'):
    print '..', obj_path
    expected_file = obj_path.replace('.o', '.json')

    cmd = WASM_LINK_METADATA + [obj_path]
    actual = run_command(cmd)

    if not os.path.exists(expected_file):
      print actual
      fail_with_error('output ' + expected_file + ' does not exist')
    expected = open(expected_file, 'rb').read()
    if actual != expected:
      fail(actual, expected)
Example #28
0
def test_s2wasm():
    print '\n[ checking .s testcases... ]\n'

    cmd = S2WASM + [
        os.path.join(options.binaryen_test, 'dot_s', 'basics.s'),
        '--import-memory'
    ]
    output = run_command(cmd)
    fail_if_not_contained(output, '(import "env" "memory" (memory $0 1))')

    extension_arg_map = {
        '.wast': [],
        '.clamp.wast': ['--trap-mode=clamp'],
        '.js.wast': ['--trap-mode=js'],
        '.jscall.wast': ['--emscripten-reserved-function-pointers=3'],
    }
    for dot_s_dir in ['dot_s', 'llvm_autogenerated']:
        dot_s_path = os.path.join(options.binaryen_test, dot_s_dir)
        for s in sorted(os.listdir(dot_s_path)):
            if not s.endswith('.s'):
                continue
            print '..', s
            for ext, ext_args in extension_arg_map.iteritems():
                wasm = s.replace('.s', ext)
                expected_file = os.path.join(options.binaryen_test, dot_s_dir,
                                             wasm)
                expected_exists = os.path.exists(expected_file)
                if ext != '.wast' and not expected_exists:
                    continue

                full = os.path.join(options.binaryen_test, dot_s_dir, s)
                stack_alloc = (['--allocate-stack=1024']
                               if dot_s_dir == 'llvm_autogenerated' else [])
                cmd = S2WASM + [full, '--emscripten-glue'
                                ] + stack_alloc + ext_args
                if s.startswith('start_'):
                    cmd.append('--start')
                actual = run_command(cmd)

                # verify output
                if not expected_exists:
                    print actual
                    fail_with_error('output ' + expected_file +
                                    ' does not exist')
                expected = open(expected_file, 'rb').read()
                if actual != expected:
                    fail(actual, expected)

                # verify with options
                cmd = S2WASM + [full, '--global-base=1024'] + stack_alloc
                run_command(cmd)

                # run wasm-shell on the .wast to verify that it parses
                cmd = WASM_SHELL + [expected_file]
                run_command(cmd)
Example #29
0
def generate_wast_files(clang_bin, lld_bin, emscripten_root):
    print '\n[ building wast files from C sources... ]\n'

    lld_path = os.path.join(shared.options.binaryen_test, 'lld')
    for src_file, ext in files_with_extensions(lld_path, ['.c', '.cpp']):
        print '..', src_file
        try:
            obj_file = src_file.replace(ext, '.o')

            src_path = os.path.join(lld_path, src_file)
            obj_path = os.path.join(lld_path, obj_file)
            run_command([
                clang_bin,
                src_path,
                '-o',
                obj_path,
                '--target=wasm32-unknown-unknown-wasm',
                '-c',
                '-nostdinc',
                '-Xclang',
                '-nobuiltininc',
                '-Xclang',
                '-nostdsysteminc',
                '-Xclang',
                '-I%s/system/include' % emscripten_root,
                '-O1',
            ])

            wasm_file = src_file.replace(ext, '.wasm')
            wast_file = src_file.replace(ext, '.wast')

            obj_path = os.path.join(lld_path, obj_file)
            wasm_path = os.path.join(lld_path, wasm_file)
            wast_path = os.path.join(lld_path, wast_file)
            run_command([
                lld_bin,
                '-flavor',
                'wasm',
                '-z',
                '-stack-size=1048576',
                obj_path,
                '-o',
                wasm_path,
                '--entry=main',
                '--allow-undefined',
                '--export',
                '__wasm_call_ctors',
                '--global-base=568',
            ])
            run_command(shared.WASM_DIS + [wasm_path, '-o', wast_path])
        finally:
            # Don't need the .o or .wasm files, don't leave them around
            shared.delete_from_orbit(obj_path)
            shared.delete_from_orbit(wasm_path)
Example #30
0
def generate_wast_files(llvm_bin, emscripten_root):
  print '\n[ building wast files from C sources... ]\n'

  lld_path = os.path.join(shared.options.binaryen_test, 'lld')
  for src_file, ext in files_with_extensions(lld_path, ['.c', '.cpp']):
    print '..', src_file
    obj_file = src_file.replace(ext, '.o')

    src_path = os.path.join(lld_path, src_file)
    obj_path = os.path.join(lld_path, obj_file)

    wasm_file = src_file.replace(ext, '.wasm')
    wast_file = src_file.replace(ext, '.wast')

    obj_path = os.path.join(lld_path, obj_file)
    wasm_path = os.path.join(lld_path, wasm_file)
    wast_path = os.path.join(lld_path, wast_file)
    is_shared = 'shared' in src_file

    compile_cmd = [
        os.path.join(llvm_bin, 'clang'), src_path, '-o', obj_path,
        '--target=wasm32-unknown-unknown-wasm',
        '-c',
        '-nostdinc',
        '-Xclang', '-nobuiltininc',
        '-Xclang', '-nostdsysteminc',
        '-Xclang', '-I%s/system/include' % emscripten_root,
        '-O1',
    ]

    link_cmd = [
        os.path.join(llvm_bin, 'wasm-ld'), '-flavor', 'wasm',
        '-z', '-stack-size=1048576',
        obj_path, '-o', wasm_path,
        '--allow-undefined',
        '--export', '__wasm_call_ctors',
        '--global-base=568',
    ]
    if is_shared:
      compile_cmd.append('-fPIC')
      compile_cmd.append('-fvisibility=default')
      link_cmd.append('-shared')
    else:
      link_cmd.append('--entry=main')

    try:
      run_command(compile_cmd)
      run_command(link_cmd)
      run_command(shared.WASM_DIS + [wasm_path, '-o', wast_path])
    finally:
      # Don't need the .o or .wasm files, don't leave them around
      shared.delete_from_orbit(obj_path)
      shared.delete_from_orbit(wasm_path)
Example #31
0
def update_lld_tests():
  print '\n[ updatring wasm-emscripten-finalize testcases... ]\n'

  for wast_path in files_with_pattern(options.binaryen_test, 'lld', '*.wast'):
    print '..', wast_path
    mem_file = wast_path + '.mem'
    extension_arg_map = {
      '.out': [],
      '.mem.out': ['--separate-data-segments', mem_file + '.mem'],
    }
    for ext, ext_args in extension_arg_map.items():
      out_path = wast_path + ext
      if ext != '.out' and not os.path.exists(out_path):
        continue
      cmd = WASM_EMSCRIPTEN_FINALIZE + [wast_path, '-S'] + ext_args
      cmd += args_for_finalize(os.path.basename(wast_path))
      actual = run_command(cmd)
      with open(out_path, 'w') as o:
        o.write(actual)
Example #32
0
def test_wasm2asm_output():
    for wasm in tests + spec_tests + extra_tests:
        if not wasm.endswith('.wast'):
            continue

        asm = os.path.basename(wasm).replace('.wast', '.2asm.js')
        expected_file = os.path.join(options.binaryen_test, asm)

        if not os.path.exists(expected_file):
            continue

        print '..', wasm

        cmd = WASM2ASM + [os.path.join(options.binaryen_test, wasm)]
        out = run_command(cmd)
        expected = open(expected_file).read()
        fail_if_not_identical(out, expected)

        if not NODEJS and not MOZJS:
            print 'No JS interpreters. Skipping spec tests.'
            continue

        open('a.2asm.js', 'w').write(out)

        cmd += ['--allow-asserts']
        out = run_command(cmd)

        open('a.2asm.asserts.js', 'w').write(out)

        # verify asm.js is valid js
        if NODEJS:
            out = run_command([NODEJS, 'a.2asm.js'])
            fail_if_not_identical(out, '')
            out = run_command([NODEJS, 'a.2asm.asserts.js'], expected_err='')
            fail_if_not_identical(out, '')

        if MOZJS:
            # verify asm.js validates, if this is asm.js code (we emit
            # almost-asm instead when we need to)
            if 'use asm' in open('a.2asm.js').read():
                # check only subset of err because mozjs emits timing info
                out = run_command(
                    [MOZJS, '-w', 'a.2asm.js'],
                    expected_err='Successfully compiled asm.js code',
                    err_contains=True)
                fail_if_not_identical(out, '')
                out = run_command([MOZJS, 'a.2asm.asserts.js'],
                                  expected_err='')
                fail_if_not_identical(out, '')
Example #33
0
def update_lld_tests():
    print '\n[ updatring wasm-emscripten-finalize testcases... ]\n'

    for wast_path in files_with_pattern(options.binaryen_test, 'lld',
                                        '*.wast'):
        print '..', wast_path
        mem_file = wast_path + '.mem'
        extension_arg_map = {
            '.out': [],
            '.mem.out': ['--separate-data-segments', mem_file + '.mem'],
        }
        for ext, ext_args in extension_arg_map.items():
            out_path = wast_path + ext
            if ext != '.out' and not os.path.exists(out_path):
                continue
            cmd = WASM_EMSCRIPTEN_FINALIZE + [wast_path, '-S'] + ext_args
            cmd += args_for_finalize(os.path.basename(wast_path))
            actual = run_command(cmd)
            with open(out_path, 'w') as o:
                o.write(actual)
Example #34
0
def test_wasm2asm_output():
    for wasm in tests + [w for w in spec_tests if '.fail' not in w]:
        if not wasm.endswith('.wast') or os.path.basename(wasm) in blacklist:
            continue

        asm = os.path.basename(wasm).replace('.wast', '.2asm.js')
        expected_file = os.path.join('test', asm)

        if not os.path.exists(expected_file):
            continue

        print '..', wasm

        cmd = WASM2ASM + [os.path.join('test', wasm)]
        out = run_command(cmd)
        expected = open(expected_file).read()
        fail_if_not_identical(out, expected)

        if not NODEJS and not MOZJS:
            print 'No JS interpreters. Skipping spec tests.'
            continue

        open('a.2asm.js', 'w').write(out)

        cmd += ['--allow-asserts']
        out = run_command(cmd)

        open('a.2asm.asserts.js', 'w').write(out)

        # verify asm.js is valid js
        if NODEJS:
            out = run_command([NODEJS, 'a.2asm.js'])
            fail_if_not_identical(out, '')
            out = run_command([NODEJS, 'a.2asm.asserts.js'], expected_err='')
            fail_if_not_identical(out, '')

        if MOZJS:
            # verify asm.js validates
            # check only subset of err because mozjs emits timing info
            out = run_command([MOZJS, '-w', 'a.2asm.js'],
                              expected_err='Successfully compiled asm.js code',
                              err_contains=True)
            fail_if_not_identical(out, '')
            out = run_command([MOZJS, 'a.2asm.asserts.js'], expected_err='')
            fail_if_not_identical(out, '')
Example #35
0
def generate_wast_files(llvm_bin, emscripten_root):
    print('\n[ building wast files from C sources... ]\n')

    lld_path = os.path.join(shared.options.binaryen_test, 'lld')
    for src_file, ext in files_with_extensions(lld_path, ['.c', '.cpp']):
        print('..', src_file)
        obj_file = src_file.replace(ext, '.o')

        src_path = os.path.join(lld_path, src_file)
        obj_path = os.path.join(lld_path, obj_file)

        wasm_file = src_file.replace(ext, '.wasm')
        wast_file = src_file.replace(ext, '.wast')

        obj_path = os.path.join(lld_path, obj_file)
        wasm_path = os.path.join(lld_path, wasm_file)
        wast_path = os.path.join(lld_path, wast_file)
        is_shared = 'shared' in src_file

        compile_cmd = [
            os.path.join(llvm_bin, 'clang'),
            src_path,
            '-o',
            obj_path,
            '--target=wasm32-unknown-unknown-wasm',
            '-c',
            '-nostdinc',
            '-Xclang',
            '-nobuiltininc',
            '-Xclang',
            '-nostdsysteminc',
            '-Xclang',
            '-I%s/system/include' % emscripten_root,
            '-O1',
        ]

        link_cmd = [
            os.path.join(llvm_bin, 'wasm-ld'),
            '-flavor',
            'wasm',
            '-z',
            '-stack-size=1048576',
            obj_path,
            '-o',
            wasm_path,
            '--allow-undefined',
            '--export',
            '__wasm_call_ctors',
            '--global-base=568',
        ]
        if is_shared:
            compile_cmd.append('-fPIC')
            compile_cmd.append('-fvisibility=default')
            link_cmd.append('-shared')
        else:
            link_cmd.append('--entry=main')

        try:
            run_command(compile_cmd)
            run_command(link_cmd)
            run_command(shared.WASM_DIS + [wasm_path, '-o', wast_path])
        finally:
            # Don't need the .o or .wasm files, don't leave them around
            shared.delete_from_orbit(obj_path)
            shared.delete_from_orbit(wasm_path)
Example #36
0
def update_wasm2js_tests():
    print '\n[ checking wasm2js ]\n'

    for opt in (0, 1):
        for wasm in tests + spec_tests + extra_wasm2js_tests:
            if not wasm.endswith('.wast'):
                continue

            if os.path.basename(wasm) in wasm2js_blacklist:
                continue

            asm = os.path.basename(wasm).replace('.wast', '.2asm.js')
            expected_file = os.path.join(wasm2js_dir, asm)
            if opt:
                expected_file += '.opt'

            # we run wasm2js on tests and spec tests only if the output
            # exists - only some work so far. the tests in extra are in
            # the test/wasm2js dir and so are specific to wasm2js, and
            # we run all of those.
            if wasm not in extra_wasm2js_tests and not os.path.exists(
                    expected_file):
                continue

            print '..', wasm

            t = os.path.join(options.binaryen_test, wasm)

            all_out = []

            for module, asserts in split_wast(t):
                with open('split.wast', 'w') as o:
                    o.write(module + '\n'.join(asserts))

                cmd = WASM2JS + ['split.wast']
                if opt:
                    cmd += ['-O']
                if 'emscripten' in wasm:
                    cmd += ['--emscripten']
                out = run_command(cmd)
                all_out.append(out)

            with open(expected_file, 'w') as o:
                o.write(''.join(all_out))

    for wasm in assert_tests:
        print '..', wasm

        asserts = os.path.basename(wasm).replace('.wast.asserts',
                                                 '.asserts.js')
        traps = os.path.basename(wasm).replace('.wast.asserts', '.traps.js')
        asserts_expected_file = os.path.join('test', asserts)
        traps_expected_file = os.path.join('test', traps)

        cmd = WASM2JS + [os.path.join(wasm2js_dir, wasm), '--allow-asserts']
        out = run_command(cmd)
        with open(asserts_expected_file, 'w') as o:
            o.write(out)

        cmd += ['--pedantic']
        out = run_command(cmd)
        with open(traps_expected_file, 'w') as o:
            o.write(out)
Example #37
0
def test_wasm2js_output():
    for opt in (0, 1):
        for wasm in tests + spec_tests + extra_wasm2js_tests:
            if not wasm.endswith('.wast'):
                continue
            basename = os.path.basename(wasm)
            if basename in wasm2js_blacklist:
                continue

            asm = basename.replace('.wast', '.2asm.js')
            expected_file = os.path.join(wasm2js_dir, asm)
            if opt:
                expected_file += '.opt'

            if not os.path.exists(expected_file):
                continue

            print '..', wasm

            t = os.path.join(options.binaryen_test, wasm)

            all_out = []

            for module, asserts in split_wast(t):
                with open('split.wast', 'w') as o:
                    o.write(module + '\n'.join(asserts))

                cmd = WASM2JS + ['split.wast']
                if opt:
                    cmd += ['-O']
                if 'emscripten' in wasm:
                    cmd += ['--emscripten']
                out = run_command(cmd)
                all_out.append(out)

                if not NODEJS and not MOZJS:
                    print 'No JS interpreters. Skipping spec tests.'
                    continue

                open('a.2asm.mjs', 'w').write(out)

                cmd += ['--allow-asserts']
                out = run_command(cmd)
                # also verify it passes pass-debug verifications
                with_pass_debug(lambda: run_command(cmd))

                open('a.2asm.asserts.mjs', 'w').write(out)

                # verify asm.js is valid js, note that we're using --experimental-modules
                # to enable ESM syntax and we're also passing a custom loader to handle the
                # `spectest` and `env` modules in our tests.
                if NODEJS:
                    node = [
                        NODEJS, '--experimental-modules', '--loader',
                        './scripts/test/node-esm-loader.mjs'
                    ]
                    cmd = node[:]
                    cmd.append('a.2asm.mjs')
                    out = run_command(cmd)
                    fail_if_not_identical(out, '')
                    cmd = node[:]
                    cmd.append('a.2asm.asserts.mjs')
                    out = run_command(
                        cmd,
                        expected_err='',
                        err_ignore='The ESM module loader is experimental')
                    fail_if_not_identical(out, '')

            fail_if_not_identical_to_file(''.join(all_out), expected_file)
Example #38
0
def test_asm2wasm():
  print '[ checking asm2wasm testcases... ]\n'

  for asm in tests:
    if not asm.endswith('.asm.js'):
      continue
    for precise in [0, 1, 2]:
      for opts in [1, 0]:
        cmd = ASM2WASM + [os.path.join(options.binaryen_test, asm)]
        if 'threads' in asm:
          cmd += ['--enable-threads']
        wasm = asm.replace('.asm.js', '.fromasm')
        if not precise:
          cmd += ['--trap-mode=allow', '--ignore-implicit-traps']
          wasm += '.imprecise'
        elif precise == 2:
          cmd += ['--trap-mode=clamp']
          wasm += '.clamp'
        if not opts:
          wasm += '.no-opts'
          if precise:
            cmd += ['-O0']  # test that -O0 does nothing
        else:
          cmd += ['-O']
        if 'debugInfo' in asm:
          cmd += ['-g']
        if 'noffi' in asm:
          cmd += ['--no-legalize-javascript-ffi']
        if precise and opts:
          # test mem init importing
          open('a.mem', 'wb').write(asm)
          cmd += ['--mem-init=a.mem']
          if asm[0] == 'e':
            cmd += ['--mem-base=1024']
        if '4GB' in asm:
          cmd += ['--mem-max=4294967296']
        if 'i64' in asm or 'wasm-only' in asm or 'noffi' in asm:
          cmd += ['--wasm-only']
        wasm = os.path.join(options.binaryen_test, wasm)
        print '..', asm, wasm

        def do_asm2wasm_test():
          actual = run_command(cmd)

          # verify output
          if not os.path.exists(wasm):
            fail_with_error('output .wast file %s does not exist' % wasm)
          fail_if_not_identical_to_file(actual, wasm)

          binary_format_check(wasm, verify_final_result=False)

        # test both normally and with pass debug (so each inter-pass state
        # is validated)
        old_pass_debug = os.environ.get('BINARYEN_PASS_DEBUG')
        try:
          os.environ['BINARYEN_PASS_DEBUG'] = '1'
          print "With BINARYEN_PASS_DEBUG=1:"
          do_asm2wasm_test()
          del os.environ['BINARYEN_PASS_DEBUG']
          print "With BINARYEN_PASS_DEBUG disabled:"
          do_asm2wasm_test()
        finally:
          if old_pass_debug is not None:
            os.environ['BINARYEN_PASS_DEBUG'] = old_pass_debug
          else:
            if 'BINARYEN_PASS_DEBUG' in os.environ:
              del os.environ['BINARYEN_PASS_DEBUG']

        # verify in wasm
        if options.interpreter:
          # remove imports, spec interpreter doesn't know what to do with them
          subprocess.check_call(WASM_OPT + ['--remove-imports', wasm],
                                stdout=open('ztemp.wast', 'w'),
                                stderr=subprocess.PIPE)
          proc = subprocess.Popen([options.interpreter, 'ztemp.wast'],
                                  stderr=subprocess.PIPE)
          out, err = proc.communicate()
          if proc.returncode != 0:
            try:  # to parse the error
              reported = err.split(':')[1]
              start, end = reported.split('-')
              start_line, start_col = map(int, start.split('.'))
              lines = open('ztemp.wast').read().split('\n')
              print
              print '=' * 80
              print lines[start_line - 1]
              print (' ' * (start_col - 1)) + '^'
              print (' ' * (start_col - 2)) + '/_\\'
              print '=' * 80
              print err
            except Exception:
              # failed to pretty-print
              fail_with_error('wasm interpreter error: ' + err)
            fail_with_error('wasm interpreter error')

        # verify debug info
        if 'debugInfo' in asm:
          jsmap = 'a.wasm.map'
          cmd += ['--source-map', jsmap,
                  '--source-map-url', 'http://example.org/' + jsmap,
                  '-o', 'a.wasm']
          run_command(cmd)
          if not os.path.isfile(jsmap):
            fail_with_error('Debug info map not created: %s' % jsmap)
          with open(jsmap, 'rb') as actual:
            fail_if_not_identical_to_file(actual.read(), wasm + '.map')
          with open('a.wasm', 'rb') as binary:
            url_section_name = bytearray([16]) + bytearray('sourceMappingURL')
            url = 'http://example.org/' + jsmap
            assert len(url) < 256, 'name too long'
            url_section_contents = bytearray([len(url)]) + bytearray(url)
            print url_section_name
            binary_contents = bytearray(binary.read())
            if url_section_name not in binary_contents:
              fail_with_error('source map url section not found in binary')
            url_section_index = binary_contents.index(url_section_name)
            if url_section_contents not in binary_contents[url_section_index:]:
              fail_with_error('source map url not found in url section')
Example #39
0
def test_asm2wasm():
  print '[ checking asm2wasm testcases... ]\n'

  for asm in tests:
    if not asm.endswith('.asm.js'):
      continue
    for precise in [0, 1, 2]:
      for opts in [1, 0]:
        cmd = ASM2WASM + [os.path.join(options.binaryen_test, asm)]
        if 'threads' in asm:
          cmd += ['--enable-threads']
        wasm = asm.replace('.asm.js', '.fromasm')
        if not precise:
          cmd += ['--trap-mode=allow', '--ignore-implicit-traps']
          wasm += '.imprecise'
        elif precise == 2:
          cmd += ['--trap-mode=clamp']
          wasm += '.clamp'
        if not opts:
          wasm += '.no-opts'
          if precise:
            cmd += ['-O0']  # test that -O0 does nothing
        else:
          cmd += ['-O']
        if 'debugInfo' in asm:
          cmd += ['-g']
        if 'noffi' in asm:
          cmd += ['--no-legalize-javascript-ffi']
        if precise and opts:
          # test mem init importing
          open('a.mem', 'wb').write(asm)
          cmd += ['--mem-init=a.mem']
          if asm[0] == 'e':
            cmd += ['--mem-base=1024']
        if 'i64' in asm or 'wasm-only' in asm or 'noffi' in asm:
          cmd += ['--wasm-only']
        wasm = os.path.join(options.binaryen_test, wasm)
        print '..', asm, wasm

        def do_asm2wasm_test():
          actual = run_command(cmd)

          # verify output
          if not os.path.exists(wasm):
            fail_with_error('output .wast file %s does not exist' % wasm)
          fail_if_not_identical_to_file(actual, wasm)

          binary_format_check(wasm, verify_final_result=False)

        # test both normally and with pass debug (so each inter-pass state
        # is validated)
        old_pass_debug = os.environ.get('BINARYEN_PASS_DEBUG')
        try:
          os.environ['BINARYEN_PASS_DEBUG'] = '1'
          print "With BINARYEN_PASS_DEBUG=1:"
          do_asm2wasm_test()
          del os.environ['BINARYEN_PASS_DEBUG']
          print "With BINARYEN_PASS_DEBUG disabled:"
          do_asm2wasm_test()
        finally:
          if old_pass_debug is not None:
            os.environ['BINARYEN_PASS_DEBUG'] = old_pass_debug
          else:
            if 'BINARYEN_PASS_DEBUG' in os.environ:
              del os.environ['BINARYEN_PASS_DEBUG']

        # verify in wasm
        if options.interpreter:
          # remove imports, spec interpreter doesn't know what to do with them
          subprocess.check_call(WASM_OPT + ['--remove-imports', wasm],
                                stdout=open('ztemp.wast', 'w'),
                                stderr=subprocess.PIPE)
          proc = subprocess.Popen([options.interpreter, 'ztemp.wast'],
                                  stderr=subprocess.PIPE)
          out, err = proc.communicate()
          if proc.returncode != 0:
            try:  # to parse the error
              reported = err.split(':')[1]
              start, end = reported.split('-')
              start_line, start_col = map(int, start.split('.'))
              lines = open('ztemp.wast').read().split('\n')
              print
              print '=' * 80
              print lines[start_line - 1]
              print (' ' * (start_col - 1)) + '^'
              print (' ' * (start_col - 2)) + '/_\\'
              print '=' * 80
              print err
            except Exception:
              # failed to pretty-print
              fail_with_error('wasm interpreter error: ' + err)
            fail_with_error('wasm interpreter error')

        # verify debug info
        if 'debugInfo' in asm:
          jsmap = 'a.wasm.map'
          cmd += ['--source-map', jsmap,
                  '--source-map-url', 'http://example.org/' + jsmap,
                  '-o', 'a.wasm']
          run_command(cmd)
          if not os.path.isfile(jsmap):
            fail_with_error('Debug info map not created: %s' % jsmap)
          with open(jsmap, 'rb') as actual:
            fail_if_not_identical_to_file(actual.read(), wasm + '.map')
          with open('a.wasm', 'rb') as binary:
            url_section_name = bytearray([16]) + bytearray('sourceMappingURL')
            url = 'http://example.org/' + jsmap
            assert len(url) < 256, 'name too long'
            url_section_contents = bytearray([len(url)]) + bytearray(url)
            print url_section_name
            binary_contents = bytearray(binary.read())
            if url_section_name not in binary_contents:
              fail_with_error('source map url section not found in binary')
            url_section_index = binary_contents.index(url_section_name)
            if url_section_contents not in binary_contents[url_section_index:]:
              fail_with_error('source map url not found in url section')