@@ -2032,4 +2032,343 @@ Module['FS_createPreloadedFile'] = FS.createPreloadedFile;
20322032var cyberDWARFFile = '{{{ BUNDLED_CD_DEBUG_FILE }}}' ;
20332033#endif
20342034
2035+ #if BINARYEN
2036+ function integrateWasmJS ( Module ) {
2037+ // wasm.js has several methods for creating the compiled code module here:
2038+ // * 'native-wasm' : use native WebAssembly support in the browser
2039+ // * 'interpret-s-expr': load s-expression code from a .wast and interpret
2040+ // * 'interpret-binary': load binary wasm and interpret
2041+ // * 'interpret-asm2wasm': load asm.js code, translate to wasm, and interpret
2042+ // * 'asmjs': no wasm, just load the asm.js code and use that (good for testing)
2043+ // The method can be set at compile time (BINARYEN_METHOD), or runtime by setting Module['wasmJSMethod'].
2044+ // The method can be a comma-separated list, in which case, we will try the
2045+ // options one by one. Some of them can fail gracefully, and then we can try
2046+ // the next.
2047+
2048+ // inputs
2049+
2050+ var method = Module [ 'wasmJSMethod' ] || '{{{ BINARYEN_METHOD }}}' ;
2051+ Module [ 'wasmJSMethod' ] = method ;
2052+
2053+ var wasmTextFile = Module [ 'wasmTextFile' ] || '{{{ WASM_TEXT_FILE }}}' ;
2054+ var wasmBinaryFile = Module [ 'wasmBinaryFile' ] || '{{{ WASM_BINARY_FILE }}}' ;
2055+ var asmjsCodeFile = Module [ 'asmjsCodeFile' ] || '{{{ ASMJS_CODE_FILE }}}' ;
2056+
2057+ // utilities
2058+
2059+ var wasmPageSize = 64 * 1024 ;
2060+
2061+ var asm2wasmImports = { // special asm2wasm imports
2062+ "f64-rem" : function ( x , y ) {
2063+ return x % y ;
2064+ } ,
2065+ "f64-to-int" : function ( x ) {
2066+ return x | 0 ;
2067+ } ,
2068+ "i32s-div" : function ( x , y ) {
2069+ return ( ( x | 0 ) / ( y | 0 ) ) | 0 ;
2070+ } ,
2071+ "i32u-div" : function ( x , y ) {
2072+ return ( ( x >>> 0 ) / ( y >>> 0 ) ) >>> 0 ;
2073+ } ,
2074+ "i32s-rem" : function ( x , y ) {
2075+ return ( ( x | 0 ) % ( y | 0 ) ) | 0 ;
2076+ } ,
2077+ "i32u-rem" : function ( x , y ) {
2078+ return ( ( x >>> 0 ) % ( y >>> 0 ) ) >>> 0 ;
2079+ } ,
2080+ "debugger" : function ( ) {
2081+ debugger ;
2082+ } ,
2083+ } ;
2084+
2085+ var info = {
2086+ 'global' : null ,
2087+ 'env' : null ,
2088+ 'asm2wasm' : asm2wasmImports ,
2089+ 'parent' : Module // Module inside wasm-js.cpp refers to wasm-js.cpp; this allows access to the outside program.
2090+ } ;
2091+
2092+ var exports = null ;
2093+
2094+ function lookupImport ( mod , base ) {
2095+ var lookup = info ;
2096+ if ( mod . indexOf ( '.' ) < 0 ) {
2097+ lookup = ( lookup || { } ) [ mod ] ;
2098+ } else {
2099+ var parts = mod . split ( '.' ) ;
2100+ lookup = ( lookup || { } ) [ parts [ 0 ] ] ;
2101+ lookup = ( lookup || { } ) [ parts [ 1 ] ] ;
2102+ }
2103+ if ( base ) {
2104+ lookup = ( lookup || { } ) [ base ] ;
2105+ }
2106+ if ( lookup === undefined ) {
2107+ abort ( 'bad lookupImport to (' + mod + ').' + base ) ;
2108+ }
2109+ return lookup ;
2110+ }
2111+
2112+ function mergeMemory ( newBuffer ) {
2113+ // The wasm instance creates its memory. But static init code might have written to
2114+ // buffer already, including the mem init file, and we must copy it over in a proper merge.
2115+ // TODO: avoid this copy, by avoiding such static init writes
2116+ // TODO: in shorter term, just copy up to the last static init write
2117+ var oldBuffer = Module [ 'buffer' ] ;
2118+ if ( newBuffer . byteLength < oldBuffer . byteLength ) {
2119+ Module [ 'printErr' ] ( 'the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here' ) ;
2120+ }
2121+ var oldView = new Int8Array ( oldBuffer ) ;
2122+ var newView = new Int8Array ( newBuffer ) ;
2123+
2124+ // If we have a mem init file, do not trample it
2125+ if ( ! memoryInitializer ) {
2126+ oldView . set ( newView . subarray ( Module [ 'STATIC_BASE' ] , Module [ 'STATIC_BASE' ] + Module [ 'STATIC_BUMP' ] ) , Module [ 'STATIC_BASE' ] ) ;
2127+ }
2128+
2129+ newView . set ( oldView ) ;
2130+ updateGlobalBuffer ( newBuffer ) ;
2131+ updateGlobalBufferViews ( ) ;
2132+ }
2133+
2134+ var WasmTypes = {
2135+ none : 0 ,
2136+ i32 : 1 ,
2137+ i64 : 2 ,
2138+ f32 : 3 ,
2139+ f64 : 4
2140+ } ;
2141+
2142+ function fixImports ( imports ) {
2143+ if ( ! { { { WASM_BACKEND } } } ) return imports ;
2144+ var ret = { } ;
2145+ for ( var i in imports ) {
2146+ var fixed = i ;
2147+ if ( fixed [ 0 ] == '_' ) fixed = fixed . substr ( 1 ) ;
2148+ ret [ fixed ] = imports [ i ] ;
2149+ }
2150+ return ret ;
2151+ }
2152+
2153+ function getBinary ( ) {
2154+ var binary ;
2155+ if ( ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER ) {
2156+ binary = Module [ 'wasmBinary' ] ;
2157+ assert ( binary , "on the web, we need the wasm binary to be preloaded and set on Module['wasmBinary']. emcc.py will do that for you when generating HTML (but not JS)" ) ;
2158+ binary = new Uint8Array ( binary ) ;
2159+ } else {
2160+ binary = Module [ 'readBinary' ] ( wasmBinaryFile ) ;
2161+ }
2162+ return binary ;
2163+ }
2164+
2165+ // do-method functions
2166+
2167+ function doJustAsm ( global , env, providedBuffer ) {
2168+ // if no Module.asm, or it's the method handler helper (see below), then apply
2169+ // the asmjs
2170+ if ( typeof Module [ 'asm' ] !== 'function' || Module [ 'asm' ] === methodHandler ) {
2171+ if ( ! Module [ 'asmPreload' ] ) {
2172+ // you can load the .asm.js file before this, to avoid this sync xhr and eval
2173+ eval ( Module [ 'read' ] ( asmjsCodeFile ) ) ; // set Module.asm
2174+ } else {
2175+ Module [ 'asm' ] = Module [ 'asmPreload' ] ;
2176+ }
2177+ }
2178+ if ( typeof Module [ 'asm '] !== 'function ') {
2179+ Module [ 'printErr '] ( 'asm evalling did not set the module properly ') ;
2180+ return false ;
2181+ }
2182+ return Module [ 'asm' ] ( global , env , providedBuffer ) ;
2183+ }
2184+
2185+ function doNativeWasm ( global , env , providedBuffer ) {
2186+ if ( typeof WebAssembly !== 'object' ) {
2187+ Module [ 'printErr' ] ( 'no native wasm support detected' ) ;
2188+ return false ;
2189+ }
2190+ // prepare memory import
2191+ if ( ! ( Module [ 'wasmMemory' ] instanceof WebAssembly . Memory ) ) {
2192+ Module [ 'printErr' ] ( 'no native wasm Memory in use' ) ;
2193+ return false ;
2194+ }
2195+ env [ 'memory' ] = Module [ 'wasmMemory' ] ;
2196+ // Load the wasm module and create an instance of using native support in the JS engine.
2197+ info [ 'global' ] = {
2198+ 'NaN' : NaN ,
2199+ 'Infinity' : Infinity
2200+ } ;
2201+ info [ 'global.Math' ] = global . Math ;
2202+ info [ 'env' ] = env ;
2203+ var instance ;
2204+ try {
2205+ instance = new WebAssembly . Instance ( new WebAssembly . Module ( getBinary ( ) ) , info )
2206+ } catch ( e ) {
2207+ Module [ 'printErr' ] ( 'failed to compile wasm module: ' + e ) ;
2208+ if ( e . toString ( ) . indexOf ( 'imported Memory with incompatible size' ) >= 0 ) {
2209+ Module [ 'printErr' ] ( 'Memory size incompatibility issues may be due to changing TOTAL_MEMORY at runtime to something too large. Use ALLOW_MEMORY_GROWTH to allow any size memory (and also make sure not to set TOTAL_MEMORY at runtime to something smaller than it was at compile time).' ) ;
2210+ }
2211+ return false ;
2212+ }
2213+ exports = instance . exports ;
2214+ if ( exports . memory ) mergeMemory ( exports . memory ) ;
2215+
2216+ Module [ "usingWasm" ] = true ;
2217+
2218+ return exports ;
2219+ }
2220+
2221+ function doWasmPolyfill ( global , env , providedBuffer , method ) {
2222+ if ( typeof WasmJS !== 'function' ) {
2223+ Module [ 'printErr' ] ( 'WasmJS not detected - polyfill not bundled?' ) ;
2224+ return false ;
2225+ }
2226+
2227+ // Use wasm.js to polyfill and execute code in a wasm interpreter.
2228+ var wasmJS = WasmJS ( { } ) ;
2229+
2230+ // XXX don't be confused. Module here is in the outside program. wasmJS is the inner wasm-js.cpp.
2231+ wasmJS [ 'outside' ] = Module ; // Inside wasm-js.cpp, Module['outside'] reaches the outside module.
2232+
2233+ // Information for the instance of the module.
2234+ wasmJS [ 'info' ] = info ;
2235+
2236+ wasmJS [ 'lookupImport' ] = lookupImport ;
2237+
2238+ assert ( providedBuffer === Module [ 'buffer' ] ) ; // we should not even need to pass it as a 3rd arg for wasm, but that's the asm.js way.
2239+
2240+ info . global = global ;
2241+ info . env = env ;
2242+
2243+ // polyfill interpreter expects an ArrayBuffer
2244+ assert ( providedBuffer === Module [ 'buffer' ] ) ;
2245+ env [ 'memory' ] = providedBuffer ;
2246+ assert ( env [ 'memory' ] instanceof ArrayBuffer ) ;
2247+
2248+ wasmJS [ 'providedTotalMemory' ] = Module [ 'buffer' ] . byteLength ;
2249+
2250+ // Prepare to generate wasm, using either asm2wasm or s-exprs
2251+ var code ;
2252+ if ( method === 'interpret-binary' ) {
2253+ code = getBinary ( ) ;
2254+ } else {
2255+ code = Module [ 'read' ] ( method == 'interpret-asm2wasm' ? asmjsCodeFile : wasmTextFile ) ;
2256+ }
2257+ var temp ;
2258+ if ( method == 'interpret-asm2wasm' ) {
2259+ temp = wasmJS [ '_malloc' ] ( code . length + 1 ) ;
2260+ wasmJS [ 'writeAsciiToMemory' ] ( code , temp ) ;
2261+ wasmJS [ '_load_asm2wasm' ] ( temp ) ;
2262+ } else if ( method === 'interpret-s-expr' ) {
2263+ temp = wasmJS [ '_malloc' ] ( code . length + 1 ) ;
2264+ wasmJS [ 'writeAsciiToMemory' ] ( code , temp ) ;
2265+ wasmJS [ '_load_s_expr2wasm' ] ( temp ) ;
2266+ } else if ( method === 'interpret-binary' ) {
2267+ temp = wasmJS [ '_malloc' ] ( code . length ) ;
2268+ wasmJS [ 'HEAPU8' ] . set ( code , temp ) ;
2269+ wasmJS [ '_load_binary2wasm' ] ( temp , code . length ) ;
2270+ } else {
2271+ throw 'what? ' + method ;
2272+ }
2273+ wasmJS [ '_free' ] ( temp ) ;
2274+
2275+ wasmJS [ '_instantiate' ] ( temp ) ;
2276+
2277+ if ( Module [ 'newBuffer' ] ) {
2278+ mergeMemory ( Module [ 'newBuffer' ] ) ;
2279+ Module [ 'newBuffer' ] = null ;
2280+ }
2281+
2282+ exports = wasmJS [ 'asmExports' ] ;
2283+
2284+ return exports ;
2285+ }
2286+
2287+ // We may have a preloaded value in Module.asm, save it
2288+ Module [ 'asmPreload' ] = Module [ 'asm' ] ;
2289+
2290+ // Memory growth integration code
2291+ Module [ 'reallocBuffer' ] = function ( size ) {
2292+ size = Math . ceil ( size / wasmPageSize ) * wasmPageSize ; // round up to wasm page size
2293+ var old = Module [ 'buffer' ] ;
2294+ var result = exports [ '__growWasmMemory' ] ( size / wasmPageSize ) ; // tiny wasm method that just does grow_memory
2295+ if ( Module [ "usingWasm" ] ) {
2296+ if ( result !== ( - 1 | 0 ) ) {
2297+ // success in native wasm memory growth, get the buffer from the memory
2298+ return Module [ 'buffer' ] = Module [ 'wasmMemory' ] . buffer ;
2299+ } else {
2300+ return null ;
2301+ }
2302+ } else {
2303+ // in interpreter, we replace Module.buffer if we allocate
2304+ return Module [ 'buffer' ] !== old ? Module [ 'buffer' ] : null ; // if it was reallocated, it changed
2305+ }
2306+ } ;
2307+
2308+ // Provide an "asm.js function" for the application, called to "link" the asm.js module. We instantiate
2309+ // the wasm module at that time, and it receives imports and provides exports and so forth, the app
2310+ // doesn't need to care that it is wasm or olyfilled wasm or asm.js.
2311+
2312+ Module [ 'asm' ] = function ( global , env , providedBuffer ) {
2313+ global = fixImports ( global ) ;
2314+ env = fixImports ( env ) ;
2315+
2316+ // import table
2317+ if ( ! env [ 'table' ] ) {
2318+ var TABLE_SIZE = Module [ 'wasmTableSize' ] ;
2319+ if ( TABLE_SIZE === undefined ) TABLE_SIZE = 1024 ; // works in binaryen interpreter at least
2320+ var MAX_TABLE_SIZE = Module [ 'wasmMaxTableSize' ] ;
2321+ if ( typeof WebAssembly === 'object' && typeof WebAssembly . Table === 'function' ) {
2322+ if ( MAX_TABLE_SIZE !== undefined ) {
2323+ env [ 'table' ] = new WebAssembly . Table ( { initial : TABLE_SIZE , maximum : MAX_TABLE_SIZE , element : 'anyfunc' } ) ;
2324+ } else {
2325+ env [ 'table' ] = new WebAssembly . Table ( { initial : TABLE_SIZE , element : 'anyfunc' } ) ;
2326+ }
2327+ } else {
2328+ env [ 'table' ] = new Array ( TABLE_SIZE ) ; // works in binaryen interpreter at least
2329+ }
2330+ Module [ 'wasmTable' ] = env [ 'table' ] ;
2331+ }
2332+
2333+ if ( ! env [ 'memoryBase' ] ) {
2334+ env [ 'memoryBase' ] = Module [ 'STATIC_BASE' ] ; // tell the memory segments where to place themselves
2335+ }
2336+ if ( ! env [ 'tableBase' ] ) {
2337+ env [ 'tableBase' ] = 0 ; // table starts at 0 by default, in dynamic linking this will change
2338+ }
2339+
2340+ // try the methods. each should return the exports if it succeeded
2341+
2342+ var exports ;
2343+ var methods = method . split ( ',' ) ;
2344+
2345+ for ( var i = 0 ; i < methods . length ; i ++ ) {
2346+ var curr = methods [ i ] ;
2347+
2348+ Module [ 'printErr' ] ( 'trying binaryen method: ' + curr ) ;
2349+
2350+ if ( curr === 'native-wasm' ) {
2351+ if ( exports = doNativeWasm ( global , env , providedBuffer ) ) break ;
2352+ } else if ( curr === 'asmjs' ) {
2353+ if ( exports = doJustAsm ( global , env , providedBuffer ) ) break ;
2354+ } else if ( curr === 'interpret-asm2wasm' || curr === 'interpret-s-expr' || curr === 'interpret-binary' ) {
2355+ if ( exports = doWasmPolyfill ( global , env , providedBuffer , curr ) ) break ;
2356+ } else {
2357+ throw 'bad method: ' + curr ;
2358+ }
2359+ }
2360+
2361+ if ( ! exports ) throw 'no binaryen method succeeded. consider enabling more options, like interpreting, if you want that: https://github.com/kripken/emscripten/wiki/WebAssembly#binaryen-methods' ;
2362+
2363+ Module [ 'printErr' ] ( 'binaryen method succeeded.' ) ;
2364+
2365+ return exports ;
2366+ } ;
2367+
2368+ var methodHandler = Module [ 'asm' ] ; // note our method handler, as we may modify Module['asm'] later
2369+ }
2370+
2371+ integrateWasmJS ( Module ) ;
2372+ #endif
2373+
20352374// === Body ===
0 commit comments