diff --git a/src/tools/wasm2wat.cc b/src/tools/wasm2wat.cc index 58e89849fe..85a1570965 100644 --- a/src/tools/wasm2wat.cc +++ b/src/tools/wasm2wat.cc @@ -38,8 +38,10 @@ static int s_verbose; static std::string s_infile; static std::string s_outfile; static Features s_features; -static WriteWatOptions s_write_wat_options; -static bool s_generate_names = false; +static bool s_generate_names; +static bool s_fold_exprs; +static bool s_inline_import; +static bool s_inline_export; static bool s_read_debug_names = true; static bool s_fail_on_custom_section_error = true; static std::unique_ptr s_log_stream; @@ -72,12 +74,12 @@ static void ParseOptions(int argc, char** argv) { ConvertBackslashToSlash(&s_outfile); }); parser.AddOption('f', "fold-exprs", "Write folded expressions where possible", - []() { s_write_wat_options.fold_exprs = true; }); + []() { s_fold_exprs = true; }); s_features.AddOptions(&parser); parser.AddOption("inline-exports", "Write all exports inline", - []() { s_write_wat_options.inline_export = true; }); + []() { s_inline_export = true; }); parser.AddOption("inline-imports", "Write all imports inline", - []() { s_write_wat_options.inline_import = true; }); + []() { s_inline_import = true; }); parser.AddOption("no-debug-names", "Ignore debug names in the binary file", []() { s_read_debug_names = false; }); parser.AddOption("ignore-custom-section-errors", @@ -132,9 +134,13 @@ int ProgramMain(int argc, char** argv) { } if (Succeeded(result)) { + WriteWatOptions wat_options(s_features); + wat_options.fold_exprs = s_fold_exprs; + wat_options.inline_import = s_inline_import; + wat_options.inline_export = s_inline_export; FileStream stream(!s_outfile.empty() ? FileStream(s_outfile) : FileStream(stdout)); - result = WriteWat(&stream, &module, s_write_wat_options); + result = WriteWat(&stream, &module, wat_options); } } FormatErrorsToFile(errors, Location::Type::Binary); diff --git a/src/tools/wat-desugar.cc b/src/tools/wat-desugar.cc index cc6a2cba8e..a11e227607 100644 --- a/src/tools/wat-desugar.cc +++ b/src/tools/wat-desugar.cc @@ -37,9 +37,11 @@ using namespace wabt; static const char* s_infile; static const char* s_outfile; -static WriteWatOptions s_write_wat_options; -static bool s_generate_names; static bool s_debug_parsing; +static bool s_fold_exprs; +static bool s_generate_names; +static bool s_inline_import; +static bool s_inline_export; static Features s_features; static const char s_description[] = @@ -64,11 +66,11 @@ static void ParseOptions(int argc, char** argv) { parser.AddOption("debug-parser", "Turn on debugging the parser of wat files", []() { s_debug_parsing = true; }); parser.AddOption('f', "fold-exprs", "Write folded expressions where possible", - []() { s_write_wat_options.fold_exprs = true; }); + []() { s_fold_exprs = true; }); parser.AddOption("inline-exports", "Write all exports inline", - []() { s_write_wat_options.inline_export = true; }); + []() { s_inline_export = true; }); parser.AddOption("inline-imports", "Write all imports inline", - []() { s_write_wat_options.inline_import = true; }); + []() { s_inline_import = true; }); s_features.AddOptions(&parser); parser.AddOption( "generate-names", @@ -115,8 +117,12 @@ int ProgramMain(int argc, char** argv) { } if (Succeeded(result)) { + WriteWatOptions wat_options(s_features); + wat_options.fold_exprs = s_fold_exprs; + wat_options.inline_import = s_inline_import; + wat_options.inline_export = s_inline_export; FileStream stream(s_outfile ? FileStream(s_outfile) : FileStream(stdout)); - result = WriteWat(&stream, module, s_write_wat_options); + result = WriteWat(&stream, module, wat_options); } } diff --git a/src/wast-parser.cc b/src/wast-parser.cc index fde32e50f5..3abac6038b 100644 --- a/src/wast-parser.cc +++ b/src/wast-parser.cc @@ -1195,13 +1195,36 @@ Result WastParser::ParseElemModuleField(Module* module) { Result WastParser::ParseEventModuleField(Module* module) { WABT_TRACE(ParseEventModuleField); EXPECT(Lpar); - auto field = MakeUnique(GetLocation()); + Location loc = GetLocation(); EXPECT(Event); - ParseBindVarOpt(&field->event.name); - CHECK_RESULT(ParseTypeUseOpt(&field->event.decl)); - CHECK_RESULT(ParseUnboundFuncSignature(&field->event.decl.sig)); + + std::string name; + ParseBindVarOpt(&name); + + ModuleFieldList export_fields; + CHECK_RESULT(ParseInlineExports(&export_fields, ExternalKind::Event)); + + if (PeekMatchLpar(TokenType::Import)) { + CheckImportOrdering(module); + auto import = MakeUnique(name); + Event& event = import->event; + CHECK_RESULT(ParseInlineImport(import.get())); + CHECK_RESULT(ParseTypeUseOpt(&event.decl)); + CHECK_RESULT(ParseUnboundFuncSignature(&event.decl.sig)); + CHECK_RESULT(ErrorIfLpar({"type", "param", "result"})); + auto field = + MakeUnique(std::move(import), GetLocation()); + module->AppendField(std::move(field)); + } else { + auto field = MakeUnique(loc, name); + CHECK_RESULT(ParseTypeUseOpt(&field->event.decl)); + CHECK_RESULT(ParseUnboundFuncSignature(&field->event.decl.sig)); + module->AppendField(std::move(field)); + } + + AppendInlineExportFields(module, &export_fields, module->events.size() - 1); + EXPECT(Rpar); - module->AppendField(std::move(field)); return Result::Ok; } diff --git a/src/wat-writer.cc b/src/wat-writer.cc index 93ac48865a..4266f99df0 100644 --- a/src/wat-writer.cc +++ b/src/wat-writer.cc @@ -1380,7 +1380,13 @@ void WatWriter::WriteTable(const Table& table) { void WatWriter::WriteElemSegment(const ElemSegment& segment) { WriteOpenSpace("elem"); - WriteNameOrIndex(segment.name, elem_segment_index_, NextChar::Space); + // The name there pre-bulk-memory was intended to refer to the table + // so don't write the segment name unless bulk memory is enabled. + if (options_.features.bulk_memory_enabled()) { + WriteNameOrIndex(segment.name, elem_segment_index_, NextChar::Space); + } else { + Writef("(;%u;)", elem_segment_index_); + } uint8_t flags = segment.GetFlags(&module); diff --git a/src/wat-writer.h b/src/wat-writer.h index ec8a3eeb71..31748bf83c 100644 --- a/src/wat-writer.h +++ b/src/wat-writer.h @@ -18,6 +18,7 @@ #define WABT_WAT_WRITER_H_ #include "src/common.h" +#include "src/feature.h" namespace wabt { @@ -25,6 +26,9 @@ struct Module; class Stream; struct WriteWatOptions { + WriteWatOptions() = default; + WriteWatOptions(const Features& features) : features(features) {} + Features features; bool fold_exprs = false; // Write folded expressions. bool inline_export = false; bool inline_import = false; diff --git a/test/roundtrip/apply-global-names.txt b/test/roundtrip/apply-global-names.txt index 2d9c1492bf..61e9475017 100644 --- a/test/roundtrip/apply-global-names.txt +++ b/test/roundtrip/apply-global-names.txt @@ -18,6 +18,6 @@ (table $T0 1 funcref) (memory $M0 1) (global $g1 i32 (global.get $m.g)) - (elem $e0 (global.get $m.g) func $f0) + (elem (;0;) (global.get $m.g) func $f0) (data $d0 (global.get $m.g) "hi")) ;;; STDOUT ;;) diff --git a/test/roundtrip/generate-func-names.txt b/test/roundtrip/generate-func-names.txt index ef6d8a8e54..a835b02bcc 100644 --- a/test/roundtrip/generate-func-names.txt +++ b/test/roundtrip/generate-func-names.txt @@ -18,5 +18,5 @@ (table $T0 3 3 funcref) (export "zero" (func $zero)) (export "one" (func $one)) - (elem $e0 (i32.const 0) func $zero $one $zero)) + (elem (;0;) (i32.const 0) func $zero $one $zero)) ;;; STDOUT ;;) diff --git a/test/roundtrip/generate-func-type-names.txt b/test/roundtrip/generate-func-type-names.txt index 998dd3cbe8..e0d81a7065 100644 --- a/test/roundtrip/generate-func-type-names.txt +++ b/test/roundtrip/generate-func-type-names.txt @@ -21,5 +21,5 @@ call_indirect $T0 (type $t0) i32.const 1) (table $T0 1 1 funcref) - (elem $e0 (i32.const 0) func $foo.bar)) + (elem (;0;) (i32.const 0) func $foo.bar)) ;;; STDOUT ;;) diff --git a/test/roundtrip/generate-some-names.txt b/test/roundtrip/generate-some-names.txt index f62d45cb20..3816663231 100644 --- a/test/roundtrip/generate-some-names.txt +++ b/test/roundtrip/generate-some-names.txt @@ -54,5 +54,5 @@ (table $T0 1 1 funcref) (export "baz" (func $import)) (export "quux" (func $func0)) - (elem $e0 (i32.const 0) func $import)) + (elem (;0;) (i32.const 0) func $import)) ;;; STDOUT ;;) diff --git a/test/roundtrip/inline-export-func.txt b/test/roundtrip/inline-export-func.txt index 4fe3964e70..917b8c099c 100644 --- a/test/roundtrip/inline-export-func.txt +++ b/test/roundtrip/inline-export-func.txt @@ -1,12 +1,12 @@ ;;; TOOL: run-roundtrip ;;; ARGS: --stdout --inline-export (module - (func $foo + (func $foo (param i32) nop) (export "foo" (func $foo))) (;; STDOUT ;;; (module - (type (;0;) (func)) - (func (;0;) (export "foo") (type 0) + (type (;0;) (func (param i32))) + (func (;0;) (export "foo") (type 0) (param i32) nop)) ;;; STDOUT ;;) diff --git a/test/run-roundtrip.py b/test/run-roundtrip.py index 8aef6f5511..99bc6bb755 100755 --- a/test/run-roundtrip.py +++ b/test/run-roundtrip.py @@ -55,11 +55,11 @@ def FilesAreEqual(filename1, filename2, verbose=False): return (OK, '') -def TwoRoundtrips(wat2wasm, wasm2wat, out_dir, filename, verbose): +def DoRoundtrip(wat2wasm, wasm2wat, out_dir, filename, verbose, stdout): basename = os.path.basename(filename) basename_noext = os.path.splitext(basename)[0] wasm1_file = os.path.join(out_dir, basename_noext + '-1.wasm') - wast2_file = os.path.join(out_dir, basename_noext + '-2.wast') + wat2_file = os.path.join(out_dir, basename_noext + '-2.wat') wasm3_file = os.path.join(out_dir, basename_noext + '-3.wasm') try: wat2wasm.RunWithArgs('-o', wasm1_file, filename) @@ -68,28 +68,16 @@ def TwoRoundtrips(wat2wasm, wasm2wat, out_dir, filename, verbose): # test) return (SKIPPED, None) try: - wasm2wat.RunWithArgs('-o', wast2_file, wasm1_file) - wat2wasm.RunWithArgs('-o', wasm3_file, wast2_file) + wasm2wat.RunWithArgs('-o', wat2_file, wasm1_file) + wat2wasm.RunWithArgs('-o', wasm3_file, wat2_file) except Error as e: return (ERROR, str(e)) - return FilesAreEqual(wasm1_file, wasm3_file, verbose) - - -def OneRoundtripToStdout(wat2wasm, wasm2wat, out_dir, filename, verbose): - basename = os.path.basename(filename) - basename_noext = os.path.splitext(basename)[0] - wasm_file = os.path.join(out_dir, basename_noext + '.wasm') - try: - wat2wasm.RunWithArgs('-o', wasm_file, filename) - except Error: - # if the file doesn't parse properly, just skip it (it may be a "bad-*" - # test) - return (SKIPPED, None) - try: - wasm2wat.RunWithArgs(wasm_file) - except Error as e: - return (ERROR, str(e)) - return (OK, '') + if stdout: + with open(wat2_file) as f: + sys.stdout.write(f.read()) + return (OK, '') + else: + return FilesAreEqual(wasm1_file, wasm3_file, verbose) def main(args): @@ -102,7 +90,7 @@ def main(args): default=find_exe.GetDefaultPath(), help='directory to search for all executables.') parser.add_argument('--stdout', action='store_true', - help='do one roundtrip and write wast output to stdout') + help='do one roundtrip and write wat output to stdout') parser.add_argument('--no-error-cmdline', help='don\'t display the subprocess\'s commandline when ' 'an error occurs', dest='error_cmdline', @@ -182,12 +170,8 @@ def main(args): return ERROR with utils.TempDirectory(options.out_dir, 'roundtrip-') as out_dir: - if options.stdout: - result, msg = OneRoundtripToStdout(wat2wasm, wasm2wat, out_dir, - filename, options.verbose) - else: - result, msg = TwoRoundtrips(wat2wasm, wasm2wat, out_dir, filename, - options.verbose) + result, msg = DoRoundtrip(wat2wasm, wasm2wat, out_dir, filename, + options.verbose, options.stdout) if result == ERROR: sys.stderr.write(msg) return result