Create a gist now

Instantly share code, notes, and snippets.

Post-process emscripten output to allow unaligned accesses
#!/usr/bin/env python
import re
import sys
# load file to be processed
with open(sys.argv[1], "r") as f:
source = f.read()
# remove all known functions for memory access
# note: this implementation uses a weak heuristic: only the closing } of a given function has no indentation
for func in ["SAFE_HEAP_LOAD", "SAFE_HEAP_LOAD_D", "SAFE_HEAP_STORE", "SAFE_HEAP_STORE_D"]:
source = re.sub("function %s\([^\)]*\)\s*{(.*\n)+?}" % func, "", source)
# we're not using emscripten's --pre-js and --post-js as it interferes with --embed-file
with open(sys.argv[1], "w") as f:
f.write("""
if (typeof(Rocky)==="undefined") {
Rocky = {};
}
Rocky.Module = function() {
""")
f.write(source)
f.write("""
// support non-aligned memory access
function SAFE_HEAP_STORE(dest, value, bytes, isFloat) {
if (dest <= 0) abort('segmentation fault storing ' + bytes + ' bytes to address ' + dest);
if (dest + bytes > Math.max(DYNAMICTOP, STATICTOP)) abort('segmentation fault, exceeded the top of the available heap when storing ' + bytes + ' bytes to address ' + dest + '. STATICTOP=' + STATICTOP + ', DYNAMICTOP=' + DYNAMICTOP);
assert(DYNAMICTOP <= TOTAL_MEMORY);
if (dest % bytes !== 0) {
for (var i = 0; i < bytes; i++) {
HEAPU8[dest + i >> 0] = (dest >> (8 * i)) & 0xff;
}
} else {
setValue(dest, value, getSafeHeapType(bytes, isFloat), 1);
}
}
function SAFE_HEAP_STORE_D(dest, value, bytes) {
SAFE_HEAP_STORE(dest, value, bytes, true);
}
function SAFE_HEAP_LOAD(dest, bytes, unsigned, isFloat) {
// overrule
if (dest <= 0) abort('segmentation fault loading ' + bytes + ' bytes from address ' + dest);
if (dest + bytes > Math.max(DYNAMICTOP, STATICTOP)) abort('segmentation fault, exceeded the top of the available heap when loading ' + bytes + ' bytes from address ' + dest + '. STATICTOP=' + STATICTOP + ', DYNAMICTOP=' + DYNAMICTOP);
assert(DYNAMICTOP <= TOTAL_MEMORY);
var type = getSafeHeapType(bytes, isFloat);
var ret;
if (dest % bytes !== 0) {
for (var i = 0; i < bytes; i++) {
ret |= HEAPU8[dest + i >> 0] << (8 * i);
}
} else {
ret = getValue(dest, type, 1);
}
if (unsigned) ret = unSign(ret, parseInt(type.substr(1)), 1);
return ret;
}
function SAFE_HEAP_LOAD_D(dest, bytes, unsigned) {
return SAFE_HEAP_LOAD(dest, bytes, unsigned, true);
}
return Module;
};
if (typeof(module) !== "undefined") {
module.exports = Rocky.Module;
}
""")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment