//"use strict"; // Various namespace-like modules var STACK_ALIGN = 16; var Variables = { globals: {}, indexedGlobals: {}, // for indexed globals, ident ==> index // Used in calculation of indexed globals nextIndexedOffset: 0, resolveAliasToIdent: function(ident) { while (1) { var varData = Variables.globals[ident]; if (!(varData && varData.targetIdent)) break; ident = varData.targetIdent; // might need to eval to turn (6) into 6 } return ident; }, }; var Types = { types: {}, // Set to true if we actually use precise i64 math: If PRECISE_I64_MATH is set, and also such math is actually // needed (+,-,*,/,% - we do not need it for bitops), or PRECISE_I64_MATH is 2 (forced) preciseI64MathUsed: (PRECISE_I64_MATH == 2) }; var firstTableIndex = FUNCTION_POINTER_ALIGNMENT * RESERVED_FUNCTION_POINTERS + 1; var Functions = { // All functions that will be implemented in this file. Maps id to signature implementedFunctions: {}, libraryFunctions: {}, // functions added from the library. value 2 means asmLibraryFunction unimplementedFunctions: {}, // library etc. functions that we need to index, maps id to signature nextIndex: firstTableIndex, // Start at a non-0 (even, see below) value neededTables: set('v', 'vi', 'ii', 'iii'), // signatures that appeared (initialized with library stuff // we always use), and we will need a function table for blockAddresses: {}, // maps functions to a map of block labels to label ids aliases: {}, // in shared modules (MAIN_MODULE or SHARED_MODULE), a list of aliases for functions that have them getSignatureLetter: function(type) { switch(type) { case 'float': return 'f'; case 'double': return 'd'; case 'void': return 'v'; default: return 'i'; } }, getSignatureType: function(letter) { switch(letter) { case 'v': return 'void'; case 'i': return 'i32'; case 'f': return 'float'; case 'd': return 'double'; default: throw 'what is this sig? ' + sig; } }, getSignature: function(returnType, argTypes, hasVarArgs) { var sig = Functions.getSignatureLetter(returnType); for (var i = 0; i < argTypes.length; i++) { var type = argTypes[i]; if (!type) break; // varargs if (type in Compiletime.FLOAT_TYPES) { sig += Functions.getSignatureLetter(type); } else { var chunks = getNumIntChunks(type); if (chunks > 0) { for (var j = 0; j < chunks; j++) sig += 'i'; } else if (type !== '...') { // some special type like a SIMD vector (anything but varargs, which we handle below) sig += Functions.getSignatureLetter(type); } } } if (hasVarArgs) sig += 'i'; return sig; }, getTable: function(sig) { return 'FUNCTION_TABLE_' + sig } }; var LibraryManager = { library: null, structs: {}, loaded: false, load: function() { if (this.library) return; var libraries = [ 'library.js', 'library_formatString.js', 'library_syscall.js' ]; if (!NO_FILESYSTEM) { libraries = libraries.concat([ 'library_path.js', 'library_fs.js', 'library_idbfs.js', 'library_memfs.js', 'library_nodefs.js', 'library_sockfs.js', 'library_workerfs.js', 'library_tty.js', 'library_lz4.js', ]); } if (!NO_BROWSER) { libraries = libraries.concat([ 'library_browser.js' ]); } libraries = libraries.concat([ 'library_sdl.js', 'library_gl.js', 'library_glut.js', 'library_xlib.js', 'library_egl.js', 'library_openal.js', 'library_glfw.js', 'library_uuid.js', 'library_glew.js', 'library_html5.js', 'library_signals.js', 'library_idbstore.js', 'library_async.js', 'library_vr.js' ]).concat(additionalLibraries); if (BOOTSTRAPPING_STRUCT_INFO) libraries = ['library_bootstrap_structInfo.js', 'library_formatString.js']; for (var i = 0; i < libraries.length; i++) { var filename = libraries[i]; var src = read(filename); try { var processed = processMacros(preprocess(src, filename)); eval(processed); } catch(e) { var details = [e, e.lineNumber ? 'line number: ' + e.lineNumber : '', (e.stack || "").toString().replace('Object.', filename)]; if (processed) { error('failure to execute js library "' + filename + '": ' + details + '\npreprocessed source (you can run a js engine on this to get a clearer error message sometimes):\n=============\n' + processed + '\n=============\n'); } else { error('failure to process js library "' + filename + '": ' + details + '\noriginal source:\n=============\n' + src + '\n=============\n'); } throw e; } } // apply synonyms. these are typically not speed-sensitive, and doing it this way makes it possible to not include hacks in the compiler // (and makes it simpler to switch between SDL versions, fastcomp and non-fastcomp, etc.). var lib = LibraryManager.library; libloop: for (var x in lib) { if (x.lastIndexOf('__') > 0) continue; // ignore __deps, __* if (lib[x + '__asm']) continue; // ignore asm library functions, those need to be fully optimized if (typeof lib[x] === 'string') { var target = x; while (typeof lib[target] === 'string') { if (lib[target].indexOf('(') >= 0) continue libloop; if (lib[target].indexOf('Math_') == 0) continue libloop; target = lib[target]; } if (lib[target + '__asm']) continue; // This is an alias of an asm library function. Also needs to be fully optimized. if (typeof lib[target] === 'undefined' || typeof lib[target] === 'function') { lib[x] = new Function('return _' + target + '.apply(null, arguments)'); if (!lib[x + '__deps']) lib[x + '__deps'] = []; lib[x + '__deps'].push(target); } } } /* // export code for CallHandlers.h printErr('============================'); for (var x in this.library) { var y = this.library[x]; if (typeof y === 'string' && x.indexOf('__sig') < 0 && x.indexOf('__postset') < 0 && y.indexOf(' ') < 0) { printErr('DEF_REDIRECT_HANDLER(' + x + ', ' + y + ');'); } } printErr('============================'); for (var x in this.library) { var y = this.library[x]; if (typeof y === 'string' && x.indexOf('__sig') < 0 && x.indexOf('__postset') < 0 && y.indexOf(' ') < 0) { printErr(' SETUP_CALL_HANDLER(' + x + ');'); } } printErr('============================'); // end export code for CallHandlers.h */ this.loaded = true; }, // Given an ident, see if it is an alias for something, and so forth, returning // the earliest ancestor (the root) getRootIdent: function(ident) { if (!this.library) return null; var ret = LibraryManager.library[ident]; if (!ret) return null; var last = ident; while (typeof ret === 'string') { last = ret; ret = LibraryManager.library[ret]; } return last; }, isStubFunction: function(ident) { if (SIDE_MODULE == 1) return false; // cannot eliminate these, as may be implement in the main module and imported by us var libCall = LibraryManager.library[ident.substr(1)]; return typeof libCall === 'function' && libCall.toString().replace(/\s/g, '') === 'function(){}' && !(ident in Functions.implementedFunctions); } }; // Safe way to access a C define. We check that we don't add library functions with missing defines. function cDefine(key) { if (key in C_DEFINES) return C_DEFINES[key]; throw 'XXX missing C define ' + key + '!'; } var EXPORTED_RUNTIME_METHODS_SET = null; function maybeExport(name) { if (!EXPORTED_RUNTIME_METHODS_SET) EXPORTED_RUNTIME_METHODS_SET = set(EXPORTED_RUNTIME_METHODS.concat(EXTRA_EXPORTED_RUNTIME_METHODS)); if (name in EXPORTED_RUNTIME_METHODS_SET) { return 'Module["' + name + '"] = ' + name + ';'; } else { return ''; } } var PassManager = { serialize: function() { print('\n//FORWARDED_DATA:' + JSON.stringify({ Functions: Functions, EXPORTED_FUNCTIONS: EXPORTED_FUNCTIONS })); }, load: function(json) { var data = JSON.parse(json); for (var i in data.Types) { Types[i] = data.Types[i]; } for (var i in data.Variables) { Variables[i] = data.Variables[i]; } for (var i in data.Functions) { Functions[i] = data.Functions[i]; } EXPORTED_FUNCTIONS = data.EXPORTED_FUNCTIONS; /* print('\n//LOADED_DATA:' + JSON.stringify({ Types: Types, Variables: Variables, Functions: Functions })); */ } };