Skip to content

Function pointer cast emulation#1468

Merged
kripken merged 16 commits into
masterfrom
fcastemu
Mar 13, 2018
Merged

Function pointer cast emulation#1468
kripken merged 16 commits into
masterfrom
fcastemu

Conversation

@kripken

@kripken kripken commented Mar 12, 2018

Copy link
Copy Markdown
Member

This adds a pass that implements "function pointer cast emulation" - allows indirect calls to go through even if the number of arguments or their types is incorrect. That is undefined behavior in C/C++ but in practice somehow works in native archs. It is even relied upon in e.g. Python.

Emscripten already has such emulation for asm.js, which also worked for asm2wasm. This implements something like it in binaryen which also allows the wasm backend to use it. As a result, Python should now be portable using the wasm backend.

The mechanism used for the emulation is to make all indirect calls use a fixed number of arguments, all of type i64, and a return type of also i64. Thunks are then placed in the table which translate the arguments properly for the target, basically by reinterpreting to i64 and back. As a result, receiving an i64 when an i32 is sent will have the upper bits all zero, and the reverse would truncate the upper bits, etc. (Note that this is different than emscripten's existing emulation, which converts (as signed) to a double. That makes sense for JS where double's can contain all numeric values, but in wasm we have i64s. Also, bitwise conversion may be more like what native archs do anyhow. It is enough for Python.)

Also adds validation for a function's type matching the function's actual params and result (surprised we didn't have that before, but we didn't, and there was even a place in the test suite where that was wrong).

Also simplifies the build script by moving two cpp files into the wasm/ subdir, so they can be built once and shared between the various tools.

@kripken kripken merged commit d52213c into master Mar 13, 2018
@kripken kripken deleted the fcastemu branch March 13, 2018 16:29
kripken added a commit to emscripten-core/emscripten that referenced this pull request Mar 15, 2018
This reworks how function cast emulation works in wasm: it uses the new binaryen pass for that (WebAssembly/binaryen#1468), which converts all indirect calls to use a simple ABI with a fixed number of arguments and i64s for all types. This lets stuff like Python work, which casts away extra arguments, making them technically invalid as wasm indirect calls without emulation.

This fixes #6309 (dynamic linking + wasm + function cast emulation in asm2wasm, which did not work) and also gets function cast emulation working in the wasm backend, enabling the test there. This should also get Python working in the wasm backend (however the test there can't be enabled as it's not compiling from source - I think we just bundled the bitcode because python was just huge).

To get asm2wasm dynamic linking working with function cast emulation, the way we get function pointers is changed: we used to get the exported function and use addFunction to add it to the table dynamically. This can't work with function cast emulation since the export is callable from JS, while function pointers need to use the i64 ABI, so we'd need to convert those at runtime, which is not practical. Instead, asm2wasm provides metadata from the backend about the function pointer for each export, and uses those directly. This is better anyhow because it's simpler and likely closer to what proper wasm dynamic linking will use eventually; also, using addFunction is tricky here since we don't know the type, so that couldn't have worked in the wasm backend anyhow.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant