diff options
Diffstat (limited to 'third_party/wasm2c/src/wabt.post.js')
-rw-r--r-- | third_party/wasm2c/src/wabt.post.js | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/third_party/wasm2c/src/wabt.post.js b/third_party/wasm2c/src/wabt.post.js new file mode 100644 index 0000000000..c71e9d038a --- /dev/null +++ b/third_party/wasm2c/src/wabt.post.js @@ -0,0 +1,376 @@ +/* + * Copyright 2016 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var WABT_OK = 0; +var WABT_ERROR = 1; +var FEATURES = [ + 'exceptions', + 'mutable_globals', + 'sat_float_to_int', + 'sign_extension', + 'simd', + 'threads', + 'multi_value', + 'tail_call', + 'bulk_memory', + 'reference_types', +]; + +/// If value is not undefined, return it. Otherwise return default_. +function maybeDefault(value, default_) { + if (value === undefined) { + return default_; + } + return value; +} + +/// Coerce value to boolean if not undefined. Otherwise return default_. +function booleanOrDefault(value, default_) { + return !!maybeDefault(value, default_); +} + +/// Allocate memory in the Module. +function malloc(size) { + var addr = Module._malloc(size); + if (addr == 0) { + throw new Error('out of memory'); + } + return addr; +} + +/// 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) { + size = buf.byteLength; + addr = malloc(size); + (new Uint8Array(HEAP8.buffer, addr, size)).set(new Uint8Array(buf)) + } else if (ArrayBuffer.isView(buf)) { + size = buf.buffer.byteLength; + addr = malloc(size); + (new Uint8Array(HEAP8.buffer, addr, size)).set(buf); + } else if (typeof buf == 'string') { + size = buf.length; + addr = malloc(size); + writeAsciiToMemory(buf, addr, true); // don't null-terminate + } else { + throw new Error('unknown buffer type: ' + buf); + } + return {addr: addr, size: size}; +} + +function allocateCString(s) { + var size = s.length; + var addr = malloc(size); + writeAsciiToMemory(s, addr); + return {addr: addr, size: size}; +} + + +/// Features +function Features(obj) { + this.addr = Module._wabt_new_features(); + for (var i = 0; i < FEATURES.length; ++i) { + var feature = FEATURES[i]; + this[feature] = obj[feature] | 0; + } +} +Features.prototype = Object.create(Object.prototype); + +Features.prototype.destroy = function() { + Module._wabt_destroy_features(this.addr); +}; + +FEATURES.forEach(function(feature) { + Object.defineProperty(Features.prototype, feature, { + enumerable: true, + get: function() { + return Module['_wabt_' + feature + '_enabled'](this.addr); + }, + set: function(newValue) { + Module['_wabt_set_' + feature + '_enabled'](this.addr, newValue | 0); + } + }); +}); + + +/// Lexer +function Lexer(filename, buffer) { + this.filenameObj = allocateCString(filename); + this.bufferObj = allocateBuffer(buffer); + this.addr = Module._wabt_new_wast_buffer_lexer( + this.filenameObj.addr, this.bufferObj.addr, this.bufferObj.size); +} +Lexer.prototype = Object.create(Object.prototype); + +Lexer.prototype.destroy = function() { + Module._wabt_destroy_wast_lexer(this.addr); + Module._free(this.bufferObj.addr); + Module._free(this.filenameObj.addr); +}; + + +/// OutputBuffer +function OutputBuffer(addr) { + this.addr = addr; +} +OutputBuffer.prototype = Object.create(Object.prototype); + +OutputBuffer.prototype.toTypedArray = function() { + if (!this.addr) { + return null; + } + + 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; +}; + +OutputBuffer.prototype.toString = function() { + if (!this.addr) { + return ''; + } + + var addr = Module._wabt_output_buffer_get_data(this.addr); + var size = Module._wabt_output_buffer_get_size(this.addr); + return UTF8ToString(addr, size); +}; + +OutputBuffer.prototype.destroy = function() { + Module._wabt_destroy_output_buffer(this.addr); +}; + + +/// Errors +function Errors(kind, lexer) { + this.kind = kind; + this.addr = Module._wabt_new_errors(); + this.lexer = lexer; +} +Errors.prototype = Object.create(Object.prototype); + +Errors.prototype.format = function() { + var buffer; + switch (this.kind) { + case 'text': + buffer = new OutputBuffer( + Module._wabt_format_text_errors(this.addr, this.lexer.addr)); + break; + case 'binary': + buffer = new OutputBuffer(Module._wabt_format_binary_errors(this.addr)); + break; + default: + throw new Error('Invalid Errors kind: ' + this.kind); + } + var message = buffer.toString(); + buffer.destroy(); + return message; +}; + +Errors.prototype.destroy = function() { + Module._wabt_destroy_errors(this.addr); + if (this.lexer) { + this.lexer.destroy(); + } +}; + + +/// parseWat +function parseWat(filename, buffer, options) { + var lexer = new Lexer(filename, buffer); + var errors = new Errors('text', lexer); + var features = new Features(options || {}); + + try { + var parseResult_addr = + Module._wabt_parse_wat(lexer.addr, features.addr, errors.addr); + + var result = Module._wabt_parse_wat_result_get_result(parseResult_addr); + if (result !== WABT_OK) { + throw new Error('parseWat failed:\n' + errors.format()); + } + + var module_addr = + Module._wabt_parse_wat_result_release_module(parseResult_addr); + var result = new WasmModule(module_addr, errors); + // Clear errors so it isn't destroyed below. + errors = null; + return result; + } finally { + Module._wabt_destroy_parse_wat_result(parseResult_addr); + features.destroy(); + if (errors) { + errors.destroy(); + } + } +} + + +// readWasm +function readWasm(buffer, options) { + var bufferObj = allocateBuffer(buffer); + var errors = new Errors('binary'); + var readDebugNames = booleanOrDefault(options.readDebugNames, false); + var features = new Features(options); + + try { + var readBinaryResult_addr = Module._wabt_read_binary( + bufferObj.addr, bufferObj.size, readDebugNames, features.addr, + errors.addr); + + var result = + Module._wabt_read_binary_result_get_result(readBinaryResult_addr); + if (result !== WABT_OK) { + throw new Error('readWasm failed:\n' + errors.format()); + } + + var module_addr = + Module._wabt_read_binary_result_release_module(readBinaryResult_addr); + var result = new WasmModule(module_addr, errors); + // Clear errors so it isn't destroyed below. + errors = null; + return result; + } finally { + Module._wabt_destroy_read_binary_result(readBinaryResult_addr); + features.destroy(); + if (errors) { + errors.destroy(); + } + Module._free(bufferObj.addr); + } +} + + +// WasmModule (can't call it Module because emscripten has claimed it.) +function WasmModule(module_addr, errors) { + this.module_addr = module_addr; + this.errors = errors; +} +WasmModule.prototype = Object.create(Object.prototype); + +WasmModule.prototype.validate = function(options) { + var features = new Features(options || {}); + try { + var result = Module._wabt_validate_module( + this.module_addr, features.addr, this.errors.addr); + if (result !== WABT_OK) { + throw new Error('validate failed:\n' + this.errors.format()); + } + } finally { + features.destroy(); + } +}; + +WasmModule.prototype.resolveNames = function() { + // No-op, this is now part of text parsing. +}; + +WasmModule.prototype.generateNames = function() { + var result = Module._wabt_generate_names_module(this.module_addr); + if (result !== WABT_OK) { + throw new Error('generateNames failed.'); + } +}; + +WasmModule.prototype.applyNames = function() { + var result = Module._wabt_apply_names_module(this.module_addr); + if (result !== WABT_OK) { + throw new Error('applyNames failed.'); + } +}; + +WasmModule.prototype.toText = function(options) { + var foldExprs = booleanOrDefault(options.foldExprs, false); + var inlineExport = booleanOrDefault(options.inlineExport, false); + + var writeModuleResult_addr = + Module._wabt_write_text_module(this.module_addr, foldExprs, inlineExport); + + var result = Module._wabt_write_module_result_get_result( + writeModuleResult_addr); + + try { + if (result !== WABT_OK) { + throw new Error('toText failed.'); + } + + var outputBuffer = new OutputBuffer( + Module._wabt_write_module_result_release_output_buffer( + writeModuleResult_addr)); + + return outputBuffer.toString(); + + } finally { + if (outputBuffer) { + outputBuffer.destroy(); + } + Module._wabt_destroy_write_module_result(writeModuleResult_addr); + } +}; + +WasmModule.prototype.toBinary = function(options) { + var log = booleanOrDefault(options.log, false); + var canonicalize_lebs = booleanOrDefault(options.canonicalize_lebs, true); + var relocatable = booleanOrDefault(options.relocatable, false); + var write_debug_names = booleanOrDefault(options.write_debug_names, false); + + var writeModuleResult_addr = Module._wabt_write_binary_module( + this.module_addr, log, canonicalize_lebs, relocatable, write_debug_names); + + var result = + Module._wabt_write_module_result_get_result(writeModuleResult_addr); + + try { + if (result !== WABT_OK) { + throw new Error('toBinary failed.'); + } + + var binaryOutputBuffer = + new OutputBuffer(Module._wabt_write_module_result_release_output_buffer( + writeModuleResult_addr)); + var logOutputBuffer = new OutputBuffer( + Module._wabt_write_module_result_release_log_output_buffer( + writeModuleResult_addr)); + + return { + buffer: binaryOutputBuffer.toTypedArray(), + log: logOutputBuffer.toString() + }; + + } finally { + if (binaryOutputBuffer) { + binaryOutputBuffer.destroy(); + } + if (logOutputBuffer) { + logOutputBuffer.destroy(); + } + Module._wabt_destroy_write_module_result(writeModuleResult_addr); + } +}; + +WasmModule.prototype.destroy = function() { + Module._wabt_destroy_module(this.module_addr); + if (this.errors) { + this.errors.destroy(); + } +}; + +Module['parseWat'] = parseWat; +Module['readWasm'] = readWasm; |