Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Compilers built using Binaryen include
* [`asm2wasm`](https://github.com/WebAssembly/binaryen/blob/master/src/asm2wasm.h) which compiles asm.js to WebAssembly
* [`AssemblyScript`](https://github.com/AssemblyScript/assemblyscript) which compiles TypeScript to Binaryen IR
* [`wasm2asm`](https://github.com/WebAssembly/binaryen/blob/master/src/wasm2asm.h) which compiles WebAssembly to asm.js
* [`mir2wasm`](https://github.com/brson/mir2wasm/) which compiles Rust MIR
* [`Asterius`](https://github.com/tweag/asterius) which compiles Haskell to WebAssembly

Binaryen also provides a set of **toolchain utilities** that can

Expand Down
6 changes: 5 additions & 1 deletion auto_update_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,11 @@ def update_binaryen_js_tests():
f.close()
if MOZJS or node_has_wasm or 'WebAssembly.' not in test_src:
cmd = [MOZJS or NODEJS, 'a.js']
out = run_command(cmd, stderr=subprocess.STDOUT)
if 'fatal' not in s:
out = run_command(cmd, stderr=subprocess.STDOUT)
else:
# expect an error - the specific error code will depend on the vm
out = run_command(cmd, stderr=subprocess.STDOUT, expected_status=None)
with open(os.path.join('test', 'binaryen.js', s + '.txt'), 'w') as o:
o.write(out)
else:
Expand Down
10 changes: 7 additions & 3 deletions check.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,11 @@ def run_binaryen_js_tests():

def test(engine):
cmd = [engine, 'a.js']
out = run_command(cmd, stderr=subprocess.STDOUT)
if 'fatal' not in s:
out = run_command(cmd, stderr=subprocess.STDOUT)
else:
# expect an error - the specific error code will depend on the vm
out = run_command(cmd, stderr=subprocess.STDOUT, expected_status=None)
expected = open(os.path.join(options.binaryen_test, 'binaryen.js', s + '.txt')).read()
if expected not in out:
fail(out, expected)
Expand Down Expand Up @@ -510,7 +514,7 @@ def run_vanilla_tests():
del os.environ['EMCC_WASM_BACKEND']


def run_gcc_torture_tests():
def run_gcc_tests():
print '\n[ checking native gcc testcases...]\n'
if not NATIVECC or not NATIVEXX:
fail_with_error('Native compiler (e.g. gcc/g++) was not found in PATH!')
Expand Down Expand Up @@ -648,7 +652,7 @@ def main():
run_vanilla_tests()
print '\n[ checking example testcases... ]\n'
if options.run_gcc_tests:
run_gcc_torture_tests()
run_gcc_tests()
if EMCC:
run_emscripten_tests()

Expand Down
2 changes: 1 addition & 1 deletion scripts/test/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def run_command(cmd, expected_status=0, stderr=None,
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=stderr, universal_newlines=True)
out, err = proc.communicate()
code = proc.returncode
if code != expected_status:
if expected_status is not None and code != expected_status:
raise Exception(('run_command failed (%s)' % code, out + str(err or '')))
err_correct = expected_err is None or \
(expected_err in err if err_contains else expected_err == err)
Expand Down
8 changes: 8 additions & 0 deletions src/binaryen-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2601,4 +2601,12 @@ BinaryenFunctionTypeRef BinaryenGetFunctionTypeBySignature(BinaryenModuleRef mod
return NULL;
}

#ifdef __EMSCRIPTEN__
// Override atexit - we don't need any global ctors to actually run, and
// otherwise we get clutter in the output in debug builds
int atexit(void (*function)(void)) {
return 0;
}
#endif

} // extern "C"
9 changes: 9 additions & 0 deletions src/js/binaryen.js-post.js
Original file line number Diff line number Diff line change
Expand Up @@ -1609,3 +1609,12 @@ Module['setDebugInfo'] = function(on) {
Module['setAPITracing'] = function(on) {
return Module['_BinaryenSetAPITracing'](on);
};

// Additional customizations

Module['exit'] = function(status) {
// Instead of exiting silently on errors, always show an error with
// a stack trace, for debuggability.
if (status != 0) throw new Error('exiting due to error: ' + status);
};

112 changes: 80 additions & 32 deletions src/wasm/wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -619,8 +619,11 @@ Name Function::getLocalNameOrGeneric(Index index) {
}

Index Function::getLocalIndex(Name name) {
assert(localIndices.count(name) > 0);
return localIndices[name];
auto iter = localIndices.find(name);
if (iter == localIndices.end()) {
Fatal() << "Function::getLocalIndex: " << name << " does not exist";
}
return iter->second;
}

Index Function::getVarIndexBase() {
Expand All @@ -638,92 +641,137 @@ Type Function::getLocalType(Index index) {
}

FunctionType* Module::getFunctionType(Name name) {
assert(functionTypesMap.count(name));
return functionTypesMap[name];
auto iter = functionTypesMap.find(name);
if (iter == functionTypesMap.end()) {
Fatal() << "Module::getFunctionType: " << name << " does not exist";
}
return iter->second;
}

Import* Module::getImport(Name name) {
assert(importsMap.count(name));
return importsMap[name];
auto iter = importsMap.find(name);
if (iter == importsMap.end()) {
Fatal() << "Module::getImport: " << name << " does not exist";
}
return iter->second;
}

Export* Module::getExport(Name name) {
assert(exportsMap.count(name));
return exportsMap[name];
auto iter = exportsMap.find(name);
if (iter == exportsMap.end()) {
Fatal() << "Module::getExport: " << name << " does not exist";
}
return iter->second;
}

Function* Module::getFunction(Name name) {
assert(functionsMap.count(name));
return functionsMap[name];
auto iter = functionsMap.find(name);
if (iter == functionsMap.end()) {
Fatal() << "Module::getFunction: " << name << " does not exist";
}
return iter->second;
}

Global* Module::getGlobal(Name name) {
assert(globalsMap.count(name));
return globalsMap[name];
auto iter = globalsMap.find(name);
if (iter == globalsMap.end()) {
Fatal() << "Module::getGlobal: " << name << " does not exist";
}
return iter->second;
}

FunctionType* Module::getFunctionTypeOrNull(Name name) {
if (!functionTypesMap.count(name))
auto iter = functionTypesMap.find(name);
if (iter == functionTypesMap.end()) {
return nullptr;
return functionTypesMap[name];
}
return iter->second;
}

Import* Module::getImportOrNull(Name name) {
if (!importsMap.count(name))
auto iter = importsMap.find(name);
if (iter == importsMap.end()) {
return nullptr;
return importsMap[name];
}
return iter->second;
}

Export* Module::getExportOrNull(Name name) {
if (!exportsMap.count(name))
auto iter = exportsMap.find(name);
if (iter == exportsMap.end()) {
return nullptr;
return exportsMap[name];
}
return iter->second;
}

Function* Module::getFunctionOrNull(Name name) {
if (!functionsMap.count(name))
auto iter = functionsMap.find(name);
if (iter == functionsMap.end()) {
return nullptr;
return functionsMap[name];
}
return iter->second;
}

Global* Module::getGlobalOrNull(Name name) {
if (!globalsMap.count(name))
auto iter = globalsMap.find(name);
if (iter == globalsMap.end()) {
return nullptr;
return globalsMap[name];
}
return iter->second;
}

void Module::addFunctionType(FunctionType* curr) {
assert(curr->name.is());
if (!curr->name.is()) {
Fatal() << "Module::addFunctionType: empty name";
}
if (getFunctionTypeOrNull(curr->name)) {
Fatal() << "Module::addFunctionType: " << curr->name << " already exists";
}
functionTypes.push_back(std::unique_ptr<FunctionType>(curr));
assert(functionTypesMap.find(curr->name) == functionTypesMap.end());
functionTypesMap[curr->name] = curr;
}

void Module::addImport(Import* curr) {
assert(curr->name.is());
if (!curr->name.is()) {
Fatal() << "Module::addImport: empty name";
}
if (getImportOrNull(curr->name)) {
Fatal() << "Module::addImport: " << curr->name << " already exists";
}
imports.push_back(std::unique_ptr<Import>(curr));
assert(importsMap.find(curr->name) == importsMap.end());
importsMap[curr->name] = curr;
}

void Module::addExport(Export* curr) {
assert(curr->name.is());
if (!curr->name.is()) {
Fatal() << "Module::addExport: empty name";
}
if (getExportOrNull(curr->name)) {
Fatal() << "Module::addExport: " << curr->name << " already exists";
}
exports.push_back(std::unique_ptr<Export>(curr));
assert(exportsMap.find(curr->name) == exportsMap.end());
exportsMap[curr->name] = curr;
}

void Module::addFunction(Function* curr) {
assert(curr->name.is());
if (!curr->name.is()) {
Fatal() << "Module::addFunction: empty name";
}
if (getFunctionOrNull(curr->name)) {
Fatal() << "Module::addFunction: " << curr->name << " already exists";
}
functions.push_back(std::unique_ptr<Function>(curr));
assert(functionsMap.find(curr->name) == functionsMap.end());
functionsMap[curr->name] = curr;
}

void Module::addGlobal(Global* curr) {
assert(curr->name.is());
if (!curr->name.is()) {
Fatal() << "Module::addGlobal: empty name";
}
if (getGlobalOrNull(curr->name)) {
Fatal() << "Module::addGlobal: " << curr->name << " already exists";
}
globals.push_back(std::unique_ptr<Global>(curr));
assert(globalsMap.find(curr->name) == globalsMap.end());
globalsMap[curr->name] = curr;
}

Expand Down
4 changes: 4 additions & 0 deletions test/binaryen.js/fatal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
var wasm = new Binaryen.Module()
wasm.addFunctionType("vI", Binaryen.i32, []);
// It will cause a fatal error to try to add the same name a second time
wasm.addFunctionType("vI", Binaryen.i32, []);
1 change: 1 addition & 0 deletions test/binaryen.js/fatal.js.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fatal: Module::addFunctionType: $vI already exists