summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md18
-rwxr-xr-xcheck.py19
-rw-r--r--src/js/wasm.js-post.js30
-rw-r--r--src/wasm-binary.h190
m---------test/emscripten0
5 files changed, 123 insertions, 134 deletions
diff --git a/README.md b/README.md
index f8d1e97c9..62912149a 100644
--- a/README.md
+++ b/README.md
@@ -121,18 +121,9 @@ The `BINARYEN` flag tells it to emit code using `wasm.js`, and the `BINARYEN_ROO
### C/C++ Source => asm2wasm => WebAssembly
-Using emcc you can generate asm.js files for direct parsing by `asm2wasm` on the commandline, for example using
+When using `emcc` with the `BINARYEN` option, it will use Binaryen to build to WebAssembly. See the [emscripten wiki](https://github.com/kripken/emscripten/wiki/WebAssembly) for more details.
-```
-emcc src.cpp -o a.html --separate-asm
-```
-
-That will emit `a.html`, `a.js`, and `a.asm.js`. That last file is the asm.js module, which you can pass into `asm2wasm`.
-
-For basic tests, that command should work, but in general you need a few more arguments to emcc, see what emcc.py does when given the `BINARYEN` option, including:
-
- * `ALIASING_FUNCTION_POINTERS=0` because WebAssembly does not allow aliased function pointers (there is a single table).
- * `GLOBAL_BASE=1000` because WebAssembly lacks global variables, so `asm2wasm` maps them onto addresses in memory. This requires that you have some reserved space for those variables. With that argument, we reserve the area up to `1000`.
+ * Build with `EMCC_DEBUG=1` in the env to see Emscripten's debug output as it runs the various tools, and also to save the intermediate files in `/tmp/emscripten_temp`. It will save both the `.s` and `.wast` files there (in addition to other files it normally saves).
### C/C++ Source => WebAssembly LLVM backend => s2wasm => WebAssembly
@@ -157,10 +148,7 @@ EMCC_WASM_BACKEND=1 ./emcc input.cpp -s BINARYEN=1
(without the env var, the `BINARYEN` option will make it use the asm.js backend, then `asm2wasm`).
- * You can see vanilla LLVM tested with Emscripten in `check.py` in this repo (look for `VANILLA_EMCC` in that file), using an Emscripten submodule.
- * Due to current limitations of the WebAssembly backend, you might want to build with `-s ONLY_MY_CODE=1 -O1`, which will avoid linking in libc (which contains varargs, which are not yet supported), and optimizes so that the stack is not used (which is also not yet supported).
- * The output when building in this mode is similar to what you get in general when building with Binaryen in Emscripten: a main `.js` file, and the compiled code in a `.wast` file alongside it.
- * Build with `EMCC_DEBUG=1` in the env to see Emscripten's debug output as it runs the various tools, and also to save the intermediate files in `/tmp/emscripten_temp`. It will save both the `.s` and `.wast` files there (in addition to other files it normally saves).
+For more details, see the [emscripten wiki](https://github.com/kripken/emscripten/wiki/WebAssembly).
## Testing
diff --git a/check.py b/check.py
index a8bd65bb4..8b1db8dac 100755
--- a/check.py
+++ b/check.py
@@ -586,19 +586,20 @@ if has_emcc:
print '\n[ checking wasm.js methods... ]\n'
- for method_init in [None, 'asm2wasm', 'wasm-s-parser', 'just-asm', 'wasm-binary']:
+ for method_init in [None, 'interpret-asm2wasm', 'interpret-s-expr', 'asmjs', 'interpret-binary']:
for success in [1, 0]:
method = method_init
command = ['emcc', '-o', 'a.wasm.js', '-s', 'BINARYEN=1', os.path.join('test', 'hello_world.c') ]
if method:
command += ['-s', 'BINARYEN_METHOD="' + method + '"']
else:
- method = 'wasm-s-parser' # this is the default
+ method = 'interpret-s-expr' # this is the default
print method, ' : ', ' '.join(command), ' => ', success
subprocess.check_call(command)
see_polyfill = 'var WasmJS = ' in open('a.wasm.js').read()
- if method and 'asm2wasm' not in method and 'wasm-s-parser' not in method and 'wasm-binary' not in method:
+
+ if method and 'interpret' not in method:
assert not see_polyfill, 'verify polyfill was not added - we specified a method, and it does not need it'
else:
assert see_polyfill, 'we need the polyfill'
@@ -608,20 +609,20 @@ if has_emcc:
asm = asm.replace('"almost asm"', '"use asm"; var not_in_asm = [].length + (true || { x: 5 }.x);')
asm = asm.replace("'almost asm'", '"use asm"; var not_in_asm = [].length + (true || { x: 5 }.x);')
open('a.wasm.asm.js', 'w').write(asm)
- if method == 'asm2wasm':
+ if method == 'interpret-asm2wasm':
os.unlink('a.wasm.wast') # we should not need the .wast
if not success:
break_cashew() # we need cashew
- elif method == 'wasm-s-parser':
+ elif method == 'interpret-s-expr':
os.unlink('a.wasm.asm.js') # we should not need the .asm.js
if not success:
os.unlink('a.wasm.wast.mappedGlobals')
- elif method == 'just-asm':
+ elif method == 'asmjs':
os.unlink('a.wasm.wast') # we should not need the .wast
break_cashew() # we don't use cashew, so ok to break it
if not success:
os.unlink('a.wasm.js')
- elif method == 'wasm-binary':
+ elif method == 'interpret-binary':
os.unlink('a.wasm.wast') # we should not need the .wast
os.unlink('a.wasm.asm.js') # we should not need the .asm.js
if not success:
@@ -656,7 +657,7 @@ if has_emcc:
extra = json.loads(open(emcc).read())
if os.path.exists('a.normal.js'): os.unlink('a.normal.js')
for opts in [[], ['-O1'], ['-O2'], ['-O3'], ['-Oz']]:
- for method in ['asm2wasm', 'wasm-s-parser', 'just-asm', 'wasm-binary']:
+ for method in ['interpret-asm2wasm', 'interpret-s-expr', 'asmjs', 'interpret-binary']:
command = ['emcc', '-o', 'a.wasm.js', '-s', 'BINARYEN=1', os.path.join('test', c)] + opts + extra
command += ['-s', 'BINARYEN_METHOD="' + method + '"']
print '....' + ' '.join(command)
@@ -683,7 +684,7 @@ if has_emcc:
execute()
- if method in ['asm2wasm', 'wasm-s-parser']:
+ if method in ['interpret-asm2wasm', 'interpret-s-expr']:
# binary and back
shutil.copyfile('a.wasm.wast', 'a.wasm.original.wast')
recreated = binary_format_check('a.wasm.wast', verify_final_result=False)
diff --git a/src/js/wasm.js-post.js b/src/js/wasm.js-post.js
index 12e9e5315..0549dbd51 100644
--- a/src/js/wasm.js-post.js
+++ b/src/js/wasm.js-post.js
@@ -17,10 +17,10 @@
function integrateWasmJS(Module) {
// wasm.js has several methods for creating the compiled code module here:
// * 'native-wasm' : use native WebAssembly support in the browser
- // * 'wasm-s-parser': load s-expression code from a .wast and interpret
- // * 'wasm-binary': load binary wasm and interpret
- // * 'asm2wasm': load asm.js code, translate to wasm, and interpret
- // * 'just-asm': no wasm, just load the asm.js code and use that (good for testing)
+ // * 'interpret-s-expr': load s-expression code from a .wast and interpret
+ // * 'interpret-binary': load binary wasm and interpret
+ // * 'interpret-asm2wasm': load asm.js code, translate to wasm, and interpret
+ // * 'asmjs': no wasm, just load the asm.js code and use that (good for testing)
// The method can be set at compile time (BINARYEN_METHOD), or runtime by setting Module['wasmJSMethod'].
// The method can be a comma-separated list, in which case, we will try the
// options one by one. Some of them can fail gracefully, and then we can try
@@ -28,7 +28,7 @@ function integrateWasmJS(Module) {
// inputs
- var method = Module['wasmJSMethod'] || {{{ wasmJSMethod }}} || 'native-wasm,wasm-s-parser'; // by default, try native and then .wast
+ var method = Module['wasmJSMethod'] || {{{ wasmJSMethod }}} || 'native-wasm,interpret-s-expr'; // by default, try native and then .wast
var wasmTextFile = Module['wasmTextFile'] || {{{ wasmTextFile }}};
var wasmBinaryFile = Module['wasmBinaryFile'] || {{{ wasmBinaryFile }}};
@@ -229,23 +229,23 @@ function integrateWasmJS(Module) {
wasmJS['providedTotalMemory'] = Module['buffer'].byteLength;
- // Prepare to generate wasm, using either asm2wasm or wasm-s-parser
+ // Prepare to generate wasm, using either asm2wasm or s-exprs
var code;
- if (method === 'wasm-binary') {
+ if (method === 'interpret-binary') {
code = getBinary();
} else {
- code = Module['read'](method == 'asm2wasm' ? asmjsCodeFile : wasmTextFile);
+ code = Module['read'](method == 'interpret-asm2wasm' ? asmjsCodeFile : wasmTextFile);
}
var temp;
- if (method == 'asm2wasm') {
+ if (method == 'interpret-asm2wasm') {
temp = wasmJS['_malloc'](code.length + 1);
wasmJS['writeAsciiToMemory'](code, temp);
wasmJS['_load_asm2wasm'](temp);
- } else if (method === 'wasm-s-parser') {
+ } else if (method === 'interpret-s-expr') {
temp = wasmJS['_malloc'](code.length + 1);
wasmJS['writeAsciiToMemory'](code, temp);
wasmJS['_load_s_expr2wasm'](temp);
- } else if (method === 'wasm-binary') {
+ } else if (method === 'interpret-binary') {
temp = wasmJS['_malloc'](code.length);
wasmJS['HEAPU8'].set(code, temp);
wasmJS['_load_binary2wasm'](temp, code.length);
@@ -261,9 +261,9 @@ function integrateWasmJS(Module) {
Module['newBuffer'] = null;
}
- if (method == 'wasm-s-parser') {
+ if (method == 'interpret-s-expr') {
applyMappedGlobals(wasmTextFile);
- } else if (method == 'wasm-binary') {
+ } else if (method == 'interpret-binary') {
applyMappedGlobals(wasmBinaryFile);
}
@@ -281,9 +281,9 @@ function integrateWasmJS(Module) {
//Module['printErr']('using wasm/js method: ' + curr);
if (curr === 'native-wasm') {
if (doNativeWasm()) return;
- } else if (curr === 'just-asm') {
+ } else if (curr === 'asmjs') {
if (doJustAsm()) return;
- } else if (curr === 'asm2wasm' || curr === 'wasm-s-parser' || curr === 'wasm-binary') {
+ } else if (curr === 'interpret-asm2wasm' || curr === 'interpret-s-expr' || curr === 'interpret-binary') {
if (doWasmPolyfill(curr)) return;
} else {
throw 'bad method: ' + curr;
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 3ce76e247..cea086ba3 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -77,8 +77,8 @@ struct LEB {
}
};
-typedef LEB<uint32_t> LEB128;
-typedef LEB<uint64_t> LEB256;
+typedef LEB<uint32_t> U32LEB;
+typedef LEB<uint64_t> U64LEB;
//
// We mostly stream into a buffer as we create the binary format, however,
@@ -122,13 +122,13 @@ public:
push_back(x & 0xff);
return *this;
}
- BufferWithRandomAccess& operator<<(LEB128 x) {
- if (debug) std::cerr << "writeLEB128: " << x.value << " (at " << size() << ")" << std::endl;
+ BufferWithRandomAccess& operator<<(U32LEB x) {
+ if (debug) std::cerr << "writeU32LEB: " << x.value << " (at " << size() << ")" << std::endl;
x.write(this);
return *this;
}
- BufferWithRandomAccess& operator<<(LEB256 x) {
- if (debug) std::cerr << "writeLEB256: " << x.value << " (at " << size() << ")" << std::endl;
+ BufferWithRandomAccess& operator<<(U64LEB x) {
+ if (debug) std::cerr << "writeU64LEB: " << x.value << " (at " << size() << ")" << std::endl;
x.write(this);
return *this;
}
@@ -167,8 +167,8 @@ public:
(*this)[i+2] = x & 0xff; x >>= 8;
(*this)[i+3] = x & 0xff;
}
- void writeAt(size_t i, LEB128 x) {
- if (debug) std::cerr << "backpatchLEB128: " << x.value << " (at " << i << ")" << std::endl;
+ void writeAt(size_t i, U32LEB x) {
+ if (debug) std::cerr << "backpatchU32LEB: " << x.value << " (at " << i << ")" << std::endl;
x.writeAt(this, i, 5); // fill all 5 bytes, we have to do this when backpatching
}
@@ -442,7 +442,7 @@ public:
o << int32_t(10); // version number
}
- int32_t writeLEB128Placeholder() {
+ int32_t writeU32LEBPlaceholder() {
int32_t ret = o.size();
o << int32_t(0);
o << int8_t(0);
@@ -451,21 +451,21 @@ public:
int32_t startSection(const char* name) {
// emit 5 bytes of 0, which we'll fill with LEB later
- auto ret = writeLEB128Placeholder();
+ auto ret = writeU32LEBPlaceholder();
writeInlineString(name);
return ret;
}
void finishSection(int32_t start) {
int32_t size = o.size() - start - 5; // section size does not include the 5 bytes of the size field itself
- o.writeAt(start, LEB128(size));
+ o.writeAt(start, U32LEB(size));
}
void writeStart() {
if (!wasm->start.is()) return;
if (debug) std::cerr << "== writeStart" << std::endl;
auto start = startSection(BinaryConsts::Section::Start);
- o << LEB128(getFunctionIndex(wasm->start.str));
+ o << U32LEB(getFunctionIndex(wasm->start.str));
finishSection(start);
}
@@ -473,8 +473,8 @@ public:
if (wasm->memory.max == 0) return;
if (debug) std::cerr << "== writeMemory" << std::endl;
auto start = startSection(BinaryConsts::Section::Memory);
- o << LEB128(wasm->memory.initial)
- << LEB128(wasm->memory.max)
+ o << U32LEB(wasm->memory.initial)
+ << U32LEB(wasm->memory.max)
<< int8_t(1); // export memory
finishSection(start);
}
@@ -483,10 +483,10 @@ public:
if (wasm->functionTypes.size() == 0) return;
if (debug) std::cerr << "== writeSignatures" << std::endl;
auto start = startSection(BinaryConsts::Section::Signatures);
- o << LEB128(wasm->functionTypes.size());
+ o << U32LEB(wasm->functionTypes.size());
for (auto* type : wasm->functionTypes) {
if (debug) std::cerr << "write one" << std::endl;
- o << LEB128(type->params.size());
+ o << U32LEB(type->params.size());
o << binaryWasmType(type->result);
for (auto param : type->params) {
o << binaryWasmType(param);
@@ -507,10 +507,10 @@ public:
if (wasm->imports.size() == 0) return;
if (debug) std::cerr << "== writeImports" << std::endl;
auto start = startSection(BinaryConsts::Section::ImportTable);
- o << LEB128(wasm->imports.size());
+ o << U32LEB(wasm->imports.size());
for (auto* import : wasm->imports) {
if (debug) std::cerr << "write one" << std::endl;
- o << LEB128(getFunctionTypeIndex(import->type->name));
+ o << U32LEB(getFunctionTypeIndex(import->type->name));
writeInlineString(import->module.str);
writeInlineString(import->base.str);
}
@@ -561,10 +561,10 @@ public:
if (wasm->functions.size() == 0) return;
if (debug) std::cerr << "== writeFunctionSignatures" << std::endl;
auto start = startSection(BinaryConsts::Section::FunctionSignatures);
- o << LEB128(wasm->functions.size());
+ o << U32LEB(wasm->functions.size());
for (auto* curr : wasm->functions) {
if (debug) std::cerr << "write one" << std::endl;
- o << LEB128(getFunctionTypeIndex(curr->type));
+ o << U32LEB(getFunctionTypeIndex(curr->type));
}
finishSection(start);
}
@@ -574,26 +574,26 @@ public:
if (debug) std::cerr << "== writeFunctions" << std::endl;
auto start = startSection(BinaryConsts::Section::Functions);
size_t total = wasm->functions.size();
- o << LEB128(total);
+ o << U32LEB(total);
for (size_t i = 0; i < total; i++) {
if (debug) std::cerr << "write one at" << o.size() << std::endl;
- size_t sizePos = writeLEB128Placeholder();
+ size_t sizePos = writeU32LEBPlaceholder();
size_t start = o.size();
Function* function = wasm->functions[i];
mappedLocals.clear();
numLocalsByType.clear();
if (debug) std::cerr << "writing" << function->name << std::endl;
mapLocals(function);
- o << LEB128(
+ o << U32LEB(
(numLocalsByType[i32] ? 1 : 0) +
(numLocalsByType[i64] ? 1 : 0) +
(numLocalsByType[f32] ? 1 : 0) +
(numLocalsByType[f64] ? 1 : 0)
);
- if (numLocalsByType[i32]) o << LEB128(numLocalsByType[i32]) << binaryWasmType(i32);
- if (numLocalsByType[i64]) o << LEB128(numLocalsByType[i64]) << binaryWasmType(i64);
- if (numLocalsByType[f32]) o << LEB128(numLocalsByType[f32]) << binaryWasmType(f32);
- if (numLocalsByType[f64]) o << LEB128(numLocalsByType[f64]) << binaryWasmType(f64);
+ if (numLocalsByType[i32]) o << U32LEB(numLocalsByType[i32]) << binaryWasmType(i32);
+ if (numLocalsByType[i64]) o << U32LEB(numLocalsByType[i64]) << binaryWasmType(i64);
+ if (numLocalsByType[f32]) o << U32LEB(numLocalsByType[f32]) << binaryWasmType(f32);
+ if (numLocalsByType[f64]) o << U32LEB(numLocalsByType[f64]) << binaryWasmType(f64);
depth = 0;
recurse(function->body);
o << int8_t(BinaryConsts::EndMarker);
@@ -601,7 +601,7 @@ public:
size_t size = o.size() - start;
assert(size <= std::numeric_limits<uint32_t>::max());
if (debug) std::cerr << "body size: " << size << ", writing at " << sizePos << ", next starts at " << o.size() << std::endl;
- o.writeAt(sizePos, LEB128(size));
+ o.writeAt(sizePos, U32LEB(size));
}
finishSection(start);
}
@@ -610,10 +610,10 @@ public:
if (wasm->exports.size() == 0) return;
if (debug) std::cerr << "== writeexports" << std::endl;
auto start = startSection(BinaryConsts::Section::ExportTable);
- o << LEB128(wasm->exports.size());
+ o << U32LEB(wasm->exports.size());
for (auto* curr : wasm->exports) {
if (debug) std::cerr << "write one" << std::endl;
- o << LEB128(getFunctionIndex(curr->value));
+ o << U32LEB(getFunctionIndex(curr->value));
writeInlineString(curr->name.str);
}
finishSection(start);
@@ -626,10 +626,10 @@ public:
if (segment.size > 0) num++;
}
auto start = startSection(BinaryConsts::Section::DataSegments);
- o << LEB128(num);
+ o << U32LEB(num);
for (auto& segment : wasm->memory.segments) {
if (segment.size == 0) continue;
- o << LEB128(segment.offset);
+ o << U32LEB(segment.offset);
writeInlineBuffer(segment.data, segment.size);
}
finishSection(start);
@@ -654,9 +654,9 @@ public:
if (wasm->table.names.size() == 0) return;
if (debug) std::cerr << "== writeFunctionTable" << std::endl;
auto start = startSection(BinaryConsts::Section::FunctionTable);
- o << LEB128(wasm->table.names.size());
+ o << U32LEB(wasm->table.names.size());
for (auto name : wasm->table.names) {
- o << LEB128(getFunctionIndex(name));
+ o << U32LEB(getFunctionIndex(name));
}
finishSection(start);
}
@@ -665,10 +665,10 @@ public:
if (wasm->functions.size() == 0) return;
if (debug) std::cerr << "== writeNames" << std::endl;
auto start = startSection(BinaryConsts::Section::Names);
- o << LEB128(wasm->functions.size());
+ o << U32LEB(wasm->functions.size());
for (auto* curr : wasm->functions) {
writeInlineString(curr->name.str);
- o << LEB128(0); // TODO: locals
+ o << U32LEB(0); // TODO: locals
}
finishSection(start);
}
@@ -682,14 +682,14 @@ public:
void writeInlineString(const char* name) {
int32_t size = strlen(name);
- o << LEB128(size);
+ o << U32LEB(size);
for (int32_t i = 0; i < size; i++) {
o << int8_t(name[i]);
}
}
void writeInlineBuffer(const char* data, size_t size) {
- o << LEB128(size);
+ o << U32LEB(size);
for (size_t i = 0; i < size; i++) {
o << int8_t(data[i]);
}
@@ -789,15 +789,15 @@ public:
}
if (curr->condition) recurse(curr->condition);
o << int8_t(curr->condition ? BinaryConsts::BrIf : BinaryConsts::Br)
- << LEB128(getBreakIndex(curr->name));
+ << U32LEB(getBreakIndex(curr->name));
}
void visitSwitch(Switch *curr) {
if (debug) std::cerr << "zz node: Switch" << std::endl;
- o << int8_t(BinaryConsts::TableSwitch) << LEB128(curr->targets.size());
+ o << int8_t(BinaryConsts::TableSwitch) << U32LEB(curr->targets.size());
for (auto target : curr->targets) {
- o << LEB128(getBreakIndex(target));
+ o << U32LEB(getBreakIndex(target));
}
- o << LEB128(getBreakIndex(curr->default_));
+ o << U32LEB(getBreakIndex(curr->default_));
recurse(curr->condition);
o << int8_t(BinaryConsts::EndMarker);
if (curr->value) {
@@ -812,14 +812,14 @@ public:
for (auto* operand : curr->operands) {
recurse(operand);
}
- o << int8_t(BinaryConsts::CallFunction) << LEB128(getFunctionIndex(curr->target));
+ o << int8_t(BinaryConsts::CallFunction) << U32LEB(getFunctionIndex(curr->target));
}
void visitCallImport(CallImport *curr) {
if (debug) std::cerr << "zz node: CallImport" << std::endl;
for (auto* operand : curr->operands) {
recurse(operand);
}
- o << int8_t(BinaryConsts::CallImport) << LEB128(getImportIndex(curr->target));
+ o << int8_t(BinaryConsts::CallImport) << U32LEB(getImportIndex(curr->target));
}
void visitCallIndirect(CallIndirect *curr) {
if (debug) std::cerr << "zz node: CallIndirect" << std::endl;
@@ -827,21 +827,21 @@ public:
for (auto* operand : curr->operands) {
recurse(operand);
}
- o << int8_t(BinaryConsts::CallIndirect) << LEB128(getFunctionTypeIndex(curr->fullType->name));
+ o << int8_t(BinaryConsts::CallIndirect) << U32LEB(getFunctionTypeIndex(curr->fullType->name));
}
void visitGetLocal(GetLocal *curr) {
if (debug) std::cerr << "zz node: GetLocal " << (o.size() + 1) << std::endl;
- o << int8_t(BinaryConsts::GetLocal) << LEB128(mappedLocals[curr->name]);
+ o << int8_t(BinaryConsts::GetLocal) << U32LEB(mappedLocals[curr->name]);
}
void visitSetLocal(SetLocal *curr) {
if (debug) std::cerr << "zz node: SetLocal" << std::endl;
recurse(curr->value);
- o << int8_t(BinaryConsts::SetLocal) << LEB128(mappedLocals[curr->name]);
+ o << int8_t(BinaryConsts::SetLocal) << U32LEB(mappedLocals[curr->name]);
}
void emitMemoryAccess(size_t alignment, size_t bytes, uint32_t offset) {
- o << LEB128(Log2(alignment ? alignment : bytes));
- o << LEB128(offset);
+ o << U32LEB(Log2(alignment ? alignment : bytes));
+ o << U32LEB(offset);
}
void visitLoad(Load *curr) {
@@ -907,11 +907,11 @@ public:
if (debug) std::cerr << "zz node: Const" << curr << " : " << curr->type << std::endl;
switch (curr->type) {
case i32: {
- o << int8_t(BinaryConsts::I32Const) << LEB128(curr->value.geti32());
+ o << int8_t(BinaryConsts::I32Const) << U32LEB(curr->value.geti32());
break;
}
case i64: {
- o << int8_t(BinaryConsts::I64Const) << LEB256(curr->value.geti64());
+ o << int8_t(BinaryConsts::I64Const) << U64LEB(curr->value.geti64());
break;
}
case f32: {
@@ -1088,9 +1088,9 @@ public:
// read sections until the end
while (more()) {
- auto sectionSize = getLEB128();
+ auto sectionSize = getU32LEB();
assert(sectionSize < pos + input.size());
- auto nameSize = getLEB128();
+ auto nameSize = getU32LEB();
auto match = [&](const char* name) {
for (size_t i = 0; i < nameSize; i++) {
if (pos + i >= input.size()) return false;
@@ -1162,22 +1162,22 @@ public:
return ret;
}
- uint32_t getLEB128() {
+ uint32_t getU32LEB() {
if (debug) std::cerr << "<==" << std::endl;
- LEB128 ret;
+ U32LEB ret;
ret.read([&]() {
return getInt8();
});
- if (debug) std::cerr << "getLEB128: " << ret.value << " ==>" << std::endl;
+ if (debug) std::cerr << "getU32LEB: " << ret.value << " ==>" << std::endl;
return ret.value;
}
- uint64_t getLEB256() {
+ uint64_t getU64LEB() {
if (debug) std::cerr << "<==" << std::endl;
- LEB256 ret;
+ U64LEB ret;
ret.read([&]() {
return getInt8();
});
- if (debug) std::cerr << "getLEB256: " << ret.value << " ==>" << std::endl;
+ if (debug) std::cerr << "getU64LEB: " << ret.value << " ==>" << std::endl;
return ret.value;
}
WasmType getWasmType() {
@@ -1202,7 +1202,7 @@ public:
Name getInlineString() {
if (debug) std::cerr << "<==" << std::endl;
- auto len = getLEB128();
+ auto len = getU32LEB();
std::string str;
for (size_t i = 0; i < len; i++) {
str = str + char(getInt8());
@@ -1250,24 +1250,24 @@ public:
void readStart() {
if (debug) std::cerr << "== readStart" << std::endl;
- startIndex = getLEB128();
+ startIndex = getU32LEB();
}
void readMemory() {
if (debug) std::cerr << "== readMemory" << std::endl;
- wasm.memory.initial = getLEB128();
- wasm.memory.max = getLEB128();
+ wasm.memory.initial = getU32LEB();
+ wasm.memory.max = getU32LEB();
verifyInt8(1); // export memory
}
void readSignatures() {
if (debug) std::cerr << "== readSignatures" << std::endl;
- size_t numTypes = getLEB128();
+ size_t numTypes = getU32LEB();
if (debug) std::cerr << "num: " << numTypes << std::endl;
for (size_t i = 0; i < numTypes; i++) {
if (debug) std::cerr << "read one" << std::endl;
auto curr = allocator.alloc<FunctionType>();
- size_t numParams = getLEB128();
+ size_t numParams = getU32LEB();
if (debug) std::cerr << "num params: " << numParams << std::endl;
curr->result = getWasmType();
for (size_t j = 0; j < numParams; j++) {
@@ -1279,13 +1279,13 @@ public:
void readImports() {
if (debug) std::cerr << "== readImports" << std::endl;
- size_t num = getLEB128();
+ size_t num = getU32LEB();
if (debug) std::cerr << "num: " << num << std::endl;
for (size_t i = 0; i < num; i++) {
if (debug) std::cerr << "read one" << std::endl;
auto curr = allocator.alloc<Import>();
curr->name = Name(std::string("import$") + std::to_string(i));
- auto index = getLEB128();
+ auto index = getU32LEB();
assert(index < wasm.functionTypes.size());
curr->type = wasm.functionTypes[index];
assert(curr->type->name.is());
@@ -1299,11 +1299,11 @@ public:
void readFunctionSignatures() {
if (debug) std::cerr << "== readFunctionSignatures" << std::endl;
- size_t num = getLEB128();
+ size_t num = getU32LEB();
if (debug) std::cerr << "num: " << num << std::endl;
for (size_t i = 0; i < num; i++) {
if (debug) std::cerr << "read one" << std::endl;
- auto index = getLEB128();
+ auto index = getU32LEB();
assert(index < wasm.functionTypes.size());
functionTypes.push_back(wasm.functionTypes[index]);
}
@@ -1322,10 +1322,10 @@ public:
void readFunctions() {
if (debug) std::cerr << "== readFunctions" << std::endl;
- size_t total = getLEB128();
+ size_t total = getU32LEB();
for (size_t i = 0; i < total; i++) {
if (debug) std::cerr << "read one at " << pos << std::endl;
- size_t size = getLEB128();
+ size_t size = getU32LEB();
assert(size > 0); // we could also check it matches the seen size
auto type = functionTypes[i];
if (debug) std::cerr << "reading" << i << std::endl;
@@ -1340,9 +1340,9 @@ public:
for (size_t j = 0; j < type->params.size(); j++) {
func->params.emplace_back(addVar(), type->params[j]);
}
- size_t numLocalTypes = getLEB128();
+ size_t numLocalTypes = getU32LEB();
for (size_t t = 0; t < numLocalTypes; t++) {
- auto num = getLEB128();
+ auto num = getU32LEB();
auto type = getWasmType();
while (num > 0) {
func->locals.emplace_back(addVar(), type);
@@ -1383,12 +1383,12 @@ public:
void readExports() {
if (debug) std::cerr << "== readExports" << std::endl;
- size_t num = getLEB128();
+ size_t num = getU32LEB();
if (debug) std::cerr << "num: " << num << std::endl;
for (size_t i = 0; i < num; i++) {
if (debug) std::cerr << "read one" << std::endl;
auto curr = allocator.alloc<Export>();
- auto index = getLEB128();
+ auto index = getU32LEB();
assert(index < functionTypes.size());
curr->name = getInlineString();
exportIndexes[curr] = index;
@@ -1450,11 +1450,11 @@ public:
void readDataSegments() {
if (debug) std::cerr << "== readDataSegments" << std::endl;
- auto num = getLEB128();
+ auto num = getU32LEB();
for (size_t i = 0; i < num; i++) {
Memory::Segment curr;
- curr.offset = getLEB128();
- auto size = getLEB128();
+ curr.offset = getU32LEB();
+ auto size = getU32LEB();
auto buffer = (char*)malloc(size);
for (size_t j = 0; j < size; j++) {
buffer[j] = char(getInt8());
@@ -1469,19 +1469,19 @@ public:
void readFunctionTable() {
if (debug) std::cerr << "== readFunctionTable" << std::endl;
- auto num = getLEB128();
+ auto num = getU32LEB();
for (size_t i = 0; i < num; i++) {
- auto index = getLEB128();
+ auto index = getU32LEB();
functionTable.push_back(index);
}
}
void readNames() {
if (debug) std::cerr << "== readNames" << std::endl;
- auto num = getLEB128();
+ auto num = getU32LEB();
for (size_t i = 0; i < num; i++) {
functions[i]->name = getInlineString();
- auto numLocals = getLEB128();
+ auto numLocals = getU32LEB();
assert(numLocals == 0); // TODO
}
}
@@ -1612,17 +1612,17 @@ public:
void visitBreak(Break *curr, uint8_t code) {
if (debug) std::cerr << "zz node: Break" << std::endl;
- curr->name = getBreakName(getLEB128());
+ curr->name = getBreakName(getU32LEB());
if (code == BinaryConsts::BrIf) curr->condition = popExpression();
curr->value = popExpression();
}
void visitSwitch(Switch *curr) {
if (debug) std::cerr << "zz node: Switch" << std::endl;
- auto numTargets = getLEB128();
+ auto numTargets = getU32LEB();
for (size_t i = 0; i < numTargets; i++) {
- curr->targets.push_back(getBreakName(getLEB128()));
+ curr->targets.push_back(getBreakName(getU32LEB()));
}
- curr->default_ = getBreakName(getLEB128());
+ curr->default_ = getBreakName(getU32LEB());
processExpressions();
curr->condition = popExpression();
processExpressions();
@@ -1631,7 +1631,7 @@ public:
}
void visitCall(Call *curr) {
if (debug) std::cerr << "zz node: Call" << std::endl;
- auto index = getLEB128();
+ auto index = getU32LEB();
auto type = functionTypes[index];
auto num = type->params.size();
curr->operands.resize(num);
@@ -1643,7 +1643,7 @@ public:
}
void visitCallImport(CallImport *curr) {
if (debug) std::cerr << "zz node: CallImport" << std::endl;
- curr->target = wasm.imports[getLEB128()]->name;
+ curr->target = wasm.imports[getU32LEB()]->name;
assert(wasm.importsMap.find(curr->target) != wasm.importsMap.end());
auto type = wasm.importsMap[curr->target]->type;
assert(type);
@@ -1657,7 +1657,7 @@ public:
}
void visitCallIndirect(CallIndirect *curr) {
if (debug) std::cerr << "zz node: CallIndirect" << std::endl;
- curr->fullType = wasm.functionTypes[getLEB128()];
+ curr->fullType = wasm.functionTypes[getU32LEB()];
auto num = curr->fullType->params.size();
curr->operands.resize(num);
for (size_t i = 0; i < num; i++) {
@@ -1668,21 +1668,21 @@ public:
}
void visitGetLocal(GetLocal *curr) {
if (debug) std::cerr << "zz node: GetLocal " << pos << std::endl;
- curr->name = mappedLocals[getLEB128()];
+ curr->name = mappedLocals[getU32LEB()];
assert(curr->name.is());
curr->type = localTypes[curr->name];
}
void visitSetLocal(SetLocal *curr) {
if (debug) std::cerr << "zz node: SetLocal" << std::endl;
- curr->name = mappedLocals[getLEB128()];
+ curr->name = mappedLocals[getU32LEB()];
assert(curr->name.is());
curr->value = popExpression();
curr->type = curr->value->type;
}
void readMemoryAccess(uint32_t& alignment, size_t bytes, uint32_t& offset) {
- alignment = Pow2(getLEB128());
- offset = getLEB128();
+ alignment = Pow2(getU32LEB());
+ offset = getU32LEB();
}
bool maybeVisitImpl(Load *curr, uint8_t code) {
@@ -1729,8 +1729,8 @@ public:
}
bool maybeVisitImpl(Const *curr, uint8_t code) {
switch (code) {
- case BinaryConsts::I32Const: curr->value = Literal(getLEB128()); break;
- case BinaryConsts::I64Const: curr->value = Literal(getLEB256()); break;
+ case BinaryConsts::I32Const: curr->value = Literal(getU32LEB()); break;
+ case BinaryConsts::I64Const: curr->value = Literal(getU64LEB()); break;
case BinaryConsts::F32Const: curr->value = Literal(getFloat32()); break;
case BinaryConsts::F64Const: curr->value = Literal(getFloat64()); break;
default: return false;
diff --git a/test/emscripten b/test/emscripten
-Subproject b4e694961408bc530155161998f0165e5d4c8ba
+Subproject 2c7867418c0159eef403b0cf673e8b9aaaf29ee