[WebAssembly] Use hardcoded list expected undefined symbols (#21)

Rather than generate wasm.syms from wasm.js (which includes
a huge superset of the number of symbols actaully expected
to be undefined at link time) simply hardcode that list as
a test file, which lld can read.
This commit is contained in:
Sam Clegg 2017-11-07 15:17:25 -08:00 committed by GitHub
parent 8116ebcd0c
commit c185c68dd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 110 additions and 81 deletions

View File

@ -951,88 +951,83 @@ var ffi = (function() {
if (arguments.length < 1)
throw new Error('Expected at least one wasm module to load.');
if (arguments[0] == '--dump-ffi-symbols') {
for (var name in ffi["env"])
print(name)
} else {
function load_wasm(file_path) {
// TODO this should be split up in load, check dependencies, and then resolve
// dependencies. That would make it easier to do lazy loading. We could do
// this by catching load exceptions + adding to ffi and trying again, but
// we're talking silly there: modules should just tell us what they want.
const buf = (typeof readbuffer === 'function')
? new Uint8Array(readbuffer(file_path))
: read(file_path, 'binary');
instance = new WebAssembly.Instance(new WebAssembly.Module(buf), ffi)
// For the application exports its memory, we use that rather than
// the one we created. In this way this code works with modules that
// import or export their memory.
if (instance.exports.memory) {
heap = instance.exports.memory.buffer;
heap_uint8 = new Uint8Array(heap);
heap_size_bytes = heap.byteLength;
}
return instance;
function load_wasm(file_path) {
// TODO this should be split up in load, check dependencies, and then resolve
// dependencies. That would make it easier to do lazy loading. We could do
// this by catching load exceptions + adding to ffi and trying again, but
// we're talking silly there: modules should just tell us what they want.
const buf = (typeof readbuffer === 'function')
? new Uint8Array(readbuffer(file_path))
: read(file_path, 'binary');
instance = new WebAssembly.Instance(new WebAssembly.Module(buf), ffi)
// For the application exports its memory, we use that rather than
// the one we created. In this way this code works with modules that
// import or export their memory.
if (instance.exports.memory) {
heap = instance.exports.memory.buffer;
heap_uint8 = new Uint8Array(heap);
heap_size_bytes = heap.byteLength;
}
return instance;
}
// Load modules in reverse, adding their exports to the ffi object.
// This is analogous to how the linker resolves symbols: the later modules
// export symbols used by the earlier modules, and allow shadowing.
// Note that all modules, as well as the main module, share a heap.
var modules = {};
for (var i = arguments.length - 1; i > 0; --i) {
var path = arguments[i];
modules[i] = load_wasm(path);
for (var f in modules[i].exports) {
// TODO wasm modules don't have hasOwnProperty. They probably should.
// The code should look like:
// if (modules[i].hasOwnProperty(f) &&
// modules[i][f] instanceof Function)
if (modules[i].exports[f] instanceof Function)
ffi['env'][f] = modules[i].exports[f];
}
}
// Load the main module once the ffi object has been fully populated.
var main_module = arguments[0];
modules[0] = load_wasm(main_module);
// TODO check that `main` exists in modules[0].exports and error out if not.
try {
var ret = modules[0].exports.main();
stdio.__flush_stdout();
print(main_module + '::main() returned ' + ret);
if (ret != stdlib.EXIT_SUCCESS)
throw new Error('main reported failure');
} catch (e) {
stdio.__flush_stdout();
if (e instanceof TerminateWasmException) {
print('Program terminated with: ' + e);
if (stdlib.__get_exit_code() != stdlib.EXIT_SUCCESS) {
throw stdlib.__get_exit_code();
}
} else if (e instanceof NotYetImplementedException) {
print(e);
throw e;
} else {
function is_runtime_trap(e) {
if ('string' != typeof e) return false;
var traps = ['unreachable',
'memory access out of bounds',
'divide by zero',
'divide result unrepresentable',
'remainder by zero',
'integer result unrepresentable',
'invalid function',
'function signature mismatch'];
for (var msg in traps) if (e == traps[msg]) return true;
return false;
}
print(is_runtime_trap(e) ?
('Runtime trap: ' + e) :
('Unknown exception of type `' + typeof(e) + '`: ' + e));
throw e;
}
// Load modules in reverse, adding their exports to the ffi object.
// This is analogous to how the linker resolves symbols: the later modules
// export symbols used by the earlier modules, and allow shadowing.
// Note that all modules, as well as the main module, share a heap.
var modules = {};
for (var i = arguments.length - 1; i > 0; --i) {
var path = arguments[i];
modules[i] = load_wasm(path);
for (var f in modules[i].exports) {
// TODO wasm modules don't have hasOwnProperty. They probably should.
// The code should look like:
// if (modules[i].hasOwnProperty(f) &&
// modules[i][f] instanceof Function)
if (modules[i].exports[f] instanceof Function)
ffi['env'][f] = modules[i].exports[f];
}
}
// Load the main module once the ffi object has been fully populated.
var main_module = arguments[0];
modules[0] = load_wasm(main_module);
// TODO check that `main` exists in modules[0].exports and error out if not.
try {
var ret = modules[0].exports.main();
stdio.__flush_stdout();
print(main_module + '::main() returned ' + ret);
if (ret != stdlib.EXIT_SUCCESS)
throw new Error('main reported failure');
} catch (e) {
stdio.__flush_stdout();
if (e instanceof TerminateWasmException) {
print('Program terminated with: ' + e);
if (stdlib.__get_exit_code() != stdlib.EXIT_SUCCESS) {
throw stdlib.__get_exit_code();
}
} else if (e instanceof NotYetImplementedException) {
print(e);
throw e;
} else {
function is_runtime_trap(e) {
if ('string' != typeof e) return false;
var traps = ['unreachable',
'memory access out of bounds',
'divide by zero',
'divide result unrepresentable',
'remainder by zero',
'integer result unrepresentable',
'invalid function',
'function signature mismatch'];
for (var msg in traps) if (e == traps[msg]) return true;
return false;
}
print(is_runtime_trap(e) ?
('Runtime trap: ' + e) :
('Unknown exception of type `' + typeof(e) + '`: ' + e));
throw e;
}
}

34
arch/wasm32/wasm.syms Normal file
View File

@ -0,0 +1,34 @@
# Symbols we want wasm.js to define at runtime
_Exit
abort
puts
# Musl syscall interface, provided by wasm.js
__syscall
__syscall0
__syscall1
__syscall2
__syscall3
__syscall4
__syscall5
__syscall6
__syscall_cp
# Symbols not supported by clang but currently expected to work on the
# wasm waterfall
# TODO(sbc): remove these
__builtin_isinff
__builtin_isinfl
__builtin_clrsb
__builtin_clrsbl
__builtin_clrsbll
__builtin_apply
__builtin_apply_args
__builtin_malloc
# Part of musl we still don't compile for wasm
__lock
__unlock
__set_thread_area
setjmp
longjmp