diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/emscripten-exported.json | 230 | ||||
-rw-r--r-- | src/emscripten-helpers.cc | 237 | ||||
-rw-r--r-- | src/source-error-handler.cc | 13 | ||||
-rw-r--r-- | src/source-error-handler.h | 20 | ||||
-rw-r--r-- | src/wabt.js | 1064 |
5 files changed, 346 insertions, 1218 deletions
diff --git a/src/emscripten-exported.json b/src/emscripten-exported.json index 43f4dff1..35f19bbf 100644 --- a/src/emscripten-exported.json +++ b/src/emscripten-exported.json @@ -1,223 +1,23 @@ -["_wabt_append_element", -"_wabt_append_host_module", -"_wabt_append_implicit_func_type", -"_wabt_append_module_field", -"_wabt_apply_names", -"_wabt_ast_format_error", -"_wabt_ast_lexer_get_source_line", -"_wabt_ast_lexer_lex", -"_wabt_ast_parser_error", -"_wabt_ast_parser_parse", -"_wabt_call_host", -"_wabt_close_file_writer", -"_wabt_close_mem_writer", -"_wabt_default_binary_error_callback", -"_wabt_default_source_error_callback", -"_wabt_destroy_action", +[ "_wabt_destroy_ast_lexer", -"_wabt_destroy_binding_hash", -"_wabt_destroy_block", -"_wabt_destroy_command", -"_wabt_destroy_command_vector_and_elements", -"_wabt_destroy_data_segment", -"_wabt_destroy_elem_segment", -"_wabt_destroy_export", -"_wabt_destroy_exported_func", -"_wabt_destroy_exported_memory", -"_wabt_destroy_exported_table", -"_wabt_destroy_expr", -"_wabt_destroy_expr_list", -"_wabt_destroy_func", -"_wabt_destroy_func_declaration", -"_wabt_destroy_func_fields", -"_wabt_destroy_func_signature", -"_wabt_destroy_func_type", -"_wabt_destroy_global", -"_wabt_destroy_import", -"_wabt_destroy_interpreter_environment", -"_wabt_destroy_interpreter_thread", -"_wabt_destroy_memory", -"_wabt_destroy_module", -"_wabt_destroy_optional_export", +"_wabt_destroy_parse_ast_result", "_wabt_destroy_output_buffer", -"_wabt_destroy_raw_module", -"_wabt_destroy_reloc_section", "_wabt_destroy_script", -"_wabt_destroy_string_slice", -"_wabt_destroy_table", -"_wabt_destroy_text_list", -"_wabt_destroy_var", -"_wabt_destroy_var_vector_and_elements", -"_wabt_disassemble", -"_wabt_disassemble_module", -"_wabt_empty_string_slice", -"_wabt_ensure_capacity", -"_wabt_extend_elements", -"_wabt_find_binding_index_by_name", -"_wabt_find_duplicate_bindings", -"_wabt_func_signatures_are_equal", -"_wabt_generate_names", -"_wabt_get_export_by_name", -"_wabt_get_first_module", -"_wabt_get_func_by_var", -"_wabt_get_func_index_by_var", -"_wabt_get_func_type_by_var", -"_wabt_get_func_type_index_by_decl", -"_wabt_get_func_type_index_by_sig", -"_wabt_get_func_type_index_by_var", -"_wabt_get_global_by_var", -"_wabt_get_global_index_by_var", -"_wabt_get_index_from_var", -"_wabt_get_interpreter_export_by_name", -"_wabt_get_local_index_by_var", -"_wabt_get_memory_by_var", -"_wabt_get_memory_index_by_var", -"_wabt_get_module_by_var", -"_wabt_get_module_index_by_var", -"_wabt_get_opcode_alignment", -"_wabt_get_table_by_var", -"_wabt_get_table_index_by_var", -"_wabt_hash_entry_is_free", -"_wabt_init_file_stream_from_existing", -"_wabt_init_file_writer", -"_wabt_init_file_writer_existing", -"_wabt_init_interpreter_environment", -"_wabt_init_interpreter_thread", -"_wabt_init_mem_writer", -"_wabt_init_mem_writer_existing", -"_wabt_init_output_buffer", -"_wabt_init_stderr_stream", -"_wabt_init_stdio", -"_wabt_init_stdout_stream", -"_wabt_init_stream", -"_wabt_insert_binding", -"_wabt_is_nan_f32", -"_wabt_is_nan_f64", -"_wabt_is_naturally_aligned", -"_wabt_make_type_binding_reverse_mapping", -"_wabt_mark_interpreter_environment", -"_wabt_move_data", +"_wabt_destroy_source_error_handler_buffer", +"_wabt_destroy_write_binary_module_result", "_wabt_new_ast_buffer_lexer", -"_wabt_new_ast_file_lexer", -"_wabt_new_binary_expr", -"_wabt_new_block_expr", -"_wabt_new_br_expr", -"_wabt_new_br_if_expr", -"_wabt_new_br_table_expr", -"_wabt_new_call_expr", -"_wabt_new_call_indirect_expr", -"_wabt_new_compare_expr", -"_wabt_new_const_expr", -"_wabt_new_convert_expr", -"_wabt_new_current_memory_expr", -"_wabt_new_drop_expr", -"_wabt_new_empty_expr", -"_wabt_new_get_global_expr", -"_wabt_new_get_local_expr", -"_wabt_new_grow_memory_expr", -"_wabt_new_if_expr", -"_wabt_new_load_expr", -"_wabt_new_loop_expr", -"_wabt_new_nop_expr", -"_wabt_new_return_expr", -"_wabt_new_select_expr", -"_wabt_new_set_global_expr", -"_wabt_new_set_local_expr", -"_wabt_new_store_expr", -"_wabt_new_tee_local_expr", -"_wabt_new_unary_expr", -"_wabt_new_unreachable_expr", -"_wabt_offsetof_binary_error_handler_on_error", -"_wabt_offsetof_binary_error_handler_user_data", -"_wabt_offsetof_location_filename", -"_wabt_offsetof_location_first_column", -"_wabt_offsetof_location_last_column", -"_wabt_offsetof_location_line", -"_wabt_offsetof_memory_writer_base", -"_wabt_offsetof_memory_writer_buf", -"_wabt_offsetof_output_buffer_capacity", -"_wabt_offsetof_output_buffer_size", -"_wabt_offsetof_output_buffer_start", -"_wabt_offsetof_read_binary_options_read_debug_names", -"_wabt_offsetof_source_error_handler_on_error", -"_wabt_offsetof_source_error_handler_source_line_max_length", -"_wabt_offsetof_source_error_handler_user_data", -"_wabt_offsetof_stream_log_stream", -"_wabt_offsetof_stream_offset", -"_wabt_offsetof_stream_result", -"_wabt_offsetof_stream_writer", -"_wabt_offsetof_string_slice_length", -"_wabt_offsetof_string_slice_start", -"_wabt_offsetof_write_binary_options_canonicalize_lebs", -"_wabt_offsetof_write_binary_options_log_stream", -"_wabt_offsetof_write_binary_options_write_debug_names", -"_wabt_offsetof_writer_move_data", -"_wabt_offsetof_writer_write_data", +"_wabt_new_source_error_handler_buffer", +"_wabt_output_buffer_get_data", +"_wabt_output_buffer_get_size", "_wabt_parse_ast", -"_wabt_parse_double", -"_wabt_parse_float", -"_wabt_parse_hexdigit", -"_wabt_parse_int32", -"_wabt_parse_int64", -"_wabt_parse_options", -"_wabt_parse_uint64", -"_wabt_print_help", -"_wabt_push_thread_value", -"_wabt_read_binary", -"_wabt_read_binary_ast", -"_wabt_read_binary_interpreter", -"_wabt_read_file", -"_wabt_read_i32_leb128", -"_wabt_read_u32_leb128", -"_wabt_remove_binding", -"_wabt_reset_interpreter_environment_to_mark", -"_wabt_resize_vector", -"_wabt_resolve_names_module", +"_wabt_parse_ast_result_get_result", +"_wabt_parse_ast_result_release_script", "_wabt_resolve_names_script", -"_wabt_run_interpreter", -"_wabt_sizeof_binary_error_handler", -"_wabt_sizeof_location", -"_wabt_sizeof_memory_writer", -"_wabt_sizeof_module", -"_wabt_sizeof_output_buffer", -"_wabt_sizeof_read_binary_options", -"_wabt_sizeof_script", -"_wabt_sizeof_source_error_handler", -"_wabt_sizeof_stream", -"_wabt_sizeof_string_slice", -"_wabt_sizeof_write_binary_options", -"_wabt_sizeof_writer", -"_wabt_steal_mem_writer_output_buffer", -"_wabt_string_slice_eq_cstr", -"_wabt_string_slice_from_cstr", -"_wabt_string_slice_is_empty", -"_wabt_string_slice_startswith", -"_wabt_string_slices_are_equal", -"_wabt_trace_pc", -"_wabt_u32_leb128_length", +"_wabt_source_error_handler_buffer_get_data", +"_wabt_source_error_handler_buffer_get_size", "_wabt_validate_script", -"_wabt_visit_expr_list", -"_wabt_visit_func", -"_wabt_write_ast", "_wabt_write_binary_module", -"_wabt_write_binary_spec_script", -"_wabt_write_data", -"_wabt_write_data_at", -"_wabt_write_double_hex", -"_wabt_write_fixed_u32_leb128", -"_wabt_write_fixed_u32_leb128_at", -"_wabt_write_fixed_u32_leb128_raw", -"_wabt_write_float_hex", -"_wabt_write_i32_leb128", -"_wabt_write_limits", -"_wabt_write_memory_dump", -"_wabt_write_opcode", -"_wabt_write_output_buffer_to_file", -"_wabt_write_str", -"_wabt_write_type", -"_wabt_write_u32", -"_wabt_write_u32_leb128", -"_wabt_write_u32_leb128_at", -"_wabt_write_u64", -"_wabt_write_u8", -"_wabt_writef"] +"_wabt_write_binary_module_result_release_binary_output_buffer", +"_wabt_write_binary_module_result_release_log_output_buffer", +"_wabt_write_binary_module_result_get_result" +] diff --git a/src/emscripten-helpers.cc b/src/emscripten-helpers.cc index 4e8d92f6..e7e8e2fc 100644 --- a/src/emscripten-helpers.cc +++ b/src/emscripten-helpers.cc @@ -17,99 +17,164 @@ #ifndef WABT_EMSCRIPTEN_HELPERS_H_ #define WABT_EMSCRIPTEN_HELPERS_H_ -#include <stddef.h> +#include <cstddef> + +#include <memory> #include "ast.h" -#include "binary-reader.h" +#include "ast-lexer.h" +#include "ast-parser.h" #include "binary-writer.h" #include "common.h" +#include "resolve-names.h" +#include "source-error-handler.h" #include "stream.h" +#include "validator.h" #include "writer.h" -/* TODO(binji): it would be nicer to generate this as static data, but it's not - * currently easy to do. Maybe use LLVM's python bindings for this? */ - -#define DEFINE_SIZEOF(Name, name) \ - size_t wabt_sizeof_##name(void) { return sizeof(Name); } - -#define DEFINE_OFFSETOF(Name, name, member) \ - size_t wabt_offsetof_##name##_##member(void) { \ - return offsetof(Name, member); \ +struct WabtParseAstResult { + wabt::Result result; + std::unique_ptr<wabt::Script> script; +}; + +struct WabtWriteBinaryModuleResult { + wabt::Result result; + std::unique_ptr<wabt::OutputBuffer> binary_buffer; + std::unique_ptr<wabt::OutputBuffer> log_buffer; +}; + +extern "C" { + +wabt::AstLexer* wabt_new_ast_buffer_lexer(const char* filename, + const void* data, + size_t size) { + return wabt::new_ast_buffer_lexer(filename, data, size); +} + +WabtParseAstResult* wabt_parse_ast( + wabt::AstLexer* lexer, + wabt::SourceErrorHandlerBuffer* error_handler) { + WabtParseAstResult* result = new WabtParseAstResult(); + wabt::Script* script = nullptr; + result->result = wabt::parse_ast(lexer, &script, error_handler); + result->script.reset(script); + return result; + +} + +wabt::Result wabt_resolve_names_script( + wabt::AstLexer* lexer, + wabt::Script* script, + wabt::SourceErrorHandlerBuffer* error_handler) { + return resolve_names_script(lexer, script, error_handler); +} + +wabt::Result wabt_validate_script( + wabt::AstLexer* lexer, + wabt::Script* script, + wabt::SourceErrorHandlerBuffer* error_handler) { + return validate_script(lexer, script, error_handler); +} + +WabtWriteBinaryModuleResult* wabt_write_binary_module(wabt::Script* script, + int log, + int canonicalize_lebs, + int relocatable, + int write_debug_names) { + wabt::MemoryStream stream; + wabt::WriteBinaryOptions options; + options.log_stream = log ? &stream : nullptr; + options.canonicalize_lebs = canonicalize_lebs; + options.relocatable = relocatable; + options.write_debug_names = write_debug_names; + + wabt::MemoryWriter writer; + wabt::Module* module = wabt::get_first_module(script); + WabtWriteBinaryModuleResult* result = new WabtWriteBinaryModuleResult(); + result->result = write_binary_module(&writer, module, &options); + if (result->result == wabt::Result::Ok) { + result->binary_buffer = writer.ReleaseOutputBuffer(); + result->log_buffer = log ? stream.ReleaseOutputBuffer() : nullptr; } - -/* See http://stackoverflow.com/a/1872506 */ -#define CONCAT(a, b) CONCAT_(a, b) -#define CONCAT_(a, b) CONCAT__(a, b) -#define CONCAT__(a, b) a##b -#define FOREACH_1(m, S, s, x, ...) m(S, s, x) -#define FOREACH_2(m, S, s, x, ...) m(S, s, x) FOREACH_1(m, S, s, __VA_ARGS__) -#define FOREACH_3(m, S, s, x, ...) m(S, s, x) FOREACH_2(m, S, s, __VA_ARGS__) -#define FOREACH_4(m, S, s, x, ...) m(S, s, x) FOREACH_3(m, S, s, __VA_ARGS__) -#define FOREACH_5(m, S, s, x, ...) m(S, s, x) FOREACH_4(m, S, s, __VA_ARGS__) -#define FOREACH_6(m, S, s, x, ...) m(S, s, x) FOREACH_5(m, S, s, __VA_ARGS__) -#define FOREACH_7(m, S, s, x, ...) m(S, s, x) FOREACH_6(m, S, s, __VA_ARGS__) -#define FOREACH_8(m, S, s, x, ...) m(S, s, x) FOREACH_7(m, S, s, __VA_ARGS__) -#define NARG(...) NARG_(__VA_ARGS__, RSEQ_N()) -#define NARG_(...) ARG_N(__VA_ARGS__) -#define ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N -#define RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0 -#define FOREACH(m, S, s, ...) FOREACH_(NARG(__VA_ARGS__), m, S, s, __VA_ARGS__) -#define FOREACH_(N, m, S, s, ...) CONCAT(FOREACH_, N)(m, S, s, __VA_ARGS__) -#define DEFINE_STRUCT0(Name, name) DEFINE_SIZEOF(Name, name) -#define DEFINE_STRUCT(Name, name, ...) \ - DEFINE_SIZEOF(Name, name) \ - FOREACH(DEFINE_OFFSETOF, Name, name, __VA_ARGS__) - -WABT_EXTERN_C_BEGIN - -/* clang-format off */ -DEFINE_STRUCT( - WabtBinaryErrorHandler, binary_error_handler, - on_error, user_data) - -DEFINE_STRUCT( - WabtLocation, location, - filename, line, first_column, last_column) - -DEFINE_STRUCT( - WabtMemoryWriter, memory_writer, - base, buf) - -DEFINE_STRUCT0( - WabtModule, module) - -DEFINE_STRUCT( - WabtOutputBuffer, output_buffer, - start, size, capacity) - -DEFINE_STRUCT( - WabtReadBinaryOptions, read_binary_options, - read_debug_names) - -DEFINE_STRUCT0( - WabtScript, script) - -DEFINE_STRUCT( - WabtSourceErrorHandler, source_error_handler, - on_error, source_line_max_length, user_data) - -DEFINE_STRUCT( - WabtStream, stream, - writer, offset, result, log_stream) - -DEFINE_STRUCT( - WabtStringSlice, string_slice, - start, length) - -DEFINE_STRUCT( - WabtWriter, writer, - write_data, move_data) - -DEFINE_STRUCT( - WabtWriteBinaryOptions, write_binary_options, - log_stream, canonicalize_lebs, write_debug_names) -/* clang-format on */ - -WABT_EXTERN_C_END + return result; +} + +void wabt_destroy_script(wabt::Script* script) { + delete script; +} + +void wabt_destroy_ast_lexer(wabt::AstLexer* lexer) { + destroy_ast_lexer(lexer); +} + +// SourceErrorHandlerBuffer +wabt::SourceErrorHandlerBuffer* wabt_new_source_error_handler_buffer(void) { + return new wabt::SourceErrorHandlerBuffer(); +} + +const void* wabt_source_error_handler_buffer_get_data( + wabt::SourceErrorHandlerBuffer* error_handler) { + return error_handler->buffer().data(); +} + +size_t wabt_source_error_handler_buffer_get_size( + wabt::SourceErrorHandlerBuffer* error_handler) { + return error_handler->buffer().size(); +} + +void wabt_destroy_source_error_handler_buffer( + wabt::SourceErrorHandlerBuffer* error_handler) { + delete error_handler; +} + +// WabtParseAstResult +wabt::Result wabt_parse_ast_result_get_result(WabtParseAstResult* result) { + return result->result; +} + +wabt::Script* wabt_parse_ast_result_release_script(WabtParseAstResult* result) { + return result->script.release(); +} + +void wabt_destroy_parse_ast_result(WabtParseAstResult* result) { + delete result; +} + +// WabtWriteBinaryModuleResult +wabt::Result wabt_write_binary_module_result_get_result( + WabtWriteBinaryModuleResult* result) { + return result->result; +} + +wabt::OutputBuffer* +wabt_write_binary_module_result_release_binary_output_buffer( + WabtWriteBinaryModuleResult* result) { + return result->binary_buffer.release(); +} + +wabt::OutputBuffer* wabt_write_binary_module_result_release_log_output_buffer( + WabtWriteBinaryModuleResult* result) { + return result->log_buffer.release(); +} + +void wabt_destroy_write_binary_module_result( + WabtWriteBinaryModuleResult* result) { + delete result; +} + +// wabt::OutputBuffer* +const void* wabt_output_buffer_get_data(wabt::OutputBuffer* output_buffer) { + return output_buffer->data.data(); +} + +size_t wabt_output_buffer_get_size(wabt::OutputBuffer* output_buffer) { + return output_buffer->data.size(); +} + +void wabt_destroy_output_buffer(wabt::OutputBuffer* output_buffer) { + delete output_buffer; +} + +} // extern "C" #endif /* WABT_EMSCRIPTEN_HELPERS_H_ */ diff --git a/src/source-error-handler.cc b/src/source-error-handler.cc index 32976b77..87074ddc 100644 --- a/src/source-error-handler.cc +++ b/src/source-error-handler.cc @@ -82,4 +82,17 @@ void SourceErrorHandlerFile::PrintErrorHeader() { fprintf(file_, " "); } +SourceErrorHandlerBuffer::SourceErrorHandlerBuffer( + size_t source_line_max_length) + : source_line_max_length_(source_line_max_length) {} + +bool SourceErrorHandlerBuffer::OnError(const Location* loc, + const std::string& error, + const std::string& source_line, + size_t source_line_column_offset) { + buffer_ += + DefaultErrorMessage(loc, error, source_line, source_line_column_offset); + return true; +} + } // namespace wabt diff --git a/src/source-error-handler.h b/src/source-error-handler.h index eaa50300..7cac7fca 100644 --- a/src/source-error-handler.h +++ b/src/source-error-handler.h @@ -86,6 +86,26 @@ class SourceErrorHandlerFile : public SourceErrorHandler { size_t source_line_max_length_; }; +class SourceErrorHandlerBuffer : public SourceErrorHandler { + public: + explicit SourceErrorHandlerBuffer(size_t source_line_max_length = 80); + + bool OnError(const Location*, + const std::string& error, + const std::string& source_line, + size_t source_line_column_offset) override; + + size_t source_line_max_length() const override { + return source_line_max_length_; + } + + const std::string& buffer() const { return buffer_; } + + private: + size_t source_line_max_length_; + std::string buffer_; +}; + } // namespace wabt #endif // WABT_SOURCE_ERROR_HANDLER_H_ diff --git a/src/wabt.js b/src/wabt.js index 483d3ffc..7bbb00c7 100644 --- a/src/wabt.js +++ b/src/wabt.js @@ -14,46 +14,16 @@ * limitations under the License. */ -var wabt = {}; - -wabt.ready = new Promise(function(resolve, reject) { - wabt.$resolve = resolve; - wabt.$reject = reject; -}); - -var Module = {}; -Module.onRuntimeInitialized = function() { - -// Helpers ///////////////////////////////////////////////////////////////////// - -function loadi8(addr) { return HEAP8[addr]; } -function loadi16(addr) { return HEAP16[addr>>1]; } -function loadi32(addr) { return HEAP32[addr>>2]; } -function loadu8(addr) { return HEAPU8[addr]; } -function loadu16(addr) { return HEAPU16[addr>>1]; } -function loadu32(addr) { return HEAPU32[addr>>2]; } -function loadf32(addr) { return HEAPF32[addr>>2]; } -function loadf64(addr) { return HEAPF64[addr>>4]; } -function storei8(addr, value) { HEAP8[addr] = value; } -function storei16(addr, value) { HEAP16[addr>>1] = value; } -function storei32(addr, value) { HEAP32[addr>>2] = value; } -function storeu8(addr, value) { HEAPU8[addr] = value; } -function storeu16(addr, value) { HEAPU16[addr>>1] = value; } -function storeu32(addr, value) { HEAPU32[addr>>2] = value; } -function storef32(addr, value) { HEAPF32[addr>>2] = value; } -function storef64(addr, value) { HEAPF64[addr>>4] = value; } - -function loadcstr(addr) { return Module.AsciiToString(addr); } -function loadstrslice(addr, len) { return Module.Pointer_stringify(addr, len); } -function loadbuffer(addr, len) { - return new Uint8Array(HEAPU8.buffer, addr, len); -} +var wabt = wabt || {}; -function sizeof(structName) { return Module['_wabt_sizeof_' + structName](); } -function offsetof(structName, fieldName) { - return Module['_wabt_offsetof_' + structName + '_' + fieldName](); -} +(function (wabt) { + +"use strict"; +var WABT_OK = 0; +var WABT_ERROR = 1; + +/// Allocate memory in the Module. function malloc(size) { var addr = Module._malloc(size); if (addr == 0) { @@ -62,450 +32,9 @@ function malloc(size) { return addr; } -function mallocz(size) { - var addr = malloc(size); - HEAPU8.fill(0, addr, addr + size); - return addr; -} - -function free(addr) { Module._free(addr); } - -// Types /////////////////////////////////////////////////////////////////////// - -function Type(name, id) { - this.name = name; - if (id) { - // alias - this.id = id; - } else { - this.id = Type.id++; - Type.map[this.id] = this; - } -} -Type.id = 0; -Type.map = {}; -Type.check = function(expected, actual) { - if (actual.id != expected.id) { - throw new Error('type mismatch; expected ' + expected.toString() + - ', got ' + actual.toString()); - } -}; -Type.prototype = Object.create(Object.prototype); -Type.prototype.toString = function(name, lastPrec) { - var result = '' - if (this.name) { - result = this.name; - if (name) { - result += ' ' + name; - } - return result; - } - name = name || ''; - var prec = this.prec; - - if (prec && lastPrec && prec > lastPrec) { - name = '(' + name + ')'; - } - - if (this.kind == 'ptr') { - return this.pointee.toString('*' + result + name, prec); - } else if (this.kind == 'array') { - return this.element.toString(result + '[]', prec); - } else if (this.kind == 'fn') { - name += '('; - if (this.params.length > 0) { - var paramNames = []; - for (var i = 0; i < this.params.length; ++i) { - paramNames.push(this.params[i].toString()); - } - name += paramNames.join(', '); - } - name += ')'; - return this.result.toString(name, prec); - } else { - throw new Error('unknown type kind'); - } -}; -Type.prototype.load = function() { - throw new Error(this.toString() + " cannot be loaded"); -}; -Type.prototype.store = function() { - throw new Error(this.toString() + " cannot be stored"); -}; -Type.prototype.call = function() { - throw new Error(this.toString() + " cannot be called"); -}; - -function PrimitiveType(name, size, sig, min, max) { - Type.call(this, name); - this.size = size; - this.sig = sig; - this.min = min; - this.max = max; -} -PrimitiveType.prototype = Object.create(Type.prototype); -PrimitiveType.prototype.kind = 'primitive' -PrimitiveType.prototype.primitive = true; -PrimitiveType.prototype.checkRange = function(value) { - if (value < this.min || value > this.max) { - throw new Error('value out of range: ' + value + ' not in [' + this.min + ',' + - this.max + ']'); - } -}; -PrimitiveType.prototype.toJS = function(value) { - return value; -}; -PrimitiveType.prototype.initAccessors = function(value, addr) { - var type = this; - value.load = function() { return type.toJS(type.load(addr)); }; - value.store = function(value) { type.store(addr, type.fromJS(value)); }; -}; - -// TODO(binji): figure out what the signature chars actually are -var Void = new PrimitiveType('Void', 0, 'v'); -var Bool = new PrimitiveType('Bool', 1, 'i'); -var I8 = new PrimitiveType('I8', 1, 'i', -128, 127); -var I16 = new PrimitiveType('I16', 2, 'i', -32768, 32767); -var I32 = new PrimitiveType('I32', 4, 'i', -0x80000000, 0x7fffffff); -var U8 = new PrimitiveType('U8', 1, 'i', 0, 255); -var U16 = new PrimitiveType('U16', 2, 'i', 0, 65535); -var U32 = new PrimitiveType('U32', 4, 'i', 0, 0xffffffff); -var U64 = new PrimitiveType('U64', 8, 'i'); -var F32 = new PrimitiveType('F32', 4, 'f'); -var F64 = new PrimitiveType('F64', 8, 'd'); - -Void.fromJS = function(value) {} -Bool.fromJS = function(value) { return !!value; }; -I8.fromJS = function(value) { this.checkRange(value); return value|0; }; -I16.fromJS = function(value) { this.checkRange(value); return value|0; }; -I32.fromJS = function(value) { this.checkRange(value); return value|0; }; -U8.fromJS = function(value) { this.checkRange(value); return value>>>0; }; -U16.fromJS = function(value) { this.checkRange(value); return value>>>0; }; -U32.fromJS = function(value) { this.checkRange(value); return value>>>0; }; -U64.fromJS = function(value) { throw new Error('u64 not yet supported'); }; -F32.fromJS = function(value) { return Math.fround(value); }; -F64.fromJS = function(value) { return +value; }; - -Bool.toJS = function(value) { return value ? true : false; }; - -Bool.load = function(addr) { return loadu8(addr); }; -I8.load = function(addr) { return loadi8(addr); }; -I16.load = function(addr) { return loadi16(addr); }; -I32.load = function(addr) { return loadi32(addr); }; -U8.load = function(addr) { return loadu8(addr); }; -U16.load = function(addr) { return loadu16(addr); }; -U32.load = function(addr) { return loadu32(addr); }; -U64.load = function(addr) { throw new Error('u64 not yet supported'); }; -F32.load = function(addr) { return loadf32(addr); }; -F64.load = function(addr) { return loadf64(addr); }; - -Bool.store = function(addr, value) { return storeu8(addr, value); }; -I8.store = function(addr, value) { return storei8(addr, value); }; -I16.store = function(addr, value) { return storei16(addr, value); }; -I32.store = function(addr, value) { return storei32(addr, value); }; -U8.store = function(addr, value) { return storeu8(addr, value); }; -U16.store = function(addr, value) { return storeu16(addr, value); }; -U32.store = function(addr, value) { return storeu32(addr, value); }; -U64.store = function(addr, value) { throw new Error('u64 not yet supported'); }; -F32.store = function(addr, value) { return storef32(addr, value); }; -F64.store = function(addr, value) { return storef64(addr, value); }; - -function Alias(name, type) { - var alias = Object.create(type); - alias.name = name; - return alias; -} - -function PtrType(type) { - Type.call(this); - this.pointee = type; -} -PtrType.map = {}; -PtrType.prototype = Object.create(Type.prototype); -PtrType.prototype.kind = 'ptr'; -PtrType.prototype.prec = 1; -PtrType.prototype.primitive = true; -PtrType.prototype.sig = 'i' -PtrType.prototype.size = 4; -PtrType.prototype.fromJS = function(value) { - if (value === null) { - return 0; - } - Value.$check(value); - Type.check(this, value.$ptrType); - return value.$addr; -}; -PtrType.prototype.toJS = function(value) { - if (value == 0) { - return null; - } - return new Value(this.pointee, value); -}; -PtrType.prototype.initAccessors = function(value, addr) { - var type = this; - value.load = function() { return type.toJS(loadu32(addr)); }; - value.store = function(value) { storeu32(addr, type.fromJS(value)); }; -}; - -function Ptr(type) { - if (type.id in PtrType.map) { - return PtrType.map[type.id]; - } - var result = new PtrType(type); - PtrType.map[type.id] = result; - return result; -} - -var VoidPtr = Ptr(Void); -var ArrayLen = Alias('ArrayLen', U32); -var BufLen = Alias('BufLen', U32); -var BufPtr = Alias('BufPtr', VoidPtr); -var Str = Alias('Str', Ptr(U8)); -var StrLen = Alias('StrLen', U32); -var StrPtr = Alias('StrPtr', Ptr(U8)); -var UserData = Alias('UserData', VoidPtr); - -Str.toJS = function(addr) { return loadcstr(addr); }; -Str.initAccessors = function(value, addr) { - value.load = function() { return loadcstr(loadu32(addr)); } -}; - -function ArrayType(type) { - Type.call(this); - this.element = type; -} -ArrayType.map = {}; -ArrayType.prototype = Object.create(Type.prototype); -ArrayType.prototype.kind = 'ptr'; -ArrayType.prototype.prec = 2; -ArrayType.prototype.primitive = true; -ArrayType.prototype.sig = 'i' -ArrayType.prototype.size = 4; -ArrayType.prototype.initAccessors = function(value, arrayAddr) { - var type = this; - value.index = function(index) { - return new Value(type.element, arrayAddr + index * type.element.size); - }; -}; - -function ArrayPtr(type) { - if (type.id in ArrayType.map) { - return ArrayType.map[type.id]; - } - var result = new ArrayType(type); - ArrayType.map[type.id] = result; - return result; -} - -function FnType(result, params) { - if (!result.primitive) { - throw new Error(result.toString() + " is not a primitive type"); - } - for (var i = 0; i < params.length; ++i) { - var param = params[i]; - if (!param.primitive) { - throw new Error(param.toString() + " is not a primitive type"); - } - } - Type.call(this); - this.result = result; - this.params = params; - this.funcSig = this.generateSig(); -} -FnType.generateKey = function(result, params) { - var key = result.id + ','; - for (var i = 0; i < params.length; ++i) { - key += params[i].id + ','; - } - return key; -}; -FnType.map = {}; -FnType.prototype = Object.create(Type.prototype); -FnType.prototype.kind = 'fn'; -FnType.prototype.prec = 3; -FnType.prototype.primitive = true; -FnType.prototype.sig = 'i' -FnType.prototype.size = 4; -FnType.prototype.generateSig = function() { - var result = this.result.sig; - for (var i = 0; i < this.params.length; ++i) { - result += this.params[i].sig; - } - return result; -}; -FnType.prototype.argsFromJS = function(inArgs) { - if (inArgs.length != this.params.length) { - throw new Error("argument count mismatch: expecting " + this.params.length + - ", got " + inArgs.length); - } - var outArgs = []; - for (var i = 0; i < inArgs.length; ++i) { - outArgs.push(this.params[i].fromJS(inArgs[i])); - } - return outArgs; -}; -FnType.prototype.argsToJS = function(inArgs) { - var outArgs = []; - for (var i = 0; i < inArgs.length; ++i) { - outArgs.push(this.params[i].toJS(inArgs[i])); - } - return outArgs; -}; -FnType.prototype.define = function(name) { - var type = this; - return function() { - var result = Module[name].apply(Module, type.argsFromJS(arguments)); - return type.result.toJS(result); - }; -}; -FnType.prototype.initAccessors = function(value, addr) { - var type = this; - value.load = function() { return new FnValue(type, loadu32(addr)); }; - value.store = function(value) { - if (!(value instanceof FnValue)) { - throw new Error('fn value ' + value + ' not instanceof FnValue'); - } - Type.check(type, value.$type); - return storeu32(addr, value.$index); - }; - value.call = function() { - var result = Runtime.dynCall(type.funcSig, loadu32(addr), - type.argsFromJS(arguments)); - return type.result.toJS(result); - }; -}; - -function Fn(result, params) { - var key = FnType.generateKey(result, params); - if (key in FnType.map) { - return FnType.map[key]; - } - var result = new FnType(result, params); - FnType.map[key] = result; - return result; -} - -function Field(name, type, offset) { - this.name = name; - this.type = type; - this.offset = offset; -} -Field.prototype = Object.create(Object.prototype); -Field.prototype.initAccessors = function(value, structAddr) { - value[this.name] = new Value(this.type, structAddr + this.offset); -}; - -function StructType(name) { - Type.call(this, name); - this.fields = {}; -} -StructType.prototype = Object.create(Type.prototype); -StructType.prototype.kind = 'struct'; -StructType.prototype.primitive = false; -StructType.prototype.define = function(cName, fieldTypes) { - this.cName = cName; - this.size = sizeof(cName); - for (fieldName in fieldTypes) { - var type = fieldTypes[fieldName]; - var offset = offsetof(cName, fieldName); - this.fields[fieldName] = new Field(fieldName, type, offset); - } -}; -StructType.prototype.describe = function() { - var result = 'struct ' + this.name + ' {\n'; - var lines = []; - for (fieldName in this.fields) { - var field = this.fields[fieldName]; - lines.push(' ' + field.type.toString(fieldName) + ';'); - } - result += lines.join('\n'); - result += '\n};'; - return result; -}; -StructType.prototype.initAccessors = function(value, addr) { - var type = this; - for (fieldName in this.fields) { - var field = this.fields[fieldName]; - field.initAccessors(value, addr); - } -}; - -function Struct(name) { - return new StructType(name); -} - -// Values ////////////////////////////////////////////////////////////////////// - -function Value(type, addr) { - this.$type = type; - this.$ptrType = Ptr(type); - this.$addr = addr; - type.initAccessors(this, this.$addr); -} -Value.$at = function(type, addr) { return new Value(type, addr); }; -Value.$malloc = function(type) { return new Value(type, mallocz(type.size)); }; -Value.$check = function(value) { - if (!(value instanceof Value)) { - throw new Error('value ' + value + ' not instanceof Value'); - } -}; -Value.prototype = Object.create(Object.prototype); -Value.prototype.toString = function() { - return '<' + this.$type + '>@' + this.$addr; -}; -Value.prototype.$free = function() { free(this.$addr); }; - -function FnValue(type, f) { - if (!(type instanceof FnType)) { - throw new Error('type ' + type + ' not instanceof FnType'); - } - this.$type = type; - if (typeof f == 'function') { - if (f.length != type.params.length) { - throw new Error("argument count mismatch: expecting " + type.params.length + - ", got " + f.length); - } - var wrapped = function() { - return type.result.fromJS(f.apply(null, type.argsToJS(arguments))); - }; - - this.$index = Runtime.addFunction(wrapped); - this.$owned = true; - } else { - // assume that if is the table index. - this.$index = f | 0; - this.$owned = false; - } -} -FnValue.prototype = Object.create(Object.prototype); -FnValue.prototype.toString = function() { - return '<' + this.type + '>@' + this.$index; -}; -FnValue.prototype.$destroy = function() { - if (this.$owned) { - Runtime.removeFunction(this.$index); - } -}; - -function StrValue(addr) { - Value.call(this, Str.pointee, addr); -} -StrValue.$at = function(addr) { return new StrValue(addr); } -StrValue.$mallocCStr = function(s) { - var addr = malloc(s.length + 1); - Module.writeAsciiToMemory(s, addr); - return new StrValue(addr); -} -StrValue.prototype = Object.create(Value.prototype); -StrValue.prototype.toString = function() { - return '<Str>@' + this.$addr; -}; - -function BufferValue(addr, size) { - Value.call(this, VoidPtr.pointee, addr); - this.size = size; -} -BufferValue.$malloc = function(buf) { +/// Convert an ArrayBuffer/TypedArray/string into a buffer that can be +/// used by the Module. +function allocateBuffer(buf) { var addr; var size; if (buf instanceof ArrayBuffer) { @@ -524,491 +53,192 @@ BufferValue.$malloc = function(buf) { } else { throw new Error('unknown buffer type: ' + buf); } - return new BufferValue(addr, size); -}; -BufferValue.prototype = Object.create(Value.prototype); -BufferValue.prototype.toString = function() { - return '<Buffer>@' + this.$addr + ', ' + this.size + ' bytes'; -}; - -// Wabt enums ////////////////////////////////////////////////////////////////// - -// WabtResult -var OK = 0; -var ERROR = 1; - -// Wabt low-level types //////////////////////////////////////////////////////// - -var I = (function() { - -var AstLexer = Struct('AstLexer'); -var BinaryErrorHandler = Struct('BinaryErrorHandler'); -var Location = Struct('Location'); -var MemoryWriter = Struct('MemoryWriter'); -var Module = Struct('Module'); -var OutputBuffer = Struct('OutputBuffer'); -var ReadBinaryOptions = Struct('ReadBinaryOptions'); -var Script = Struct('Script'); -var SourceErrorHandler = Struct('SourceErrorHandler'); -var Stream = Struct('Stream'); -var StrSlice = Struct('StrSlice'); -var WriteBinaryOptions = Struct('WriteBinaryOptions'); -var Writer = Struct('Writer'); - -var BinaryErrorHandlerCallback = Fn(Void, [U32, Str, UserData]); -var SourceErrorHandlerCallback = - Fn(Void, [Ptr(Location), Str, StrPtr, StrLen, U32, UserData]); - -BinaryErrorHandler.define('binary_error_handler', { - on_error: BinaryErrorHandlerCallback, - user_data: UserData, -}); - -Location.define('location', { - filename: Str, - line: U32, - first_column: U32, - last_column: U32, -}); - -MemoryWriter.define('memory_writer', { - base: Writer, - buf: OutputBuffer, -}); - -Module.define('module'); - -OutputBuffer.define('output_buffer', { - start: BufPtr, - size: BufLen, - capacity: U32, -}); - -ReadBinaryOptions.define('read_binary_options', { - read_debug_names: Bool, -}); - -Script.define('script'); - -SourceErrorHandler.define('source_error_handler', { - on_error: SourceErrorHandlerCallback, - source_line_max_length: U32, - user_data: UserData, -}); - -Stream.define('stream', { - writer: Ptr(Writer), - result: U32, - offset: U32, - log_stream: Ptr(Stream), -}); - -StrSlice.define('string_slice', { - start: StrPtr, - length: StrLen, -}); - -WriteBinaryOptions.define('write_binary_options', { - log_stream: Ptr(Stream), - canonicalize_lebs: Bool, - write_debug_names: Bool, -}); - -Writer.define('writer', { - write_data: Fn(I32, [U32, BufPtr, BufLen, UserData]), - move_data: Fn(I32, [U32, U32, U32, UserData]), -}); - -// Wabt low-level functions //////////////////////////////////////////////////// - -var closeMemWriter = Fn(Void, [Ptr(MemoryWriter)]).define('_wabt_close_mem_writer'); -var defaultBinaryErrorCallback = BinaryErrorHandlerCallback.define('_wabt_default_binary_error_callback'); -var defaultSourceErrorCallback = SourceErrorHandlerCallback.define('_wabt_default_source_error_callback'); -var destroyAstLexer = Fn(Void, [Ptr(AstLexer)]).define('_wabt_destroy_ast_lexer'); -var destroyOutputBuffer = Fn(Void, [Ptr(OutputBuffer)]).define('_wabt_destroy_output_buffer'); -var destroyScript = Fn(Void, [Ptr(Script)]).define('_wabt_destroy_script'); -var getFirstModule = Fn(Ptr(Module), [Ptr(Script)]).define('_wabt_get_first_module'); -var initMemWriter = Fn(I32, [Ptr(MemoryWriter)]).define('_wabt_init_mem_writer'); -var initStream = Fn(Void, [Ptr(Stream), Ptr(Writer), Ptr(Stream)]).define('_wabt_init_stream'); -var newAstBufferLexer = Fn(Ptr(AstLexer), [Str, BufPtr, BufLen]).define('_wabt_new_ast_buffer_lexer'); -var parseAst = Fn(I32, [Ptr(AstLexer), Ptr(Script), Ptr(SourceErrorHandler)]).define('_wabt_parse_ast'); -var resolveNamesScript = Fn(I32, [Ptr(AstLexer), Ptr(Script), Ptr(SourceErrorHandler)]).define('_wabt_resolve_names_script'); -var validateScript = Fn(I32, [Ptr(AstLexer), Ptr(Script), Ptr(SourceErrorHandler)]).define('_wabt_validate_script'); -var writeBinaryModule = Fn(I32, [Ptr(Writer), Ptr(Module), Ptr(WriteBinaryOptions)]).define('_wabt_write_binary_module'); - -return { - // Types - AstLexer: AstLexer, - BinaryErrorHandler: BinaryErrorHandler, - Location: Location, - MemoryWriter: MemoryWriter, - Module: Module, - OutputBuffer: OutputBuffer, - ReadBinaryOptions: ReadBinaryOptions, - Script: Script, - SourceErrorHandler: SourceErrorHandler, - Stream: Stream, - StrSlice: StrSlice, - WriteBinaryOptions: WriteBinaryOptions, - Writer: Writer, - - // Functions - closeMemWriter: closeMemWriter, - defaultBinaryErrorCallback: defaultBinaryErrorCallback, - defaultSourceErrorCallback: defaultSourceErrorCallback, - destroyAstLexer: destroyAstLexer, - destroyOutputBuffer: destroyOutputBuffer, - destroyScript: destroyScript, - getFirstModule: getFirstModule, - initMemWriter: initMemWriter, - initStream: initStream, - newAstBufferLexer: newAstBufferLexer, - parseAst: parseAst, - resolveNamesScript: resolveNamesScript, - validateScript: validateScript, - writeBinaryModule: writeBinaryModule, -}; - -})(); - -// Helpers for friendly objects //////////////////////////////////////////////// - -function define$From(obj) { - obj.$from = function($) { - var o = Object.create(obj.prototype); - o.$ = $; - return o; - }; + return {addr: addr, size: size}; } -function definePrimitiveGetter(proto, name, cName) { - cName = cName || name; - Object.defineProperty(proto, name, { - get: function() { return this.$[cName].load(); } - }); +function allocateCString(s) { + var size = s.length; + var addr = malloc(size); + Module.writeAsciiToMemory(s, addr); + return {addr: addr, size: size}; } -function definePrimitiveGetterSetter(proto, name, cName) { - cName = cName || name; - Object.defineProperty(proto, name, { - get: function() { return this.$[cName].load(); }, - set: function(value) { this.$[cName].store(value); }, - }); -} -function defineStrGetter(proto, name, cName) { - cName = cName || name; - Object.defineProperty(proto, name, { - get: function() { - return this.$[cName].load(); - } - }); +/// Lexer +function Lexer(filename, buffer) { + this.filenameObj = allocateCString(filename); + this.bufferObj = allocateBuffer(buffer); + this.addr = Module._wabt_new_ast_buffer_lexer( + this.filenameObj.addr, this.bufferObj.addr, this.bufferObj.size); } +Lexer.prototype = Object.create(Object.prototype); -// Get a StrSlice, given a pointer and length -function defineStrSliceGetter(proto, name, ptrName, lenName) { - Object.defineProperty(proto, name, { - get: function() { - var offset = this.$[ptrName].load(); - var length = this.$[lenName].load(); - return loadstrslice(offset.$addr, length); - } - }); -} +Lexer.prototype.destroy = function() { + Module._wabt_destroy_ast_lexer(this.addr); + Module._free(this.bufferObj.addr); + Module._free(this.filenameObj.addr); +}; -// Get a StrSlice, given a StrSlice object -function defineStrSliceObjGetter(proto, name, cName) { - cName = cName || name; - Object.defineProperty(proto, name, { - get: function() { - var offset = this.$[cName].start.load(); - var length = this.$[cName].length.load(); - return loadstrslice(offset.$addr, length); - } - }); -} -function defineBufferGetter(proto, name, ptrName, lenName) { - Object.defineProperty(proto, name, { - get: function() { - var offset = this.$[ptrName].load(); - var length = this.$[lenName].load(); - return loadbuffer(offset.$addr, length); - } - }); +/// OutputBuffer +function OutputBuffer(addr) { + this.addr = addr; } +OutputBuffer.prototype = Object.create(Object.prototype); -// Friendly objects //////////////////////////////////////////////////////////// +OutputBuffer.prototype.toTypedArray = function() { + if (!this.addr) { + return null; + } -// Writer -function Writer(writeData, moveData) { - this.$ = Value.$malloc(I.Writer); - this.$writeData = new FnValue(I.Writer.fields.write_data.type, writeData); - this.$moveData = new FnValue(I.Writer.fields.move_data.type, moveData); - this.$.write_data.store(this.$writeData); - this.$.move_data.store(this.$moveData); -} -define$From(Writer); -Writer.prototype = Object.create(Object.prototype); -Writer.prototype.$destroy = function() { - this.$moveData.$destroy(); - this.$writeData.$destroy(); - this.$.$free(); + var addr = Module._wabt_output_buffer_get_data(this.addr); + var size = Module._wabt_output_buffer_get_size(this.addr); + var buffer = new Uint8Array(size); + buffer.set(new Uint8Array(HEAPU8.buffer, addr, size)); + return buffer; }; -// MemoryWriter -function MemoryWriter() { - this.$ = Value.$malloc(I.MemoryWriter); - var result = I.initMemWriter(this.$); - if (result != OK) { - throw new Error('unable to initialize MemoryWriter'); +OutputBuffer.prototype.toString = function() { + if (!this.addr) { + return ''; } - this.writer = Writer.$from(this.$.base); - this.buf = OutputBuffer.$from(this.$.buf); -} -MemoryWriter.prototype = Object.create(MemoryWriter.prototype); -MemoryWriter.prototype.$destroy = function() { - I.closeMemWriter(this.$); - this.$.$free(); + + var addr = Module._wabt_output_buffer_get_data(this.addr); + var size = Module._wabt_output_buffer_get_size(this.addr); + return Module.Pointer_stringify(addr, size); }; -// OutputBuffer -function OutputBuffer() { - this.$ = null; -} -define$From(OutputBuffer); -OutputBuffer.prototype = Object.create(Object.prototype); -defineBufferGetter(OutputBuffer.prototype, 'buf', 'start', 'size'); -defineStrSliceGetter(OutputBuffer.prototype, 'bufStr', 'start', 'size'); -definePrimitiveGetter(OutputBuffer.prototype, 'size'); -definePrimitiveGetter(OutputBuffer.prototype, 'capacity'); -OutputBuffer.prototype.$destroy = function() { - I.destroyOutputBuffer(this.$); - this.$.$free(); +OutputBuffer.prototype.destroy = function() { + Module._wabt_destroy_output_buffer(this.addr); }; -// Stream -function Stream(writer, logStream) { - this.$ = Value.$malloc(I.Stream); - I.initStream(this.$, writer.$, logStream ? logStream.$ : null); + +/// ErrorHandler +function ErrorHandler() { + this.addr = Module._wabt_new_source_error_handler_buffer(); } -Stream.prototype = Object.create(Object.prototype); -definePrimitiveGetter(Stream.prototype, 'offset'); -definePrimitiveGetter(Stream.prototype, 'result'); -Stream.prototype.$destroy = function() { - this.$.$free(); -}; +ErrorHandler.prototype = Object.create(Object.prototype); -// StringStream -function StringStream() { - this.$writer = new MemoryWriter(); - Stream.call(this, this.$writer.writer, null); +ErrorHandler.prototype.getMessage = function() { + var addr = Module._wabt_source_error_handler_buffer_get_data(this.addr); + var size = Module._wabt_source_error_handler_buffer_get_size(this.addr); + return Module.Pointer_stringify(addr, size); } -StringStream.prototype = Object.create(Object.prototype); -Object.defineProperty(StringStream.prototype, 'string', { - get: function() { - return this.$writer.buf.bufStr; - } -}); -StringStream.prototype.$destroy = function() { - Stream.prototype.$destroy.call(this); - this.$writer.$destroy(); + +ErrorHandler.prototype.destroy = function() { + Module._wabt_destroy_source_error_handler_buffer(this.addr); }; -// parseAst + +/// parseAst function parseAst(filename, buffer) { - var sourceLineMaxLength = 80; - var astLexer = new AstLexer(filename, buffer); - var errorHandler = new SourceErrorHandler(sourceLineMaxLength); - var script = new Script(); - var result = I.parseAst(astLexer.$, script.$, errorHandler.$); - script.$astLexer = astLexer; - script.$errorHandler = errorHandler; - if (result != OK) { - script.$destroy(); - throw new Error('parseAst failed:\n' + errorHandler.errorMessage); - } - return script; -} + var lexer = new Lexer(filename, buffer); + var errorHandler = new ErrorHandler(); -// AstLexer -function AstLexer(filename, buffer) { - this.$filename = StrValue.$mallocCStr(filename); - this.$buffer = BufferValue.$malloc(buffer); - this.$ = I.newAstBufferLexer(this.$filename, this.$buffer, this.$buffer.size); - if (this.$ === null) { - this.$buffer.$free(); - this.$filename.$free(); - throw new Error('unable to create AstLexer'); - } -} -AstLexer.prototype = Object.create(Object.prototype); -AstLexer.prototype.$destroy = function() { - I.destroyAstLexer(this.$); - this.$.$free(); - this.$buffer.$free(); - this.$filename.$free(); -} + try { + var parseResult_addr = + Module._wabt_parse_ast(lexer.addr, errorHandler.addr); -// SourceErrorHandler -function SourceErrorHandler(sourceLineMaxLength) { - this.$ = Value.$malloc(I.SourceErrorHandler); - var wrapper = function(loc, error, sourceLine, sourceLineLength, - sourceLineColumnOffset, userData){ - loc = Location.$from(loc); - sourceLine = loadstrslice(sourceLine.$addr, sourceLineLength); - - var lines = [ - loc.filename + ':' + loc.line + ':' + loc.firstColumn, - error - ]; - if (sourceLine.length > 0) { - var numSpaces = loc.firstColumn - 1 - sourceLineColumnOffset; - var numCarets = - Math.min(loc.lastColumn - loc.firstColumn, sourceLine.length); - lines.push(sourceLine); - lines.push(' '.repeat(numSpaces) + '^'.repeat(numCarets)); + var result = Module._wabt_parse_ast_result_get_result(parseResult_addr); + if (result !== WABT_OK) { + throw new Error('parseAst failed:\n' + errorHandler.getMessage()); } - this.errorMessage += lines.join('\n') + '\n'; - }.bind(this); - this.$callback = - new FnValue(I.SourceErrorHandler.fields.on_error.type, wrapper); - this.$.on_error.store(this.$callback); - this.$.source_line_max_length.store(sourceLineMaxLength); - this.errorMessage = ''; -} -SourceErrorHandler.prototype = Object.create(Object.prototype); -SourceErrorHandler.prototype.$destroy = function() { - this.$callback.$destroy(); - this.$.$free(); -}; -// Location -function Location() { - this.$ = null; + var script_addr = + Module._wabt_parse_ast_result_release_script(parseResult_addr); + var result = new Script(lexer, script_addr); + // Clear lexer so it isn't destroyed below. + lexer = null; + return result; + } finally { + Module._wabt_destroy_parse_ast_result(parseResult_addr); + errorHandler.destroy(); + if (lexer) { + lexer.destroy(); + } + } } -define$From(Location); -Location.prototype = Object.create(Object.prototype); -defineStrGetter(Location.prototype, 'filename'); -definePrimitiveGetter(Location.prototype, 'line'); -definePrimitiveGetter(Location.prototype, 'firstColumn', 'first_column'); -definePrimitiveGetter(Location.prototype, 'lastColumn', 'last_column'); -Location.prototype.$destroy = function() { - this.$.$free(); -}; -// Script -function Script() { - this.$ = Value.$malloc(I.Script); - this.$astLexer = null; - this.$errorHandler = null; + +/// Script +function Script(lexer, script_addr) { + this.lexer = lexer; + this.script_addr = script_addr; } Script.prototype = Object.create(Object.prototype); + Script.prototype.resolveNames = function() { - var result = - I.resolveNamesScript(this.$astLexer.$, this.$, this.$errorHandler.$); - if (result != OK) { - throw new Error('resolveNames failed:\n' + this.$errorHandler.errorMessage); + var errorHandler = new ErrorHandler(); + try { + var result = Module._wabt_resolve_names_script( + this.lexer.addr, this.script_addr, errorHandler.addr); + if (result !== WABT_OK) { + throw new Error('resolveNames failed:\n' + errorHandler.getMessage()); + } + } finally { + errorHandler.destroy(); } }; + Script.prototype.validate = function() { - var result = I.validateScript(this.$astLexer.$, this.$, this.$errorHandler.$); - if (result != OK) { - throw new Error('validate failed:\n' + this.$errorHandler.errorMessage); - } -}; -Script.prototype.toBinary = function(options) { - var mw = new MemoryWriter(); - options = new WriteBinaryOptions(options || {}); + var errorHandler = new ErrorHandler(); try { - var module = I.getFirstModule(this.$); - if (module.$addr === 0) { - throw new Error('Script has no module.'); - } - var result = I.writeBinaryModule(mw.writer.$, module, options.$); - if (result != OK) { - throw new Error('writeBinaryModule failed'); + var result = Module._wabt_validate_script(this.lexer.addr, this.script_addr, + errorHandler.addr); + if (result !== WABT_OK) { + throw new Error('validate failed:\n' + errorHandler.getMessage()); } - return {buffer: mw.buf.buf, log: options.log} } finally { - options.$destroy(); - mw.$destroy(); + errorHandler.destroy(); } }; -Script.prototype.$destroy = function() { - I.destroyScript(this.$); - if (this.$errorHandler) this.$errorHandler.$destroy(); - if (this.$astLexer) this.$astLexer.$destroy(); - this.$.$free(); -}; -// WriteBinaryOptions -function WriteBinaryOptions(options) { - this.$ = Value.$malloc(I.WriteBinaryOptions); - if (options.log) { - this.$logStream = new StringStream(); - this.$.log_stream.store(this.$logStream.$); - } else { - this.$logStream = null; - this.$.log_stream.store(null); - } - var optBool = function(v, def) { return v === undefined ? def : v; }; - this.$.canonicalize_lebs.store(optBool(options.canonicalizeLebs, true)); - this.$.write_debug_names.store(optBool(options.writeDebugNames, false)); -} -WriteBinaryOptions.prototype = Object.create(Object.prototype); -Object.defineProperty(WriteBinaryOptions.prototype, 'log', { - get: function() { - return this.$logStream ? this.$logStream.string : ''; - } -}); -WriteBinaryOptions.prototype.$destroy = function() { - if (this.$logStream) { - this.$logStream.$destroy(); - } - this.$.$free(); -}; +Script.prototype.toBinary = function(options) { + var log = options.log || false; + var canonicalize_lebs = options.canonicalize_lebs || true; + var relocatable = options.relocatable || false; + var write_debug_names = options.write_debug_names || false; -// BinaryErrorHandler -function BinaryErrorHandler() { - this.$ = Value.$malloc(I.BinaryErrorHandler); - this.$callback = new FnValue( - I.BinaryErrorHandler.fields.on_error.type, - function(offset, error, userData) { - this.errorMessage += '@0x' + offset.toString(16) + ': ' + error + '\n'; - }.bind(this)); - this.$.on_error.store(this.$callback); - this.$.user_data.store(null); - this.errorMessage = ''; -} -BinaryErrorHandler.prototype = Object.create(Object.prototype); -BinaryErrorHandler.prototype.$destroy = function() { - this.$callback.$destroy(); - this.$.$free(); -}; + var writeBinaryResult_addr = Module._wabt_write_binary_module( + this.script_addr, log, canonicalize_lebs, relocatable, write_debug_names); -// ReadBinaryOptions -function ReadBinaryOptions(options) { - this.$ = Value.$malloc(I.ReadBinaryOptions); - this.$.read_debug_names.store(options.readDebugNames || false); -} -ReadBinaryOptions.prototype = Object.create(Object.prototype); -ReadBinaryOptions.prototype.$destroy = function() { - this.$.$free(); -}; + var result = Module._wabt_write_binary_module_result_get_result( + writeBinaryResult_addr); + try { + if (result !== WABT_OK) { + throw new Error('writeBinaryModule failed.'); + } -//////////////////////////////////////////////////////////////////////////////// + var binaryOutputBuffer = new OutputBuffer( + Module._wabt_write_binary_module_result_release_binary_output_buffer( + writeBinaryResult_addr)); + var logOutputBuffer = new OutputBuffer( + Module._wabt_write_binary_module_result_release_log_output_buffer( + writeBinaryResult_addr)); -var resolve = wabt.$resolve; + return { + buffer : binaryOutputBuffer.toTypedArray(), + log : logOutputBuffer.toString() + }; -wabt = { - ready: wabt.ready, + } finally { + if (binaryOutputBuffer) { + binaryOutputBuffer.destroy(); + } + if (logOutputBuffer) { + logOutputBuffer.destroy(); + } + Module._wabt_destroy_write_binary_module_result(writeBinaryResult_addr); + } +}; - // Functions - parseAst: parseAst, +Script.prototype.destroy = function() { + Module._wabt_destroy_script(this.script_addr); + this.lexer.destroy(); }; -resolve(); +wabt.ready = Promise.resolve(); +wabt.parseAst = parseAst; -}; +})(wabt); |