diff options
Diffstat (limited to 'test/run-spec-wasm2c.py')
-rwxr-xr-x | test/run-spec-wasm2c.py | 698 |
1 files changed, 349 insertions, 349 deletions
diff --git a/test/run-spec-wasm2c.py b/test/run-spec-wasm2c.py index 2f986f73..7ec17e24 100755 --- a/test/run-spec-wasm2c.py +++ b/test/run-spec-wasm2c.py @@ -18,9 +18,9 @@ from __future__ import print_function import argparse try: - from cStringIO import StringIO + from cStringIO import StringIO except ImportError: - from io import StringIO + from io import StringIO import json import os import re @@ -36,390 +36,390 @@ WASM2C_DIR = os.path.join(find_exe.REPO_ROOT_DIR, 'wasm2c') def ReinterpretF32(f32_bits): - return struct.unpack('<f', struct.pack('<I', f32_bits))[0] + return struct.unpack('<f', struct.pack('<I', f32_bits))[0] def F32ToC(f32_bits): - F32_SIGN_BIT = 0x80000000 - F32_INF = 0x7f800000 - F32_SIG_MASK = 0x7fffff - - if (f32_bits & F32_INF) == F32_INF: - sign = '-' if (f32_bits & F32_SIGN_BIT) == F32_SIGN_BIT else '' - # NaN or infinity - if f32_bits & F32_SIG_MASK: - # NaN - return '%smake_nan_f32(0x%06x)' % (sign, f32_bits & F32_SIG_MASK) + F32_SIGN_BIT = 0x80000000 + F32_INF = 0x7f800000 + F32_SIG_MASK = 0x7fffff + + if (f32_bits & F32_INF) == F32_INF: + sign = '-' if (f32_bits & F32_SIGN_BIT) == F32_SIGN_BIT else '' + # NaN or infinity + if f32_bits & F32_SIG_MASK: + # NaN + return '%smake_nan_f32(0x%06x)' % (sign, f32_bits & F32_SIG_MASK) + else: + return '%sINFINITY' % sign + elif f32_bits == F32_SIGN_BIT: + return '-0.f' else: - return '%sINFINITY' % sign - elif f32_bits == F32_SIGN_BIT: - return '-0.f' - else: - s = '%.9g' % ReinterpretF32(f32_bits) - if '.' not in s: - s += '.' - return s + 'f' + s = '%.9g' % ReinterpretF32(f32_bits) + if '.' not in s: + s += '.' + return s + 'f' def ReinterpretF64(f64_bits): - return struct.unpack('<d', struct.pack('<Q', f64_bits))[0] + return struct.unpack('<d', struct.pack('<Q', f64_bits))[0] def F64ToC(f64_bits): - F64_SIGN_BIT = 0x8000000000000000 - F64_INF = 0x7ff0000000000000 - F64_SIG_MASK = 0xfffffffffffff - - if (f64_bits & F64_INF) == F64_INF: - sign = '-' if (f64_bits & F64_SIGN_BIT) == F64_SIGN_BIT else '' - # NaN or infinity - if f64_bits & F64_SIG_MASK: - # NaN - return '%smake_nan_f64(0x%06x)' % (sign, f64_bits & F64_SIG_MASK) + F64_SIGN_BIT = 0x8000000000000000 + F64_INF = 0x7ff0000000000000 + F64_SIG_MASK = 0xfffffffffffff + + if (f64_bits & F64_INF) == F64_INF: + sign = '-' if (f64_bits & F64_SIGN_BIT) == F64_SIGN_BIT else '' + # NaN or infinity + if f64_bits & F64_SIG_MASK: + # NaN + return '%smake_nan_f64(0x%06x)' % (sign, f64_bits & F64_SIG_MASK) + else: + return '%sINFINITY' % sign + elif f64_bits == F64_SIGN_BIT: + return '-0.0' else: - return '%sINFINITY' % sign - elif f64_bits == F64_SIGN_BIT: - return '-0.0' - else: - return '%.17g' % ReinterpretF64(f64_bits) + return '%.17g' % ReinterpretF64(f64_bits) def MangleType(t): - return {'i32': 'i', 'i64': 'j', 'f32': 'f', 'f64': 'd'}[t] + return {'i32': 'i', 'i64': 'j', 'f32': 'f', 'f64': 'd'}[t] def MangleTypes(types): - if not types: - return 'v' - return ''.join(MangleType(t) for t in types) + if not types: + return 'v' + return ''.join(MangleType(t) for t in types) def MangleName(s): - result = 'Z_' - for c in s.encode('utf-8'): - # NOTE(binji): Z is not allowed. - if c in '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY0123456789': - result += c - else: - result += 'Z%02X' % ord(c) - return result + result = 'Z_' + for c in s.encode('utf-8'): + # NOTE(binji): Z is not allowed. + if c in '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY0123456789': + result += c + else: + result += 'Z%02X' % ord(c) + return result def IsModuleCommand(command): - return (command['type'] == 'module' or - command['type'] == 'assert_uninstantiable') + return (command['type'] == 'module' or + command['type'] == 'assert_uninstantiable') class CWriter(object): - def __init__(self, spec_json, prefix, out_file, out_dir): - self.source_filename = os.path.basename(spec_json['source_filename']) - self.commands = spec_json['commands'] - self.out_file = out_file - self.out_dir = out_dir - self.prefix = prefix - self.module_idx = 0 - self.module_name_to_idx = {} - self.module_prefix_map = {} - - def Write(self): - self._MaybeWriteDummyModule() - self._CacheModulePrefixes() - self._WriteIncludes() - self.out_file.write(self.prefix) - self.out_file.write("\nvoid run_spec_tests(void) {\n\n") - for command in self.commands: - self._WriteCommand(command) - self.out_file.write("\n}\n") - - def GetModuleFilenames(self): - return [c['filename'] for c in self.commands if IsModuleCommand(c)] - - def GetModulePrefix(self, idx_or_name=None): - if idx_or_name is not None: - return self.module_prefix_map[idx_or_name] - return self.module_prefix_map[self.module_idx - 1] - - def _CacheModulePrefixes(self): - idx = 0 - for command in self.commands: - if IsModuleCommand(command): - name = os.path.basename(command['filename']) - name = os.path.splitext(name)[0] - name = re.sub(r'[^a-zA-Z0-9_]', '_', name) - name = MangleName(name) - - self.module_prefix_map[idx] = name - - if 'name' in command: - self.module_name_to_idx[command['name']] = idx - self.module_prefix_map[command['name']] = name - - idx += 1 - elif command['type'] == 'register': - name = MangleName(command['as']) - if 'name' in command: - self.module_prefix_map[command['name']] = name - name_idx = self.module_name_to_idx[command['name']] + def __init__(self, spec_json, prefix, out_file, out_dir): + self.source_filename = os.path.basename(spec_json['source_filename']) + self.commands = spec_json['commands'] + self.out_file = out_file + self.out_dir = out_dir + self.prefix = prefix + self.module_idx = 0 + self.module_name_to_idx = {} + self.module_prefix_map = {} + + def Write(self): + self._MaybeWriteDummyModule() + self._CacheModulePrefixes() + self._WriteIncludes() + self.out_file.write(self.prefix) + self.out_file.write("\nvoid run_spec_tests(void) {\n\n") + for command in self.commands: + self._WriteCommand(command) + self.out_file.write("\n}\n") + + def GetModuleFilenames(self): + return [c['filename'] for c in self.commands if IsModuleCommand(c)] + + def GetModulePrefix(self, idx_or_name=None): + if idx_or_name is not None: + return self.module_prefix_map[idx_or_name] + return self.module_prefix_map[self.module_idx - 1] + + def _CacheModulePrefixes(self): + idx = 0 + for command in self.commands: + if IsModuleCommand(command): + name = os.path.basename(command['filename']) + name = os.path.splitext(name)[0] + name = re.sub(r'[^a-zA-Z0-9_]', '_', name) + name = MangleName(name) + + self.module_prefix_map[idx] = name + + if 'name' in command: + self.module_name_to_idx[command['name']] = idx + self.module_prefix_map[command['name']] = name + + idx += 1 + elif command['type'] == 'register': + name = MangleName(command['as']) + if 'name' in command: + self.module_prefix_map[command['name']] = name + name_idx = self.module_name_to_idx[command['name']] + else: + name_idx = idx - 1 + + self.module_prefix_map[name_idx] = name + + def _MaybeWriteDummyModule(self): + if len(self.GetModuleFilenames()) == 0: + # This test doesn't have any valid modules, so just use a dummy instead. + filename = utils.ChangeExt(self.source_filename, '-dummy.wasm') + with open(os.path.join(self.out_dir, filename), 'wb') as wasm_file: + wasm_file.write(b'\x00\x61\x73\x6d\x01\x00\x00\x00') + + dummy_command = {'type': 'module', 'line': 0, 'filename': filename} + self.commands.insert(0, dummy_command) + + def _WriteFileAndLine(self, command): + self.out_file.write('// %s:%d\n' % (self.source_filename, command['line'])) + + def _WriteIncludes(self): + idx = 0 + for filename in self.GetModuleFilenames(): + header = os.path.splitext(filename)[0] + '.h' + self.out_file.write( + '#define WASM_RT_MODULE_PREFIX %s\n' % self.GetModulePrefix(idx)) + self.out_file.write("#include \"%s\"\n" % header) + self.out_file.write('#undef WASM_RT_MODULE_PREFIX\n\n') + idx += 1 + + def _WriteCommand(self, command): + command_funcs = { + 'module': self._WriteModuleCommand, + 'assert_uninstantiable': self._WriteAssertUninstantiableCommand, + 'action': self._WriteActionCommand, + 'assert_return': self._WriteAssertReturnCommand, + 'assert_return_canonical_nan': self._WriteAssertReturnNanCommand, + 'assert_return_arithmetic_nan': self._WriteAssertReturnNanCommand, + 'assert_trap': self._WriteAssertActionCommand, + 'assert_exhaustion': self._WriteAssertActionCommand, + } + + func = command_funcs.get(command['type']) + if func is not None: + self._WriteFileAndLine(command) + func(command) + self.out_file.write('\n') + + def _WriteModuleCommand(self, command): + self.module_idx += 1 + self.out_file.write('%sinit();\n' % self.GetModulePrefix()) + + def _WriteAssertUninstantiableCommand(self, command): + self.module_idx += 1 + self.out_file.write('ASSERT_TRAP(%sinit());\n' % self.GetModulePrefix()) + + def _WriteActionCommand(self, command): + self.out_file.write('%s;\n' % self._Action(command)) + + def _WriteAssertReturnCommand(self, command): + expected = command['expected'] + if len(expected) == 1: + assert_map = { + 'i32': 'ASSERT_RETURN_I32', + 'f32': 'ASSERT_RETURN_F32', + 'i64': 'ASSERT_RETURN_I64', + 'f64': 'ASSERT_RETURN_F64', + } + + type_ = expected[0]['type'] + assert_macro = assert_map[type_] + self.out_file.write('%s(%s, %s);\n' % + (assert_macro, + self._Action(command), + self._ConstantList(expected))) + elif len(expected) == 0: + self._WriteAssertActionCommand(command) else: - name_idx = idx - 1 - - self.module_prefix_map[name_idx] = name - - def _MaybeWriteDummyModule(self): - if len(self.GetModuleFilenames()) == 0: - # This test doesn't have any valid modules, so just use a dummy instead. - filename = utils.ChangeExt(self.source_filename, '-dummy.wasm') - with open(os.path.join(self.out_dir, filename), 'wb') as wasm_file: - wasm_file.write(b'\x00\x61\x73\x6d\x01\x00\x00\x00') - - dummy_command = {'type': 'module', 'line': 0, 'filename': filename} - self.commands.insert(0, dummy_command) - - def _WriteFileAndLine(self, command): - self.out_file.write('// %s:%d\n' % (self.source_filename, command['line'])) - - def _WriteIncludes(self): - idx = 0 - for filename in self.GetModuleFilenames(): - header = os.path.splitext(filename)[0] + '.h' - self.out_file.write( - '#define WASM_RT_MODULE_PREFIX %s\n' % self.GetModulePrefix(idx)) - self.out_file.write("#include \"%s\"\n" % header) - self.out_file.write('#undef WASM_RT_MODULE_PREFIX\n\n') - idx += 1 - - def _WriteCommand(self, command): - command_funcs = { - 'module': self._WriteModuleCommand, - 'assert_uninstantiable': self._WriteAssertUninstantiableCommand, - 'action': self._WriteActionCommand, - 'assert_return': self._WriteAssertReturnCommand, - 'assert_return_canonical_nan': self._WriteAssertReturnNanCommand, - 'assert_return_arithmetic_nan': self._WriteAssertReturnNanCommand, - 'assert_trap': self._WriteAssertActionCommand, - 'assert_exhaustion': self._WriteAssertActionCommand, - } - - func = command_funcs.get(command['type']) - if func is not None: - self._WriteFileAndLine(command) - func(command) - self.out_file.write('\n') - - def _WriteModuleCommand(self, command): - self.module_idx += 1 - self.out_file.write('%sinit();\n' % self.GetModulePrefix()) - - def _WriteAssertUninstantiableCommand(self, command): - self.module_idx += 1 - self.out_file.write('ASSERT_TRAP(%sinit());\n' % self.GetModulePrefix()) - - def _WriteActionCommand(self, command): - self.out_file.write('%s;\n' % self._Action(command)) - - def _WriteAssertReturnCommand(self, command): - expected = command['expected'] - if len(expected) == 1: - assert_map = { - 'i32': 'ASSERT_RETURN_I32', - 'f32': 'ASSERT_RETURN_F32', - 'i64': 'ASSERT_RETURN_I64', - 'f64': 'ASSERT_RETURN_F64', - } - - type_ = expected[0]['type'] - assert_macro = assert_map[type_] - self.out_file.write('%s(%s, %s);\n' % - (assert_macro, - self._Action(command), - self._ConstantList(expected))) - elif len(expected) == 0: - self._WriteAssertActionCommand(command) - else: - raise Error('Unexpected result with multiple values: %s' % expected) - - def _WriteAssertReturnNanCommand(self, command): - assert_map = { - ('assert_return_canonical_nan', 'f32'): 'ASSERT_RETURN_CANONICAL_NAN_F32', - ('assert_return_canonical_nan', 'f64'): 'ASSERT_RETURN_CANONICAL_NAN_F64', - ('assert_return_arithmetic_nan', 'f32'): 'ASSERT_RETURN_ARITHMETIC_NAN_F32', - ('assert_return_arithmetic_nan', 'f64'): 'ASSERT_RETURN_ARITHMETIC_NAN_F64', - } - - expected = command['expected'] - type_ = expected[0]['type'] - assert_macro = assert_map[(command['type'], type_)] - - self.out_file.write('%s(%s);\n' % (assert_macro, self._Action(command))) - - def _WriteAssertActionCommand(self, command): - assert_map = { - 'assert_exhaustion': 'ASSERT_EXHAUSTION', - 'assert_return': 'ASSERT_RETURN', - 'assert_trap': 'ASSERT_TRAP', - } - - assert_macro = assert_map[command['type']] - self.out_file.write('%s(%s);\n' % (assert_macro, self._Action(command))) - - def _Constant(self, const): - type_ = const['type'] - value = int(const['value']) - if type_ == 'i32': - return '%su' % value - elif type_ == 'i64': - return '%sull' % value - elif type_ == 'f32': - return F32ToC(value) - elif type_ == 'f64': - return F64ToC(value) - else: - assert False - - def _ConstantList(self, consts): - return ', '.join(self._Constant(const) for const in consts) - - def _ActionSig(self, action, expected): - type_ = action['type'] - result_types = [result['type'] for result in expected] - arg_types = [arg['type'] for arg in action.get('args', [])] - if type_ == 'invoke': - return MangleTypes(result_types) + MangleTypes(arg_types) - elif type_ == 'get': - return MangleType(result_types[0]) - else: - raise Error('Unexpected action type: %s' % type_) - - def _Action(self, command): - action = command['action'] - expected = command['expected'] - type_ = action['type'] - mangled_module_name = self.GetModulePrefix(action.get('module')) - field = (mangled_module_name + MangleName(action['field']) + - MangleName(self._ActionSig(action, expected))) - if type_ == 'invoke': - return '%s(%s)' % (field, self._ConstantList(action.get('args', []))) - elif type_ == 'get': - return '*%s' % field - else: - raise Error('Unexpected action type: %s' % type_) + raise Error('Unexpected result with multiple values: %s' % expected) + + def _WriteAssertReturnNanCommand(self, command): + assert_map = { + ('assert_return_canonical_nan', 'f32'): 'ASSERT_RETURN_CANONICAL_NAN_F32', + ('assert_return_canonical_nan', 'f64'): 'ASSERT_RETURN_CANONICAL_NAN_F64', + ('assert_return_arithmetic_nan', 'f32'): 'ASSERT_RETURN_ARITHMETIC_NAN_F32', + ('assert_return_arithmetic_nan', 'f64'): 'ASSERT_RETURN_ARITHMETIC_NAN_F64', + } + + expected = command['expected'] + type_ = expected[0]['type'] + assert_macro = assert_map[(command['type'], type_)] + + self.out_file.write('%s(%s);\n' % (assert_macro, self._Action(command))) + + def _WriteAssertActionCommand(self, command): + assert_map = { + 'assert_exhaustion': 'ASSERT_EXHAUSTION', + 'assert_return': 'ASSERT_RETURN', + 'assert_trap': 'ASSERT_TRAP', + } + + assert_macro = assert_map[command['type']] + self.out_file.write('%s(%s);\n' % (assert_macro, self._Action(command))) + + def _Constant(self, const): + type_ = const['type'] + value = int(const['value']) + if type_ == 'i32': + return '%su' % value + elif type_ == 'i64': + return '%sull' % value + elif type_ == 'f32': + return F32ToC(value) + elif type_ == 'f64': + return F64ToC(value) + else: + assert False + + def _ConstantList(self, consts): + return ', '.join(self._Constant(const) for const in consts) + + def _ActionSig(self, action, expected): + type_ = action['type'] + result_types = [result['type'] for result in expected] + arg_types = [arg['type'] for arg in action.get('args', [])] + if type_ == 'invoke': + return MangleTypes(result_types) + MangleTypes(arg_types) + elif type_ == 'get': + return MangleType(result_types[0]) + else: + raise Error('Unexpected action type: %s' % type_) + + def _Action(self, command): + action = command['action'] + expected = command['expected'] + type_ = action['type'] + mangled_module_name = self.GetModulePrefix(action.get('module')) + field = (mangled_module_name + MangleName(action['field']) + + MangleName(self._ActionSig(action, expected))) + if type_ == 'invoke': + return '%s(%s)' % (field, self._ConstantList(action.get('args', []))) + elif type_ == 'get': + return '*%s' % field + else: + raise Error('Unexpected action type: %s' % type_) def Compile(cc, c_filename, out_dir, *args): - out_dir = os.path.abspath(out_dir) - o_filename = utils.ChangeDir(utils.ChangeExt(c_filename, '.o'), out_dir) - cc.RunWithArgs('-c', '-o', o_filename, c_filename, *args, cwd=out_dir) - return o_filename + out_dir = os.path.abspath(out_dir) + o_filename = utils.ChangeDir(utils.ChangeExt(c_filename, '.o'), out_dir) + cc.RunWithArgs('-c', '-o', o_filename, c_filename, *args, cwd=out_dir) + return o_filename def Link(cc, o_filenames, main_exe, out_dir, *args): - args = ['-o', main_exe] + o_filenames + list(args) - cc.RunWithArgs(*args, cwd=out_dir) + args = ['-o', main_exe] + o_filenames + list(args) + cc.RunWithArgs(*args, cwd=out_dir) def main(args): - parser = argparse.ArgumentParser() - parser.add_argument('-o', '--out-dir', metavar='PATH', - help='output directory for files.') - parser.add_argument('-P', '--prefix', metavar='PATH', help='prefix file.', - default=os.path.join(SCRIPT_DIR, 'spec-wasm2c-prefix.c')) - parser.add_argument('--bindir', metavar='PATH', - default=find_exe.GetDefaultPath(), - help='directory to search for all executables.') - parser.add_argument('--wasmrt-dir', metavar='PATH', - help='directory with wasm-rt files', default=WASM2C_DIR) - parser.add_argument('--cc', metavar='PATH', - help='the path to the C compiler', default='cc') - parser.add_argument('--cflags', metavar='FLAGS', - help='additional flags for C compiler.', - action='append', default=[]) - parser.add_argument('--compile', help='compile the C code (default)', - dest='compile', action='store_true') - parser.add_argument('--no-compile', help='don\'t compile the C code', - dest='compile', action='store_false') - parser.set_defaults(compile=True) - parser.add_argument('--no-run', help='don\'t run the compiled executable', - dest='run', action='store_false') - parser.add_argument('-v', '--verbose', help='print more diagnotic messages.', - action='store_true') - parser.add_argument('--no-error-cmdline', - help='don\'t display the subprocess\'s commandline when ' - 'an error occurs', dest='error_cmdline', - action='store_false') - parser.add_argument('-p', '--print-cmd', - help='print the commands that are run.', - action='store_true') - parser.add_argument('file', help='wast file.') - options = parser.parse_args(args) - - with utils.TempDirectory(options.out_dir, 'run-spec-wasm2c-') as out_dir: - # Parse JSON file and generate main .c file with calls to test functions. - wast2json = utils.Executable( - find_exe.GetWast2JsonExecutable(options.bindir), - error_cmdline=options.error_cmdline) - wast2json.AppendOptionalArgs({'-v': options.verbose}) - - json_file_path = utils.ChangeDir( - utils.ChangeExt(options.file, '.json'), out_dir) - wast2json.RunWithArgs(options.file, '-o', json_file_path) - - wasm2c = utils.Executable( - find_exe.GetWasm2CExecutable(options.bindir), - error_cmdline=options.error_cmdline) - - cc = utils.Executable(options.cc, *options.cflags) - - with open(json_file_path) as json_file: - spec_json = json.load(json_file) - - prefix = '' - if options.prefix: - with open(options.prefix) as prefix_file: - prefix = prefix_file.read() + '\n' - - output = StringIO() - cwriter = CWriter(spec_json, prefix, output, out_dir) - cwriter.Write() - - main_filename = utils.ChangeExt(json_file_path, '-main.c') - with open(main_filename, 'w') as out_main_file: - out_main_file.write(output.getvalue()) - - o_filenames = [] - includes = '-I%s' % options.wasmrt_dir - - # Compile wasm-rt-impl. - wasm_rt_impl_c = os.path.join(options.wasmrt_dir, 'wasm-rt-impl.c') - o_filenames.append(Compile(cc, wasm_rt_impl_c, out_dir, includes)) - - for i, wasm_filename in enumerate(cwriter.GetModuleFilenames()): - c_filename = utils.ChangeExt(wasm_filename, '.c') - wasm2c.RunWithArgs(wasm_filename, '-o', c_filename, cwd=out_dir) - if options.compile: - defines = '-DWASM_RT_MODULE_PREFIX=%s' % cwriter.GetModulePrefix(i) - o_filenames.append(Compile(cc, c_filename, out_dir, includes, defines)) - - if options.compile: - main_c = os.path.basename(main_filename) - o_filenames.append(Compile(cc, main_c, out_dir, includes, defines)) - main_exe = os.path.basename(utils.ChangeExt(json_file_path, '')) - Link(cc, o_filenames, main_exe, out_dir, '-lm') - - if options.compile and options.run: - utils.Executable(os.path.join(out_dir, main_exe), - forward_stdout=True).RunWithArgs() - - return 0 + parser = argparse.ArgumentParser() + parser.add_argument('-o', '--out-dir', metavar='PATH', + help='output directory for files.') + parser.add_argument('-P', '--prefix', metavar='PATH', help='prefix file.', + default=os.path.join(SCRIPT_DIR, 'spec-wasm2c-prefix.c')) + parser.add_argument('--bindir', metavar='PATH', + default=find_exe.GetDefaultPath(), + help='directory to search for all executables.') + parser.add_argument('--wasmrt-dir', metavar='PATH', + help='directory with wasm-rt files', default=WASM2C_DIR) + parser.add_argument('--cc', metavar='PATH', + help='the path to the C compiler', default='cc') + parser.add_argument('--cflags', metavar='FLAGS', + help='additional flags for C compiler.', + action='append', default=[]) + parser.add_argument('--compile', help='compile the C code (default)', + dest='compile', action='store_true') + parser.add_argument('--no-compile', help='don\'t compile the C code', + dest='compile', action='store_false') + parser.set_defaults(compile=True) + parser.add_argument('--no-run', help='don\'t run the compiled executable', + dest='run', action='store_false') + parser.add_argument('-v', '--verbose', help='print more diagnotic messages.', + action='store_true') + parser.add_argument('--no-error-cmdline', + help='don\'t display the subprocess\'s commandline when ' + 'an error occurs', dest='error_cmdline', + action='store_false') + parser.add_argument('-p', '--print-cmd', + help='print the commands that are run.', + action='store_true') + parser.add_argument('file', help='wast file.') + options = parser.parse_args(args) + + with utils.TempDirectory(options.out_dir, 'run-spec-wasm2c-') as out_dir: + # Parse JSON file and generate main .c file with calls to test functions. + wast2json = utils.Executable( + find_exe.GetWast2JsonExecutable(options.bindir), + error_cmdline=options.error_cmdline) + wast2json.AppendOptionalArgs({'-v': options.verbose}) + + json_file_path = utils.ChangeDir( + utils.ChangeExt(options.file, '.json'), out_dir) + wast2json.RunWithArgs(options.file, '-o', json_file_path) + + wasm2c = utils.Executable( + find_exe.GetWasm2CExecutable(options.bindir), + error_cmdline=options.error_cmdline) + + cc = utils.Executable(options.cc, *options.cflags) + + with open(json_file_path) as json_file: + spec_json = json.load(json_file) + + prefix = '' + if options.prefix: + with open(options.prefix) as prefix_file: + prefix = prefix_file.read() + '\n' + + output = StringIO() + cwriter = CWriter(spec_json, prefix, output, out_dir) + cwriter.Write() + + main_filename = utils.ChangeExt(json_file_path, '-main.c') + with open(main_filename, 'w') as out_main_file: + out_main_file.write(output.getvalue()) + + o_filenames = [] + includes = '-I%s' % options.wasmrt_dir + + # Compile wasm-rt-impl. + wasm_rt_impl_c = os.path.join(options.wasmrt_dir, 'wasm-rt-impl.c') + o_filenames.append(Compile(cc, wasm_rt_impl_c, out_dir, includes)) + + for i, wasm_filename in enumerate(cwriter.GetModuleFilenames()): + c_filename = utils.ChangeExt(wasm_filename, '.c') + wasm2c.RunWithArgs(wasm_filename, '-o', c_filename, cwd=out_dir) + if options.compile: + defines = '-DWASM_RT_MODULE_PREFIX=%s' % cwriter.GetModulePrefix(i) + o_filenames.append(Compile(cc, c_filename, out_dir, includes, defines)) + + if options.compile: + main_c = os.path.basename(main_filename) + o_filenames.append(Compile(cc, main_c, out_dir, includes, defines)) + main_exe = os.path.basename(utils.ChangeExt(json_file_path, '')) + Link(cc, o_filenames, main_exe, out_dir, '-lm') + + if options.compile and options.run: + utils.Executable(os.path.join(out_dir, main_exe), + forward_stdout=True).RunWithArgs() + + return 0 if __name__ == '__main__': - try: - sys.exit(main(sys.argv[1:])) - except Error as e: - # TODO(binji): gcc will output unicode quotes in errors since the terminal - # environment allows it, but python2 stderr will always attempt to convert - # to ascii first, which fails. This will replace the invalid characters - # instead, which is ugly, but works. - sys.stderr.write(u'{0}\n'.format(e).encode('ascii', 'replace')) - sys.exit(1) + try: + sys.exit(main(sys.argv[1:])) + except Error as e: + # TODO(binji): gcc will output unicode quotes in errors since the terminal + # environment allows it, but python2 stderr will always attempt to convert + # to ascii first, which fails. This will replace the invalid characters + # instead, which is ugly, but works. + sys.stderr.write(u'{0}\n'.format(e).encode('ascii', 'replace')) + sys.exit(1) |