From 4153f5bc83f5ea6ba80db7dc4256db353eacef98 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Tue, 24 Jul 2018 11:08:15 -0400 Subject: [PATCH 1/4] Update emscripten to 1.38.10 --- Makefile.envs | 6 +- emsdk/Makefile | 9 +- emsdk/files/library.js | 4800 ----------------- emsdk/files/library_browser.js | 1518 ------ emsdk/files/preamble.js | 2482 --------- emsdk/files/support.js | 546 -- .../float-remainder-in-side-module.patch | 38 - 7 files changed, 7 insertions(+), 9392 deletions(-) delete mode 100644 emsdk/files/library.js delete mode 100644 emsdk/files/library_browser.js delete mode 100644 emsdk/files/preamble.js delete mode 100644 emsdk/files/support.js delete mode 100644 emsdk/patches/float-remainder-in-side-module.patch diff --git a/Makefile.envs b/Makefile.envs index b94e90988..419fd8252 100644 --- a/Makefile.envs +++ b/Makefile.envs @@ -1,10 +1,10 @@ -export PATH := $(PYODIDE_ROOT)/ccache:$(PYODIDE_ROOT)/emsdk/emsdk:$(PYODIDE_ROOT)/emsdk/emsdk/clang/tag-e-1.38.4/build_tag-e1.38.4_64/bin:$(PYODIDE_ROOT)/emsdk/emsdk/node/8.9.1_64bit/bin:$(PYODIDE_ROOT)/emsdk/emsdk/emscripten/tag-1.38.4:$(PYODIDE_ROOT)/emsdk/emsdk/binaryen/tag-1.38.4_64bit_binaryen/bin:$(PATH) +export PATH := $(PYODIDE_ROOT)/ccache:$(PYODIDE_ROOT)/emsdk/emsdk:$(PYODIDE_ROOT)/emsdk/emsdk/clang/tag-e-1.38.4/build_tag-e1.38.10_64/bin:$(PYODIDE_ROOT)/emsdk/emsdk/node/8.9.1_64bit/bin:$(PYODIDE_ROOT)/emsdk/emsdk/emscripten/tag-1.38.10:$(PYODIDE_ROOT)/emsdk/emsdk/binaryen/tag-1.38.10_64bit_binaryen/bin:$(PATH) export EMSDK = $(PYODIDE_ROOT)/emsdk/emsdk export EM_CONFIG = $(PYODIDE_ROOT)/emsdk/emsdk/.emscripten export EM_CACHE = $(PYODIDE_ROOT)/emsdk/emsdk/.emscripten_cache -export EMSCRIPTEN = $(PYODIDE_ROOT)/emsdk/emsdk/emscripten/tag-1.38.4 -export BINARYEN_ROOT = $(PYODIDE_ROOT)/emsdk/emsdk/binaryen/tag-1.38.4_64bit_binaryen +export EMSCRIPTEN = $(PYODIDE_ROOT)/emsdk/emsdk/emscripten/tag-1.38.10 +export BINARYEN_ROOT = $(PYODIDE_ROOT)/emsdk/emsdk/binaryen/tag-1.38.10_64bit_binaryen export PYVERSION=3.6.4 export PYMINOR=$(basename $(PYVERSION)) diff --git a/emsdk/Makefile b/emsdk/Makefile index 3b5964142..1c7164ab1 100644 --- a/emsdk/Makefile +++ b/emsdk/Makefile @@ -9,15 +9,14 @@ emsdk/.complete: sed -i -e "s#CPU_CORES = max(multiprocessing.cpu_count()-1, 1)#CPU_CORES = 3#g" emsdk/emsdk ( \ cd emsdk ; \ - ./emsdk install --build=Release sdk-tag-1.38.4-64bit binaryen-tag-1.38.4-64bit ; \ + ./emsdk install --build=Release sdk-tag-1.38.10-64bit binaryen-tag-1.38.10-64bit ; \ cd .. ; \ (cat patches/*.patch | patch -p1) ; \ - cp files/* emsdk/emscripten/tag-1.38.4/src/ ; \ - cd emsdk/binaryen/tag-1.38.4_64bit_binaryen/ ; \ + cd emsdk/binaryen/tag-1.38.10_64bit_binaryen/ ; \ make ; \ cd ../.. ; \ - cp binaryen/tag-1.38.4/bin/binaryen.js binaryen/tag-1.38.4_64bit_binaryen/bin ; \ - ./emsdk activate --embedded --build=Release sdk-tag-1.38.4-64bit binaryen-tag-1.38.4-64bit ; \ + cp binaryen/tag-1.38.10/bin/binaryen.js binaryen/tag-1.38.10_64bit_binaryen/bin ; \ + ./emsdk activate --embedded --build=Release sdk-tag-1.38.10-64bit binaryen-tag-1.38.10-64bit ; \ touch .complete \ ) diff --git a/emsdk/files/library.js b/emsdk/files/library.js deleted file mode 100644 index b8ead8fc0..000000000 --- a/emsdk/files/library.js +++ /dev/null @@ -1,4800 +0,0 @@ -//"use strict"; - -// An implementation of basic necessary libraries for the web. This integrates -// with a compiled libc and with the rest of the JS runtime. -// -// We search the Library object when there is an external function. If the -// entry in the Library is a function, we insert it. If it is a string, we -// do another lookup in the library (a simple way to write a function once, -// if it can be called by different names). We also allow dependencies, -// using __deps. Initialization code to be run after allocating all -// global constants can be defined by __postset. -// -// Note that the full function name will be '_' + the name in the Library -// object. For convenience, the short name appears here. Note that if you add a -// new function with an '_', it will not be found. - -// Memory allocated during startup, in postsets, should only be ALLOC_STATIC - -LibraryManager.library = { - // keep this low in memory, because we flatten arrays with them in them -#if USE_PTHREADS - stdin: '; if (ENVIRONMENT_IS_PTHREAD) _stdin = PthreadWorkerInit._stdin; else PthreadWorkerInit._stdin = _stdin = allocate(1, "i32*", ALLOC_STATIC)', - stdout: '; if (ENVIRONMENT_IS_PTHREAD) _stdout = PthreadWorkerInit._stdout; else PthreadWorkerInit._stdout = _stdout = allocate(1, "i32*", ALLOC_STATIC)', - stderr: '; if (ENVIRONMENT_IS_PTHREAD) _stderr = PthreadWorkerInit._stderr; else PthreadWorkerInit._stderr = _stderr = allocate(1, "i32*", ALLOC_STATIC)', - _impure_ptr: '; if (ENVIRONMENT_IS_PTHREAD) __impure_ptr = PthreadWorkerInit.__impure_ptr; else PthreadWorkerInit.__impure_ptr __impure_ptr = allocate(1, "i32*", ALLOC_STATIC)', - __dso_handle: '; if (ENVIRONMENT_IS_PTHREAD) ___dso_handle = PthreadWorkerInit.___dso_handle; else PthreadWorkerInit.___dso_handle = ___dso_handle = allocate(1, "i32*", ALLOC_STATIC)', -#else - stdin: '{{{ makeStaticAlloc(1) }}}', - stdout: '{{{ makeStaticAlloc(1) }}}', - stderr: '{{{ makeStaticAlloc(1) }}}', - _impure_ptr: '{{{ makeStaticAlloc(1) }}}', - __dso_handle: '{{{ makeStaticAlloc(1) }}}', -#endif - - $PROCINFO: { - // permissions - /* - uid: 0, - gid: 0, - euid: 0, - egid: 0, - suid: 0, - sgid: 0, - fsuid: 0, - fsgid: 0, - */ - // process identification - ppid: 1, - pid: 42, - sid: 42, - pgid: 42 - }, - - // ========================================================================== - // utime.h - // ========================================================================== - - utime__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'], - utime__proxy: 'sync', - utime__sig: 'iii', - utime: function(path, times) { - // int utime(const char *path, const struct utimbuf *times); - // http://pubs.opengroup.org/onlinepubs/009695399/basedefs/utime.h.html - var time; - if (times) { - // NOTE: We don't keep track of access timestamps. - var offset = {{{ C_STRUCTS.utimbuf.modtime }}}; - time = {{{ makeGetValue('times', 'offset', 'i32') }}}; - time *= 1000; - } else { - time = Date.now(); - } - path = Pointer_stringify(path); - try { - FS.utime(path, time, time); - return 0; - } catch (e) { - FS.handleFSError(e); - return -1; - } - }, - - utimes__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'], - utimes__proxy: 'sync', - utimes__sig: 'iii', - utimes: function(path, times) { - var time; - if (times) { - var offset = {{{ C_STRUCTS.timeval.__size__ }}} + {{{ C_STRUCTS.timeval.tv_sec }}}; - time = {{{ makeGetValue('times', 'offset', 'i32') }}} * 1000; - offset = {{{ C_STRUCTS.timeval.__size__ }}} + {{{ C_STRUCTS.timeval.tv_usec }}}; - time += {{{ makeGetValue('times', 'offset', 'i32') }}} / 1000; - } else { - time = Date.now(); - } - path = Pointer_stringify(path); - try { - FS.utime(path, time, time); - return 0; - } catch (e) { - FS.handleFSError(e); - return -1; - } - }, - - // ========================================================================== - // sys/file.h - // ========================================================================== - - flock: function(fd, operation) { - // int flock(int fd, int operation); - // Pretend to succeed - return 0; - }, - - chroot__deps: ['__setErrNo', '$ERRNO_CODES'], - chroot__proxy: 'sync', - chroot__sig: 'ii', - chroot: function(path) { - // int chroot(const char *path); - // http://pubs.opengroup.org/onlinepubs/7908799/xsh/chroot.html - ___setErrNo(ERRNO_CODES.EACCES); - return -1; - }, - - fpathconf__deps: ['__setErrNo', '$ERRNO_CODES'], - fpathconf__proxy: 'sync', - fpathconf__sig: 'iii', - fpathconf: function(fildes, name) { - // long fpathconf(int fildes, int name); - // http://pubs.opengroup.org/onlinepubs/000095399/functions/encrypt.html - // NOTE: The first parameter is ignored, so pathconf == fpathconf. - // The constants here aren't real values. Just mimicking glibc. - switch (name) { - case {{{ cDefine('_PC_LINK_MAX') }}}: - return 32000; - case {{{ cDefine('_PC_MAX_CANON') }}}: - case {{{ cDefine('_PC_MAX_INPUT') }}}: - case {{{ cDefine('_PC_NAME_MAX') }}}: - return 255; - case {{{ cDefine('_PC_PATH_MAX') }}}: - case {{{ cDefine('_PC_PIPE_BUF') }}}: - case {{{ cDefine('_PC_REC_MIN_XFER_SIZE') }}}: - case {{{ cDefine('_PC_REC_XFER_ALIGN') }}}: - case {{{ cDefine('_PC_ALLOC_SIZE_MIN') }}}: - return 4096; - case {{{ cDefine('_PC_CHOWN_RESTRICTED') }}}: - case {{{ cDefine('_PC_NO_TRUNC') }}}: - case {{{ cDefine('_PC_2_SYMLINKS') }}}: - return 1; - case {{{ cDefine('_PC_VDISABLE') }}}: - return 0; - case {{{ cDefine('_PC_SYNC_IO') }}}: - case {{{ cDefine('_PC_ASYNC_IO') }}}: - case {{{ cDefine('_PC_PRIO_IO') }}}: - case {{{ cDefine('_PC_SOCK_MAXBUF') }}}: - case {{{ cDefine('_PC_REC_INCR_XFER_SIZE') }}}: - case {{{ cDefine('_PC_REC_MAX_XFER_SIZE') }}}: - case {{{ cDefine('_PC_SYMLINK_MAX') }}}: - return -1; - case {{{ cDefine('_PC_FILESIZEBITS') }}}: - return 64; - } - ___setErrNo(ERRNO_CODES.EINVAL); - return -1; - }, - pathconf: 'fpathconf', - - confstr__deps: ['__setErrNo', '$ERRNO_CODES', '$ENV'], - confstr__proxy: 'sync', - confstr__sig: 'iiii', - confstr: function(name, buf, len) { - // size_t confstr(int name, char *buf, size_t len); - // http://pubs.opengroup.org/onlinepubs/000095399/functions/confstr.html - var value; - switch (name) { - case {{{ cDefine('_CS_PATH') }}}: - value = ENV['PATH'] || '/'; - break; - case {{{ cDefine('_CS_POSIX_V6_WIDTH_RESTRICTED_ENVS') }}}: - // Mimicking glibc. - value = 'POSIX_V6_ILP32_OFF32\nPOSIX_V6_ILP32_OFFBIG'; - break; - case {{{ cDefine('_CS_GNU_LIBC_VERSION') }}}: - // This JS implementation was tested against this glibc version. - value = 'glibc 2.14'; - break; - case {{{ cDefine('_CS_GNU_LIBPTHREAD_VERSION') }}}: - // We don't support pthreads. - value = ''; - break; - case {{{ cDefine('_CS_POSIX_V6_ILP32_OFF32_LIBS') }}}: - case {{{ cDefine('_CS_POSIX_V6_ILP32_OFFBIG_LIBS') }}}: - case {{{ cDefine('_CS_POSIX_V6_LP64_OFF64_CFLAGS') }}}: - case {{{ cDefine('_CS_POSIX_V6_LP64_OFF64_LDFLAGS') }}}: - case {{{ cDefine('_CS_POSIX_V6_LP64_OFF64_LIBS') }}}: - case {{{ cDefine('_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS') }}}: - case {{{ cDefine('_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS') }}}: - case {{{ cDefine('_CS_POSIX_V6_LPBIG_OFFBIG_LIBS') }}}: - value = ''; - break; - case {{{ cDefine('_CS_POSIX_V6_ILP32_OFF32_CFLAGS') }}}: - case {{{ cDefine('_CS_POSIX_V6_ILP32_OFF32_LDFLAGS') }}}: - case {{{ cDefine('_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS') }}}: - value = '-m32'; - break; - case {{{ cDefine('_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS') }}}: - value = '-m32 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'; - break; - default: - ___setErrNo(ERRNO_CODES.EINVAL); - return 0; - } - if (len == 0 || buf == 0) { - return value.length + 1; - } else { - var length = Math.min(len, value.length); - for (var i = 0; i < length; i++) { - {{{ makeSetValue('buf', 'i', 'value.charCodeAt(i)', 'i8') }}}; - } - if (len > length) {{{ makeSetValue('buf', 'i++', '0', 'i8') }}}; - return i; - } - }, - - execl__deps: ['__setErrNo', '$ERRNO_CODES'], - execl: function(/* ... */) { - // int execl(const char *path, const char *arg0, ... /*, (char *)0 */); - // http://pubs.opengroup.org/onlinepubs/009695399/functions/exec.html - // We don't support executing external code. - ___setErrNo(ERRNO_CODES.ENOEXEC); - return -1; - }, - execle: 'execl', - execlp: 'execl', - execv: 'execl', - execve: 'execl', - execvp: 'execl', - __execvpe: 'execl', - fexecve: 'execl', - - _exit: function(status) { - // void _exit(int status); - // http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html - Module['exit'](status); - }, - - fork__deps: ['__setErrNo', '$ERRNO_CODES'], - fork: function() { - // pid_t fork(void); - // http://pubs.opengroup.org/onlinepubs/000095399/functions/fork.html - // We don't support multiple processes. - ___setErrNo(ERRNO_CODES.EAGAIN); - return -1; - }, - vfork: 'fork', - posix_spawn: 'fork', - posix_spawnp: 'fork', - - setgroups__deps: ['__setErrNo', '$ERRNO_CODES', 'sysconf'], - setgroups: function(ngroups, gidset) { - // int setgroups(int ngroups, const gid_t *gidset); - // https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man2/setgroups.2.html - if (ngroups < 1 || ngroups > _sysconf({{{ cDefine('_SC_NGROUPS_MAX') }}})) { - ___setErrNo(ERRNO_CODES.EINVAL); - return -1; - } else { - // We have just one process/user/group, so it makes no sense to set groups. - ___setErrNo(ERRNO_CODES.EPERM); - return -1; - } - }, - getpagesize: function() { - // int getpagesize(void); - return PAGE_SIZE; - }, - - sysconf__deps: ['__setErrNo', '$ERRNO_CODES'], - sysconf__proxy: 'sync', - sysconf__sig: 'ii', - sysconf: function(name) { - // long sysconf(int name); - // http://pubs.opengroup.org/onlinepubs/009695399/functions/sysconf.html - switch(name) { - case {{{ cDefine('_SC_PAGE_SIZE') }}}: return PAGE_SIZE; - case {{{ cDefine('_SC_PHYS_PAGES') }}}: -#if WASM - var maxHeapSize = 2*1024*1024*1024 - 65536; -#else - var maxHeapSize = 2*1024*1024*1024 - 16777216; -#endif -#if WASM_MEM_MAX != -1 - maxHeapSize = {{{ WASM_MEM_MAX }}}; -#endif -#if !ALLOW_MEMORY_GROWTH - maxHeapSize = HEAPU8.length; -#endif - return maxHeapSize / PAGE_SIZE; - case {{{ cDefine('_SC_ADVISORY_INFO') }}}: - case {{{ cDefine('_SC_BARRIERS') }}}: - case {{{ cDefine('_SC_ASYNCHRONOUS_IO') }}}: - case {{{ cDefine('_SC_CLOCK_SELECTION') }}}: - case {{{ cDefine('_SC_CPUTIME') }}}: - case {{{ cDefine('_SC_FSYNC') }}}: - case {{{ cDefine('_SC_IPV6') }}}: - case {{{ cDefine('_SC_MAPPED_FILES') }}}: - case {{{ cDefine('_SC_MEMLOCK') }}}: - case {{{ cDefine('_SC_MEMLOCK_RANGE') }}}: - case {{{ cDefine('_SC_MEMORY_PROTECTION') }}}: - case {{{ cDefine('_SC_MESSAGE_PASSING') }}}: - case {{{ cDefine('_SC_MONOTONIC_CLOCK') }}}: - case {{{ cDefine('_SC_PRIORITIZED_IO') }}}: - case {{{ cDefine('_SC_PRIORITY_SCHEDULING') }}}: - case {{{ cDefine('_SC_RAW_SOCKETS') }}}: - case {{{ cDefine('_SC_READER_WRITER_LOCKS') }}}: - case {{{ cDefine('_SC_REALTIME_SIGNALS') }}}: - case {{{ cDefine('_SC_SEMAPHORES') }}}: - case {{{ cDefine('_SC_SHARED_MEMORY_OBJECTS') }}}: - case {{{ cDefine('_SC_SPAWN') }}}: - case {{{ cDefine('_SC_SPIN_LOCKS') }}}: - case {{{ cDefine('_SC_SYNCHRONIZED_IO') }}}: - case {{{ cDefine('_SC_THREAD_ATTR_STACKADDR') }}}: - case {{{ cDefine('_SC_THREAD_ATTR_STACKSIZE') }}}: - case {{{ cDefine('_SC_THREAD_CPUTIME') }}}: - case {{{ cDefine('_SC_THREAD_PRIO_INHERIT') }}}: - case {{{ cDefine('_SC_THREAD_PRIO_PROTECT') }}}: - case {{{ cDefine('_SC_THREAD_PROCESS_SHARED') }}}: - case {{{ cDefine('_SC_THREAD_SAFE_FUNCTIONS') }}}: - case {{{ cDefine('_SC_THREADS') }}}: - case {{{ cDefine('_SC_TIMEOUTS') }}}: - case {{{ cDefine('_SC_TIMERS') }}}: - case {{{ cDefine('_SC_VERSION') }}}: - case {{{ cDefine('_SC_2_C_BIND') }}}: - case {{{ cDefine('_SC_2_C_DEV') }}}: - case {{{ cDefine('_SC_2_CHAR_TERM') }}}: - case {{{ cDefine('_SC_2_LOCALEDEF') }}}: - case {{{ cDefine('_SC_2_SW_DEV') }}}: - case {{{ cDefine('_SC_2_VERSION') }}}: - return 200809; - case {{{ cDefine('_SC_THREAD_PRIORITY_SCHEDULING') }}}: - return 0; - case {{{ cDefine('_SC_MQ_OPEN_MAX') }}}: - case {{{ cDefine('_SC_XOPEN_STREAMS') }}}: - case {{{ cDefine('_SC_XBS5_LP64_OFF64') }}}: - case {{{ cDefine('_SC_XBS5_LPBIG_OFFBIG') }}}: - case {{{ cDefine('_SC_AIO_LISTIO_MAX') }}}: - case {{{ cDefine('_SC_AIO_MAX') }}}: - case {{{ cDefine('_SC_SPORADIC_SERVER') }}}: - case {{{ cDefine('_SC_THREAD_SPORADIC_SERVER') }}}: - case {{{ cDefine('_SC_TRACE') }}}: - case {{{ cDefine('_SC_TRACE_EVENT_FILTER') }}}: - case {{{ cDefine('_SC_TRACE_EVENT_NAME_MAX') }}}: - case {{{ cDefine('_SC_TRACE_INHERIT') }}}: - case {{{ cDefine('_SC_TRACE_LOG') }}}: - case {{{ cDefine('_SC_TRACE_NAME_MAX') }}}: - case {{{ cDefine('_SC_TRACE_SYS_MAX') }}}: - case {{{ cDefine('_SC_TRACE_USER_EVENT_MAX') }}}: - case {{{ cDefine('_SC_TYPED_MEMORY_OBJECTS') }}}: - case {{{ cDefine('_SC_V6_LP64_OFF64') }}}: - case {{{ cDefine('_SC_V6_LPBIG_OFFBIG') }}}: - case {{{ cDefine('_SC_2_FORT_DEV') }}}: - case {{{ cDefine('_SC_2_FORT_RUN') }}}: - case {{{ cDefine('_SC_2_PBS') }}}: - case {{{ cDefine('_SC_2_PBS_ACCOUNTING') }}}: - case {{{ cDefine('_SC_2_PBS_CHECKPOINT') }}}: - case {{{ cDefine('_SC_2_PBS_LOCATE') }}}: - case {{{ cDefine('_SC_2_PBS_MESSAGE') }}}: - case {{{ cDefine('_SC_2_PBS_TRACK') }}}: - case {{{ cDefine('_SC_2_UPE') }}}: - case {{{ cDefine('_SC_THREAD_THREADS_MAX') }}}: - case {{{ cDefine('_SC_SEM_NSEMS_MAX') }}}: - case {{{ cDefine('_SC_SYMLOOP_MAX') }}}: - case {{{ cDefine('_SC_TIMER_MAX') }}}: - return -1; - case {{{ cDefine('_SC_V6_ILP32_OFF32') }}}: - case {{{ cDefine('_SC_V6_ILP32_OFFBIG') }}}: - case {{{ cDefine('_SC_JOB_CONTROL') }}}: - case {{{ cDefine('_SC_REGEXP') }}}: - case {{{ cDefine('_SC_SAVED_IDS') }}}: - case {{{ cDefine('_SC_SHELL') }}}: - case {{{ cDefine('_SC_XBS5_ILP32_OFF32') }}}: - case {{{ cDefine('_SC_XBS5_ILP32_OFFBIG') }}}: - case {{{ cDefine('_SC_XOPEN_CRYPT') }}}: - case {{{ cDefine('_SC_XOPEN_ENH_I18N') }}}: - case {{{ cDefine('_SC_XOPEN_LEGACY') }}}: - case {{{ cDefine('_SC_XOPEN_REALTIME') }}}: - case {{{ cDefine('_SC_XOPEN_REALTIME_THREADS') }}}: - case {{{ cDefine('_SC_XOPEN_SHM') }}}: - case {{{ cDefine('_SC_XOPEN_UNIX') }}}: - return 1; - case {{{ cDefine('_SC_THREAD_KEYS_MAX') }}}: - case {{{ cDefine('_SC_IOV_MAX') }}}: - case {{{ cDefine('_SC_GETGR_R_SIZE_MAX') }}}: - case {{{ cDefine('_SC_GETPW_R_SIZE_MAX') }}}: - case {{{ cDefine('_SC_OPEN_MAX') }}}: - return 1024; - case {{{ cDefine('_SC_RTSIG_MAX') }}}: - case {{{ cDefine('_SC_EXPR_NEST_MAX') }}}: - case {{{ cDefine('_SC_TTY_NAME_MAX') }}}: - return 32; - case {{{ cDefine('_SC_ATEXIT_MAX') }}}: - case {{{ cDefine('_SC_DELAYTIMER_MAX') }}}: - case {{{ cDefine('_SC_SEM_VALUE_MAX') }}}: - return 2147483647; - case {{{ cDefine('_SC_SIGQUEUE_MAX') }}}: - case {{{ cDefine('_SC_CHILD_MAX') }}}: - return 47839; - case {{{ cDefine('_SC_BC_SCALE_MAX') }}}: - case {{{ cDefine('_SC_BC_BASE_MAX') }}}: - return 99; - case {{{ cDefine('_SC_LINE_MAX') }}}: - case {{{ cDefine('_SC_BC_DIM_MAX') }}}: - return 2048; - case {{{ cDefine('_SC_ARG_MAX') }}}: return 2097152; - case {{{ cDefine('_SC_NGROUPS_MAX') }}}: return 65536; - case {{{ cDefine('_SC_MQ_PRIO_MAX') }}}: return 32768; - case {{{ cDefine('_SC_RE_DUP_MAX') }}}: return 32767; - case {{{ cDefine('_SC_THREAD_STACK_MIN') }}}: return 16384; - case {{{ cDefine('_SC_BC_STRING_MAX') }}}: return 1000; - case {{{ cDefine('_SC_XOPEN_VERSION') }}}: return 700; - case {{{ cDefine('_SC_LOGIN_NAME_MAX') }}}: return 256; - case {{{ cDefine('_SC_COLL_WEIGHTS_MAX') }}}: return 255; - case {{{ cDefine('_SC_CLK_TCK') }}}: return 100; - case {{{ cDefine('_SC_HOST_NAME_MAX') }}}: return 64; - case {{{ cDefine('_SC_AIO_PRIO_DELTA_MAX') }}}: return 20; - case {{{ cDefine('_SC_STREAM_MAX') }}}: return 16; - case {{{ cDefine('_SC_TZNAME_MAX') }}}: return 6; - case {{{ cDefine('_SC_THREAD_DESTRUCTOR_ITERATIONS') }}}: return 4; - case {{{ cDefine('_SC_NPROCESSORS_ONLN') }}}: { - if (typeof navigator === 'object') return navigator['hardwareConcurrency'] || 1; - return 1; - } - } - ___setErrNo(ERRNO_CODES.EINVAL); - return -1; - }, - - // Implement a Linux-like 'memory area' for our 'process'. - // Changes the size of the memory area by |bytes|; returns the - // address of the previous top ('break') of the memory area - // We control the "dynamic" memory - DYNAMIC_BASE to DYNAMICTOP - sbrk__asm: true, - sbrk__sig: ['ii'], - sbrk__deps: ['__setErrNo'], - sbrk: function(increment) { - increment = increment|0; - var oldDynamicTop = 0; - var oldDynamicTopOnChange = 0; - var newDynamicTop = 0; - var totalMemory = 0; -#if USE_PTHREADS - totalMemory = getTotalMemory()|0; - - // Perform a compare-and-swap loop to update the new dynamic top value. This is because - // this function can becalled simultaneously in multiple threads. - do { - oldDynamicTop = Atomics_load(HEAP32, DYNAMICTOP_PTR>>2)|0; - newDynamicTop = oldDynamicTop + increment | 0; - // Asking to increase dynamic top to a too high value? In pthreads builds we cannot - // enlarge memory, so this needs to fail. - if (((increment|0) > 0 & (newDynamicTop|0) < (oldDynamicTop|0)) // Detect and fail if we would wrap around signed 32-bit int. - | (newDynamicTop|0) < 0 // Also underflow, sbrk() should be able to be used to subtract. - | (newDynamicTop|0) > (totalMemory|0)) { -#if ABORTING_MALLOC - abortOnCannotGrowMemory()|0; -#else - ___setErrNo({{{ cDefine('ENOMEM') }}}); - return -1; -#endif - } - // Attempt to update the dynamic top to new value. Another thread may have beat this thread to the update, - // in which case we will need to start over by iterating the loop body again. - oldDynamicTopOnChange = Atomics_compareExchange(HEAP32, DYNAMICTOP_PTR>>2, oldDynamicTop|0, newDynamicTop|0)|0; - } while((oldDynamicTopOnChange|0) != (oldDynamicTop|0)); -#else // singlethreaded build: (-s USE_PTHREADS=0) - oldDynamicTop = HEAP32[DYNAMICTOP_PTR>>2]|0; - newDynamicTop = oldDynamicTop + increment | 0; - - if (((increment|0) > 0 & (newDynamicTop|0) < (oldDynamicTop|0)) // Detect and fail if we would wrap around signed 32-bit int. - | (newDynamicTop|0) < 0) { // Also underflow, sbrk() should be able to be used to subtract. -#if ABORTING_MALLOC - abortOnCannotGrowMemory()|0; -#endif - ___setErrNo({{{ cDefine('ENOMEM') }}}); - return -1; - } - - HEAP32[DYNAMICTOP_PTR>>2] = newDynamicTop; - totalMemory = getTotalMemory()|0; - if ((newDynamicTop|0) > (totalMemory|0)) { - if ((enlargeMemory()|0) == 0) { - HEAP32[DYNAMICTOP_PTR>>2] = oldDynamicTop; - ___setErrNo({{{ cDefine('ENOMEM') }}}); - return -1; - } - } -#endif - return oldDynamicTop|0; - }, - - brk__asm: true, - brk__sig: ['ii'], - brk: function(newDynamicTop) { - newDynamicTop = newDynamicTop|0; - var oldDynamicTop = 0; - var totalMemory = 0; -#if USE_PTHREADS - totalMemory = getTotalMemory()|0; - // Asking to increase dynamic top to a too high value? In pthreads builds we cannot - // enlarge memory, so this needs to fail. - if ((newDynamicTop|0) < 0 | (newDynamicTop|0) > (totalMemory|0)) { -#if ABORTING_MALLOC - abortOnCannotGrowMemory()|0; -#else - ___setErrNo({{{ cDefine('ENOMEM') }}}); - return -1; -#endif - } - Atomics_store(HEAP32, DYNAMICTOP_PTR>>2, newDynamicTop|0)|0; -#else // singlethreaded build: (-s USE_PTHREADS=0) - if ((newDynamicTop|0) < 0) { -#if ABORTING_MALLOC - abortOnCannotGrowMemory()|0; -#endif - ___setErrNo({{{ cDefine('ENOMEM') }}}); - return -1; - } - - oldDynamicTop = HEAP32[DYNAMICTOP_PTR>>2]|0; - HEAP32[DYNAMICTOP_PTR>>2] = newDynamicTop; - totalMemory = getTotalMemory()|0; - if ((newDynamicTop|0) > (totalMemory|0)) { - if ((enlargeMemory()|0) == 0) { - ___setErrNo({{{ cDefine('ENOMEM') }}}); - HEAP32[DYNAMICTOP_PTR>>2] = oldDynamicTop; - return -1; - } - } -#endif - return 0; - }, - - system__deps: ['__setErrNo', '$ERRNO_CODES'], - system: function(command) { - // int system(const char *command); - // http://pubs.opengroup.org/onlinepubs/000095399/functions/system.html - // Can't call external programs. - ___setErrNo(ERRNO_CODES.EAGAIN); - return -1; - }, - - // ========================================================================== - // stdlib.h - // ========================================================================== - - // tiny, fake malloc/free implementation. If the program actually uses malloc, - // a compiled version will be used; this will only be used if the runtime - // needs to allocate something, for which this is good enough if otherwise - // no malloc is needed. - malloc: function(bytes) { - /* Over-allocate to make sure it is byte-aligned by 8. - * This will leak memory, but this is only the dummy - * implementation (replaced by dlmalloc normally) so - * not an issue. - */ -#if ASSERTIONS == 2 - warnOnce('using stub malloc (reference it from C to have the real one included)'); -#endif - var ptr = dynamicAlloc(bytes + 8); - return (ptr+8) & 0xFFFFFFF8; - }, - free: function() { -#if ASSERTIONS == 2 - warnOnce('using stub free (reference it from C to have the real one included)'); -#endif -}, - - abs: 'Math_abs', - labs: 'Math_abs', - - exit__deps: ['_exit'], - exit: function(status) { - __exit(status); - }, - _Exit__deps: ['exit'], - _Exit: function(status) { - __exit(status); - }, - - _ZSt9terminatev__deps: ['exit'], - _ZSt9terminatev: function() { - _exit(-1234); - }, - - atexit__proxy: 'sync', - atexit__sig: 'ii', - atexit: function(func, arg) { -#if ASSERTIONS -#if NO_EXIT_RUNTIME == 1 - warnOnce('atexit() called, but NO_EXIT_RUNTIME is set, so atexits() will not be called. set NO_EXIT_RUNTIME to 0 (see the FAQ)'); -#endif -#endif - __ATEXIT__.unshift({ func: func, arg: arg }); - }, - __cxa_atexit: 'atexit', - - // used in rust, clang when doing thread_local statics - __cxa_thread_atexit: 'atexit', - __cxa_thread_atexit_impl: 'atexit', - - abort: function() { - Module['abort'](); - }, - - environ__deps: ['$ENV'], -#if USE_PTHREADS - environ: '; if (ENVIRONMENT_IS_PTHREAD) _environ = PthreadWorkerInit._environ; else PthreadWorkerInit._environ = _environ = allocate(1, "i32*", ALLOC_STATIC)', -#else - environ: '{{{ makeStaticAlloc(1) }}}', -#endif - __environ__deps: ['environ'], - __environ: 'environ', - __buildEnvironment__deps: ['__environ'], - __buildEnvironment: function(env) { - // WARNING: Arbitrary limit! - var MAX_ENV_VALUES = 64; - var TOTAL_ENV_SIZE = 1024; - - // Statically allocate memory for the environment. - var poolPtr; - var envPtr; - if (!___buildEnvironment.called) { - ___buildEnvironment.called = true; - // Set default values. Use string keys for Closure Compiler compatibility. - ENV['USER'] = ENV['LOGNAME'] = 'web_user'; - ENV['PATH'] = '/'; - ENV['PWD'] = '/'; - ENV['HOME'] = '/home/web_user'; - ENV['LANG'] = 'C.UTF-8'; - ENV['_'] = Module['thisProgram']; - // Allocate memory. - poolPtr = staticAlloc(TOTAL_ENV_SIZE); - envPtr = staticAlloc(MAX_ENV_VALUES * {{{ Runtime.POINTER_SIZE }}}); - {{{ makeSetValue('envPtr', '0', 'poolPtr', 'i8*') }}}; - {{{ makeSetValue(makeGlobalUse('_environ'), 0, 'envPtr', 'i8*') }}}; - } else { - envPtr = {{{ makeGetValue(makeGlobalUse('_environ'), '0', 'i8**') }}}; - poolPtr = {{{ makeGetValue('envPtr', '0', 'i8*') }}}; - } - - // Collect key=value lines. - var strings = []; - var totalSize = 0; - for (var key in env) { - if (typeof env[key] === 'string') { - var line = key + '=' + env[key]; - strings.push(line); - totalSize += line.length; - } - } - if (totalSize > TOTAL_ENV_SIZE) { - throw new Error('Environment size exceeded TOTAL_ENV_SIZE!'); - } - - // Make new. - var ptrSize = {{{ Runtime.getNativeTypeSize('i8*') }}}; - for (var i = 0; i < strings.length; i++) { - var line = strings[i]; - writeAsciiToMemory(line, poolPtr); - {{{ makeSetValue('envPtr', 'i * ptrSize', 'poolPtr', 'i8*') }}}; - poolPtr += line.length + 1; - } - {{{ makeSetValue('envPtr', 'strings.length * ptrSize', '0', 'i8*') }}}; - }, - $ENV__deps: ['__buildEnvironment'], -#if USE_PTHREADS - $ENV__postset: 'if (!ENVIRONMENT_IS_PTHREAD) ___buildEnvironment(ENV);', -#else - $ENV__postset: '___buildEnvironment(ENV);', -#endif - $ENV: {}, - getenv__deps: ['$ENV'], - getenv__proxy: 'sync', - getenv__sig: 'ii', - getenv: function(name) { - // char *getenv(const char *name); - // http://pubs.opengroup.org/onlinepubs/009695399/functions/getenv.html - if (name === 0) return 0; - name = Pointer_stringify(name); - if (!ENV.hasOwnProperty(name)) return 0; - - if (_getenv.ret) _free(_getenv.ret); - _getenv.ret = allocateUTF8(ENV[name]); - return _getenv.ret; - }, - clearenv__deps: ['$ENV', '__buildEnvironment'], - clearenv__proxy: 'sync', - clearenv__sig: 'i', - clearenv: function() { - // int clearenv (void); - // http://www.gnu.org/s/hello/manual/libc/Environment-Access.html#index-clearenv-3107 - ENV = {}; - ___buildEnvironment(ENV); - return 0; - }, - setenv__deps: ['$ENV', '__buildEnvironment', '$ERRNO_CODES', '__setErrNo'], - setenv__proxy: 'sync', - setenv__sig: 'iiii', - setenv: function(envname, envval, overwrite) { - // int setenv(const char *envname, const char *envval, int overwrite); - // http://pubs.opengroup.org/onlinepubs/009695399/functions/setenv.html - if (envname === 0) { - ___setErrNo(ERRNO_CODES.EINVAL); - return -1; - } - var name = Pointer_stringify(envname); - var val = Pointer_stringify(envval); - if (name === '' || name.indexOf('=') !== -1) { - ___setErrNo(ERRNO_CODES.EINVAL); - return -1; - } - if (ENV.hasOwnProperty(name) && !overwrite) return 0; - ENV[name] = val; - ___buildEnvironment(ENV); - return 0; - }, - unsetenv__deps: ['$ENV', '__buildEnvironment', '$ERRNO_CODES', '__setErrNo'], - unsetenv__proxy: 'sync', - unsetenv__sig: 'ii', - unsetenv: function(name) { - // int unsetenv(const char *name); - // http://pubs.opengroup.org/onlinepubs/009695399/functions/unsetenv.html - if (name === 0) { - ___setErrNo(ERRNO_CODES.EINVAL); - return -1; - } - name = Pointer_stringify(name); - if (name === '' || name.indexOf('=') !== -1) { - ___setErrNo(ERRNO_CODES.EINVAL); - return -1; - } - if (ENV.hasOwnProperty(name)) { - delete ENV[name]; - ___buildEnvironment(ENV); - } - return 0; - }, - putenv__deps: ['$ENV', '__buildEnvironment', '$ERRNO_CODES', '__setErrNo'], - putenv__proxy: 'sync', - putenv__sig: 'ii', - putenv: function(string) { - // int putenv(char *string); - // http://pubs.opengroup.org/onlinepubs/009695399/functions/putenv.html - // WARNING: According to the standard (and the glibc implementation), the - // string is taken by reference so future changes are reflected. - // We copy it instead, possibly breaking some uses. - if (string === 0) { - ___setErrNo(ERRNO_CODES.EINVAL); - return -1; - } - string = Pointer_stringify(string); - var splitPoint = string.indexOf('=') - if (string === '' || string.indexOf('=') === -1) { - ___setErrNo(ERRNO_CODES.EINVAL); - return -1; - } - var name = string.slice(0, splitPoint); - var value = string.slice(splitPoint + 1); - if (!(name in ENV) || ENV[name] !== value) { - ENV[name] = value; - ___buildEnvironment(ENV); - } - return 0; - }, - - getloadavg: function(loadavg, nelem) { - // int getloadavg(double loadavg[], int nelem); - // http://linux.die.net/man/3/getloadavg - var limit = Math.min(nelem, 3); - var doubleSize = {{{ Runtime.getNativeTypeSize('double') }}}; - for (var i = 0; i < limit; i++) { - {{{ makeSetValue('loadavg', 'i * doubleSize', '0.1', 'double') }}}; - } - return limit; - }, - - // For compatibility, call to rand() when code requests arc4random(), although this is *not* at all - // as strong as rc4 is. See https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/arc4random.3.html - arc4random: 'rand', - - // ========================================================================== - // string.h - // ========================================================================== - - memcpy__inline: function(dest, src, num, align) { - var ret = ''; - ret += makeCopyValues(dest, src, num, 'null', null, align); - return ret; - }, - - emscripten_memcpy_big: function(dest, src, num) { - HEAPU8.set(HEAPU8.subarray(src, src+num), dest); - return dest; - }, - - memcpy__asm: true, - memcpy__sig: 'iiii', - memcpy__deps: ['emscripten_memcpy_big'], - memcpy: function(dest, src, num) { - dest = dest|0; src = src|0; num = num|0; - var ret = 0; - var aligned_dest_end = 0; - var block_aligned_dest_end = 0; - var dest_end = 0; - // Test against a benchmarked cutoff limit for when HEAPU8.set() becomes faster to use. - if ((num|0) >= -#if SIMD - 196608 -#else - 8192 -#endif - ) { - return _emscripten_memcpy_big(dest|0, src|0, num|0)|0; - } - - ret = dest|0; - dest_end = (dest + num)|0; - if ((dest&3) == (src&3)) { - // The initial unaligned < 4-byte front. - while (dest & 3) { - if ((num|0) == 0) return ret|0; - {{{ makeSetValueAsm('dest', 0, makeGetValueAsm('src', 0, 'i8'), 'i8') }}}; - dest = (dest+1)|0; - src = (src+1)|0; - num = (num-1)|0; - } - aligned_dest_end = (dest_end & -4)|0; - block_aligned_dest_end = (aligned_dest_end - 64)|0; - while ((dest|0) <= (block_aligned_dest_end|0) ) { -#if SIMD - SIMD_Int32x4_store(HEAPU8, dest, SIMD_Int32x4_load(HEAPU8, src)); - SIMD_Int32x4_store(HEAPU8, dest+16, SIMD_Int32x4_load(HEAPU8, src+16)); - SIMD_Int32x4_store(HEAPU8, dest+32, SIMD_Int32x4_load(HEAPU8, src+32)); - SIMD_Int32x4_store(HEAPU8, dest+48, SIMD_Int32x4_load(HEAPU8, src+48)); -#else - {{{ makeSetValueAsm('dest', 0, makeGetValueAsm('src', 0, 'i32'), 'i32') }}}; - {{{ makeSetValueAsm('dest', 4, makeGetValueAsm('src', 4, 'i32'), 'i32') }}}; - {{{ makeSetValueAsm('dest', 8, makeGetValueAsm('src', 8, 'i32'), 'i32') }}}; - {{{ makeSetValueAsm('dest', 12, makeGetValueAsm('src', 12, 'i32'), 'i32') }}}; - {{{ makeSetValueAsm('dest', 16, makeGetValueAsm('src', 16, 'i32'), 'i32') }}}; - {{{ makeSetValueAsm('dest', 20, makeGetValueAsm('src', 20, 'i32'), 'i32') }}}; - {{{ makeSetValueAsm('dest', 24, makeGetValueAsm('src', 24, 'i32'), 'i32') }}}; - {{{ makeSetValueAsm('dest', 28, makeGetValueAsm('src', 28, 'i32'), 'i32') }}}; - {{{ makeSetValueAsm('dest', 32, makeGetValueAsm('src', 32, 'i32'), 'i32') }}}; - {{{ makeSetValueAsm('dest', 36, makeGetValueAsm('src', 36, 'i32'), 'i32') }}}; - {{{ makeSetValueAsm('dest', 40, makeGetValueAsm('src', 40, 'i32'), 'i32') }}}; - {{{ makeSetValueAsm('dest', 44, makeGetValueAsm('src', 44, 'i32'), 'i32') }}}; - {{{ makeSetValueAsm('dest', 48, makeGetValueAsm('src', 48, 'i32'), 'i32') }}}; - {{{ makeSetValueAsm('dest', 52, makeGetValueAsm('src', 52, 'i32'), 'i32') }}}; - {{{ makeSetValueAsm('dest', 56, makeGetValueAsm('src', 56, 'i32'), 'i32') }}}; - {{{ makeSetValueAsm('dest', 60, makeGetValueAsm('src', 60, 'i32'), 'i32') }}}; -#endif - dest = (dest+64)|0; - src = (src+64)|0; - } - while ((dest|0) < (aligned_dest_end|0) ) { - {{{ makeSetValueAsm('dest', 0, makeGetValueAsm('src', 0, 'i32'), 'i32') }}}; - dest = (dest+4)|0; - src = (src+4)|0; - } - } else { - // In the unaligned copy case, unroll a bit as well. - aligned_dest_end = (dest_end - 4)|0; - while ((dest|0) < (aligned_dest_end|0) ) { - {{{ makeSetValueAsm('dest', 0, makeGetValueAsm('src', 0, 'i8'), 'i8') }}}; - {{{ makeSetValueAsm('dest', 1, makeGetValueAsm('src', 1, 'i8'), 'i8') }}}; - {{{ makeSetValueAsm('dest', 2, makeGetValueAsm('src', 2, 'i8'), 'i8') }}}; - {{{ makeSetValueAsm('dest', 3, makeGetValueAsm('src', 3, 'i8'), 'i8') }}}; - dest = (dest+4)|0; - src = (src+4)|0; - } - } - // The remaining unaligned < 4 byte tail. - while ((dest|0) < (dest_end|0)) { - {{{ makeSetValueAsm('dest', 0, makeGetValueAsm('src', 0, 'i8'), 'i8') }}}; - dest = (dest+1)|0; - src = (src+1)|0; - } - return ret|0; - }, - - llvm_memcpy_i32: 'memcpy', - llvm_memcpy_i64: 'memcpy', - llvm_memcpy_p0i8_p0i8_i32: 'memcpy', - llvm_memcpy_p0i8_p0i8_i64: 'memcpy', - - memmove__sig: 'iiii', - memmove__asm: true, - memmove__deps: ['memcpy'], - memmove: function(dest, src, num) { - dest = dest|0; src = src|0; num = num|0; - var ret = 0; - if (((src|0) < (dest|0)) & ((dest|0) < ((src + num)|0))) { - // Unlikely case: Copy backwards in a safe manner - ret = dest; - src = (src + num)|0; - dest = (dest + num)|0; - while ((num|0) > 0) { - dest = (dest - 1)|0; - src = (src - 1)|0; - num = (num - 1)|0; - {{{ makeSetValueAsm('dest', 0, makeGetValueAsm('src', 0, 'i8'), 'i8') }}}; - } - dest = ret; - } else { - _memcpy(dest, src, num) | 0; - } - return dest | 0; - }, - llvm_memmove_i32: 'memmove', - llvm_memmove_i64: 'memmove', - llvm_memmove_p0i8_p0i8_i32: 'memmove', - llvm_memmove_p0i8_p0i8_i64: 'memmove', - - memset__inline: function(ptr, value, num, align) { - return makeSetValues(ptr, 0, value, 'null', num, align); - }, - memset__sig: 'iiii', - memset__asm: true, - memset: function(ptr, value, num) { - ptr = ptr|0; value = value|0; num = num|0; - var end = 0, aligned_end = 0, block_aligned_end = 0, value4 = 0; -#if SIMD - var value16 = SIMD_Int32x4(0,0,0,0); -#endif - end = (ptr + num)|0; - - value = value & 0xff; - if ((num|0) >= 67 /* 64 bytes for an unrolled loop + 3 bytes for unaligned head*/) { - while ((ptr&3) != 0) { - {{{ makeSetValueAsm('ptr', 0, 'value', 'i8') }}}; - ptr = (ptr+1)|0; - } - - aligned_end = (end & -4)|0; - block_aligned_end = (aligned_end - 64)|0; - value4 = value | (value << 8) | (value << 16) | (value << 24); -#if SIMD - value16 = SIMD_Int32x4_splat(value4); -#endif - - while((ptr|0) <= (block_aligned_end|0)) { -#if SIMD - SIMD_Int32x4_store(HEAPU8, ptr, value16); - SIMD_Int32x4_store(HEAPU8, ptr+16, value16); - SIMD_Int32x4_store(HEAPU8, ptr+32, value16); - SIMD_Int32x4_store(HEAPU8, ptr+48, value16); -#else - {{{ makeSetValueAsm('ptr', 0, 'value4', 'i32') }}}; - {{{ makeSetValueAsm('ptr', 4, 'value4', 'i32') }}}; - {{{ makeSetValueAsm('ptr', 8, 'value4', 'i32') }}}; - {{{ makeSetValueAsm('ptr', 12, 'value4', 'i32') }}}; - {{{ makeSetValueAsm('ptr', 16, 'value4', 'i32') }}}; - {{{ makeSetValueAsm('ptr', 20, 'value4', 'i32') }}}; - {{{ makeSetValueAsm('ptr', 24, 'value4', 'i32') }}}; - {{{ makeSetValueAsm('ptr', 28, 'value4', 'i32') }}}; - {{{ makeSetValueAsm('ptr', 32, 'value4', 'i32') }}}; - {{{ makeSetValueAsm('ptr', 36, 'value4', 'i32') }}}; - {{{ makeSetValueAsm('ptr', 40, 'value4', 'i32') }}}; - {{{ makeSetValueAsm('ptr', 44, 'value4', 'i32') }}}; - {{{ makeSetValueAsm('ptr', 48, 'value4', 'i32') }}}; - {{{ makeSetValueAsm('ptr', 52, 'value4', 'i32') }}}; - {{{ makeSetValueAsm('ptr', 56, 'value4', 'i32') }}}; - {{{ makeSetValueAsm('ptr', 60, 'value4', 'i32') }}}; -#endif - ptr = (ptr + 64)|0; - } - - while ((ptr|0) < (aligned_end|0) ) { - {{{ makeSetValueAsm('ptr', 0, 'value4', 'i32') }}}; - ptr = (ptr+4)|0; - } - } - // The remaining bytes. - while ((ptr|0) < (end|0)) { - {{{ makeSetValueAsm('ptr', 0, 'value', 'i8') }}}; - ptr = (ptr+1)|0; - } - return (end-num)|0; - }, - llvm_memset_i32: 'memset', - llvm_memset_p0i8_i32: 'memset', - llvm_memset_p0i8_i64: 'memset', - - // ========================================================================== - // GCC/LLVM specifics - // ========================================================================== - __builtin_prefetch: function(){}, - - // ========================================================================== - // LLVM specifics - // ========================================================================== - - llvm_va_start__inline: function(ptr) { - // varargs - we received a pointer to the varargs as a final 'extra' parameter called 'varrp' - // 2-word structure: struct { void* start; void* currentOffset; } - return makeSetValue(ptr, 0, 'varrp', 'void*') + ';' + makeSetValue(ptr, Runtime.QUANTUM_SIZE, 0, 'void*'); - }, - - llvm_va_end: function() {}, - - llvm_va_copy: function(ppdest, ppsrc) { - // copy the list start - {{{ makeCopyValues('ppdest', 'ppsrc', Runtime.QUANTUM_SIZE, 'null', null, 1) }}}; - - // copy the list's current offset (will be advanced with each call to va_arg) - {{{ makeCopyValues('(ppdest+'+Runtime.QUANTUM_SIZE+')', '(ppsrc+'+Runtime.QUANTUM_SIZE+')', Runtime.QUANTUM_SIZE, 'null', null, 1) }}}; - }, - - llvm_bswap_i16__asm: true, - llvm_bswap_i16__sig: 'ii', - llvm_bswap_i16: function(x) { - x = x|0; - return (((x&0xff)<<8) | ((x>>8)&0xff))|0; - }, - - llvm_bswap_i32__asm: true, - llvm_bswap_i32__sig: 'ii', - llvm_bswap_i32: function(x) { - x = x|0; - return (((x&0xff)<<24) | (((x>>8)&0xff)<<16) | (((x>>16)&0xff)<<8) | (x>>>24))|0; - }, - - llvm_bswap_i64__deps: ['llvm_bswap_i32'], - llvm_bswap_i64: function(l, h) { - var retl = _llvm_bswap_i32(h)>>>0; - var reth = _llvm_bswap_i32(l)>>>0; - {{{ makeStructuralReturn(['retl', 'reth']) }}}; - }, - - llvm_ctlz_i8__asm: true, - llvm_ctlz_i8__sig: 'ii', - llvm_ctlz_i8: function(x, isZeroUndef) { - x = x | 0; - isZeroUndef = isZeroUndef | 0; - return (Math_clz32(x & 0xff) | 0) - 24 | 0; - }, - - llvm_ctlz_i16__asm: true, - llvm_ctlz_i16__sig: 'ii', - llvm_ctlz_i16: function(x, isZeroUndef) { - x = x | 0; - isZeroUndef = isZeroUndef | 0; - return (Math_clz32(x & 0xffff) | 0) - 16 | 0 - }, - - llvm_ctlz_i64__asm: true, - llvm_ctlz_i64__sig: 'iii', - llvm_ctlz_i64: function(l, h, isZeroUndef) { - l = l | 0; - h = h | 0; - isZeroUndef = isZeroUndef | 0; - var ret = 0; - ret = Math_clz32(h) | 0; - if ((ret | 0) == 32) ret = ret + (Math_clz32(l) | 0) | 0; - {{{ makeSetTempRet0('0') }}}; - return ret | 0; - }, - -#if WASM == 0 // binaryen will convert these calls to wasm anyhow - llvm_cttz_i32__asm: true, -#endif - llvm_cttz_i32__sig: 'ii', - llvm_cttz_i32: function(x) { // Note: Currently doesn't take isZeroUndef() - x = x | 0; - return (x ? (31 - (Math_clz32((x ^ (x - 1))) | 0) | 0) : 32) | 0; - }, - - llvm_cttz_i64__deps: ['llvm_cttz_i32'], - llvm_cttz_i64: function(l, h) { - var ret = _llvm_cttz_i32(l); - if (ret == 32) ret += _llvm_cttz_i32(h); - {{{ makeStructuralReturn(['ret', '0']) }}}; - }, - - llvm_ctpop_i32__asm: true, - llvm_ctpop_i32__sig: 'ii', - llvm_ctpop_i32: function(x) { - // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel - // http://bits.stephan-brumme.com/countBits.html - x = x | 0; - x = x - ((x >>> 1) & 0x55555555) | 0; - x = (x & 0x33333333) + ((x >>> 2) & 0x33333333) | 0; - return (Math_imul((x + (x >>> 4) & 252645135 /* 0xF0F0F0F, but hits uglify parse bug? */), 0x1010101) >>> 24) | 0; - }, - - llvm_ctpop_i64__deps: ['llvm_ctpop_i32'], - llvm_ctpop_i64__asm: true, - llvm_ctpop_i64__sig: 'iii', - llvm_ctpop_i64: function(l, h) { - l = l | 0; - h = h | 0; - return (_llvm_ctpop_i32(l) | 0) + (_llvm_ctpop_i32(h) | 0) | 0; - }, - - llvm_trap: function() { - abort('trap!'); - }, - - llvm_prefetch: function(){}, - - __assert_fail: function(condition, filename, line, func) { - abort('Assertion failed: ' + Pointer_stringify(condition) + ', at: ' + [filename ? Pointer_stringify(filename) : 'unknown filename', line, func ? Pointer_stringify(func) : 'unknown function']); - }, - - __assert_func: function(filename, line, func, condition) { - abort('Assertion failed: ' + (condition ? Pointer_stringify(condition) : 'unknown condition') + ', at: ' + [filename ? Pointer_stringify(filename) : 'unknown filename', line, func ? Pointer_stringify(func) : 'unknown function']); - }, - - $EXCEPTIONS: { - last: 0, - caught: [], - infos: {}, - deAdjust: function(adjusted) { - if (!adjusted || EXCEPTIONS.infos[adjusted]) return adjusted; - for (var key in EXCEPTIONS.infos) { - var ptr = +key; // the iteration key is a string, and if we throw this, it must be an integer as that is what we look for - var info = EXCEPTIONS.infos[ptr]; - if (info.adjusted === adjusted) { -#if EXCEPTION_DEBUG - Module.printErr('de-adjusted exception ptr ' + adjusted + ' to ' + ptr); -#endif - return ptr; - } - } -#if EXCEPTION_DEBUG - Module.printErr('no de-adjustment for unknown exception ptr ' + adjusted); -#endif - return adjusted; - }, - addRef: function(ptr) { -#if EXCEPTION_DEBUG - Module.printErr('addref ' + ptr); -#endif - if (!ptr) return; - var info = EXCEPTIONS.infos[ptr]; - info.refcount++; - }, - decRef: function(ptr) { -#if EXCEPTION_DEBUG - Module.printErr('decref ' + ptr); -#endif - if (!ptr) return; - var info = EXCEPTIONS.infos[ptr]; - assert(info.refcount > 0); - info.refcount--; - // A rethrown exception can reach refcount 0; it must not be discarded - // Its next handler will clear the rethrown flag and addRef it, prior to - // final decRef and destruction here - if (info.refcount === 0 && !info.rethrown) { - if (info.destructor) { -#if WASM_BACKEND == 0 - Module['dynCall_vi'](info.destructor, ptr); -#else - // In Wasm, destructors return 'this' as in ARM - Module['dynCall_ii'](info.destructor, ptr); -#endif - } - delete EXCEPTIONS.infos[ptr]; - ___cxa_free_exception(ptr); -#if EXCEPTION_DEBUG - Module.printErr('decref freeing exception ' + [ptr, EXCEPTIONS.last, 'stack', EXCEPTIONS.caught]); -#endif - } - }, - clearRef: function(ptr) { - if (!ptr) return; - var info = EXCEPTIONS.infos[ptr]; - info.refcount = 0; - }, - }, - - // Exceptions - __cxa_allocate_exception__deps: ['malloc'], - __cxa_allocate_exception: function(size) { - return _malloc(size); - }, - __cxa_free_exception__deps: ['free'], - __cxa_free_exception: function(ptr) { - try { - return _free(ptr); - } catch(e) { // XXX FIXME -#if ASSERTIONS - Module.printErr('exception during cxa_free_exception: ' + e); -#endif - } - }, - __cxa_increment_exception_refcount__deps: ['$EXCEPTIONS'], - __cxa_increment_exception_refcount: function(ptr) { - EXCEPTIONS.addRef(EXCEPTIONS.deAdjust(ptr)); - }, - __cxa_decrement_exception_refcount__deps: ['$EXCEPTIONS'], - __cxa_decrement_exception_refcount: function(ptr) { - EXCEPTIONS.decRef(EXCEPTIONS.deAdjust(ptr)); - }, - // Here, we throw an exception after recording a couple of values that we need to remember - // We also remember that it was the last exception thrown as we need to know that later. - __cxa_throw__sig: 'viii', - __cxa_throw__deps: ['_ZSt18uncaught_exceptionv', '__cxa_find_matching_catch', '$EXCEPTIONS'], - __cxa_throw: function(ptr, type, destructor) { -#if EXCEPTION_DEBUG - Module.printErr('Compiled code throwing an exception, ' + [ptr,type,destructor]); -#endif - EXCEPTIONS.infos[ptr] = { - ptr: ptr, - adjusted: ptr, - type: type, - destructor: destructor, - refcount: 0, - caught: false, - rethrown: false - }; - EXCEPTIONS.last = ptr; - if (!("uncaught_exception" in __ZSt18uncaught_exceptionv)) { - __ZSt18uncaught_exceptionv.uncaught_exception = 1; - } else { - __ZSt18uncaught_exceptionv.uncaught_exception++; - } - {{{ makeThrow('ptr') }}} - }, - // This exception will be caught twice, but while begin_catch runs twice, - // we early-exit from end_catch when the exception has been rethrown, so - // pop that here from the caught exceptions. - __cxa_rethrow__deps: ['__cxa_end_catch', '$EXCEPTIONS'], - __cxa_rethrow: function() { - var ptr = EXCEPTIONS.caught.pop(); - ptr = EXCEPTIONS.deAdjust(ptr); - if (!EXCEPTIONS.infos[ptr].rethrown) { - // Only pop if the corresponding push was through rethrow_primary_exception - EXCEPTIONS.caught.push(ptr) - EXCEPTIONS.infos[ptr].rethrown = true; - } -#if EXCEPTION_DEBUG - Module.printErr('Compiled code RE-throwing an exception, popped ' + [ptr, EXCEPTIONS.last, 'stack', EXCEPTIONS.caught]); -#endif - EXCEPTIONS.last = ptr; - {{{ makeThrow('ptr') }}} - }, - llvm_eh_exception__deps: ['$EXCEPTIONS'], - llvm_eh_exception: function() { - return EXCEPTIONS.last; - }, - llvm_eh_selector__jsargs: true, - llvm_eh_selector__deps: ['$EXCEPTIONS'], - llvm_eh_selector: function(unused_exception_value, personality/*, varargs*/) { - var type = EXCEPTIONS.last; - for (var i = 2; i < arguments.length; i++) { - if (arguments[i] == type) return type; - } - return 0; - }, - llvm_eh_typeid_for: function(type) { - return type; - }, - __cxa_begin_catch__deps: ['_ZSt18uncaught_exceptionv', '$EXCEPTIONS'], - __cxa_begin_catch: function(ptr) { - var info = EXCEPTIONS.infos[ptr]; - if (info && !info.caught) { - info.caught = true; - __ZSt18uncaught_exceptionv.uncaught_exception--; - } - if (info) info.rethrown = false; - EXCEPTIONS.caught.push(ptr); -#if EXCEPTION_DEBUG - Module.printErr('cxa_begin_catch ' + [ptr, 'stack', EXCEPTIONS.caught]); -#endif - EXCEPTIONS.addRef(EXCEPTIONS.deAdjust(ptr)); - return ptr; - }, - // We're done with a catch. Now, we can run the destructor if there is one - // and free the exception. Note that if the dynCall on the destructor fails - // due to calling apply on undefined, that means that the destructor is - // an invalid index into the FUNCTION_TABLE, so something has gone wrong. - __cxa_end_catch__deps: ['__cxa_free_exception', '$EXCEPTIONS'], - __cxa_end_catch: function() { - // Clear state flag. - Module['setThrew'](0); - // Call destructor if one is registered then clear it. - var ptr = EXCEPTIONS.caught.pop(); -#if EXCEPTION_DEBUG - Module.printErr('cxa_end_catch popped ' + [ptr, EXCEPTIONS.last, 'stack', EXCEPTIONS.caught]); -#endif - if (ptr) { - EXCEPTIONS.decRef(EXCEPTIONS.deAdjust(ptr)); - EXCEPTIONS.last = 0; // XXX in decRef? - } - }, - __cxa_get_exception_ptr: function(ptr) { -#if EXCEPTION_DEBUG - Module.printErr('cxa_get_exception_ptr ' + ptr); -#endif - // TODO: use info.adjusted? - return ptr; - }, - _ZSt18uncaught_exceptionv: function() { // std::uncaught_exception() - return !!__ZSt18uncaught_exceptionv.uncaught_exception; - }, - __cxa_uncaught_exception__deps: ['_ZSt18uncaught_exceptionv'], - __cxa_uncaught_exception: function() { - return !!__ZSt18uncaught_exceptionv.uncaught_exception; - }, - - __cxa_call_unexpected: function(exception) { - Module.printErr('Unexpected exception thrown, this is not properly supported - aborting'); - ABORT = true; - throw exception; - }, - - __cxa_current_primary_exception: function() { - var ret = EXCEPTIONS.caught[EXCEPTIONS.caught.length-1] || 0; - if (ret) EXCEPTIONS.addRef(EXCEPTIONS.deAdjust(ret)); - return ret; - }, - - __cxa_rethrow_primary_exception__deps: ['__cxa_rethrow'], - __cxa_rethrow_primary_exception: function(ptr) { - if (!ptr) return; - EXCEPTIONS.caught.push(ptr); - EXCEPTIONS.infos[ptr].rethrown = true; - ___cxa_rethrow(); - }, - - terminate: '__cxa_call_unexpected', - - __gxx_personality_v0__deps: ['_ZSt18uncaught_exceptionv', '__cxa_find_matching_catch'], - __gxx_personality_v0: function() { - }, - - __gcc_personality_v0: function() { - }, - - // Finds a suitable catch clause for when an exception is thrown. - // In normal compilers, this functionality is handled by the C++ - // 'personality' routine. This is passed a fairly complex structure - // relating to the context of the exception and makes judgements - // about how to handle it. Some of it is about matching a suitable - // catch clause, and some of it is about unwinding. We already handle - // unwinding using 'if' blocks around each function, so the remaining - // functionality boils down to picking a suitable 'catch' block. - // We'll do that here, instead, to keep things simpler. - - __cxa_find_matching_catch__deps: ['__resumeException', '$EXCEPTIONS'], - __cxa_find_matching_catch: function() { - var thrown = EXCEPTIONS.last; - if (!thrown) { - // just pass through the null ptr - {{{ makeStructuralReturn([0, 0]) }}}; - } - var info = EXCEPTIONS.infos[thrown]; - var throwntype = info.type; - if (!throwntype) { - // just pass through the thrown ptr - {{{ makeStructuralReturn(['thrown', 0]) }}}; - } - var typeArray = Array.prototype.slice.call(arguments); - - var pointer = Module['___cxa_is_pointer_type'](throwntype); - // can_catch receives a **, add indirection - if (!___cxa_find_matching_catch.buffer) ___cxa_find_matching_catch.buffer = _malloc(4); -#if EXCEPTION_DEBUG - Module.print("can_catch on " + [thrown]); -#endif - {{{ makeSetValue('___cxa_find_matching_catch.buffer', '0', 'thrown', '*') }}}; - thrown = ___cxa_find_matching_catch.buffer; - // The different catch blocks are denoted by different types. - // Due to inheritance, those types may not precisely match the - // type of the thrown object. Find one which matches, and - // return the type of the catch block which should be called. - for (var i = 0; i < typeArray.length; i++) { - if (typeArray[i] && Module['___cxa_can_catch'](typeArray[i], throwntype, thrown)) { - thrown = {{{ makeGetValue('thrown', '0', '*') }}}; // undo indirection - info.adjusted = thrown; -#if EXCEPTION_DEBUG - Module.print(" can_catch found " + [thrown, typeArray[i]]); -#endif - {{{ makeStructuralReturn(['thrown', 'typeArray[i]']) }}}; - } - } - // Shouldn't happen unless we have bogus data in typeArray - // or encounter a type for which emscripten doesn't have suitable - // typeinfo defined. Best-efforts match just in case. - thrown = {{{ makeGetValue('thrown', '0', '*') }}}; // undo indirection - {{{ makeStructuralReturn(['thrown', 'throwntype']) }}}; - }, - - __resumeException__deps: ['$EXCEPTIONS', function() { Functions.libraryFunctions['___resumeException'] = 1 }], // will be called directly from compiled code - __resumeException: function(ptr) { -#if EXCEPTION_DEBUG - Module.print("Resuming exception " + [ptr, EXCEPTIONS.last]); -#endif - if (!EXCEPTIONS.last) { EXCEPTIONS.last = ptr; } - {{{ makeThrow('ptr') }}} - }, - - llvm_stacksave: function() { - var self = _llvm_stacksave; - if (!self.LLVM_SAVEDSTACKS) { - self.LLVM_SAVEDSTACKS = []; - } - self.LLVM_SAVEDSTACKS.push(stackSave()); - return self.LLVM_SAVEDSTACKS.length-1; - }, - llvm_stackrestore: function(p) { - var self = _llvm_stacksave; - var ret = self.LLVM_SAVEDSTACKS[p]; - self.LLVM_SAVEDSTACKS.splice(p, 1); - stackRestore(ret); - }, - - __cxa_pure_virtual: function() { - ABORT = true; - throw 'Pure virtual function called!'; - }, - - llvm_flt_rounds: function() { - return -1; // 'indeterminable' for FLT_ROUNDS - }, - - llvm_expect_i32__inline: function(val, expected) { - return '(' + val + ')'; - }, - - llvm_objectsize_i32: function() { return -1 }, // TODO: support this - - llvm_dbg_declare__inline: function() { throw 'llvm_debug_declare' }, // avoid warning - - llvm_bitreverse_i32__asm: true, - llvm_bitreverse_i32__sig: 'ii', - llvm_bitreverse_i32: function(x) { - x = x|0; - x = ((x & 0xaaaaaaaa) >>> 1) | ((x & 0x55555555) << 1); - x = ((x & 0xcccccccc) >>> 2) | ((x & 0x33333333) << 2); - x = ((x & 0xf0f0f0f0) >>> 4) | ((x & 0x0f0f0f0f) << 4); - x = ((x & 0xff00ff00) >>> 8) | ((x & 0x00ff00ff) << 8); - return (x >>> 16) | (x << 16); - }, - - // llvm-nacl - - llvm_nacl_atomic_store_i32__inline: true, - - llvm_nacl_atomic_cmpxchg_i8__inline: true, - llvm_nacl_atomic_cmpxchg_i16__inline: true, - llvm_nacl_atomic_cmpxchg_i32__inline: true, - - // ========================================================================== - // llvm-mono integration - // ========================================================================== - - llvm_mono_load_i8_p0i8: function(ptr) { - return {{{ makeGetValue('ptr', 0, 'i8') }}}; - }, - - llvm_mono_store_i8_p0i8: function(value, ptr) { - {{{ makeSetValue('ptr', 0, 'value', 'i8') }}}; - }, - - llvm_mono_load_i16_p0i16: function(ptr) { - return {{{ makeGetValue('ptr', 0, 'i16') }}}; - }, - - llvm_mono_store_i16_p0i16: function(value, ptr) { - {{{ makeSetValue('ptr', 0, 'value', 'i16') }}}; - }, - - llvm_mono_load_i32_p0i32: function(ptr) { - return {{{ makeGetValue('ptr', 0, 'i32') }}}; - }, - - llvm_mono_store_i32_p0i32: function(value, ptr) { - {{{ makeSetValue('ptr', 0, 'value', 'i32') }}}; - }, - - // ========================================================================== - // math.h - // ========================================================================== - - cos: 'Math_cos', - cosf: 'Math_cos', - cosl: 'Math_cos', - sin: 'Math_sin', - sinf: 'Math_sin', - sinl: 'Math_sin', - tan: 'Math_tan', - tanf: 'Math_tan', - tanl: 'Math_tan', - acos: 'Math_acos', - acosf: 'Math_acos', - acosl: 'Math_acos', - asin: 'Math_asin', - asinf: 'Math_asin', - asinl: 'Math_asin', - atan: 'Math_atan', - atanf: 'Math_atan', - atanl: 'Math_atan', - atan2: 'Math_atan2', - atan2f: 'Math_atan2', - atan2l: 'Math_atan2', - exp: 'Math_exp', - expf: 'Math_exp', - expl: 'Math_exp', - log: 'Math_log', - logf: 'Math_log', - logl: 'Math_log', - sqrt: 'Math_sqrt', - sqrtf: 'Math_sqrt', - sqrtl: 'Math_sqrt', - fabs: 'Math_abs', - fabsf: 'Math_abs', - fabsl: 'Math_abs', - llvm_fabs_f32: 'Math_abs', - llvm_fabs_f64: 'Math_abs', - ceil: 'Math_ceil', - ceilf: 'Math_ceil', - ceill: 'Math_ceil', - floor: 'Math_floor', - floorf: 'Math_floor', - floorl: 'Math_floor', - pow: 'Math_pow', - powf: 'Math_pow', - powl: 'Math_pow', - llvm_sqrt_f32: 'Math_sqrt', - llvm_sqrt_f64: 'Math_sqrt', - llvm_pow_f32: 'Math_pow', - llvm_pow_f64: 'Math_pow', - llvm_powi_f32: 'Math_pow', - llvm_powi_f64: 'Math_pow', - llvm_log_f32: 'Math_log', - llvm_log_f64: 'Math_log', - llvm_exp_f32: 'Math_exp', - llvm_exp_f64: 'Math_exp', - llvm_cos_f32: 'Math_cos', - llvm_cos_f64: 'Math_cos', - llvm_sin_f32: 'Math_sin', - llvm_sin_f64: 'Math_sin', - llvm_trunc_f32: 'Math_trunc', - llvm_trunc_f64: 'Math_trunc', - llvm_ceil_f32: 'Math_ceil', - llvm_ceil_f64: 'Math_ceil', - llvm_floor_f32: 'Math_floor', - llvm_floor_f64: 'Math_floor', - - llvm_exp2_f32: function(x) { - return Math.pow(2, x); - }, - llvm_exp2_f64: 'llvm_exp2_f32', - - llvm_log2_f32: function(x) { - return Math.log(x) / Math.LN2; // TODO: Math.log2, when browser support is there - }, - llvm_log2_f64: 'llvm_log2_f32', - - llvm_log10_f32: function(x) { - return Math.log(x) / Math.LN10; // TODO: Math.log10, when browser support is there - }, - llvm_log10_f64: 'llvm_log10_f32', - - llvm_copysign_f32: function(x, y) { - return y < 0 || (y === 0 && 1/y < 0) ? -Math_abs(x) : Math_abs(x); - }, - - llvm_copysign_f64: function(x, y) { - return y < 0 || (y === 0 && 1/y < 0) ? -Math_abs(x) : Math_abs(x); - }, - - round__asm: true, - round__sig: 'dd', - round: function(d) { - d = +d; - return d >= +0 ? +Math_floor(d + +0.5) : +Math_ceil(d - +0.5); - }, - - roundf__asm: true, - roundf__sig: 'ff', - roundf: function(d) { - d = +d; - return d >= +0 ? +Math_floor(d + +0.5) : +Math_ceil(d - +0.5); - }, - - llvm_round_f64__asm: true, - llvm_round_f64__sig: 'dd', - llvm_round_f64: function(d) { - d = +d; - return d >= +0 ? +Math_floor(d + +0.5) : +Math_ceil(d - +0.5); - }, - - llvm_round_f32__asm: true, - llvm_round_f32__sig: 'ff', - llvm_round_f32: function(f) { - f = +f; - return f >= +0 ? +Math_floor(f + +0.5) : +Math_ceil(f - +0.5); // TODO: use fround? - }, - - rintf__asm: true, - rintf__sig: 'ff', - rintf__deps: ['round'], - rintf: function(f) { - f = +f; - return (f - +Math_floor(f) != .5) ? +_round(f) : +_round(f / +2) * +2; - }, - - // TODO: fround? - llvm_rint_f32__asm: true, - llvm_rint_f32__sig: 'ff', - llvm_rint_f32__deps: ['roundf'], - llvm_rint_f32: function(f) { - f = +f; - return (f - +Math_floor(f) != .5) ? +_roundf(f) : +_roundf(f / +2) * +2; - }, - - llvm_rint_f64__asm: true, - llvm_rint_f64__sig: 'dd', - llvm_rint_f64__deps: ['round'], - llvm_rint_f64: function(f) { - f = +f; - return (f - +Math_floor(f) != .5) ? +_round(f) : +_round(f / +2) * +2; - }, - - // TODO: fround? - llvm_nearbyint_f32__asm: true, - llvm_nearbyint_f32__sig: 'ff', - llvm_nearbyint_f32__deps: ['roundf'], - llvm_nearbyint_f32: function(f) { - f = +f; - return (f - +Math_floor(f) != .5) ? +_roundf(f) : +_roundf(f / +2) * +2; - }, - - llvm_nearbyint_f64__asm: true, - llvm_nearbyint_f64__sig: 'dd', - llvm_nearbyint_f64__deps: ['round'], - llvm_nearbyint_f64: function(f) { - f = +f; - return (f - +Math_floor(f) != .5) ? +_round(f) : +_round(f / +2) * +2; - }, - - // min/max num do not quite match the behavior of JS and wasm min/max: - // llvm and libc return the non-NaN if one is NaN, while JS and wasm - // return the NaN :( - // see also https://github.com/WebAssembly/design/issues/214 - llvm_minnum_f32__asm: true, - llvm_minnum_f32__sig: 'ff', - llvm_minnum_f32: function(x, y) { - x = +x; - y = +y; - if (x != x) return +y; - if (y != y) return +x; - return +Math_min(+x, +y); - }, - - llvm_minnum_f64__asm: true, - llvm_minnum_f64__sig: 'dd', - llvm_minnum_f64: function(x, y) { - x = +x; - y = +y; - if (x != x) return +y; - if (y != y) return +x; - return +Math_min(+x, +y); - }, - - llvm_maxnum_f32__asm: true, - llvm_maxnum_f32__sig: 'ff', - llvm_maxnum_f32: function(x, y) { - x = +x; - y = +y; - if (x != x) return +y; - if (y != y) return +x; - return +Math_max(+x, +y); - }, - - llvm_maxnum_f64__asm: true, - llvm_maxnum_f64__sig: 'dd', - llvm_maxnum_f64: function(x, y) { - x = +x; - y = +y; - if (x != x) return +y; - if (y != y) return +x; - return +Math_max(+x, +y); - }, - - _reallyNegative: function(x) { - return x < 0 || (x === 0 && (1/x) === -Infinity); - }, - - // ========================================================================== - // dlfcn.h - Dynamic library loading - // - // Some limitations: - // - // * Minification on each file separately may not work, as they will - // have different shortened names. You can in theory combine them, then - // minify, then split... perhaps. - // - // * LLVM optimizations may fail. If the child wants to access a function - // in the parent, LLVM opts may remove it from the parent when it is - // being compiled. Not sure how to tell LLVM to not do so. - // ========================================================================== - - $DLFCN: { - error: null, - errorMsg: null, - loadedLibs: {}, // handle -> [refcount, name, lib_object] - loadedLibNames: {}, // name -> handle - }, - // void* dlopen(const char* filename, int flag); - dlopen__deps: ['$DLFCN', '$FS', '$ENV'], - dlopen__proxy: 'sync', - dlopen__sig: 'iii', - dlopen: function(filename, flag) { -#if MAIN_MODULE == 0 - abort("To use dlopen, you need to use Emscripten's linking support, see https://github.com/kripken/emscripten/wiki/Linking"); -#endif - // void *dlopen(const char *file, int mode); - // http://pubs.opengroup.org/onlinepubs/009695399/functions/dlopen.html - var searchpaths = []; - if (filename === 0) { - filename = '__self__'; - } else { - var strfilename = Pointer_stringify(filename); - var isValidFile = function (filename) { - var target = FS.findObject(filename); - return target && !target.isFolder && !target.isDevice; - }; - - if (isValidFile(strfilename)) { - filename = strfilename; - } else { - if (ENV['LD_LIBRARY_PATH']) { - searchpaths = ENV['LD_LIBRARY_PATH'].split(':'); - } - - for (var ident in searchpaths) { - var searchfile = PATH.join2(searchpaths[ident],strfilename); - if (isValidFile(searchfile)) { - filename = searchfile; - break; - } - } - } - } - - if (DLFCN.loadedLibNames[filename]) { - // Already loaded; increment ref count and return. - var handle = DLFCN.loadedLibNames[filename]; - DLFCN.loadedLibs[handle].refcount++; - return handle; - } - - var lib_module; - if (filename === '__self__') { - var handle = -1; - lib_module = Module; - } else { - if (Module['preloadedWasm'] !== undefined && - Module['preloadedWasm'][filename] !== undefined) { - lib_module = Module['preloadedWasm'][filename]; - } else { - var target = FS.findObject(filename); - if (!target || target.isFolder || target.isDevice) { - DLFCN.errorMsg = 'Could not find dynamic lib: ' + filename; - return 0; - } - FS.forceLoadFile(target); - - try { -#if WASM - // the shared library is a shared wasm library (see tools/shared.py WebAssembly.make_shared_library) - var lib_data = FS.readFile(filename, { encoding: 'binary' }); - if (!(lib_data instanceof Uint8Array)) lib_data = new Uint8Array(lib_data); - //Module.printErr('libfile ' + filename + ' size: ' + lib_data.length); - lib_module = loadWebAssemblyModule(lib_data); -#else - // the shared library is a JS file, which we eval - var lib_data = FS.readFile(filename, { encoding: 'utf8' }); - lib_module = eval(lib_data)( - alignFunctionTables(), - Module - ); -#endif - } catch (e) { -#if ASSERTIONS - Module.printErr('Error in loading dynamic library: ' + e); -#endif - DLFCN.errorMsg = 'Could not evaluate dynamic lib: ' + filename + '\n' + e; - return 0; - } - } - - // Not all browsers support Object.keys(). - var handle = 1; - for (var key in DLFCN.loadedLibs) { - if (DLFCN.loadedLibs.hasOwnProperty(key)) handle++; - } - - // We don't care about RTLD_NOW and RTLD_LAZY. - if (flag & 256) { // RTLD_GLOBAL - for (var ident in lib_module) { - if (lib_module.hasOwnProperty(ident)) { - // When RTLD_GLOBAL is enable, the symbols defined by this shared object will be made - // available for symbol resolution of subsequently loaded shared objects. - // - // We should copy the symbols (which include methods and variables) from SIDE_MODULE to MAIN_MODULE. - // - // Module of SIDE_MODULE has not only the symbols (which should be copied) - // but also others (print*, asmGlobal*, FUNCTION_TABLE_**, NAMED_GLOBALS, and so on). - // - // When the symbol (which should be copied) is method, Module._* 's type becomes function. - // When the symbol (which should be copied) is variable, Module._* 's type becomes number. - // - // Except for the symbol prefix (_), there is no difference in the symbols (which should be copied) and others. - // So this just copies over compiled symbols (which start with _). - if (ident[0] == '_') { - Module[ident] = lib_module[ident]; - } - } - } - } - } - DLFCN.loadedLibs[handle] = { - refcount: 1, - name: filename, - module: lib_module - }; - DLFCN.loadedLibNames[filename] = handle; - - return handle; - }, - // int dlclose(void* handle); - dlclose__deps: ['$DLFCN'], - dlclose__proxy: 'sync', - dlclose__sig: 'ii', - dlclose: function(handle) { - // int dlclose(void *handle); - // http://pubs.opengroup.org/onlinepubs/009695399/functions/dlclose.html - if (!DLFCN.loadedLibs[handle]) { - DLFCN.errorMsg = 'Tried to dlclose() unopened handle: ' + handle; - return 1; - } else { - var lib_record = DLFCN.loadedLibs[handle]; - if (--lib_record.refcount == 0) { - if (lib_record.module.cleanups) { - lib_record.module.cleanups.forEach(function(cleanup) { cleanup() }); - } - delete DLFCN.loadedLibNames[lib_record.name]; - delete DLFCN.loadedLibs[handle]; - } - return 0; - } - }, - // void* dlsym(void* handle, const char* symbol); - dlsym__deps: ['$DLFCN'], - dlsym__proxy: 'sync', - dlsym__sig: 'iii', - dlsym: function(handle, symbol) { - // void *dlsym(void *restrict handle, const char *restrict name); - // http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html - symbol = Pointer_stringify(symbol); - - if (!DLFCN.loadedLibs[handle]) { - DLFCN.errorMsg = 'Tried to dlsym() from an unopened handle: ' + handle; - return 0; - } else { - var lib = DLFCN.loadedLibs[handle]; - symbol = '_' + symbol; - if (!lib.module.hasOwnProperty(symbol)) { - DLFCN.errorMsg = ('Tried to lookup unknown symbol "' + symbol + - '" in dynamic lib: ' + lib.name); - return 0; - } else { - var result = lib.module[symbol]; - if (typeof result === 'function') { -#if WASM -#if EMULATED_FUNCTION_POINTERS - // for wasm with emulated function pointers, the i64 ABI is used for all - // function calls, so we can't just call addFunction on something JS - // can call (which does not use that ABI), as the function pointer would - // not be usable from wasm. instead, the wasm has exported function pointers - // for everything we need, with prefix fp$, use those - result = lib.module['fp$' + symbol]; - if (typeof result === 'object') { - // a breaking change in the wasm spec, globals are now objects - // https://github.com/WebAssembly/mutable-global/issues/1 - result = result.value; - } -#if ASSERTIONS - assert(typeof result === 'number', 'could not find function pointer for ' + symbol); -#endif // ASSERTIONS - return result; -#endif // EMULATED_FUNCTION_POINTERS -#endif // WASM - // convert the exported function into a function pointer using our generic - // JS mechanism. - return addFunction(result); - } - return result; - } - } - }, - // char* dlerror(void); - dlerror__deps: ['$DLFCN'], - dlerror__proxy: 'sync', - dlerror__sig: 'i', - dlerror: function() { - // char *dlerror(void); - // http://pubs.opengroup.org/onlinepubs/009695399/functions/dlerror.html - if (DLFCN.errorMsg === null) { - return 0; - } else { - if (DLFCN.error) _free(DLFCN.error); - var msgArr = intArrayFromString(DLFCN.errorMsg); - DLFCN.error = allocate(msgArr, 'i8', ALLOC_NORMAL); - DLFCN.errorMsg = null; - return DLFCN.error; - } - }, - - dladdr__proxy: 'sync', - dladdr__sig: 'iii', - dladdr: function(addr, info) { - // report all function pointers as coming from this program itself XXX not really correct in any way - var fname = allocate(intArrayFromString(Module['thisProgram'] || './this.program'), 'i8', ALLOC_NORMAL); // XXX leak - {{{ makeSetValue('info', 0, 'fname', 'i32') }}}; - {{{ makeSetValue('info', QUANTUM_SIZE, '0', 'i32') }}}; - {{{ makeSetValue('info', QUANTUM_SIZE*2, '0', 'i32') }}}; - {{{ makeSetValue('info', QUANTUM_SIZE*3, '0', 'i32') }}}; - return 1; - }, - - // ========================================================================== - // pwd.h - // ========================================================================== - - // TODO: Implement. - // http://pubs.opengroup.org/onlinepubs/009695399/basedefs/pwd.h.html - getpwuid: function(uid) { - return 0; // NULL - }, - - - // ========================================================================== - // time.h - // ========================================================================== - - clock: function() { - if (_clock.start === undefined) _clock.start = Date.now(); - return ((Date.now() - _clock.start) * ({{{ cDefine('CLOCKS_PER_SEC') }}} / 1000))|0; - }, - - time: function(ptr) { - var ret = (Date.now()/1000)|0; - if (ptr) { - {{{ makeSetValue('ptr', 0, 'ret', 'i32') }}}; - } - return ret; - }, - - difftime: function(time1, time0) { - return time1 - time0; - }, - - // Statically allocated time struct. -#if USE_PTHREADS - __tm_current: '; if (ENVIRONMENT_IS_PTHREAD) ___tm_current = PthreadWorkerInit.___tm_current; else PthreadWorkerInit.___tm_current = ___tm_current = allocate({{{ C_STRUCTS.tm.__size__ }}}, "i8", ALLOC_STATIC)', - __tm_timezone: '; if (ENVIRONMENT_IS_PTHREAD) ___tm_timezone = PthreadWorkerInit.___tm_timezone; else PthreadWorkerInit.___tm_timezone = ___tm_timezone = allocate(intArrayFromString("GMT"), "i8", ALLOC_STATIC)', - __tm_formatted: '; if (ENVIRONMENT_IS_PTHREAD) ___tm_formatted = PthreadWorkerInit.___tm_formatted; else PthreadWorkerInit.___tm_formatted = ___tm_formatted = allocate({{{ C_STRUCTS.tm.__size__ }}}, "i8", ALLOC_STATIC)', -#else - __tm_current: '{{{ makeStaticAlloc(C_STRUCTS.tm.__size__) }}}', - // Statically allocated copy of the string "GMT" for gmtime() to point to - __tm_timezone: 'allocate(intArrayFromString("GMT"), "i8", ALLOC_STATIC)', - // Statically allocated time strings. - __tm_formatted: '{{{ makeStaticAlloc(C_STRUCTS.tm.__size__) }}}', -#endif - mktime__deps: ['tzset'], - mktime: function(tmPtr) { - _tzset(); - var date = new Date({{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_year, 'i32') }}} + 1900, - {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_mon, 'i32') }}}, - {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_mday, 'i32') }}}, - {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_hour, 'i32') }}}, - {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_min, 'i32') }}}, - {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_sec, 'i32') }}}, - 0); - - // There's an ambiguous hour when the time goes back; the tm_isdst field is - // used to disambiguate it. Date() basically guesses, so we fix it up if it - // guessed wrong, or fill in tm_isdst with the guess if it's -1. - var dst = {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_isdst, 'i32') }}}; - var guessedOffset = date.getTimezoneOffset(); - var start = new Date(date.getFullYear(), 0, 1); - var summerOffset = new Date(2000, 6, 1).getTimezoneOffset(); - var winterOffset = start.getTimezoneOffset(); - var dstOffset = Math.min(winterOffset, summerOffset); // DST is in December in South - if (dst < 0) { - // Attention: some regions don't have DST at all. - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_isdst, 'Number(summerOffset != winterOffset && dstOffset == guessedOffset)', 'i32') }}}; - } else if ((dst > 0) != (dstOffset == guessedOffset)) { - var nonDstOffset = Math.max(winterOffset, summerOffset); - var trueOffset = dst > 0 ? dstOffset : nonDstOffset; - // Don't try setMinutes(date.getMinutes() + ...) -- it's messed up. - date.setTime(date.getTime() + (trueOffset - guessedOffset)*60000); - } - - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_wday, 'date.getDay()', 'i32') }}}; - var yday = ((date.getTime() - start.getTime()) / (1000 * 60 * 60 * 24))|0; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_yday, 'yday', 'i32') }}}; - - return (date.getTime() / 1000)|0; - }, - timelocal: 'mktime', - - gmtime__deps: ['__tm_current', 'gmtime_r'], - gmtime: function(time) { - return _gmtime_r(time, ___tm_current); - }, - - gmtime_r__deps: ['__tm_timezone'], - gmtime_r: function(time, tmPtr) { - var date = new Date({{{ makeGetValue('time', 0, 'i32') }}}*1000); - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_sec, 'date.getUTCSeconds()', 'i32') }}}; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_min, 'date.getUTCMinutes()', 'i32') }}}; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_hour, 'date.getUTCHours()', 'i32') }}}; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_mday, 'date.getUTCDate()', 'i32') }}}; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_mon, 'date.getUTCMonth()', 'i32') }}}; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_year, 'date.getUTCFullYear()-1900', 'i32') }}}; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_wday, 'date.getUTCDay()', 'i32') }}}; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_gmtoff, '0', 'i32') }}}; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_isdst, '0', 'i32') }}}; - var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0); - var yday = ((date.getTime() - start) / (1000 * 60 * 60 * 24))|0; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_yday, 'yday', 'i32') }}}; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_zone, '___tm_timezone', 'i32') }}}; - - return tmPtr; - }, - timegm__deps: ['tzset'], - timegm: function(tmPtr) { - _tzset(); - var time = Date.UTC({{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_year, 'i32') }}} + 1900, - {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_mon, 'i32') }}}, - {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_mday, 'i32') }}}, - {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_hour, 'i32') }}}, - {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_min, 'i32') }}}, - {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_sec, 'i32') }}}, - 0); - var date = new Date(time); - - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_wday, 'date.getUTCDay()', 'i32') }}}; - var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0); - var yday = ((date.getTime() - start) / (1000 * 60 * 60 * 24))|0; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_yday, 'yday', 'i32') }}}; - - return (date.getTime() / 1000)|0; - }, - - localtime__deps: ['__tm_current', 'localtime_r'], - localtime: function(time) { - return _localtime_r(time, ___tm_current); - }, - - localtime_r__deps: ['__tm_timezone', 'tzset'], - localtime_r: function(time, tmPtr) { - _tzset(); - var date = new Date({{{ makeGetValue('time', 0, 'i32') }}}*1000); - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_sec, 'date.getSeconds()', 'i32') }}}; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_min, 'date.getMinutes()', 'i32') }}}; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_hour, 'date.getHours()', 'i32') }}}; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_mday, 'date.getDate()', 'i32') }}}; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_mon, 'date.getMonth()', 'i32') }}}; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_year, 'date.getFullYear()-1900', 'i32') }}}; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_wday, 'date.getDay()', 'i32') }}}; - - var start = new Date(date.getFullYear(), 0, 1); - var yday = ((date.getTime() - start.getTime()) / (1000 * 60 * 60 * 24))|0; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_yday, 'yday', 'i32') }}}; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_gmtoff, '-(date.getTimezoneOffset() * 60)', 'i32') }}}; - - // Attention: DST is in December in South, and some regions don't have DST at all. - var summerOffset = new Date(2000, 6, 1).getTimezoneOffset(); - var winterOffset = start.getTimezoneOffset(); - var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset))|0; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_isdst, 'dst', 'i32') }}}; - - var zonePtr = {{{ makeGetValue('__get_tzname()', 'dst ? ' + Runtime.QUANTUM_SIZE + ' : 0', 'i32') }}}; - {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_zone, 'zonePtr', 'i32') }}}; - - return tmPtr; - }, - - asctime__deps: ['__tm_formatted', 'asctime_r'], - asctime: function(tmPtr) { - return _asctime_r(tmPtr, ___tm_formatted); - }, - - asctime_r__deps: ['__tm_formatted', 'mktime'], - asctime_r: function(tmPtr, buf) { - var date = { - tm_sec: {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_sec, 'i32') }}}, - tm_min: {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_min, 'i32') }}}, - tm_hour: {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_hour, 'i32') }}}, - tm_mday: {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_mday, 'i32') }}}, - tm_mon: {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_mon, 'i32') }}}, - tm_year: {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_year, 'i32') }}}, - tm_wday: {{{ makeGetValue('tmPtr', C_STRUCTS.tm.tm_wday, 'i32') }}} - }; - var days = [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ]; - var months = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]; - var s = days[date.tm_wday] + ' ' + months[date.tm_mon] + - (date.tm_mday < 10 ? ' ' : ' ') + date.tm_mday + - (date.tm_hour < 10 ? ' 0' : ' ') + date.tm_hour + - (date.tm_min < 10 ? ':0' : ':') + date.tm_min + - (date.tm_sec < 10 ? ':0' : ':') + date.tm_sec + - ' ' + (1900 + date.tm_year) + "\n"; - - // asctime_r is specced to behave in an undefined manner if the algorithm would attempt - // to write out more than 26 bytes (including the null terminator). - // See http://pubs.opengroup.org/onlinepubs/9699919799/functions/asctime.html - // Our undefined behavior is to truncate the write to at most 26 bytes, including null terminator. - stringToUTF8(s, buf, 26); - return buf; - }, - - ctime__deps: ['__tm_current', 'ctime_r'], - ctime: function(timer) { - return _ctime_r(timer, ___tm_current); - }, - - ctime_r__deps: ['localtime_r', 'asctime_r'], - ctime_r: function(time, buf) { - var stack = stackSave(); - var rv = _asctime_r(_localtime_r(time, stackAlloc({{{ C_STRUCTS.tm.__size__ }}})), buf); - stackRestore(stack); - return rv; - }, - - dysize: function(year) { - var leap = ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))); - return leap ? 366 : 365; - }, - - // TODO: Initialize these to defaults on startup from system settings. - // Note: glibc has one fewer underscore for all of these. Also used in other related functions (timegm) - tzset__proxy: 'sync', - tzset__sig: 'v', - tzset: function() { - // TODO: Use (malleable) environment variables instead of system settings. - if (_tzset.called) return; - _tzset.called = true; - - // timezone is specified as seconds west of UTC ("The external variable - // `timezone` shall be set to the difference, in seconds, between - // Coordinated Universal Time (UTC) and local standard time."), the same - // as returned by getTimezoneOffset(). - // See http://pubs.opengroup.org/onlinepubs/009695399/functions/tzset.html - {{{ makeSetValue('__get_timezone()', '0', '(new Date()).getTimezoneOffset() * 60', 'i32') }}}; - - var winter = new Date(2000, 0, 1); - var summer = new Date(2000, 6, 1); - {{{ makeSetValue('__get_daylight()', '0', 'Number(winter.getTimezoneOffset() != summer.getTimezoneOffset())', 'i32') }}}; - - function extractZone(date) { - var match = date.toTimeString().match(/\(([A-Za-z ]+)\)$/); - return match ? match[1] : "GMT"; - }; - var winterName = extractZone(winter); - var summerName = extractZone(summer); - var winterNamePtr = allocate(intArrayFromString(winterName), 'i8', ALLOC_NORMAL); - var summerNamePtr = allocate(intArrayFromString(summerName), 'i8', ALLOC_NORMAL); - if (summer.getTimezoneOffset() < winter.getTimezoneOffset()) { - // Northern hemisphere - {{{ makeSetValue('__get_tzname()', '0', 'winterNamePtr', 'i32') }}}; - {{{ makeSetValue('__get_tzname()', Runtime.QUANTUM_SIZE, 'summerNamePtr', 'i32') }}}; - } else { - {{{ makeSetValue('__get_tzname()', '0', 'summerNamePtr', 'i32') }}}; - {{{ makeSetValue('__get_tzname()', Runtime.QUANTUM_SIZE, 'winterNamePtr', 'i32') }}}; - } - }, - - stime__deps: ['$ERRNO_CODES', '__setErrNo'], - stime: function(when) { - ___setErrNo(ERRNO_CODES.EPERM); - return -1; - }, - - __map_file__deps: ['$ERRNO_CODES', '__setErrNo'], - __map_file: function(pathname, size) { - ___setErrNo(ERRNO_CODES.EPERM); - return -1; - }, - - _MONTH_DAYS_REGULAR: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], - _MONTH_DAYS_LEAP: [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], - - _isLeapYear: function(year) { - return year%4 === 0 && (year%100 !== 0 || year%400 === 0); - }, - - _arraySum: function(array, index) { - var sum = 0; - for (var i = 0; i <= index; sum += array[i++]); - return sum; - }, - - _addDays__deps: ['_isLeapYear', '_MONTH_DAYS_LEAP', '_MONTH_DAYS_REGULAR'], - _addDays: function(date, days) { - var newDate = new Date(date.getTime()); - while(days > 0) { - var leap = __isLeapYear(newDate.getFullYear()); - var currentMonth = newDate.getMonth(); - var daysInCurrentMonth = (leap ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR)[currentMonth]; - - if (days > daysInCurrentMonth-newDate.getDate()) { - // we spill over to next month - days -= (daysInCurrentMonth-newDate.getDate()+1); - newDate.setDate(1); - if (currentMonth < 11) { - newDate.setMonth(currentMonth+1) - } else { - newDate.setMonth(0); - newDate.setFullYear(newDate.getFullYear()+1); - } - } else { - // we stay in current month - newDate.setDate(newDate.getDate()+days); - return newDate; - } - } - - return newDate; - }, - - strftime__deps: ['_isLeapYear', '_arraySum', '_addDays', '_MONTH_DAYS_REGULAR', '_MONTH_DAYS_LEAP'], - strftime: function(s, maxsize, format, tm) { - // size_t strftime(char *restrict s, size_t maxsize, const char *restrict format, const struct tm *restrict timeptr); - // http://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html - - var tm_zone = {{{ makeGetValue('tm', C_STRUCTS.tm.tm_zone, 'i32') }}}; - - var date = { - tm_sec: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_sec, 'i32') }}}, - tm_min: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_min, 'i32') }}}, - tm_hour: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_hour, 'i32') }}}, - tm_mday: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_mday, 'i32') }}}, - tm_mon: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_mon, 'i32') }}}, - tm_year: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_year, 'i32') }}}, - tm_wday: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_wday, 'i32') }}}, - tm_yday: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_yday, 'i32') }}}, - tm_isdst: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_isdst, 'i32') }}}, - tm_gmtoff: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_gmtoff, 'i32') }}}, - tm_zone: tm_zone ? Pointer_stringify(tm_zone) : '' - }; - - var pattern = Pointer_stringify(format); - - // expand format - var EXPANSION_RULES_1 = { - '%c': '%a %b %d %H:%M:%S %Y', // Replaced by the locale's appropriate date and time representation - e.g., Mon Aug 3 14:02:01 2013 - '%D': '%m/%d/%y', // Equivalent to %m / %d / %y - '%F': '%Y-%m-%d', // Equivalent to %Y - %m - %d - '%h': '%b', // Equivalent to %b - '%r': '%I:%M:%S %p', // Replaced by the time in a.m. and p.m. notation - '%R': '%H:%M', // Replaced by the time in 24-hour notation - '%T': '%H:%M:%S', // Replaced by the time - '%x': '%m/%d/%y', // Replaced by the locale's appropriate date representation - '%X': '%H:%M:%S' // Replaced by the locale's appropriate date representation - }; - for (var rule in EXPANSION_RULES_1) { - pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_1[rule]); - } - - var WEEKDAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; - var MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; - - function leadingSomething(value, digits, character) { - var str = typeof value === 'number' ? value.toString() : (value || ''); - while (str.length < digits) { - str = character[0]+str; - } - return str; - }; - - function leadingNulls(value, digits) { - return leadingSomething(value, digits, '0'); - }; - - function compareByDay(date1, date2) { - function sgn(value) { - return value < 0 ? -1 : (value > 0 ? 1 : 0); - }; - - var compare; - if ((compare = sgn(date1.getFullYear()-date2.getFullYear())) === 0) { - if ((compare = sgn(date1.getMonth()-date2.getMonth())) === 0) { - compare = sgn(date1.getDate()-date2.getDate()); - } - } - return compare; - }; - - function getFirstWeekStartDate(janFourth) { - switch (janFourth.getDay()) { - case 0: // Sunday - return new Date(janFourth.getFullYear()-1, 11, 29); - case 1: // Monday - return janFourth; - case 2: // Tuesday - return new Date(janFourth.getFullYear(), 0, 3); - case 3: // Wednesday - return new Date(janFourth.getFullYear(), 0, 2); - case 4: // Thursday - return new Date(janFourth.getFullYear(), 0, 1); - case 5: // Friday - return new Date(janFourth.getFullYear()-1, 11, 31); - case 6: // Saturday - return new Date(janFourth.getFullYear()-1, 11, 30); - } - }; - - function getWeekBasedYear(date) { - var thisDate = __addDays(new Date(date.tm_year+1900, 0, 1), date.tm_yday); - - var janFourthThisYear = new Date(thisDate.getFullYear(), 0, 4); - var janFourthNextYear = new Date(thisDate.getFullYear()+1, 0, 4); - - var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear); - var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear); - - if (compareByDay(firstWeekStartThisYear, thisDate) <= 0) { - // this date is after the start of the first week of this year - if (compareByDay(firstWeekStartNextYear, thisDate) <= 0) { - return thisDate.getFullYear()+1; - } else { - return thisDate.getFullYear(); - } - } else { - return thisDate.getFullYear()-1; - } - }; - - var EXPANSION_RULES_2 = { - '%a': function(date) { - return WEEKDAYS[date.tm_wday].substring(0,3); - }, - '%A': function(date) { - return WEEKDAYS[date.tm_wday]; - }, - '%b': function(date) { - return MONTHS[date.tm_mon].substring(0,3); - }, - '%B': function(date) { - return MONTHS[date.tm_mon]; - }, - '%C': function(date) { - var year = date.tm_year+1900; - return leadingNulls((year/100)|0,2); - }, - '%d': function(date) { - return leadingNulls(date.tm_mday, 2); - }, - '%e': function(date) { - return leadingSomething(date.tm_mday, 2, ' '); - }, - '%g': function(date) { - // %g, %G, and %V give values according to the ISO 8601:2000 standard week-based year. - // In this system, weeks begin on a Monday and week 1 of the year is the week that includes - // January 4th, which is also the week that includes the first Thursday of the year, and - // is also the first week that contains at least four days in the year. - // If the first Monday of January is the 2nd, 3rd, or 4th, the preceding days are part of - // the last week of the preceding year; thus, for Saturday 2nd January 1999, - // %G is replaced by 1998 and %V is replaced by 53. If December 29th, 30th, - // or 31st is a Monday, it and any following days are part of week 1 of the following year. - // Thus, for Tuesday 30th December 1997, %G is replaced by 1998 and %V is replaced by 01. - - return getWeekBasedYear(date).toString().substring(2); - }, - '%G': function(date) { - return getWeekBasedYear(date); - }, - '%H': function(date) { - return leadingNulls(date.tm_hour, 2); - }, - '%I': function(date) { - var twelveHour = date.tm_hour; - if (twelveHour == 0) twelveHour = 12; - else if (twelveHour > 12) twelveHour -= 12; - return leadingNulls(twelveHour, 2); - }, - '%j': function(date) { - // Day of the year (001-366) - return leadingNulls(date.tm_mday+__arraySum(__isLeapYear(date.tm_year+1900) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, date.tm_mon-1), 3); - }, - '%m': function(date) { - return leadingNulls(date.tm_mon+1, 2); - }, - '%M': function(date) { - return leadingNulls(date.tm_min, 2); - }, - '%n': function() { - return '\n'; - }, - '%p': function(date) { - if (date.tm_hour >= 0 && date.tm_hour < 12) { - return 'AM'; - } else { - return 'PM'; - } - }, - '%S': function(date) { - return leadingNulls(date.tm_sec, 2); - }, - '%t': function() { - return '\t'; - }, - '%u': function(date) { - var day = new Date(date.tm_year+1900, date.tm_mon+1, date.tm_mday, 0, 0, 0, 0); - return day.getDay() || 7; - }, - '%U': function(date) { - // Replaced by the week number of the year as a decimal number [00,53]. - // The first Sunday of January is the first day of week 1; - // days in the new year before this are in week 0. [ tm_year, tm_wday, tm_yday] - var janFirst = new Date(date.tm_year+1900, 0, 1); - var firstSunday = janFirst.getDay() === 0 ? janFirst : __addDays(janFirst, 7-janFirst.getDay()); - var endDate = new Date(date.tm_year+1900, date.tm_mon, date.tm_mday); - - // is target date after the first Sunday? - if (compareByDay(firstSunday, endDate) < 0) { - // calculate difference in days between first Sunday and endDate - var februaryFirstUntilEndMonth = __arraySum(__isLeapYear(endDate.getFullYear()) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, endDate.getMonth()-1)-31; - var firstSundayUntilEndJanuary = 31-firstSunday.getDate(); - var days = firstSundayUntilEndJanuary+februaryFirstUntilEndMonth+endDate.getDate(); - return leadingNulls(Math.ceil(days/7), 2); - } - - return compareByDay(firstSunday, janFirst) === 0 ? '01': '00'; - }, - '%V': function(date) { - // Replaced by the week number of the year (Monday as the first day of the week) - // as a decimal number [01,53]. If the week containing 1 January has four - // or more days in the new year, then it is considered week 1. - // Otherwise, it is the last week of the previous year, and the next week is week 1. - // Both January 4th and the first Thursday of January are always in week 1. [ tm_year, tm_wday, tm_yday] - var janFourthThisYear = new Date(date.tm_year+1900, 0, 4); - var janFourthNextYear = new Date(date.tm_year+1901, 0, 4); - - var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear); - var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear); - - var endDate = __addDays(new Date(date.tm_year+1900, 0, 1), date.tm_yday); - - if (compareByDay(endDate, firstWeekStartThisYear) < 0) { - // if given date is before this years first week, then it belongs to the 53rd week of last year - return '53'; - } - - if (compareByDay(firstWeekStartNextYear, endDate) <= 0) { - // if given date is after next years first week, then it belongs to the 01th week of next year - return '01'; - } - - // given date is in between CW 01..53 of this calendar year - var daysDifference; - if (firstWeekStartThisYear.getFullYear() < date.tm_year+1900) { - // first CW of this year starts last year - daysDifference = date.tm_yday+32-firstWeekStartThisYear.getDate() - } else { - // first CW of this year starts this year - daysDifference = date.tm_yday+1-firstWeekStartThisYear.getDate(); - } - return leadingNulls(Math.ceil(daysDifference/7), 2); - }, - '%w': function(date) { - var day = new Date(date.tm_year+1900, date.tm_mon+1, date.tm_mday, 0, 0, 0, 0); - return day.getDay(); - }, - '%W': function(date) { - // Replaced by the week number of the year as a decimal number [00,53]. - // The first Monday of January is the first day of week 1; - // days in the new year before this are in week 0. [ tm_year, tm_wday, tm_yday] - var janFirst = new Date(date.tm_year, 0, 1); - var firstMonday = janFirst.getDay() === 1 ? janFirst : __addDays(janFirst, janFirst.getDay() === 0 ? 1 : 7-janFirst.getDay()+1); - var endDate = new Date(date.tm_year+1900, date.tm_mon, date.tm_mday); - - // is target date after the first Monday? - if (compareByDay(firstMonday, endDate) < 0) { - var februaryFirstUntilEndMonth = __arraySum(__isLeapYear(endDate.getFullYear()) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, endDate.getMonth()-1)-31; - var firstMondayUntilEndJanuary = 31-firstMonday.getDate(); - var days = firstMondayUntilEndJanuary+februaryFirstUntilEndMonth+endDate.getDate(); - return leadingNulls(Math.ceil(days/7), 2); - } - return compareByDay(firstMonday, janFirst) === 0 ? '01': '00'; - }, - '%y': function(date) { - // Replaced by the last two digits of the year as a decimal number [00,99]. [ tm_year] - return (date.tm_year+1900).toString().substring(2); - }, - '%Y': function(date) { - // Replaced by the year as a decimal number (for example, 1997). [ tm_year] - return date.tm_year+1900; - }, - '%z': function(date) { - // Replaced by the offset from UTC in the ISO 8601:2000 standard format ( +hhmm or -hhmm ). - // For example, "-0430" means 4 hours 30 minutes behind UTC (west of Greenwich). - var off = date.tm_gmtoff; - var ahead = off >= 0; - off = Math.abs(off) / 60; - // convert from minutes into hhmm format (which means 60 minutes = 100 units) - off = (off / 60)*100 + (off % 60); - return (ahead ? '+' : '-') + String("0000" + off).slice(-4); - }, - '%Z': function(date) { - return date.tm_zone; - }, - '%%': function() { - return '%'; - } - }; - for (var rule in EXPANSION_RULES_2) { - if (pattern.indexOf(rule) >= 0) { - pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_2[rule](date)); - } - } - - var bytes = intArrayFromString(pattern, false); - if (bytes.length > maxsize) { - return 0; - } - - writeArrayToMemory(bytes, s); - return bytes.length-1; - }, - strftime_l__deps: ['strftime'], - strftime_l: function(s, maxsize, format, tm) { - return _strftime(s, maxsize, format, tm); // no locale support yet - }, - - strptime__deps: ['_isLeapYear', '_arraySum', '_addDays', '_MONTH_DAYS_REGULAR', '_MONTH_DAYS_LEAP'], - strptime: function(buf, format, tm) { - // char *strptime(const char *restrict buf, const char *restrict format, struct tm *restrict tm); - // http://pubs.opengroup.org/onlinepubs/009695399/functions/strptime.html - var pattern = Pointer_stringify(format); - - // escape special characters - // TODO: not sure we really need to escape all of these in JS regexps - var SPECIAL_CHARS = '\\!@#$^&*()+=-[]/{}|:<>?,.'; - for (var i=0, ii=SPECIAL_CHARS.length; i=0; i=pattern.indexOf('%')) { - capture.push(pattern[i+1]); - pattern = pattern.replace(new RegExp('\\%'+pattern[i+1], 'g'), ''); - } - - var matches = new RegExp('^'+pattern, "i").exec(Pointer_stringify(buf)) - // Module['print'](Pointer_stringify(buf)+ ' is matched by '+((new RegExp('^'+pattern)).source)+' into: '+JSON.stringify(matches)); - - function initDate() { - function fixup(value, min, max) { - return (typeof value !== 'number' || isNaN(value)) ? min : (value>=min ? (value<=max ? value: max): min); - }; - return { - year: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_year, 'i32', 0, 0, 1) }}} + 1900 , 1970, 9999), - month: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_mon, 'i32', 0, 0, 1) }}}, 0, 11), - day: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_mday, 'i32', 0, 0, 1) }}}, 1, 31), - hour: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_hour, 'i32', 0, 0, 1) }}}, 0, 23), - min: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_min, 'i32', 0, 0, 1) }}}, 0, 59), - sec: fixup({{{ makeGetValue('tm', C_STRUCTS.tm.tm_sec, 'i32', 0, 0, 1) }}}, 0, 59) - }; - }; - - if (matches) { - var date = initDate(); - var value; - - function getMatch(symbol) { - var pos = capture.indexOf(symbol); - // check if symbol appears in regexp - if (pos >= 0) { - // return matched value or null (falsy!) for non-matches - return matches[pos+1]; - } - return; - } - - // seconds - if ((value=getMatch('S'))) { - date.sec = parseInt(value); - } - - // minutes - if ((value=getMatch('M'))) { - date.min = parseInt(value); - } - - // hours - if ((value=getMatch('H'))) { - // 24h clock - date.hour = parseInt(value); - } else if ((value = getMatch('I'))) { - // AM/PM clock - var hour = parseInt(value); - if ((value=getMatch('p'))) { - hour += value.toUpperCase()[0] === 'P' ? 12 : 0; - } - date.hour = hour; - } - - // year - if ((value=getMatch('Y'))) { - // parse from four-digit year - date.year = parseInt(value); - } else if ((value=getMatch('y'))) { - // parse from two-digit year... - var year = parseInt(value); - if ((value=getMatch('C'))) { - // ...and century - year += parseInt(value)*100; - } else { - // ...and rule-of-thumb - year += year<69 ? 2000 : 1900; - } - date.year = year; - } - - // month - if ((value=getMatch('m'))) { - // parse from month number - date.month = parseInt(value)-1; - } else if ((value=getMatch('b'))) { - // parse from month name - date.month = MONTH_NUMBERS[value.substring(0,3).toUpperCase()] || 0; - // TODO: derive month from day in year+year, week number+day of week+year - } - - // day - if ((value=getMatch('d'))) { - // get day of month directly - date.day = parseInt(value); - } else if ((value=getMatch('j'))) { - // get day of month from day of year ... - var day = parseInt(value); - var leapYear = __isLeapYear(date.year); - for (var month=0; month<12; ++month) { - var daysUntilMonth = __arraySum(leapYear ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, month-1); - if (day<=daysUntilMonth+(leapYear ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR)[month]) { - date.day = day-daysUntilMonth; - } - } - } else if ((value=getMatch('a'))) { - // get day of month from weekday ... - var weekDay = value.substring(0,3).toUpperCase(); - if ((value=getMatch('U'))) { - // ... and week number (Sunday being first day of week) - // Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. - // All days in a new year preceding the first Sunday are considered to be in week 0. - var weekDayNumber = DAY_NUMBERS_SUN_FIRST[weekDay]; - var weekNumber = parseInt(value); - - // January 1st - var janFirst = new Date(date.year, 0, 1); - var endDate; - if (janFirst.getDay() === 0) { - // Jan 1st is a Sunday, and, hence in the 1st CW - endDate = __addDays(janFirst, weekDayNumber+7*(weekNumber-1)); - } else { - // Jan 1st is not a Sunday, and, hence still in the 0th CW - endDate = __addDays(janFirst, 7-janFirst.getDay()+weekDayNumber+7*(weekNumber-1)); - } - date.day = endDate.getDate(); - date.month = endDate.getMonth(); - } else if ((value=getMatch('W'))) { - // ... and week number (Monday being first day of week) - // Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. - // All days in a new year preceding the first Monday are considered to be in week 0. - var weekDayNumber = DAY_NUMBERS_MON_FIRST[weekDay]; - var weekNumber = parseInt(value); - - // January 1st - var janFirst = new Date(date.year, 0, 1); - var endDate; - if (janFirst.getDay()===1) { - // Jan 1st is a Monday, and, hence in the 1st CW - endDate = __addDays(janFirst, weekDayNumber+7*(weekNumber-1)); - } else { - // Jan 1st is not a Monday, and, hence still in the 0th CW - endDate = __addDays(janFirst, 7-janFirst.getDay()+1+weekDayNumber+7*(weekNumber-1)); - } - - date.day = endDate.getDate(); - date.month = endDate.getMonth(); - } - } - - /* - tm_sec int seconds after the minute 0-61* - tm_min int minutes after the hour 0-59 - tm_hour int hours since midnight 0-23 - tm_mday int day of the month 1-31 - tm_mon int months since January 0-11 - tm_year int years since 1900 - tm_wday int days since Sunday 0-6 - tm_yday int days since January 1 0-365 - tm_isdst int Daylight Saving Time flag - */ - - var fullDate = new Date(date.year, date.month, date.day, date.hour, date.min, date.sec, 0); - {{{ makeSetValue('tm', C_STRUCTS.tm.tm_sec, 'fullDate.getSeconds()', 'i32') }}}; - {{{ makeSetValue('tm', C_STRUCTS.tm.tm_min, 'fullDate.getMinutes()', 'i32') }}}; - {{{ makeSetValue('tm', C_STRUCTS.tm.tm_hour, 'fullDate.getHours()', 'i32') }}}; - {{{ makeSetValue('tm', C_STRUCTS.tm.tm_mday, 'fullDate.getDate()', 'i32') }}}; - {{{ makeSetValue('tm', C_STRUCTS.tm.tm_mon, 'fullDate.getMonth()', 'i32') }}}; - {{{ makeSetValue('tm', C_STRUCTS.tm.tm_year, 'fullDate.getFullYear()-1900', 'i32') }}}; - {{{ makeSetValue('tm', C_STRUCTS.tm.tm_wday, 'fullDate.getDay()', 'i32') }}}; - {{{ makeSetValue('tm', C_STRUCTS.tm.tm_yday, '__arraySum(__isLeapYear(fullDate.getFullYear()) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, fullDate.getMonth()-1)+fullDate.getDate()-1', 'i32') }}}; - {{{ makeSetValue('tm', C_STRUCTS.tm.tm_isdst, '0', 'i32') }}}; - - // we need to convert the matched sequence into an integer array to take care of UTF-8 characters > 0x7F - // TODO: not sure that intArrayFromString handles all unicode characters correctly - return buf+intArrayFromString(matches[0]).length-1; - } - - return 0; - }, - strptime_l__deps: ['strptime'], - strptime_l: function(buf, format, tm) { - return _strptime(buf, format, tm); // no locale support yet - }, - - getdate: function(string) { - // struct tm *getdate(const char *string); - // http://pubs.opengroup.org/onlinepubs/009695399/functions/getdate.html - // TODO: Implement. - return 0; - }, - - // ========================================================================== - // sys/time.h - // ========================================================================== - - clock_gettime__deps: ['emscripten_get_now', 'emscripten_get_now_is_monotonic', '$ERRNO_CODES', '__setErrNo'], - clock_gettime: function(clk_id, tp) { - // int clock_gettime(clockid_t clk_id, struct timespec *tp); - var now; - if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) { - now = Date.now(); - } else if (clk_id === {{{ cDefine('CLOCK_MONOTONIC') }}} && _emscripten_get_now_is_monotonic()) { - now = _emscripten_get_now(); - } else { - ___setErrNo(ERRNO_CODES.EINVAL); - return -1; - } - {{{ makeSetValue('tp', C_STRUCTS.timespec.tv_sec, '(now/1000)|0', 'i32') }}}; // seconds - {{{ makeSetValue('tp', C_STRUCTS.timespec.tv_nsec, '((now % 1000)*1000*1000)|0', 'i32') }}}; // nanoseconds - return 0; - }, - __clock_gettime: 'clock_gettime', // musl internal alias - clock_settime__deps: ['$ERRNO_CODES', '__setErrNo'], - clock_settime: function(clk_id, tp) { - // int clock_settime(clockid_t clk_id, const struct timespec *tp); - // Nothing. - ___setErrNo(clk_id === {{{ cDefine('CLOCK_REALTIME') }}} ? ERRNO_CODES.EPERM - : ERRNO_CODES.EINVAL); - return -1; - }, - clock_getres__deps: ['emscripten_get_now_res', 'emscripten_get_now_is_monotonic', '$ERRNO_CODES', '__setErrNo'], - clock_getres: function(clk_id, res) { - // int clock_getres(clockid_t clk_id, struct timespec *res); - var nsec; - if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) { - nsec = 1000 * 1000; // educated guess that it's milliseconds - } else if (clk_id === {{{ cDefine('CLOCK_MONOTONIC') }}} && _emscripten_get_now_is_monotonic()) { - nsec = _emscripten_get_now_res(); - } else { - ___setErrNo(ERRNO_CODES.EINVAL); - return -1; - } - {{{ makeSetValue('res', C_STRUCTS.timespec.tv_sec, '(nsec/1000000000)|0', 'i32') }}}; - {{{ makeSetValue('res', C_STRUCTS.timespec.tv_nsec, 'nsec', 'i32') }}} // resolution is nanoseconds - return 0; - }, - clock_getcpuclockid__deps: ['$PROCINFO'], - clock_getcpuclockid: function(pid, clk_id) { - if (pid < 0) return ERRNO_CODES.ESRCH; - if (pid !== 0 && pid !== PROCINFO.pid) return ERRNO_CODES.ENOSYS; - if (clk_id) {{{ makeSetValue('clk_id', 0, 2/*CLOCK_PROCESS_CPUTIME_ID*/, 'i32') }}}; - return 0; - }, - // http://pubs.opengroup.org/onlinepubs/000095399/basedefs/sys/time.h.html - gettimeofday: function(ptr) { - var now = Date.now(); - {{{ makeSetValue('ptr', C_STRUCTS.timeval.tv_sec, '(now/1000)|0', 'i32') }}}; // seconds - {{{ makeSetValue('ptr', C_STRUCTS.timeval.tv_usec, '((now % 1000)*1000)|0', 'i32') }}}; // microseconds - return 0; - }, - - // ========================================================================== - // sys/timeb.h - // ========================================================================== - - ftime: function(p) { - var millis = Date.now(); - {{{ makeSetValue('p', C_STRUCTS.timeb.time, '(millis/1000)|0', 'i32') }}}; - {{{ makeSetValue('p', C_STRUCTS.timeb.millitm, 'millis % 1000', 'i16') }}}; - {{{ makeSetValue('p', C_STRUCTS.timeb.timezone, '0', 'i16') }}}; // Obsolete field - {{{ makeSetValue('p', C_STRUCTS.timeb.dstflag, '0', 'i16') }}}; // Obsolete field - return 0; - }, - - // ========================================================================== - // sys/times.h - // ========================================================================== - - times__deps: ['memset'], - times: function(buffer) { - // clock_t times(struct tms *buffer); - // http://pubs.opengroup.org/onlinepubs/009695399/functions/times.html - // NOTE: This is fake, since we can't calculate real CPU time usage in JS. - if (buffer !== 0) { - _memset(buffer, 0, {{{ C_STRUCTS.tms.__size__ }}}); - } - return 0; - }, - - // ========================================================================== - // sys/types.h - // ========================================================================== - // http://www.kernel.org/doc/man-pages/online/pages/man3/minor.3.html - makedev: function(maj, min) { - return ((maj) << 8 | (min)); - }, - gnu_dev_makedev: 'makedev', - major: function(dev) { - return ((dev) >> 8); - }, - gnu_dev_major: 'major', - minor: function(dev) { - return ((dev) & 0xff); - }, - gnu_dev_minor: 'minor', - - // ========================================================================== - // setjmp.h - // ========================================================================== - - // asm.js-style setjmp/longjmp support for wasm binaryen backend. - // In asm.js compilation, various variables including setjmpId will be - // generated within 'var asm' in emscripten.py, while in wasm compilation, - // wasm side is considered as 'asm' so they are not generated. But - // saveSetjmp() needs setjmpId and no other functions in wasm side needs it. - // So we declare it here if WASM_BACKEND=1. -#if WASM_BACKEND == 1 - $setjmpId: 0, -#endif - - saveSetjmp__asm: true, - saveSetjmp__sig: 'iii', -#if WASM_BACKEND == 1 - saveSetjmp__deps: ['realloc', '$setjmpId'], -#else - saveSetjmp__deps: ['realloc'], -#endif - saveSetjmp: function(env, label, table, size) { - // Not particularly fast: slow table lookup of setjmpId to label. But setjmp - // prevents relooping anyhow, so slowness is to be expected. And typical case - // is 1 setjmp per invocation, or less. - env = env|0; - label = label|0; - table = table|0; - size = size|0; - var i = 0; - setjmpId = (setjmpId+1)|0; - {{{ makeSetValueAsm('env', '0', 'setjmpId', 'i32') }}}; - while ((i|0) < (size|0)) { - if ({{{ makeGetValueAsm('table', '(i<<3)', 'i32') }}} == 0) { - {{{ makeSetValueAsm('table', '(i<<3)', 'setjmpId', 'i32') }}}; - {{{ makeSetValueAsm('table', '(i<<3)+4', 'label', 'i32') }}}; - // prepare next slot - {{{ makeSetValueAsm('table', '(i<<3)+8', '0', 'i32') }}}; - {{{ makeSetTempRet0('size') }}}; - return table | 0; - } - i = i+1|0; - } - // grow the table - size = (size*2)|0; - table = _realloc(table|0, 8*(size+1|0)|0) | 0; - table = _saveSetjmp(env|0, label|0, table|0, size|0) | 0; - {{{ makeSetTempRet0('size') }}}; - return table | 0; - }, - - testSetjmp__asm: true, - testSetjmp__sig: 'iii', - testSetjmp: function(id, table, size) { - id = id|0; - table = table|0; - size = size|0; - var i = 0, curr = 0; - while ((i|0) < (size|0)) { - curr = {{{ makeGetValueAsm('table', '(i<<3)', 'i32') }}}; - if ((curr|0) == 0) break; - if ((curr|0) == (id|0)) { - return {{{ makeGetValueAsm('table', '(i<<3)+4', 'i32') }}}; - } - i = i+1|0; - } - return 0; - }, - - setjmp__deps: ['saveSetjmp', 'testSetjmp'], - setjmp__inline: function(env) { - // Save the label - return '_saveSetjmp(' + env + ', label, setjmpTable)|0'; - }, - - longjmp__deps: ['saveSetjmp', 'testSetjmp'], - longjmp: function(env, value) { - Module['setThrew'](env, value || 1); - throw 'longjmp'; - }, - emscripten_longjmp__deps: ['longjmp'], - emscripten_longjmp: function(env, value) { - _longjmp(env, value); - }, - - // ========================================================================== - // sys/wait.h - // ========================================================================== - - wait__deps: ['$ERRNO_CODES', '__setErrNo'], - wait: function(stat_loc) { - // pid_t wait(int *stat_loc); - // http://pubs.opengroup.org/onlinepubs/009695399/functions/wait.html - // Makes no sense in a single-process environment. - ___setErrNo(ERRNO_CODES.ECHILD); - return -1; - }, - // NOTE: These aren't really the same, but we use the same stub for them all. - waitid: 'wait', - waitpid: 'wait', - wait3: 'wait', - wait4: 'wait', - - // ========================================================================== - // errno.h - // ========================================================================== - - $ERRNO_CODES: { - EPERM: {{{ cDefine('EPERM') }}}, - ENOENT: {{{ cDefine('ENOENT') }}}, - ESRCH: {{{ cDefine('ESRCH') }}}, - EINTR: {{{ cDefine('EINTR') }}}, - EIO: {{{ cDefine('EIO') }}}, - ENXIO: {{{ cDefine('ENXIO') }}}, - E2BIG: {{{ cDefine('E2BIG') }}}, - ENOEXEC: {{{ cDefine('ENOEXEC') }}}, - EBADF: {{{ cDefine('EBADF') }}}, - ECHILD: {{{ cDefine('ECHILD') }}}, - EAGAIN: {{{ cDefine('EAGAIN') }}}, - EWOULDBLOCK: {{{ cDefine('EWOULDBLOCK') }}}, - ENOMEM: {{{ cDefine('ENOMEM') }}}, - EACCES: {{{ cDefine('EACCES') }}}, - EFAULT: {{{ cDefine('EFAULT') }}}, - ENOTBLK: {{{ cDefine('ENOTBLK') }}}, - EBUSY: {{{ cDefine('EBUSY') }}}, - EEXIST: {{{ cDefine('EEXIST') }}}, - EXDEV: {{{ cDefine('EXDEV') }}}, - ENODEV: {{{ cDefine('ENODEV') }}}, - ENOTDIR: {{{ cDefine('ENOTDIR') }}}, - EISDIR: {{{ cDefine('EISDIR') }}}, - EINVAL: {{{ cDefine('EINVAL') }}}, - ENFILE: {{{ cDefine('ENFILE') }}}, - EMFILE: {{{ cDefine('EMFILE') }}}, - ENOTTY: {{{ cDefine('ENOTTY') }}}, - ETXTBSY: {{{ cDefine('ETXTBSY') }}}, - EFBIG: {{{ cDefine('EFBIG') }}}, - ENOSPC: {{{ cDefine('ENOSPC') }}}, - ESPIPE: {{{ cDefine('ESPIPE') }}}, - EROFS: {{{ cDefine('EROFS') }}}, - EMLINK: {{{ cDefine('EMLINK') }}}, - EPIPE: {{{ cDefine('EPIPE') }}}, - EDOM: {{{ cDefine('EDOM') }}}, - ERANGE: {{{ cDefine('ERANGE') }}}, - ENOMSG: {{{ cDefine('ENOMSG') }}}, - EIDRM: {{{ cDefine('EIDRM') }}}, - ECHRNG: {{{ cDefine('ECHRNG') }}}, - EL2NSYNC: {{{ cDefine('EL2NSYNC') }}}, - EL3HLT: {{{ cDefine('EL3HLT') }}}, - EL3RST: {{{ cDefine('EL3RST') }}}, - ELNRNG: {{{ cDefine('ELNRNG') }}}, - EUNATCH: {{{ cDefine('EUNATCH') }}}, - ENOCSI: {{{ cDefine('ENOCSI') }}}, - EL2HLT: {{{ cDefine('EL2HLT') }}}, - EDEADLK: {{{ cDefine('EDEADLK') }}}, - ENOLCK: {{{ cDefine('ENOLCK') }}}, - EBADE: {{{ cDefine('EBADE') }}}, - EBADR: {{{ cDefine('EBADR') }}}, - EXFULL: {{{ cDefine('EXFULL') }}}, - ENOANO: {{{ cDefine('ENOANO') }}}, - EBADRQC: {{{ cDefine('EBADRQC') }}}, - EBADSLT: {{{ cDefine('EBADSLT') }}}, - EDEADLOCK: {{{ cDefine('EDEADLOCK') }}}, - EBFONT: {{{ cDefine('EBFONT') }}}, - ENOSTR: {{{ cDefine('ENOSTR') }}}, - ENODATA: {{{ cDefine('ENODATA') }}}, - ETIME: {{{ cDefine('ETIME') }}}, - ENOSR: {{{ cDefine('ENOSR') }}}, - ENONET: {{{ cDefine('ENONET') }}}, - ENOPKG: {{{ cDefine('ENOPKG') }}}, - EREMOTE: {{{ cDefine('EREMOTE') }}}, - ENOLINK: {{{ cDefine('ENOLINK') }}}, - EADV: {{{ cDefine('EADV') }}}, - ESRMNT: {{{ cDefine('ESRMNT') }}}, - ECOMM: {{{ cDefine('ECOMM') }}}, - EPROTO: {{{ cDefine('EPROTO') }}}, - EMULTIHOP: {{{ cDefine('EMULTIHOP') }}}, - EDOTDOT: {{{ cDefine('EDOTDOT') }}}, - EBADMSG: {{{ cDefine('EBADMSG') }}}, - ENOTUNIQ: {{{ cDefine('ENOTUNIQ') }}}, - EBADFD: {{{ cDefine('EBADFD') }}}, - EREMCHG: {{{ cDefine('EREMCHG') }}}, - ELIBACC: {{{ cDefine('ELIBACC') }}}, - ELIBBAD: {{{ cDefine('ELIBBAD') }}}, - ELIBSCN: {{{ cDefine('ELIBSCN') }}}, - ELIBMAX: {{{ cDefine('ELIBMAX') }}}, - ELIBEXEC: {{{ cDefine('ELIBEXEC') }}}, - ENOSYS: {{{ cDefine('ENOSYS') }}}, - ENOTEMPTY: {{{ cDefine('ENOTEMPTY') }}}, - ENAMETOOLONG: {{{ cDefine('ENAMETOOLONG') }}}, - ELOOP: {{{ cDefine('ELOOP') }}}, - EOPNOTSUPP: {{{ cDefine('EOPNOTSUPP') }}}, - EPFNOSUPPORT: {{{ cDefine('EPFNOSUPPORT') }}}, - ECONNRESET: {{{ cDefine('ECONNRESET') }}}, - ENOBUFS: {{{ cDefine('ENOBUFS') }}}, - EAFNOSUPPORT: {{{ cDefine('EAFNOSUPPORT') }}}, - EPROTOTYPE: {{{ cDefine('EPROTOTYPE') }}}, - ENOTSOCK: {{{ cDefine('ENOTSOCK') }}}, - ENOPROTOOPT: {{{ cDefine('ENOPROTOOPT') }}}, - ESHUTDOWN: {{{ cDefine('ESHUTDOWN') }}}, - ECONNREFUSED: {{{ cDefine('ECONNREFUSED') }}}, - EADDRINUSE: {{{ cDefine('EADDRINUSE') }}}, - ECONNABORTED: {{{ cDefine('ECONNABORTED') }}}, - ENETUNREACH: {{{ cDefine('ENETUNREACH') }}}, - ENETDOWN: {{{ cDefine('ENETDOWN') }}}, - ETIMEDOUT: {{{ cDefine('ETIMEDOUT') }}}, - EHOSTDOWN: {{{ cDefine('EHOSTDOWN') }}}, - EHOSTUNREACH: {{{ cDefine('EHOSTUNREACH') }}}, - EINPROGRESS: {{{ cDefine('EINPROGRESS') }}}, - EALREADY: {{{ cDefine('EALREADY') }}}, - EDESTADDRREQ: {{{ cDefine('EDESTADDRREQ') }}}, - EMSGSIZE: {{{ cDefine('EMSGSIZE') }}}, - EPROTONOSUPPORT: {{{ cDefine('EPROTONOSUPPORT') }}}, - ESOCKTNOSUPPORT: {{{ cDefine('ESOCKTNOSUPPORT') }}}, - EADDRNOTAVAIL: {{{ cDefine('EADDRNOTAVAIL') }}}, - ENETRESET: {{{ cDefine('ENETRESET') }}}, - EISCONN: {{{ cDefine('EISCONN') }}}, - ENOTCONN: {{{ cDefine('ENOTCONN') }}}, - ETOOMANYREFS: {{{ cDefine('ETOOMANYREFS') }}}, - EUSERS: {{{ cDefine('EUSERS') }}}, - EDQUOT: {{{ cDefine('EDQUOT') }}}, - ESTALE: {{{ cDefine('ESTALE') }}}, - ENOTSUP: {{{ cDefine('ENOTSUP') }}}, - ENOMEDIUM: {{{ cDefine('ENOMEDIUM') }}}, - EILSEQ: {{{ cDefine('EILSEQ') }}}, - EOVERFLOW: {{{ cDefine('EOVERFLOW') }}}, - ECANCELED: {{{ cDefine('ECANCELED') }}}, - ENOTRECOVERABLE: {{{ cDefine('ENOTRECOVERABLE') }}}, - EOWNERDEAD: {{{ cDefine('EOWNERDEAD') }}}, - ESTRPIPE: {{{ cDefine('ESTRPIPE') }}}, - }, - $ERRNO_MESSAGES: { - 0: 'Success', - {{{ cDefine('EPERM') }}}: 'Not super-user', - {{{ cDefine('ENOENT') }}}: 'No such file or directory', - {{{ cDefine('ESRCH') }}}: 'No such process', - {{{ cDefine('EINTR') }}}: 'Interrupted system call', - {{{ cDefine('EIO') }}}: 'I/O error', - {{{ cDefine('ENXIO') }}}: 'No such device or address', - {{{ cDefine('E2BIG') }}}: 'Arg list too long', - {{{ cDefine('ENOEXEC') }}}: 'Exec format error', - {{{ cDefine('EBADF') }}}: 'Bad file number', - {{{ cDefine('ECHILD') }}}: 'No children', - {{{ cDefine('EWOULDBLOCK') }}}: 'No more processes', - {{{ cDefine('ENOMEM') }}}: 'Not enough core', - {{{ cDefine('EACCES') }}}: 'Permission denied', - {{{ cDefine('EFAULT') }}}: 'Bad address', - {{{ cDefine('ENOTBLK') }}}: 'Block device required', - {{{ cDefine('EBUSY') }}}: 'Mount device busy', - {{{ cDefine('EEXIST') }}}: 'File exists', - {{{ cDefine('EXDEV') }}}: 'Cross-device link', - {{{ cDefine('ENODEV') }}}: 'No such device', - {{{ cDefine('ENOTDIR') }}}: 'Not a directory', - {{{ cDefine('EISDIR') }}}: 'Is a directory', - {{{ cDefine('EINVAL') }}}: 'Invalid argument', - {{{ cDefine('ENFILE') }}}: 'Too many open files in system', - {{{ cDefine('EMFILE') }}}: 'Too many open files', - {{{ cDefine('ENOTTY') }}}: 'Not a typewriter', - {{{ cDefine('ETXTBSY') }}}: 'Text file busy', - {{{ cDefine('EFBIG') }}}: 'File too large', - {{{ cDefine('ENOSPC') }}}: 'No space left on device', - {{{ cDefine('ESPIPE') }}}: 'Illegal seek', - {{{ cDefine('EROFS') }}}: 'Read only file system', - {{{ cDefine('EMLINK') }}}: 'Too many links', - {{{ cDefine('EPIPE') }}}: 'Broken pipe', - {{{ cDefine('EDOM') }}}: 'Math arg out of domain of func', - {{{ cDefine('ERANGE') }}}: 'Math result not representable', - {{{ cDefine('ENOMSG') }}}: 'No message of desired type', - {{{ cDefine('EIDRM') }}}: 'Identifier removed', - {{{ cDefine('ECHRNG') }}}: 'Channel number out of range', - {{{ cDefine('EL2NSYNC') }}}: 'Level 2 not synchronized', - {{{ cDefine('EL3HLT') }}}: 'Level 3 halted', - {{{ cDefine('EL3RST') }}}: 'Level 3 reset', - {{{ cDefine('ELNRNG') }}}: 'Link number out of range', - {{{ cDefine('EUNATCH') }}}: 'Protocol driver not attached', - {{{ cDefine('ENOCSI') }}}: 'No CSI structure available', - {{{ cDefine('EL2HLT') }}}: 'Level 2 halted', - {{{ cDefine('EDEADLK') }}}: 'Deadlock condition', - {{{ cDefine('ENOLCK') }}}: 'No record locks available', - {{{ cDefine('EBADE') }}}: 'Invalid exchange', - {{{ cDefine('EBADR') }}}: 'Invalid request descriptor', - {{{ cDefine('EXFULL') }}}: 'Exchange full', - {{{ cDefine('ENOANO') }}}: 'No anode', - {{{ cDefine('EBADRQC') }}}: 'Invalid request code', - {{{ cDefine('EBADSLT') }}}: 'Invalid slot', - {{{ cDefine('EDEADLOCK') }}}: 'File locking deadlock error', - {{{ cDefine('EBFONT') }}}: 'Bad font file fmt', - {{{ cDefine('ENOSTR') }}}: 'Device not a stream', - {{{ cDefine('ENODATA') }}}: 'No data (for no delay io)', - {{{ cDefine('ETIME') }}}: 'Timer expired', - {{{ cDefine('ENOSR') }}}: 'Out of streams resources', - {{{ cDefine('ENONET') }}}: 'Machine is not on the network', - {{{ cDefine('ENOPKG') }}}: 'Package not installed', - {{{ cDefine('EREMOTE') }}}: 'The object is remote', - {{{ cDefine('ENOLINK') }}}: 'The link has been severed', - {{{ cDefine('EADV') }}}: 'Advertise error', - {{{ cDefine('ESRMNT') }}}: 'Srmount error', - {{{ cDefine('ECOMM') }}}: 'Communication error on send', - {{{ cDefine('EPROTO') }}}: 'Protocol error', - {{{ cDefine('EMULTIHOP') }}}: 'Multihop attempted', - {{{ cDefine('EDOTDOT') }}}: 'Cross mount point (not really error)', - {{{ cDefine('EBADMSG') }}}: 'Trying to read unreadable message', - {{{ cDefine('ENOTUNIQ') }}}: 'Given log. name not unique', - {{{ cDefine('EBADFD') }}}: 'f.d. invalid for this operation', - {{{ cDefine('EREMCHG') }}}: 'Remote address changed', - {{{ cDefine('ELIBACC') }}}: 'Can access a needed shared lib', - {{{ cDefine('ELIBBAD') }}}: 'Accessing a corrupted shared lib', - {{{ cDefine('ELIBSCN') }}}: '.lib section in a.out corrupted', - {{{ cDefine('ELIBMAX') }}}: 'Attempting to link in too many libs', - {{{ cDefine('ELIBEXEC') }}}: 'Attempting to exec a shared library', - {{{ cDefine('ENOSYS') }}}: 'Function not implemented', - {{{ cDefine('ENOTEMPTY') }}}: 'Directory not empty', - {{{ cDefine('ENAMETOOLONG') }}}: 'File or path name too long', - {{{ cDefine('ELOOP') }}}: 'Too many symbolic links', - {{{ cDefine('EOPNOTSUPP') }}}: 'Operation not supported on transport endpoint', - {{{ cDefine('EPFNOSUPPORT') }}}: 'Protocol family not supported', - {{{ cDefine('ECONNRESET') }}}: 'Connection reset by peer', - {{{ cDefine('ENOBUFS') }}}: 'No buffer space available', - {{{ cDefine('EAFNOSUPPORT') }}}: 'Address family not supported by protocol family', - {{{ cDefine('EPROTOTYPE') }}}: 'Protocol wrong type for socket', - {{{ cDefine('ENOTSOCK') }}}: 'Socket operation on non-socket', - {{{ cDefine('ENOPROTOOPT') }}}: 'Protocol not available', - {{{ cDefine('ESHUTDOWN') }}}: 'Can\'t send after socket shutdown', - {{{ cDefine('ECONNREFUSED') }}}: 'Connection refused', - {{{ cDefine('EADDRINUSE') }}}: 'Address already in use', - {{{ cDefine('ECONNABORTED') }}}: 'Connection aborted', - {{{ cDefine('ENETUNREACH') }}}: 'Network is unreachable', - {{{ cDefine('ENETDOWN') }}}: 'Network interface is not configured', - {{{ cDefine('ETIMEDOUT') }}}: 'Connection timed out', - {{{ cDefine('EHOSTDOWN') }}}: 'Host is down', - {{{ cDefine('EHOSTUNREACH') }}}: 'Host is unreachable', - {{{ cDefine('EINPROGRESS') }}}: 'Connection already in progress', - {{{ cDefine('EALREADY') }}}: 'Socket already connected', - {{{ cDefine('EDESTADDRREQ') }}}: 'Destination address required', - {{{ cDefine('EMSGSIZE') }}}: 'Message too long', - {{{ cDefine('EPROTONOSUPPORT') }}}: 'Unknown protocol', - {{{ cDefine('ESOCKTNOSUPPORT') }}}: 'Socket type not supported', - {{{ cDefine('EADDRNOTAVAIL') }}}: 'Address not available', - {{{ cDefine('ENETRESET') }}}: 'Connection reset by network', - {{{ cDefine('EISCONN') }}}: 'Socket is already connected', - {{{ cDefine('ENOTCONN') }}}: 'Socket is not connected', - {{{ cDefine('ETOOMANYREFS') }}}: 'Too many references', - {{{ cDefine('EUSERS') }}}: 'Too many users', - {{{ cDefine('EDQUOT') }}}: 'Quota exceeded', - {{{ cDefine('ESTALE') }}}: 'Stale file handle', - {{{ cDefine('ENOTSUP') }}}: 'Not supported', - {{{ cDefine('ENOMEDIUM') }}}: 'No medium (in tape drive)', - {{{ cDefine('EILSEQ') }}}: 'Illegal byte sequence', - {{{ cDefine('EOVERFLOW') }}}: 'Value too large for defined data type', - {{{ cDefine('ECANCELED') }}}: 'Operation canceled', - {{{ cDefine('ENOTRECOVERABLE') }}}: 'State not recoverable', - {{{ cDefine('EOWNERDEAD') }}}: 'Previous owner died', - {{{ cDefine('ESTRPIPE') }}}: 'Streams pipe error', - }, - __setErrNo: function(value) { - if (Module['___errno_location']) {{{ makeSetValue("Module['___errno_location']()", 0, 'value', 'i32') }}}; -#if ASSERTIONS - else Module.printErr('failed to set errno from JS'); -#endif - return value; - }, - - // ========================================================================== - // sched.h (stubs only - no thread support yet!) - // ========================================================================== - sched_yield: function() { - return 0; - }, - - // ========================================================================== - // arpa/inet.h - // ========================================================================== - - // old ipv4 only functions - inet_addr__deps: ['_inet_pton4_raw'], - inet_addr: function(ptr) { - var addr = __inet_pton4_raw(Pointer_stringify(ptr)); - if (addr === null) { - return -1; - } - return addr; - }, - - // ========================================================================== - // netinet/in.h - // ========================================================================== - -#if USE_PTHREADS - in6addr_any: '; if (ENVIRONMENT_IS_PTHREAD) _in6addr_any = PthreadWorkerInit._in6addr_any; else PthreadWorkerInit._in6addr_any = _in6addr_any = allocate([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], "i8", ALLOC_STATIC)', - in6addr_loopback: '; if (ENVIRONMENT_IS_PTHREAD) _in6addr_loopback = PthreadWorkerInit._in6addr_loopback; else PthreadWorkerInit._in6addr_loopback = _in6addr_loopback = allocate([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], "i8", ALLOC_STATIC)', -#else - in6addr_any: - 'allocate([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], "i8", ALLOC_STATIC)', - in6addr_loopback: - 'allocate([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], "i8", ALLOC_STATIC)', -#endif - - // ========================================================================== - // netdb.h - // ========================================================================== - - _inet_pton4_raw: function(str) { - var b = str.split('.'); - for (var i = 0; i < 4; i++) { - var tmp = Number(b[i]); - if (isNaN(tmp)) return null; - b[i] = tmp; - } - return (b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)) >>> 0; - }, - _inet_ntop4_raw: function(addr) { - return (addr & 0xff) + '.' + ((addr >> 8) & 0xff) + '.' + ((addr >> 16) & 0xff) + '.' + ((addr >> 24) & 0xff) - }, - _inet_pton6_raw__deps: ['htons'], - _inet_pton6_raw: function(str) { - var words; - var w, offset, z, i; - /* http://home.deds.nl/~aeron/regex/ */ - var valid6regx = /^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i - var parts = []; - if (!valid6regx.test(str)) { - return null; - } - if (str === "::") { - return [0, 0, 0, 0, 0, 0, 0, 0]; - } - // Z placeholder to keep track of zeros when splitting the string on ":" - if (str.indexOf("::") === 0) { - str = str.replace("::", "Z:"); // leading zeros case - } else { - str = str.replace("::", ":Z:"); - } - - if (str.indexOf(".") > 0) { - // parse IPv4 embedded stress - str = str.replace(new RegExp('[.]', 'g'), ":"); - words = str.split(":"); - words[words.length-4] = parseInt(words[words.length-4]) + parseInt(words[words.length-3])*256; - words[words.length-3] = parseInt(words[words.length-2]) + parseInt(words[words.length-1])*256; - words = words.slice(0, words.length-2); - } else { - words = str.split(":"); - } - - offset = 0; z = 0; - for (w=0; w < words.length; w++) { - if (typeof words[w] === 'string') { - if (words[w] === 'Z') { - // compressed zeros - write appropriate number of zero words - for (z = 0; z < (8 - words.length+1); z++) { - parts[w+z] = 0; - } - offset = z-1; - } else { - // parse hex to field to 16-bit value and write it in network byte-order - parts[w+offset] = _htons(parseInt(words[w],16)); - } - } else { - // parsed IPv4 words - parts[w+offset] = words[w]; - } - } - return [ - (parts[1] << 16) | parts[0], - (parts[3] << 16) | parts[2], - (parts[5] << 16) | parts[4], - (parts[7] << 16) | parts[6] - ]; - }, - _inet_pton6__deps: ['_inet_pton6_raw'], - _inet_pton6: function(src, dst) { - var ints = __inet_pton6_raw(Pointer_stringify(src)); - if (ints === null) { - return 0; - } - for (var i = 0; i < 4; i++) { - {{{ makeSetValue('dst', 'i*4', 'ints[i]', 'i32') }}}; - } - return 1; - }, - _inet_ntop6_raw__deps: ['_inet_ntop4_raw'], - _inet_ntop6_raw: function(ints) { - // ref: http://www.ietf.org/rfc/rfc2373.txt - section 2.5.4 - // Format for IPv4 compatible and mapped 128-bit IPv6 Addresses - // 128-bits are split into eight 16-bit words - // stored in network byte order (big-endian) - // | 80 bits | 16 | 32 bits | - // +-----------------------------------------------------------------+ - // | 10 bytes | 2 | 4 bytes | - // +--------------------------------------+--------------------------+ - // + 5 words | 1 | 2 words | - // +--------------------------------------+--------------------------+ - // |0000..............................0000|0000| IPv4 ADDRESS | (compatible) - // +--------------------------------------+----+---------------------+ - // |0000..............................0000|FFFF| IPv4 ADDRESS | (mapped) - // +--------------------------------------+----+---------------------+ - var str = ""; - var word = 0; - var longest = 0; - var lastzero = 0; - var zstart = 0; - var len = 0; - var i = 0; - var parts = [ - ints[0] & 0xffff, - (ints[0] >> 16), - ints[1] & 0xffff, - (ints[1] >> 16), - ints[2] & 0xffff, - (ints[2] >> 16), - ints[3] & 0xffff, - (ints[3] >> 16) - ]; - - // Handle IPv4-compatible, IPv4-mapped, loopback and any/unspecified addresses - - var hasipv4 = true; - var v4part = ""; - // check if the 10 high-order bytes are all zeros (first 5 words) - for (i = 0; i < 5; i++) { - if (parts[i] !== 0) { hasipv4 = false; break; } - } - - if (hasipv4) { - // low-order 32-bits store an IPv4 address (bytes 13 to 16) (last 2 words) - v4part = __inet_ntop4_raw(parts[6] | (parts[7] << 16)); - // IPv4-mapped IPv6 address if 16-bit value (bytes 11 and 12) == 0xFFFF (6th word) - if (parts[5] === -1) { - str = "::ffff:"; - str += v4part; - return str; - } - // IPv4-compatible IPv6 address if 16-bit value (bytes 11 and 12) == 0x0000 (6th word) - if (parts[5] === 0) { - str = "::"; - //special case IPv6 addresses - if(v4part === "0.0.0.0") v4part = ""; // any/unspecified address - if(v4part === "0.0.0.1") v4part = "1";// loopback address - str += v4part; - return str; - } - } - - // Handle all other IPv6 addresses - - // first run to find the longest contiguous zero words - for (word = 0; word < 8; word++) { - if (parts[word] === 0) { - if (word - lastzero > 1) { - len = 0; - } - lastzero = word; - len++; - } - if (len > longest) { - longest = len; - zstart = word - longest + 1; - } - } - - for (word = 0; word < 8; word++) { - if (longest > 1) { - // compress contiguous zeros - to produce "::" - if (parts[word] === 0 && word >= zstart && word < (zstart + longest) ) { - if (word === zstart) { - str += ":"; - if (zstart === 0) str += ":"; //leading zeros case - } - continue; - } - } - // converts 16-bit words from big-endian to little-endian before converting to hex string - str += Number(_ntohs(parts[word] & 0xffff)).toString(16); - str += word < 7 ? ":" : ""; - } - return str; - }, - - _read_sockaddr__deps: ['$Sockets', '_inet_ntop4_raw', '_inet_ntop6_raw'], - _read_sockaddr: function (sa, salen) { - // family / port offsets are common to both sockaddr_in and sockaddr_in6 - var family = {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in.sin_family, 'i16') }}}; - var port = _ntohs({{{ makeGetValue('sa', C_STRUCTS.sockaddr_in.sin_port, 'i16') }}}); - var addr; - - switch (family) { - case {{{ cDefine('AF_INET') }}}: - if (salen !== {{{ C_STRUCTS.sockaddr_in.__size__ }}}) { - return { errno: ERRNO_CODES.EINVAL }; - } - addr = {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in.sin_addr.s_addr, 'i32') }}}; - addr = __inet_ntop4_raw(addr); - break; - case {{{ cDefine('AF_INET6') }}}: - if (salen !== {{{ C_STRUCTS.sockaddr_in6.__size__ }}}) { - return { errno: ERRNO_CODES.EINVAL }; - } - addr = [ - {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+0, 'i32') }}}, - {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+4, 'i32') }}}, - {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+8, 'i32') }}}, - {{{ makeGetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+12, 'i32') }}} - ]; - addr = __inet_ntop6_raw(addr); - break; - default: - return { errno: ERRNO_CODES.EAFNOSUPPORT }; - } - - return { family: family, addr: addr, port: port }; - }, - _write_sockaddr__deps: ['$Sockets', '_inet_pton4_raw', '_inet_pton6_raw'], - _write_sockaddr: function (sa, family, addr, port) { - switch (family) { - case {{{ cDefine('AF_INET') }}}: - addr = __inet_pton4_raw(addr); - {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in.sin_family, 'family', 'i16') }}}; - {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in.sin_addr.s_addr, 'addr', 'i32') }}}; - {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in.sin_port, '_htons(port)', 'i16') }}}; - break; - case {{{ cDefine('AF_INET6') }}}: - addr = __inet_pton6_raw(addr); - {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_family, 'family', 'i32') }}}; - {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+0, 'addr[0]', 'i32') }}}; - {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+4, 'addr[1]', 'i32') }}}; - {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+8, 'addr[2]', 'i32') }}}; - {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_addr.__in6_union.__s6_addr+12, 'addr[3]', 'i32') }}}; - {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_port, '_htons(port)', 'i16') }}}; - {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_flowinfo, '0', 'i32') }}}; - {{{ makeSetValue('sa', C_STRUCTS.sockaddr_in6.sin6_scope_id, '0', 'i32') }}}; - break; - default: - return { errno: ERRNO_CODES.EAFNOSUPPORT }; - } - // kind of lame, but let's match _read_sockaddr's interface - return {}; - }, - - // We can't actually resolve hostnames in the browser, so instead - // we're generating fake IP addresses with lookup_name that we can - // resolve later on with lookup_addr. - // We do the aliasing in 172.29.*.*, giving us 65536 possibilities. - $DNS__deps: ['_inet_pton4_raw', '_inet_pton6_raw'], - $DNS: { - address_map: { - id: 1, - addrs: {}, - names: {} - }, - - lookup_name: function (name) { - // If the name is already a valid ipv4 / ipv6 address, don't generate a fake one. - var res = __inet_pton4_raw(name); - if (res !== null) { - return name; - } - res = __inet_pton6_raw(name); - if (res !== null) { - return name; - } - - // See if this name is already mapped. - var addr; - - if (DNS.address_map.addrs[name]) { - addr = DNS.address_map.addrs[name]; - } else { - var id = DNS.address_map.id++; - assert(id < 65535, 'exceeded max address mappings of 65535'); - - addr = '172.29.' + (id & 0xff) + '.' + (id & 0xff00); - - DNS.address_map.names[addr] = name; - DNS.address_map.addrs[name] = addr; - } - - return addr; - }, - - lookup_addr: function (addr) { - if (DNS.address_map.names[addr]) { - return DNS.address_map.names[addr]; - } - - return null; - } - }, - - // note: lots of leaking here! - gethostbyaddr__deps: ['$DNS', 'gethostbyname', '_inet_ntop4_raw'], - gethostbyaddr__proxy: 'sync', - gethostbyaddr__sig: 'iiii', - gethostbyaddr: function (addr, addrlen, type) { - if (type !== {{{ cDefine('AF_INET') }}}) { - ___setErrNo(ERRNO_CODES.EAFNOSUPPORT); - // TODO: set h_errno - return null; - } - addr = {{{ makeGetValue('addr', '0', 'i32') }}}; // addr is in_addr - var host = __inet_ntop4_raw(addr); - var lookup = DNS.lookup_addr(host); - if (lookup) { - host = lookup; - } - var hostp = allocate(intArrayFromString(host), 'i8', ALLOC_STACK); - return _gethostbyname(hostp); - }, - - gethostbyname__deps: ['$DNS', '_inet_pton4_raw'], - gethostbyname__proxy: 'sync', - gethostbyname__sig: 'ii', - gethostbyname: function(name) { - name = Pointer_stringify(name); - - // generate hostent - var ret = _malloc({{{ C_STRUCTS.hostent.__size__ }}}); // XXX possibly leaked, as are others here - var nameBuf = _malloc(name.length+1); - stringToUTF8(name, nameBuf, name.length+1); - {{{ makeSetValue('ret', C_STRUCTS.hostent.h_name, 'nameBuf', 'i8*') }}}; - var aliasesBuf = _malloc(4); - {{{ makeSetValue('aliasesBuf', '0', '0', 'i8*') }}}; - {{{ makeSetValue('ret', C_STRUCTS.hostent.h_aliases, 'aliasesBuf', 'i8**') }}}; - var afinet = {{{ cDefine('AF_INET') }}}; - {{{ makeSetValue('ret', C_STRUCTS.hostent.h_addrtype, 'afinet', 'i32') }}}; - {{{ makeSetValue('ret', C_STRUCTS.hostent.h_length, '4', 'i32') }}}; - var addrListBuf = _malloc(12); - {{{ makeSetValue('addrListBuf', '0', 'addrListBuf+8', 'i32*') }}}; - {{{ makeSetValue('addrListBuf', '4', '0', 'i32*') }}}; - {{{ makeSetValue('addrListBuf', '8', '__inet_pton4_raw(DNS.lookup_name(name))', 'i32') }}}; - {{{ makeSetValue('ret', C_STRUCTS.hostent.h_addr_list, 'addrListBuf', 'i8**') }}}; - return ret; - }, - - gethostbyname_r__deps: ['gethostbyname'], - gethostbyname_r__proxy: 'sync', - gethostbyname_r__sig: 'iiiiiii', - gethostbyname_r: function(name, ret, buf, buflen, out, err) { - var data = _gethostbyname(name); - _memcpy(ret, data, {{{ C_STRUCTS.hostent.__size__ }}}); - _free(data); - {{{ makeSetValue('err', '0', '0', 'i32') }}}; - {{{ makeSetValue('out', '0', 'ret', '*') }}}; - return 0; - }, - - getaddrinfo__deps: ['$Sockets', '$DNS', '_inet_pton4_raw', '_inet_ntop4_raw', '_inet_pton6_raw', '_inet_ntop6_raw', '_write_sockaddr'], - getaddrinfo__proxy: 'sync', - getaddrinfo__sig: 'iiiii', - getaddrinfo: function(node, service, hint, out) { - // Note getaddrinfo currently only returns a single addrinfo with ai_next defaulting to NULL. When NULL - // hints are specified or ai_family set to AF_UNSPEC or ai_socktype or ai_protocol set to 0 then we - // really should provide a linked list of suitable addrinfo values. - var addrs = []; - var canon = null; - var addr = 0; - var port = 0; - var flags = 0; - var family = {{{ cDefine('AF_UNSPEC') }}}; - var type = 0; - var proto = 0; - var ai, last; - - function allocaddrinfo(family, type, proto, canon, addr, port) { - var sa, salen, ai; - var res; - - salen = family === {{{ cDefine('AF_INET6') }}} ? - {{{ C_STRUCTS.sockaddr_in6.__size__ }}} : - {{{ C_STRUCTS.sockaddr_in.__size__ }}}; - addr = family === {{{ cDefine('AF_INET6') }}} ? - __inet_ntop6_raw(addr) : - __inet_ntop4_raw(addr); - sa = _malloc(salen); - res = __write_sockaddr(sa, family, addr, port); - assert(!res.errno); - - ai = _malloc({{{ C_STRUCTS.addrinfo.__size__ }}}); - {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_family, 'family', 'i32') }}}; - {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_socktype, 'type', 'i32') }}}; - {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_protocol, 'proto', 'i32') }}}; - {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_canonname, 'canon', 'i32') }}}; - {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_addr, 'sa', '*') }}}; - if (family === {{{ cDefine('AF_INET6') }}}) { - {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_addrlen, C_STRUCTS.sockaddr_in6.__size__, 'i32') }}}; - } else { - {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_addrlen, C_STRUCTS.sockaddr_in.__size__, 'i32') }}}; - } - {{{ makeSetValue('ai', C_STRUCTS.addrinfo.ai_next, '0', 'i32') }}}; - - return ai; - } - - if (hint) { - flags = {{{ makeGetValue('hint', C_STRUCTS.addrinfo.ai_flags, 'i32') }}}; - family = {{{ makeGetValue('hint', C_STRUCTS.addrinfo.ai_family, 'i32') }}}; - type = {{{ makeGetValue('hint', C_STRUCTS.addrinfo.ai_socktype, 'i32') }}}; - proto = {{{ makeGetValue('hint', C_STRUCTS.addrinfo.ai_protocol, 'i32') }}}; - } - if (type && !proto) { - proto = type === {{{ cDefine('SOCK_DGRAM') }}} ? {{{ cDefine('IPPROTO_UDP') }}} : {{{ cDefine('IPPROTO_TCP') }}}; - } - if (!type && proto) { - type = proto === {{{ cDefine('IPPROTO_UDP') }}} ? {{{ cDefine('SOCK_DGRAM') }}} : {{{ cDefine('SOCK_STREAM') }}}; - } - - // If type or proto are set to zero in hints we should really be returning multiple addrinfo values, but for - // now default to a TCP STREAM socket so we can at least return a sensible addrinfo given NULL hints. - if (proto === 0) { - proto = {{{ cDefine('IPPROTO_TCP') }}}; - } - if (type === 0) { - type = {{{ cDefine('SOCK_STREAM') }}}; - } - - if (!node && !service) { - return {{{ cDefine('EAI_NONAME') }}}; - } - if (flags & ~({{{ cDefine('AI_PASSIVE') }}}|{{{ cDefine('AI_CANONNAME') }}}|{{{ cDefine('AI_NUMERICHOST') }}}| - {{{ cDefine('AI_NUMERICSERV') }}}|{{{ cDefine('AI_V4MAPPED') }}}|{{{ cDefine('AI_ALL') }}}|{{{ cDefine('AI_ADDRCONFIG') }}})) { - return {{{ cDefine('EAI_BADFLAGS') }}}; - } - if (hint !== 0 && ({{{ makeGetValue('hint', C_STRUCTS.addrinfo.ai_flags, 'i32') }}} & {{{ cDefine('AI_CANONNAME') }}}) && !node) { - return {{{ cDefine('EAI_BADFLAGS') }}}; - } - if (flags & {{{ cDefine('AI_ADDRCONFIG') }}}) { - // TODO - return {{{ cDefine('EAI_NONAME') }}}; - } - if (type !== 0 && type !== {{{ cDefine('SOCK_STREAM') }}} && type !== {{{ cDefine('SOCK_DGRAM') }}}) { - return {{{ cDefine('EAI_SOCKTYPE') }}}; - } - if (family !== {{{ cDefine('AF_UNSPEC') }}} && family !== {{{ cDefine('AF_INET') }}} && family !== {{{ cDefine('AF_INET6') }}}) { - return {{{ cDefine('EAI_FAMILY') }}}; - } - - if (service) { - service = Pointer_stringify(service); - port = parseInt(service, 10); - - if (isNaN(port)) { - if (flags & {{{ cDefine('AI_NUMERICSERV') }}}) { - return {{{ cDefine('EAI_NONAME') }}}; - } - // TODO support resolving well-known service names from: - // http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt - return {{{ cDefine('EAI_SERVICE') }}}; - } - } - - if (!node) { - if (family === {{{ cDefine('AF_UNSPEC') }}}) { - family = {{{ cDefine('AF_INET') }}}; - } - if ((flags & {{{ cDefine('AI_PASSIVE') }}}) === 0) { - if (family === {{{ cDefine('AF_INET') }}}) { - addr = _htonl({{{ cDefine('INADDR_LOOPBACK') }}}); - } else { - addr = [0, 0, 0, 1]; - } - } - ai = allocaddrinfo(family, type, proto, null, addr, port); - {{{ makeSetValue('out', '0', 'ai', '*') }}}; - return 0; - } - - // - // try as a numeric address - // - node = Pointer_stringify(node); - addr = __inet_pton4_raw(node); - if (addr !== null) { - // incoming node is a valid ipv4 address - if (family === {{{ cDefine('AF_UNSPEC') }}} || family === {{{ cDefine('AF_INET') }}}) { - family = {{{ cDefine('AF_INET') }}}; - } - else if (family === {{{ cDefine('AF_INET6') }}} && (flags & {{{ cDefine('AI_V4MAPPED') }}})) { - addr = [0, 0, _htonl(0xffff), addr]; - family = {{{ cDefine('AF_INET6') }}}; - } else { - return {{{ cDefine('EAI_NONAME') }}}; - } - } else { - addr = __inet_pton6_raw(node); - if (addr !== null) { - // incoming node is a valid ipv6 address - if (family === {{{ cDefine('AF_UNSPEC') }}} || family === {{{ cDefine('AF_INET6') }}}) { - family = {{{ cDefine('AF_INET6') }}}; - } else { - return {{{ cDefine('EAI_NONAME') }}}; - } - } - } - if (addr != null) { - ai = allocaddrinfo(family, type, proto, node, addr, port); - {{{ makeSetValue('out', '0', 'ai', '*') }}}; - return 0; - } - if (flags & {{{ cDefine('AI_NUMERICHOST') }}}) { - return {{{ cDefine('EAI_NONAME') }}}; - } - - // - // try as a hostname - // - // resolve the hostname to a temporary fake address - node = DNS.lookup_name(node); - addr = __inet_pton4_raw(node); - if (family === {{{ cDefine('AF_UNSPEC') }}}) { - family = {{{ cDefine('AF_INET') }}}; - } else if (family === {{{ cDefine('AF_INET6') }}}) { - addr = [0, 0, _htonl(0xffff), addr]; - } - ai = allocaddrinfo(family, type, proto, null, addr, port); - {{{ makeSetValue('out', '0', 'ai', '*') }}}; - return 0; - }, - - getnameinfo__deps: ['$Sockets', '$DNS', '_read_sockaddr'], - getnameinfo: function (sa, salen, node, nodelen, serv, servlen, flags) { - var info = __read_sockaddr(sa, salen); - if (info.errno) { - return {{{ cDefine('EAI_FAMILY') }}}; - } - var port = info.port; - var addr = info.addr; - - var overflowed = false; - - if (node && nodelen) { - var lookup; - if ((flags & {{{ cDefine('NI_NUMERICHOST') }}}) || !(lookup = DNS.lookup_addr(addr))) { - if (flags & {{{ cDefine('NI_NAMEREQD') }}}) { - return {{{ cDefine('EAI_NONAME') }}}; - } - } else { - addr = lookup; - } - var numBytesWrittenExclNull = stringToUTF8(addr, node, nodelen); - - if (numBytesWrittenExclNull+1 >= nodelen) { - overflowed = true; - } - } - - if (serv && servlen) { - port = '' + port; - var numBytesWrittenExclNull = stringToUTF8(port, serv, servlen); - - if (numBytesWrittenExclNull+1 >= servlen) { - overflowed = true; - } - } - - if (overflowed) { - // Note: even when we overflow, getnameinfo() is specced to write out the truncated results. - return {{{ cDefine('EAI_OVERFLOW') }}}; - } - - return 0; - }, - // Can't use a literal for $GAI_ERRNO_MESSAGES as was done for $ERRNO_MESSAGES as the keys (e.g. EAI_BADFLAGS) - // are actually negative numbers and you can't have expressions as keys in JavaScript literals. - $GAI_ERRNO_MESSAGES: {}, - - gai_strerror__deps: ['$GAI_ERRNO_MESSAGES'], - gai_strerror: function(val) { - var buflen = 256; - - // On first call to gai_strerror we initialise the buffer and populate the error messages. - if (!_gai_strerror.buffer) { - _gai_strerror.buffer = _malloc(buflen); - - GAI_ERRNO_MESSAGES['0'] = 'Success'; - GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_BADFLAGS') }}}] = 'Invalid value for \'ai_flags\' field'; - GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_NONAME') }}}] = 'NAME or SERVICE is unknown'; - GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_AGAIN') }}}] = 'Temporary failure in name resolution'; - GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_FAIL') }}}] = 'Non-recoverable failure in name res'; - GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_FAMILY') }}}] = '\'ai_family\' not supported'; - GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_SOCKTYPE') }}}] = '\'ai_socktype\' not supported'; - GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_SERVICE') }}}] = 'SERVICE not supported for \'ai_socktype\''; - GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_MEMORY') }}}] = 'Memory allocation failure'; - GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_SYSTEM') }}}] = 'System error returned in \'errno\''; - GAI_ERRNO_MESSAGES['' + {{{ cDefine('EAI_OVERFLOW') }}}] = 'Argument buffer overflow'; - } - - var msg = 'Unknown error'; - - if (val in GAI_ERRNO_MESSAGES) { - if (GAI_ERRNO_MESSAGES[val].length > buflen - 1) { - msg = 'Message too long'; // EMSGSIZE message. This should never occur given the GAI_ERRNO_MESSAGES above. - } else { - msg = GAI_ERRNO_MESSAGES[val]; - } - } - - writeAsciiToMemory(msg, _gai_strerror.buffer); - return _gai_strerror.buffer; - }, - - // Implement netdb.h protocol entry (getprotoent, getprotobyname, getprotobynumber, setprotoent, endprotoent) - // http://pubs.opengroup.org/onlinepubs/9699919799/functions/getprotobyname.html - // The Protocols object holds our 'fake' protocols 'database'. - $Protocols: { - list: [], - map: {} - }, - setprotoent__deps: ['$Protocols'], - setprotoent: function(stayopen) { - // void setprotoent(int stayopen); - - // Allocate and populate a protoent structure given a name, protocol number and array of aliases - function allocprotoent(name, proto, aliases) { - // write name into buffer - var nameBuf = _malloc(name.length + 1); - writeAsciiToMemory(name, nameBuf); - - // write aliases into buffer - var j = 0; - var length = aliases.length; - var aliasListBuf = _malloc((length + 1) * 4); // Use length + 1 so we have space for the terminating NULL ptr. - - for (var i = 0; i < length; i++, j += 4) { - var alias = aliases[i]; - var aliasBuf = _malloc(alias.length + 1); - writeAsciiToMemory(alias, aliasBuf); - {{{ makeSetValue('aliasListBuf', 'j', 'aliasBuf', 'i8*') }}}; - } - {{{ makeSetValue('aliasListBuf', 'j', '0', 'i8*') }}}; // Terminating NULL pointer. - - // generate protoent - var pe = _malloc({{{ C_STRUCTS.protoent.__size__ }}}); - {{{ makeSetValue('pe', C_STRUCTS.protoent.p_name, 'nameBuf', 'i8*') }}}; - {{{ makeSetValue('pe', C_STRUCTS.protoent.p_aliases, 'aliasListBuf', 'i8**') }}}; - {{{ makeSetValue('pe', C_STRUCTS.protoent.p_proto, 'proto', 'i32') }}}; - return pe; - }; - - // Populate the protocol 'database'. The entries are limited to tcp and udp, though it is fairly trivial - // to add extra entries from /etc/protocols if desired - though not sure if that'd actually be useful. - var list = Protocols.list; - var map = Protocols.map; - if (list.length === 0) { - var entry = allocprotoent('tcp', 6, ['TCP']); - list.push(entry); - map['tcp'] = map['6'] = entry; - entry = allocprotoent('udp', 17, ['UDP']); - list.push(entry); - map['udp'] = map['17'] = entry; - } - - _setprotoent.index = 0; - }, - - endprotoent: function() { - // void endprotoent(void); - // We're not using a real protocol database so we don't do a real close. - }, - - getprotoent__deps: ['setprotoent', '$Protocols'], - getprotoent: function(number) { - // struct protoent *getprotoent(void); - // reads the next entry from the protocols 'database' or return NULL if 'eof' - if (_setprotoent.index === Protocols.list.length) { - return 0; - } else { - var result = Protocols.list[_setprotoent.index++]; - return result; - } - }, - - getprotobyname__deps: ['setprotoent', '$Protocols'], - getprotobyname: function(name) { - // struct protoent *getprotobyname(const char *); - name = Pointer_stringify(name); - _setprotoent(true); - var result = Protocols.map[name]; - return result; - }, - - getprotobynumber__deps: ['setprotoent', '$Protocols'], - getprotobynumber: function(number) { - // struct protoent *getprotobynumber(int proto); - _setprotoent(true); - var result = Protocols.map[number]; - return result; - }, - - // ========================================================================== - // sockets. Note that the implementation assumes all sockets are always - // nonblocking - // ========================================================================== -#if SOCKET_WEBRTC - $Sockets__deps: ['__setErrNo', '$ERRNO_CODES', - function() { return 'var SocketIO = ' + read('socket.io.js') + ';\n' }, - function() { return 'var Peer = ' + read('wrtcp.js') + ';\n' }], -#else - $Sockets__deps: ['__setErrNo', '$ERRNO_CODES'], -#endif - $Sockets: { - BUFFER_SIZE: 10*1024, // initial size - MAX_BUFFER_SIZE: 10*1024*1024, // maximum size we will grow the buffer - - nextFd: 1, - fds: {}, - nextport: 1, - maxport: 65535, - peer: null, - connections: {}, - portmap: {}, - localAddr: 0xfe00000a, // Local address is always 10.0.0.254 - addrPool: [ 0x0200000a, 0x0300000a, 0x0400000a, 0x0500000a, - 0x0600000a, 0x0700000a, 0x0800000a, 0x0900000a, 0x0a00000a, - 0x0b00000a, 0x0c00000a, 0x0d00000a, 0x0e00000a] /* 0x0100000a is reserved */ - }, - - // pwd.h - - getpwnam: function() { throw 'getpwnam: TODO' }, - setpwent: function() { throw 'setpwent: TODO' }, - getpwent: function() { throw 'getpwent: TODO' }, - endpwent: function() { throw 'endpwent: TODO' }, - - // ========================================================================== - // emscripten.h - // ========================================================================== - - emscripten_run_script: function(ptr) { - {{{ makeEval('eval(Pointer_stringify(ptr));') }}} - }, - - emscripten_run_script_int: function(ptr) { - {{{ makeEval('return eval(Pointer_stringify(ptr))|0;') }}} - }, - - emscripten_run_script_string: function(ptr) { - {{{ makeEval("var s = eval(Pointer_stringify(ptr)) + '';") }}} - var me = _emscripten_run_script_string; - var len = lengthBytesUTF8(s); - if (!me.bufferSize || me.bufferSize < len+1) { - if (me.bufferSize) _free(me.buffer); - me.bufferSize = len+1; - me.buffer = _malloc(me.bufferSize); - } - stringToUTF8(s, me.buffer, me.bufferSize); - return me.buffer; - }, - - emscripten_random: function() { - return Math.random(); - }, - - emscripten_get_now: function() { abort() }, // replaced by the postset at startup time - emscripten_get_now__postset: "if (ENVIRONMENT_IS_NODE) {\n" + - " _emscripten_get_now = function _emscripten_get_now_actual() {\n" + - " var t = process['hrtime']();\n" + - " return t[0] * 1e3 + t[1] / 1e6;\n" + - " };\n" + -#if USE_PTHREADS -// Pthreads need their clocks synchronized to the execution of the main thread, so give them a special form of the function. - "} else if (ENVIRONMENT_IS_PTHREAD) {\n" + - " _emscripten_get_now = function() { return performance['now']() - __performance_now_clock_drift; };\n" + -#endif - "} else if (typeof dateNow !== 'undefined') {\n" + - " _emscripten_get_now = dateNow;\n" + - "} else if (typeof self === 'object' && self['performance'] && typeof self['performance']['now'] === 'function') {\n" + - " _emscripten_get_now = function() { return self['performance']['now'](); };\n" + - "} else if (typeof performance === 'object' && typeof performance['now'] === 'function') {\n" + - " _emscripten_get_now = function() { return performance['now'](); };\n" + - "} else {\n" + - " _emscripten_get_now = Date.now;\n" + - "}", - - emscripten_get_now_res: function() { // return resolution of get_now, in nanoseconds - if (ENVIRONMENT_IS_NODE) { - return 1; // nanoseconds - } else if (typeof dateNow !== 'undefined' || - ((ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && self['performance'] && self['performance']['now'])) { - return 1000; // microseconds (1/1000 of a millisecond) - } else { - return 1000*1000; // milliseconds - } - }, - - emscripten_get_now_is_monotonic__deps: ['emscripten_get_now'], - emscripten_get_now_is_monotonic: function() { - // return whether emscripten_get_now is guaranteed monotonic; the Date.now - // implementation is not :( - return ENVIRONMENT_IS_NODE || (typeof dateNow !== 'undefined') || - ((ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && self['performance'] && self['performance']['now']); - }, - - // Returns [parentFuncArguments, functionName, paramListName] - _emscripten_traverse_stack: function(args) { - if (!args || !args.callee || !args.callee.name) { - return [null, '', '']; - } - - var funstr = args.callee.toString(); - var funcname = args.callee.name; - var str = '('; - var first = true; - for (var i in args) { - var a = args[i]; - if (!first) { - str += ", "; - } - first = false; - if (typeof a === 'number' || typeof a === 'string') { - str += a; - } else { - str += '(' + typeof a + ')'; - } - } - str += ')'; - var caller = args.callee.caller; - args = caller ? caller.arguments : []; - if (first) - str = ''; - return [args, funcname, str]; - }, - - emscripten_get_callstack_js__deps: ['_emscripten_traverse_stack'], - emscripten_get_callstack_js: function(flags) { - var callstack = jsStackTrace(); - - // Find the symbols in the callstack that corresponds to the functions that report callstack information, and remove everyhing up to these from the output. - var iThisFunc = callstack.lastIndexOf('_emscripten_log'); - var iThisFunc2 = callstack.lastIndexOf('_emscripten_get_callstack'); - var iNextLine = callstack.indexOf('\n', Math.max(iThisFunc, iThisFunc2))+1; - callstack = callstack.slice(iNextLine); - - // If user requested to see the original source stack, but no source map information is available, just fall back to showing the JS stack. - if (flags & 8/*EM_LOG_C_STACK*/ && typeof emscripten_source_map === 'undefined') { - warnOnce('Source map information is not available, emscripten_log with EM_LOG_C_STACK will be ignored. Build with "--pre-js $EMSCRIPTEN/src/emscripten-source-map.min.js" linker flag to add source map loading to code.'); - flags ^= 8/*EM_LOG_C_STACK*/; - flags |= 16/*EM_LOG_JS_STACK*/; - } - - var stack_args = null; - if (flags & 128 /*EM_LOG_FUNC_PARAMS*/) { - // To get the actual parameters to the functions, traverse the stack via the unfortunately deprecated 'arguments.callee' method, if it works: - stack_args = __emscripten_traverse_stack(arguments); - while (stack_args[1].indexOf('_emscripten_') >= 0) - stack_args = __emscripten_traverse_stack(stack_args[0]); - } - - // Process all lines: - var lines = callstack.split('\n'); - callstack = ''; - var newFirefoxRe = new RegExp('\\s*(.*?)@(.*?):([0-9]+):([0-9]+)'); // New FF30 with column info: extract components of form ' Object._main@http://server.com:4324:12' - var firefoxRe = new RegExp('\\s*(.*?)@(.*):(.*)(:(.*))?'); // Old FF without column info: extract components of form ' Object._main@http://server.com:4324' - var chromeRe = new RegExp('\\s*at (.*?) \\\((.*):(.*):(.*)\\\)'); // Extract components of form ' at Object._main (http://server.com/file.html:4324:12)' - - for (var l in lines) { - var line = lines[l]; - - var jsSymbolName = ''; - var file = ''; - var lineno = 0; - var column = 0; - - var parts = chromeRe.exec(line); - if (parts && parts.length == 5) { - jsSymbolName = parts[1]; - file = parts[2]; - lineno = parts[3]; - column = parts[4]; - } else { - parts = newFirefoxRe.exec(line); - if (!parts) parts = firefoxRe.exec(line); - if (parts && parts.length >= 4) { - jsSymbolName = parts[1]; - file = parts[2]; - lineno = parts[3]; - column = parts[4]|0; // Old Firefox doesn't carry column information, but in new FF30, it is present. See https://bugzilla.mozilla.org/show_bug.cgi?id=762556 - } else { - // Was not able to extract this line for demangling/sourcemapping purposes. Output it as-is. - callstack += line + '\n'; - continue; - } - } - - // Try to demangle the symbol, but fall back to showing the original JS symbol name if not available. - var cSymbolName = (flags & 32/*EM_LOG_DEMANGLE*/) ? demangle(jsSymbolName) : jsSymbolName; - if (!cSymbolName) { - cSymbolName = jsSymbolName; - } - - var haveSourceMap = false; - - if (flags & 8/*EM_LOG_C_STACK*/) { - var orig = emscripten_source_map.originalPositionFor({line: lineno, column: column}); - haveSourceMap = (orig && orig.source); - if (haveSourceMap) { - if (flags & 64/*EM_LOG_NO_PATHS*/) { - orig.source = orig.source.substring(orig.source.replace(/\\/g, "/").lastIndexOf('/')+1); - } - callstack += ' at ' + cSymbolName + ' (' + orig.source + ':' + orig.line + ':' + orig.column + ')\n'; - } - } - if ((flags & 16/*EM_LOG_JS_STACK*/) || !haveSourceMap) { - if (flags & 64/*EM_LOG_NO_PATHS*/) { - file = file.substring(file.replace(/\\/g, "/").lastIndexOf('/')+1); - } - callstack += (haveSourceMap ? (' = '+jsSymbolName) : (' at '+cSymbolName)) + ' (' + file + ':' + lineno + ':' + column + ')\n'; - } - - // If we are still keeping track with the callstack by traversing via 'arguments.callee', print the function parameters as well. - if (flags & 128 /*EM_LOG_FUNC_PARAMS*/ && stack_args[0]) { - if (stack_args[1] == jsSymbolName && stack_args[2].length > 0) { - callstack = callstack.replace(/\s+$/, ''); - callstack += ' with values: ' + stack_args[1] + stack_args[2] + '\n'; - } - stack_args = __emscripten_traverse_stack(stack_args[0]); - } - } - // Trim extra whitespace at the end of the output. - callstack = callstack.replace(/\s+$/, ''); - return callstack; - }, - - emscripten_get_callstack__deps: ['emscripten_get_callstack_js'], - emscripten_get_callstack: function(flags, str, maxbytes) { - var callstack = _emscripten_get_callstack_js(flags); - // User can query the required amount of bytes to hold the callstack. - if (!str || maxbytes <= 0) { - return lengthBytesUTF8(callstack)+1; - } - // Output callstack string as C string to HEAP. - var bytesWrittenExcludingNull = stringToUTF8(callstack, str, maxbytes); - - // Return number of bytes written, including null. - return bytesWrittenExcludingNull+1; - }, - - emscripten_log_js__deps: ['emscripten_get_callstack_js'], - emscripten_log_js: function(flags, str) { - if (flags & 24/*EM_LOG_C_STACK | EM_LOG_JS_STACK*/) { - str = str.replace(/\s+$/, ''); // Ensure the message and the callstack are joined cleanly with exactly one newline. - str += (str.length > 0 ? '\n' : '') + _emscripten_get_callstack_js(flags); - } - - if (flags & 1 /*EM_LOG_CONSOLE*/) { - if (flags & 4 /*EM_LOG_ERROR*/) { - console.error(str); - } else if (flags & 2 /*EM_LOG_WARN*/) { - console.warn(str); - } else { - console.log(str); - } - } else if (flags & 6 /*EM_LOG_ERROR|EM_LOG_WARN*/) { - Module.printErr(str); - } else { - Module.print(str); - } - }, - - emscripten_log__deps: ['_formatString', 'emscripten_log_js'], - emscripten_log: function(flags, varargs) { - // Extract the (optionally-existing) printf format specifier field from varargs. - var format = {{{ makeGetValue('varargs', '0', 'i32', undefined, undefined, true) }}}; - varargs += {{{ Math.max(Runtime.getNativeFieldSize('i32'), Runtime.getAlignSize('i32', null, true)) }}}; - var str = ''; - if (format) { - var result = __formatString(format, varargs); - for(var i = 0 ; i < result.length; ++i) { - str += String.fromCharCode(result[i]); - } - } - _emscripten_log_js(flags, str); - }, - - emscripten_get_compiler_setting: function(name) { - name = Pointer_stringify(name); - - var ret = getCompilerSetting(name); - if (typeof ret === 'number') return ret; - - if (!_emscripten_get_compiler_setting.cache) _emscripten_get_compiler_setting.cache = {}; - var cache = _emscripten_get_compiler_setting.cache; - var fullname = name + '__str'; - var fullret = cache[fullname]; - if (fullret) return fullret; - return cache[fullname] = allocate(intArrayFromString(ret + ''), 'i8', ALLOC_NORMAL); - }, - - emscripten_debugger: function() { - debugger; - }, - - emscripten_print_double: function(x, to, max) { - var str = x + ''; - if (to) return stringToUTF8(str, to, max); - else return lengthBytesUTF8(str); - }, - - //============================ - // i64 math - //============================ - - i64Add__asm: true, - i64Add__sig: 'iiiii', - i64Add: function(a, b, c, d) { - /* - x = a + b*2^32 - y = c + d*2^32 - result = l + h*2^32 - */ - a = a|0; b = b|0; c = c|0; d = d|0; - var l = 0, h = 0; - l = (a + c)>>>0; - h = (b + d + (((l>>>0) < (a>>>0))|0))>>>0; // Add carry from low word to high word on overflow. - {{{ makeStructuralReturn(['l|0', 'h'], true) }}}; - }, - - i64Subtract__asm: true, - i64Subtract__sig: 'iiiii', - i64Subtract: function(a, b, c, d) { - a = a|0; b = b|0; c = c|0; d = d|0; - var l = 0, h = 0; - l = (a - c)>>>0; - h = (b - d)>>>0; - h = (b - d - (((c>>>0) > (a>>>0))|0))>>>0; // Borrow one from high word to low word on underflow. - {{{ makeStructuralReturn(['l|0', 'h'], true) }}}; - }, - - bitshift64Shl__asm: true, - bitshift64Shl__sig: 'iiii', - bitshift64Shl: function(low, high, bits) { - low = low|0; high = high|0; bits = bits|0; - var ander = 0; - if ((bits|0) < 32) { - ander = ((1 << bits) - 1)|0; - {{{ makeSetTempRet0('(high << bits) | ((low&(ander << (32 - bits))) >>> (32 - bits))') }}}; - return low << bits; - } - {{{ makeSetTempRet0('low << (bits - 32)') }}}; - return 0; - }, - bitshift64Ashr__asm: true, - bitshift64Ashr__sig: 'iiii', - bitshift64Ashr: function(low, high, bits) { - low = low|0; high = high|0; bits = bits|0; - var ander = 0; - if ((bits|0) < 32) { - ander = ((1 << bits) - 1)|0; - {{{ makeSetTempRet0('high >> bits') }}}; - return (low >>> bits) | ((high&ander) << (32 - bits)); - } - {{{ makeSetTempRet0('(high|0) < 0 ? -1 : 0') }}}; - return (high >> (bits - 32))|0; - }, - bitshift64Lshr__asm: true, - bitshift64Lshr__sig: 'iiii', - bitshift64Lshr: function(low, high, bits) { - low = low|0; high = high|0; bits = bits|0; - var ander = 0; - if ((bits|0) < 32) { - ander = ((1 << bits) - 1)|0; - {{{ makeSetTempRet0('high >>> bits') }}}; - return (low >>> bits) | ((high&ander) << (32 - bits)); - } - {{{ makeSetTempRet0('0') }}}; - return (high >>> (bits - 32))|0; - }, - - // misc shims for musl - __lock: function() {}, - __unlock: function() {}, - __lockfile: function() { return 1 }, - __unlockfile: function(){}, - - // ubsan (undefined behavior sanitizer) support - __ubsan_handle_float_cast_overflow: function(id, post) { - abort('Undefined behavior! ubsan_handle_float_cast_overflow: ' + [id, post]); - }, - - // USE_FULL_LIBRARY hacks - realloc: function() { throw 'bad' }, - - // libunwind - - _Unwind_Backtrace__deps: ['emscripten_get_callstack_js'], - _Unwind_Backtrace: function(func, arg) { - var trace = _emscripten_get_callstack_js(); - var parts = trace.split('\n'); - for (var i = 0; i < parts.length; i++) { - var ret = Module['dynCall_iii'](func, 0, arg); - if (ret !== 0) return; - } - }, - - _Unwind_GetIPInfo: function() { - abort('Unwind_GetIPInfo'); - }, - - _Unwind_FindEnclosingFunction: function() { - return 0; // we cannot succeed - }, - - _Unwind_RaiseException__deps: ['__cxa_throw'], - _Unwind_RaiseException: function(ex) { - Module.printErr('Warning: _Unwind_RaiseException is not correctly implemented'); - return ___cxa_throw(ex, 0, 0); - }, - - _Unwind_DeleteException: function(ex) { - Module.printErr('TODO: Unwind_DeleteException'); - }, - - // autodebugging - - emscripten_autodebug_i64: function(line, valuel, valueh) { - Module.print('AD:' + [line, valuel, valueh]); - }, - emscripten_autodebug_i32: function(line, value) { - Module.print('AD:' + [line, value]); - }, - emscripten_autodebug_i16: function(line, value) { - Module.print('AD:' + [line, value]); - }, - emscripten_autodebug_i8: function(line, value) { - Module.print('AD:' + [line, value]); - }, - emscripten_autodebug_float: function(line, value) { - Module.print('AD:' + [line, value]); - }, - emscripten_autodebug_double: function(line, value) { - Module.print('AD:' + [line, value]); - }, - - // misc definitions to avoid unnecessary unresolved symbols from fastcomp - emscripten_prep_setjmp: true, - emscripten_cleanup_setjmp: true, - emscripten_check_longjmp: true, - emscripten_get_longjmp_result: true, - emscripten_setjmp: true, - emscripten_preinvoke: true, - emscripten_postinvoke: true, - emscripten_resume: true, - emscripten_landingpad: true, - getHigh32: true, - setHigh32: true, - FtoILow: true, - FtoIHigh: true, - DtoILow: true, - DtoIHigh: true, - BDtoILow: true, - BDtoIHigh: true, - SItoF: true, - UItoF: true, - SItoD: true, - UItoD: true, - BItoD: true, - llvm_dbg_value: true, - llvm_debugtrap: true, - llvm_ctlz_i32: true, - emscripten_asm_const: true, - emscripten_asm_const_int: true, - emscripten_asm_const_double: true, - emscripten_asm_const_int_sync_on_main_thread: true, - emscripten_asm_const_double_sync_on_main_thread: true, - emscripten_asm_const_async_on_main_thread: true, - - // ======== compiled code from system/lib/compiler-rt , see readme therein - __muldsi3__asm: true, - __muldsi3__sig: 'iii', - __muldsi3: function($a, $b) { - $a = $a | 0; - $b = $b | 0; - var $1 = 0, $2 = 0, $3 = 0, $6 = 0, $8 = 0, $11 = 0, $12 = 0; - $1 = $a & 65535; - $2 = $b & 65535; - $3 = Math_imul($2, $1) | 0; - $6 = $a >>> 16; - $8 = ($3 >>> 16) + (Math_imul($2, $6) | 0) | 0; - $11 = $b >>> 16; - $12 = Math_imul($11, $1) | 0; - return ({{{ makeSetTempRet0('(($8 >>> 16) + (Math_imul($11, $6) | 0) | 0) + ((($8 & 65535) + $12 | 0) >>> 16) | 0') }}}, 0 | ($8 + $12 << 16 | $3 & 65535)) | 0; - }, - __divdi3__sig: 'iiiii', - __divdi3__asm: true, - __divdi3__deps: ['__udivmoddi4', 'i64Subtract'], - __divdi3: function($a$0, $a$1, $b$0, $b$1) { - $a$0 = $a$0 | 0; - $a$1 = $a$1 | 0; - $b$0 = $b$0 | 0; - $b$1 = $b$1 | 0; - var $1$0 = 0, $1$1 = 0, $2$0 = 0, $2$1 = 0, $4$0 = 0, $4$1 = 0, $6$0 = 0, $7$0 = 0, $7$1 = 0, $8$0 = 0, $10$0 = 0; - $1$0 = $a$1 >> 31 | (($a$1 | 0) < 0 ? -1 : 0) << 1; - $1$1 = (($a$1 | 0) < 0 ? -1 : 0) >> 31 | (($a$1 | 0) < 0 ? -1 : 0) << 1; - $2$0 = $b$1 >> 31 | (($b$1 | 0) < 0 ? -1 : 0) << 1; - $2$1 = (($b$1 | 0) < 0 ? -1 : 0) >> 31 | (($b$1 | 0) < 0 ? -1 : 0) << 1; - $4$0 = _i64Subtract($1$0 ^ $a$0 | 0, $1$1 ^ $a$1 | 0, $1$0 | 0, $1$1 | 0) | 0; - $4$1 = {{{ makeGetTempRet0() }}}; - $6$0 = _i64Subtract($2$0 ^ $b$0 | 0, $2$1 ^ $b$1 | 0, $2$0 | 0, $2$1 | 0) | 0; - $7$0 = $2$0 ^ $1$0; - $7$1 = $2$1 ^ $1$1; - $8$0 = ___udivmoddi4($4$0, $4$1, $6$0, {{{ makeGetTempRet0() }}}, 0) | 0; - $10$0 = _i64Subtract($8$0 ^ $7$0 | 0, {{{ makeGetTempRet0() }}} ^ $7$1 | 0, $7$0 | 0, $7$1 | 0) | 0; - return $10$0 | 0; - }, - __remdi3__sig: 'iiiii', - __remdi3__asm: true, - __remdi3__deps: ['__udivmoddi4', 'i64Subtract'], - __remdi3: function($a$0, $a$1, $b$0, $b$1) { - $a$0 = $a$0 | 0; - $a$1 = $a$1 | 0; - $b$0 = $b$0 | 0; - $b$1 = $b$1 | 0; - var $rem = 0, $1$0 = 0, $1$1 = 0, $2$0 = 0, $2$1 = 0, $4$0 = 0, $4$1 = 0, $6$0 = 0, $10$0 = 0, $10$1 = 0, __stackBase__ = 0; - __stackBase__ = STACKTOP; - STACKTOP = STACKTOP + 16 | 0; - $rem = __stackBase__ | 0; - $1$0 = $a$1 >> 31 | (($a$1 | 0) < 0 ? -1 : 0) << 1; - $1$1 = (($a$1 | 0) < 0 ? -1 : 0) >> 31 | (($a$1 | 0) < 0 ? -1 : 0) << 1; - $2$0 = $b$1 >> 31 | (($b$1 | 0) < 0 ? -1 : 0) << 1; - $2$1 = (($b$1 | 0) < 0 ? -1 : 0) >> 31 | (($b$1 | 0) < 0 ? -1 : 0) << 1; - $4$0 = _i64Subtract($1$0 ^ $a$0 | 0, $1$1 ^ $a$1 | 0, $1$0 | 0, $1$1 | 0) | 0; - $4$1 = {{{ makeGetTempRet0() }}}; - $6$0 = _i64Subtract($2$0 ^ $b$0 | 0, $2$1 ^ $b$1 | 0, $2$0 | 0, $2$1 | 0) | 0; - ___udivmoddi4($4$0, $4$1, $6$0, {{{ makeGetTempRet0() }}}, $rem) | 0; - $10$0 = _i64Subtract(HEAP32[$rem >> 2] ^ $1$0 | 0, HEAP32[$rem + 4 >> 2] ^ $1$1 | 0, $1$0 | 0, $1$1 | 0) | 0; - $10$1 = {{{ makeGetTempRet0() }}}; - STACKTOP = __stackBase__; - return ({{{ makeSetTempRet0('$10$1') }}}, $10$0) | 0; - }, - __muldi3__sig: 'iiiii', - __muldi3__asm: true, - __muldi3__deps: ['__muldsi3'], - __muldi3: function($a$0, $a$1, $b$0, $b$1) { - $a$0 = $a$0 | 0; - $a$1 = $a$1 | 0; - $b$0 = $b$0 | 0; - $b$1 = $b$1 | 0; - var $x_sroa_0_0_extract_trunc = 0, $y_sroa_0_0_extract_trunc = 0, $1$0 = 0, $1$1 = 0, $2 = 0; - $x_sroa_0_0_extract_trunc = $a$0; - $y_sroa_0_0_extract_trunc = $b$0; - $1$0 = ___muldsi3($x_sroa_0_0_extract_trunc, $y_sroa_0_0_extract_trunc) | 0; - $1$1 = {{{ makeGetTempRet0() }}}; - $2 = Math_imul($a$1, $y_sroa_0_0_extract_trunc) | 0; - return ({{{ makeSetTempRet0('((Math_imul($b$1, $x_sroa_0_0_extract_trunc) | 0) + $2 | 0) + $1$1 | $1$1 & 0') }}}, 0 | $1$0 & -1) | 0; - }, - __udivdi3__sig: 'iiiii', - __udivdi3__asm: true, - __udivdi3__deps: ['__udivmoddi4'], - __udivdi3: function($a$0, $a$1, $b$0, $b$1) { - $a$0 = $a$0 | 0; - $a$1 = $a$1 | 0; - $b$0 = $b$0 | 0; - $b$1 = $b$1 | 0; - var $1$0 = 0; - $1$0 = ___udivmoddi4($a$0, $a$1, $b$0, $b$1, 0) | 0; - return $1$0 | 0; - }, - __uremdi3__sig: 'iiiii', - __uremdi3__asm: true, - __uremdi3__deps: ['__udivmoddi4'], - __uremdi3: function($a$0, $a$1, $b$0, $b$1) { - $a$0 = $a$0 | 0; - $a$1 = $a$1 | 0; - $b$0 = $b$0 | 0; - $b$1 = $b$1 | 0; - var $rem = 0, __stackBase__ = 0; - __stackBase__ = STACKTOP; - STACKTOP = STACKTOP + 16 | 0; - $rem = __stackBase__ | 0; - ___udivmoddi4($a$0, $a$1, $b$0, $b$1, $rem) | 0; - STACKTOP = __stackBase__; - return ({{{ makeSetTempRet0('HEAP32[$rem + 4 >> 2] | 0') }}}, HEAP32[$rem >> 2] | 0) | 0; - }, - __udivmoddi4__sig: 'iiiiii', - __udivmoddi4__asm: true, - __udivmoddi4__deps: ['i64Add', 'i64Subtract', 'llvm_cttz_i32'], - __udivmoddi4: function($a$0, $a$1, $b$0, $b$1, $rem) { - $a$0 = $a$0 | 0; - $a$1 = $a$1 | 0; - $b$0 = $b$0 | 0; - $b$1 = $b$1 | 0; - $rem = $rem | 0; - var $n_sroa_0_0_extract_trunc = 0, $n_sroa_1_4_extract_shift$0 = 0, $n_sroa_1_4_extract_trunc = 0, $d_sroa_0_0_extract_trunc = 0, $d_sroa_1_4_extract_shift$0 = 0, $d_sroa_1_4_extract_trunc = 0, $4 = 0, $17 = 0, $37 = 0, $49 = 0, $51 = 0, $57 = 0, $58 = 0, $66 = 0, $78 = 0, $86 = 0, $88 = 0, $89 = 0, $91 = 0, $92 = 0, $95 = 0, $105 = 0, $117 = 0, $119 = 0, $125 = 0, $126 = 0, $130 = 0, $q_sroa_1_1_ph = 0, $q_sroa_0_1_ph = 0, $r_sroa_1_1_ph = 0, $r_sroa_0_1_ph = 0, $sr_1_ph = 0, $d_sroa_0_0_insert_insert99$0 = 0, $d_sroa_0_0_insert_insert99$1 = 0, $137$0 = 0, $137$1 = 0, $carry_0203 = 0, $sr_1202 = 0, $r_sroa_0_1201 = 0, $r_sroa_1_1200 = 0, $q_sroa_0_1199 = 0, $q_sroa_1_1198 = 0, $147 = 0, $149 = 0, $r_sroa_0_0_insert_insert42$0 = 0, $r_sroa_0_0_insert_insert42$1 = 0, $150$1 = 0, $151$0 = 0, $152 = 0, $154$0 = 0, $r_sroa_0_0_extract_trunc = 0, $r_sroa_1_4_extract_trunc = 0, $155 = 0, $carry_0_lcssa$0 = 0, $carry_0_lcssa$1 = 0, $r_sroa_0_1_lcssa = 0, $r_sroa_1_1_lcssa = 0, $q_sroa_0_1_lcssa = 0, $q_sroa_1_1_lcssa = 0, $q_sroa_0_0_insert_ext75$0 = 0, $q_sroa_0_0_insert_ext75$1 = 0, $q_sroa_0_0_insert_insert77$1 = 0, $_0$0 = 0, $_0$1 = 0; - $n_sroa_0_0_extract_trunc = $a$0; - $n_sroa_1_4_extract_shift$0 = $a$1; - $n_sroa_1_4_extract_trunc = $n_sroa_1_4_extract_shift$0; - $d_sroa_0_0_extract_trunc = $b$0; - $d_sroa_1_4_extract_shift$0 = $b$1; - $d_sroa_1_4_extract_trunc = $d_sroa_1_4_extract_shift$0; - if (($n_sroa_1_4_extract_trunc | 0) == 0) { - $4 = ($rem | 0) != 0; - if (($d_sroa_1_4_extract_trunc | 0) == 0) { - if ($4) { - HEAP32[$rem >> 2] = ($n_sroa_0_0_extract_trunc >>> 0) % ($d_sroa_0_0_extract_trunc >>> 0); - HEAP32[$rem + 4 >> 2] = 0; - } - $_0$1 = 0; - $_0$0 = ($n_sroa_0_0_extract_trunc >>> 0) / ($d_sroa_0_0_extract_trunc >>> 0) >>> 0; - return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0; - } else { - if (!$4) { - $_0$1 = 0; - $_0$0 = 0; - return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0; - } - HEAP32[$rem >> 2] = $a$0 & -1; - HEAP32[$rem + 4 >> 2] = $a$1 & 0; - $_0$1 = 0; - $_0$0 = 0; - return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0; - } - } - $17 = ($d_sroa_1_4_extract_trunc | 0) == 0; - do { - if (($d_sroa_0_0_extract_trunc | 0) == 0) { - if ($17) { - if (($rem | 0) != 0) { - HEAP32[$rem >> 2] = ($n_sroa_1_4_extract_trunc >>> 0) % ($d_sroa_0_0_extract_trunc >>> 0); - HEAP32[$rem + 4 >> 2] = 0; - } - $_0$1 = 0; - $_0$0 = ($n_sroa_1_4_extract_trunc >>> 0) / ($d_sroa_0_0_extract_trunc >>> 0) >>> 0; - return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0; - } - if (($n_sroa_0_0_extract_trunc | 0) == 0) { - if (($rem | 0) != 0) { - HEAP32[$rem >> 2] = 0; - HEAP32[$rem + 4 >> 2] = ($n_sroa_1_4_extract_trunc >>> 0) % ($d_sroa_1_4_extract_trunc >>> 0); - } - $_0$1 = 0; - $_0$0 = ($n_sroa_1_4_extract_trunc >>> 0) / ($d_sroa_1_4_extract_trunc >>> 0) >>> 0; - return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0; - } - $37 = $d_sroa_1_4_extract_trunc - 1 | 0; - if (($37 & $d_sroa_1_4_extract_trunc | 0) == 0) { - if (($rem | 0) != 0) { - HEAP32[$rem >> 2] = 0 | $a$0 & -1; - HEAP32[$rem + 4 >> 2] = $37 & $n_sroa_1_4_extract_trunc | $a$1 & 0; - } - $_0$1 = 0; - $_0$0 = $n_sroa_1_4_extract_trunc >>> ((_llvm_cttz_i32($d_sroa_1_4_extract_trunc | 0) | 0) >>> 0); - return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0; - } - $49 = Math_clz32($d_sroa_1_4_extract_trunc | 0) | 0; - $51 = $49 - (Math_clz32($n_sroa_1_4_extract_trunc | 0) | 0) | 0; - if ($51 >>> 0 <= 30) { - $57 = $51 + 1 | 0; - $58 = 31 - $51 | 0; - $sr_1_ph = $57; - $r_sroa_0_1_ph = $n_sroa_1_4_extract_trunc << $58 | $n_sroa_0_0_extract_trunc >>> ($57 >>> 0); - $r_sroa_1_1_ph = $n_sroa_1_4_extract_trunc >>> ($57 >>> 0); - $q_sroa_0_1_ph = 0; - $q_sroa_1_1_ph = $n_sroa_0_0_extract_trunc << $58; - break; - } - if (($rem | 0) == 0) { - $_0$1 = 0; - $_0$0 = 0; - return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0; - } - HEAP32[$rem >> 2] = 0 | $a$0 & -1; - HEAP32[$rem + 4 >> 2] = $n_sroa_1_4_extract_shift$0 | $a$1 & 0; - $_0$1 = 0; - $_0$0 = 0; - return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0; - } else { - if (!$17) { - $117 = Math_clz32($d_sroa_1_4_extract_trunc | 0) | 0; - $119 = $117 - (Math_clz32($n_sroa_1_4_extract_trunc | 0) | 0) | 0; - if ($119 >>> 0 <= 31) { - $125 = $119 + 1 | 0; - $126 = 31 - $119 | 0; - $130 = $119 - 31 >> 31; - $sr_1_ph = $125; - $r_sroa_0_1_ph = $n_sroa_0_0_extract_trunc >>> ($125 >>> 0) & $130 | $n_sroa_1_4_extract_trunc << $126; - $r_sroa_1_1_ph = $n_sroa_1_4_extract_trunc >>> ($125 >>> 0) & $130; - $q_sroa_0_1_ph = 0; - $q_sroa_1_1_ph = $n_sroa_0_0_extract_trunc << $126; - break; - } - if (($rem | 0) == 0) { - $_0$1 = 0; - $_0$0 = 0; - return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0; - } - HEAP32[$rem >> 2] = 0 | $a$0 & -1; - HEAP32[$rem + 4 >> 2] = $n_sroa_1_4_extract_shift$0 | $a$1 & 0; - $_0$1 = 0; - $_0$0 = 0; - return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0; - } - $66 = $d_sroa_0_0_extract_trunc - 1 | 0; - if (($66 & $d_sroa_0_0_extract_trunc | 0) != 0) { - $86 = (Math_clz32($d_sroa_0_0_extract_trunc | 0) | 0) + 33 | 0; - $88 = $86 - (Math_clz32($n_sroa_1_4_extract_trunc | 0) | 0) | 0; - $89 = 64 - $88 | 0; - $91 = 32 - $88 | 0; - $92 = $91 >> 31; - $95 = $88 - 32 | 0; - $105 = $95 >> 31; - $sr_1_ph = $88; - $r_sroa_0_1_ph = $91 - 1 >> 31 & $n_sroa_1_4_extract_trunc >>> ($95 >>> 0) | ($n_sroa_1_4_extract_trunc << $91 | $n_sroa_0_0_extract_trunc >>> ($88 >>> 0)) & $105; - $r_sroa_1_1_ph = $105 & $n_sroa_1_4_extract_trunc >>> ($88 >>> 0); - $q_sroa_0_1_ph = $n_sroa_0_0_extract_trunc << $89 & $92; - $q_sroa_1_1_ph = ($n_sroa_1_4_extract_trunc << $89 | $n_sroa_0_0_extract_trunc >>> ($95 >>> 0)) & $92 | $n_sroa_0_0_extract_trunc << $91 & $88 - 33 >> 31; - break; - } - if (($rem | 0) != 0) { - HEAP32[$rem >> 2] = $66 & $n_sroa_0_0_extract_trunc; - HEAP32[$rem + 4 >> 2] = 0; - } - if (($d_sroa_0_0_extract_trunc | 0) == 1) { - $_0$1 = $n_sroa_1_4_extract_shift$0 | $a$1 & 0; - $_0$0 = 0 | $a$0 & -1; - return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0; - } else { - $78 = _llvm_cttz_i32($d_sroa_0_0_extract_trunc | 0) | 0; - $_0$1 = 0 | $n_sroa_1_4_extract_trunc >>> ($78 >>> 0); - $_0$0 = $n_sroa_1_4_extract_trunc << 32 - $78 | $n_sroa_0_0_extract_trunc >>> ($78 >>> 0) | 0; - return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0; - } - } - } while (0); - if (($sr_1_ph | 0) == 0) { - $q_sroa_1_1_lcssa = $q_sroa_1_1_ph; - $q_sroa_0_1_lcssa = $q_sroa_0_1_ph; - $r_sroa_1_1_lcssa = $r_sroa_1_1_ph; - $r_sroa_0_1_lcssa = $r_sroa_0_1_ph; - $carry_0_lcssa$1 = 0; - $carry_0_lcssa$0 = 0; - } else { - $d_sroa_0_0_insert_insert99$0 = 0 | $b$0 & -1; - $d_sroa_0_0_insert_insert99$1 = $d_sroa_1_4_extract_shift$0 | $b$1 & 0; - $137$0 = _i64Add($d_sroa_0_0_insert_insert99$0 | 0, $d_sroa_0_0_insert_insert99$1 | 0, -1, -1) | 0; - $137$1 = {{{ makeGetTempRet0() }}}; - $q_sroa_1_1198 = $q_sroa_1_1_ph; - $q_sroa_0_1199 = $q_sroa_0_1_ph; - $r_sroa_1_1200 = $r_sroa_1_1_ph; - $r_sroa_0_1201 = $r_sroa_0_1_ph; - $sr_1202 = $sr_1_ph; - $carry_0203 = 0; - while (1) { - $147 = $q_sroa_0_1199 >>> 31 | $q_sroa_1_1198 << 1; - $149 = $carry_0203 | $q_sroa_0_1199 << 1; - $r_sroa_0_0_insert_insert42$0 = 0 | ($r_sroa_0_1201 << 1 | $q_sroa_1_1198 >>> 31); - $r_sroa_0_0_insert_insert42$1 = $r_sroa_0_1201 >>> 31 | $r_sroa_1_1200 << 1 | 0; - _i64Subtract($137$0 | 0, $137$1 | 0, $r_sroa_0_0_insert_insert42$0 | 0, $r_sroa_0_0_insert_insert42$1 | 0) | 0; - $150$1 = {{{ makeGetTempRet0() }}}; - $151$0 = $150$1 >> 31 | (($150$1 | 0) < 0 ? -1 : 0) << 1; - $152 = $151$0 & 1; - $154$0 = _i64Subtract($r_sroa_0_0_insert_insert42$0 | 0, $r_sroa_0_0_insert_insert42$1 | 0, $151$0 & $d_sroa_0_0_insert_insert99$0 | 0, ((($150$1 | 0) < 0 ? -1 : 0) >> 31 | (($150$1 | 0) < 0 ? -1 : 0) << 1) & $d_sroa_0_0_insert_insert99$1 | 0) | 0; - $r_sroa_0_0_extract_trunc = $154$0; - $r_sroa_1_4_extract_trunc = {{{ makeGetTempRet0() }}}; - $155 = $sr_1202 - 1 | 0; - if (($155 | 0) == 0) { - break; - } else { - $q_sroa_1_1198 = $147; - $q_sroa_0_1199 = $149; - $r_sroa_1_1200 = $r_sroa_1_4_extract_trunc; - $r_sroa_0_1201 = $r_sroa_0_0_extract_trunc; - $sr_1202 = $155; - $carry_0203 = $152; - } - } - $q_sroa_1_1_lcssa = $147; - $q_sroa_0_1_lcssa = $149; - $r_sroa_1_1_lcssa = $r_sroa_1_4_extract_trunc; - $r_sroa_0_1_lcssa = $r_sroa_0_0_extract_trunc; - $carry_0_lcssa$1 = 0; - $carry_0_lcssa$0 = $152; - } - $q_sroa_0_0_insert_ext75$0 = $q_sroa_0_1_lcssa; - $q_sroa_0_0_insert_ext75$1 = 0; - $q_sroa_0_0_insert_insert77$1 = $q_sroa_1_1_lcssa | $q_sroa_0_0_insert_ext75$1; - if (($rem | 0) != 0) { - HEAP32[$rem >> 2] = 0 | $r_sroa_0_1_lcssa; - HEAP32[$rem + 4 >> 2] = $r_sroa_1_1_lcssa | 0; - } - $_0$1 = (0 | $q_sroa_0_0_insert_ext75$0) >>> 31 | $q_sroa_0_0_insert_insert77$1 << 1 | ($q_sroa_0_0_insert_ext75$1 << 1 | $q_sroa_0_0_insert_ext75$0 >>> 31) & 0 | $carry_0_lcssa$1; - $_0$0 = ($q_sroa_0_0_insert_ext75$0 << 1 | 0 >>> 31) & -2 | $carry_0_lcssa$0; - return ({{{ makeSetTempRet0('$_0$1') }}}, $_0$0) | 0; - }, - // ======================================================================= - -}; - -function autoAddDeps(object, name) { - name = [name]; - for (var item in object) { - if (item.substr(-6) != '__deps') { - if (!object[item + '__deps']) { - object[item + '__deps'] = name; - } else { - object[item + '__deps'].push(name[0]); // add to existing list - } - } - } -} - diff --git a/emsdk/files/library_browser.js b/emsdk/files/library_browser.js deleted file mode 100644 index 4258835ea..000000000 --- a/emsdk/files/library_browser.js +++ /dev/null @@ -1,1518 +0,0 @@ -//"use strict"; - -// Utilities for browser environments -var LibraryBrowser = { - $Browser__deps: ['emscripten_set_main_loop', 'emscripten_set_main_loop_timing'], - $Browser__postset: 'Module["requestFullScreen"] = function Module_requestFullScreen(lockPointer, resizeCanvas, vrDevice) { Module.printErr("Module.requestFullScreen is deprecated. Please call Module.requestFullscreen instead."); Module["requestFullScreen"] = Module["requestFullscreen"]; Browser.requestFullScreen(lockPointer, resizeCanvas, vrDevice) };\n' + // exports - 'Module["requestFullscreen"] = function Module_requestFullscreen(lockPointer, resizeCanvas, vrDevice) { Browser.requestFullscreen(lockPointer, resizeCanvas, vrDevice) };\n' + // exports - 'Module["requestAnimationFrame"] = function Module_requestAnimationFrame(func) { Browser.requestAnimationFrame(func) };\n' + - 'Module["setCanvasSize"] = function Module_setCanvasSize(width, height, noUpdates) { Browser.setCanvasSize(width, height, noUpdates) };\n' + - 'Module["pauseMainLoop"] = function Module_pauseMainLoop() { Browser.mainLoop.pause() };\n' + - 'Module["resumeMainLoop"] = function Module_resumeMainLoop() { Browser.mainLoop.resume() };\n' + - 'Module["getUserMedia"] = function Module_getUserMedia() { Browser.getUserMedia() }\n' + - 'Module["createContext"] = function Module_createContext(canvas, useWebGL, setInModule, webGLContextAttributes) { return Browser.createContext(canvas, useWebGL, setInModule, webGLContextAttributes) }', - $Browser: { - mainLoop: { - scheduler: null, - method: '', - // Each main loop is numbered with a ID in sequence order. Only one main loop can run at a time. This variable stores the ordinal number of the main loop that is currently - // allowed to run. All previous main loops will quit themselves. This is incremented whenever a new main loop is created. - currentlyRunningMainloop: 0, - func: null, // The main loop tick function that will be called at each iteration. - arg: 0, // The argument that will be passed to the main loop. (of type void*) - timingMode: 0, - timingValue: 0, - currentFrameNumber: 0, - queue: [], - pause: function() { - Browser.mainLoop.scheduler = null; - Browser.mainLoop.currentlyRunningMainloop++; // Incrementing this signals the previous main loop that it's now become old, and it must return. - }, - resume: function() { - Browser.mainLoop.currentlyRunningMainloop++; - var timingMode = Browser.mainLoop.timingMode; - var timingValue = Browser.mainLoop.timingValue; - var func = Browser.mainLoop.func; - Browser.mainLoop.func = null; - _emscripten_set_main_loop(func, 0, false, Browser.mainLoop.arg, true /* do not set timing and call scheduler, we will do it on the next lines */); - _emscripten_set_main_loop_timing(timingMode, timingValue); - Browser.mainLoop.scheduler(); - }, - updateStatus: function() { - if (Module['setStatus']) { - var message = Module['statusMessage'] || 'Please wait...'; - var remaining = Browser.mainLoop.remainingBlockers; - var expected = Browser.mainLoop.expectedBlockers; - if (remaining) { - if (remaining < expected) { - Module['setStatus'](message + ' (' + (expected - remaining) + '/' + expected + ')'); - } else { - Module['setStatus'](message); - } - } else { - Module['setStatus'](''); - } - } - }, - runIter: function(func) { - if (ABORT) return; - if (Module['preMainLoop']) { - var preRet = Module['preMainLoop'](); - if (preRet === false) { - return; // |return false| skips a frame - } - } - try { - func(); - } catch (e) { - if (e instanceof ExitStatus) { - return; - } else { - if (e && typeof e === 'object' && e.stack) Module.printErr('exception thrown: ' + [e, e.stack]); - throw e; - } - } - if (Module['postMainLoop']) Module['postMainLoop'](); - } - }, - isFullscreen: false, - pointerLock: false, - moduleContextCreatedCallbacks: [], - workers: [], - - init: function() { - if (!Module["preloadPlugins"]) Module["preloadPlugins"] = []; // needs to exist even in workers - - if (Browser.initted) return; - Browser.initted = true; - - try { - new Blob(); - Browser.hasBlobConstructor = true; - } catch(e) { - Browser.hasBlobConstructor = false; - console.log("warning: no blob constructor, cannot create blobs with mimetypes"); - } - Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : (!Browser.hasBlobConstructor ? console.log("warning: no BlobBuilder") : null)); - Browser.URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : undefined; - if (!Module.noImageDecoding && typeof Browser.URLObject === 'undefined') { - console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available."); - Module.noImageDecoding = true; - } - - // Support for plugins that can process preloaded files. You can add more of these to - // your app by creating and appending to Module.preloadPlugins. - // - // Each plugin is asked if it can handle a file based on the file's name. If it can, - // it is given the file's raw data. When it is done, it calls a callback with the file's - // (possibly modified) data. For example, a plugin might decompress a file, or it - // might create some side data structure for use later (like an Image element, etc.). - - var imagePlugin = {}; - imagePlugin['canHandle'] = function imagePlugin_canHandle(name) { - return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name); - }; - imagePlugin['handle'] = function imagePlugin_handle(byteArray, name, onload, onerror) { - var b = null; - if (Browser.hasBlobConstructor) { - try { - b = new Blob([byteArray], { type: Browser.getMimetype(name) }); - if (b.size !== byteArray.length) { // Safari bug #118630 - // Safari's Blob can only take an ArrayBuffer - b = new Blob([(new Uint8Array(byteArray)).buffer], { type: Browser.getMimetype(name) }); - } - } catch(e) { - warnOnce('Blob constructor present but fails: ' + e + '; falling back to blob builder'); - } - } - if (!b) { - var bb = new Browser.BlobBuilder(); - bb.append((new Uint8Array(byteArray)).buffer); // we need to pass a buffer, and must copy the array to get the right data range - b = bb.getBlob(); - } - var url = Browser.URLObject.createObjectURL(b); -#if ASSERTIONS - assert(typeof url == 'string', 'createObjectURL must return a url as a string'); -#endif - var img = new Image(); - img.onload = function img_onload() { - assert(img.complete, 'Image ' + name + ' could not be decoded'); - var canvas = document.createElement('canvas'); - canvas.width = img.width; - canvas.height = img.height; - var ctx = canvas.getContext('2d'); - ctx.drawImage(img, 0, 0); - Module["preloadedImages"][name] = canvas; - Browser.URLObject.revokeObjectURL(url); - if (onload) onload(byteArray); - }; - img.onerror = function img_onerror(event) { - console.log('Image ' + url + ' could not be decoded'); - if (onerror) onerror(); - }; - img.src = url; - }; - Module['preloadPlugins'].push(imagePlugin); - - var audioPlugin = {}; - audioPlugin['canHandle'] = function audioPlugin_canHandle(name) { - return !Module.noAudioDecoding && name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 }; - }; - audioPlugin['handle'] = function audioPlugin_handle(byteArray, name, onload, onerror) { - var done = false; - function finish(audio) { - if (done) return; - done = true; - Module["preloadedAudios"][name] = audio; - if (onload) onload(byteArray); - } - function fail() { - if (done) return; - done = true; - Module["preloadedAudios"][name] = new Audio(); // empty shim - if (onerror) onerror(); - } - if (Browser.hasBlobConstructor) { - try { - var b = new Blob([byteArray], { type: Browser.getMimetype(name) }); - } catch(e) { - return fail(); - } - var url = Browser.URLObject.createObjectURL(b); // XXX we never revoke this! -#if ASSERTIONS - assert(typeof url == 'string', 'createObjectURL must return a url as a string'); -#endif - var audio = new Audio(); - audio.addEventListener('canplaythrough', function() { finish(audio) }, false); // use addEventListener due to chromium bug 124926 - audio.onerror = function audio_onerror(event) { - if (done) return; - console.log('warning: browser could not fully decode audio ' + name + ', trying slower base64 approach'); - function encode64(data) { - var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - var PAD = '='; - var ret = ''; - var leftchar = 0; - var leftbits = 0; - for (var i = 0; i < data.length; i++) { - leftchar = (leftchar << 8) | data[i]; - leftbits += 8; - while (leftbits >= 6) { - var curr = (leftchar >> (leftbits-6)) & 0x3f; - leftbits -= 6; - ret += BASE[curr]; - } - } - if (leftbits == 2) { - ret += BASE[(leftchar&3) << 4]; - ret += PAD + PAD; - } else if (leftbits == 4) { - ret += BASE[(leftchar&0xf) << 2]; - ret += PAD; - } - return ret; - } - audio.src = 'data:audio/x-' + name.substr(-3) + ';base64,' + encode64(byteArray); - finish(audio); // we don't wait for confirmation this worked - but it's worth trying - }; - audio.src = url; - // workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror - Browser.safeSetTimeout(function() { - finish(audio); // try to use it even though it is not necessarily ready to play - }, 10000); - } else { - return fail(); - } - }; - Module['preloadPlugins'].push(audioPlugin); - -#if (WASM != 0) && (MAIN_MODULE != 0) - var wasmPlugin = {}; - wasmPlugin['asyncWasmLoadPromise'] = new Promise( - function(resolve, reject) { return resolve(); }); - wasmPlugin['canHandle'] = function(name) { - return !Module.noWasmDecoding && (name.endsWith('.so') || name.endsWith('.wasm')); - }; - wasmPlugin['handle'] = function(byteArray, name, onload, onerror) { - // loadWebAssemblyModule can not load modules out-of-order, so rather - // than just running the promises in parallel, this makes a chain of - // promises to run in series. - this.asyncWasmLoadPromise = this.asyncWasmLoadPromise.then( - function() { - return Module.loadWebAssemblyModule(byteArray, true) - }).then( - function(module) { - Module.preloadedWasm[name] = module; - onload(); - }, - function(err) { - console.warn("Couldn't instantiate wasm: " + name + " '" + err + "'"); - onerror(); - }); - }; - Module['preloadPlugins'].push(wasmPlugin); -#endif - - // Canvas event setup - - function pointerLockChange() { - Browser.pointerLock = document['pointerLockElement'] === Module['canvas'] || - document['mozPointerLockElement'] === Module['canvas'] || - document['webkitPointerLockElement'] === Module['canvas'] || - document['msPointerLockElement'] === Module['canvas']; - } - var canvas = Module['canvas']; - if (canvas) { - // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module - // Module['forcedAspectRatio'] = 4 / 3; - - canvas.requestPointerLock = canvas['requestPointerLock'] || - canvas['mozRequestPointerLock'] || - canvas['webkitRequestPointerLock'] || - canvas['msRequestPointerLock'] || - function(){}; - canvas.exitPointerLock = document['exitPointerLock'] || - document['mozExitPointerLock'] || - document['webkitExitPointerLock'] || - document['msExitPointerLock'] || - function(){}; // no-op if function does not exist - canvas.exitPointerLock = canvas.exitPointerLock.bind(document); - - document.addEventListener('pointerlockchange', pointerLockChange, false); - document.addEventListener('mozpointerlockchange', pointerLockChange, false); - document.addEventListener('webkitpointerlockchange', pointerLockChange, false); - document.addEventListener('mspointerlockchange', pointerLockChange, false); - - if (Module['elementPointerLock']) { - canvas.addEventListener("click", function(ev) { - if (!Browser.pointerLock && Module['canvas'].requestPointerLock) { - Module['canvas'].requestPointerLock(); - ev.preventDefault(); - } - }, false); - } - } - }, - - createContext: function(canvas, useWebGL, setInModule, webGLContextAttributes) { - if (useWebGL && Module.ctx && canvas == Module.canvas) return Module.ctx; // no need to recreate GL context if it's already been created for this canvas. - - var ctx; - var contextHandle; - if (useWebGL) { - // For GLES2/desktop GL compatibility, adjust a few defaults to be different to WebGL defaults, so that they align better with the desktop defaults. - var contextAttributes = { - antialias: false, - alpha: false - }; - - if (webGLContextAttributes) { - for (var attribute in webGLContextAttributes) { - contextAttributes[attribute] = webGLContextAttributes[attribute]; - } - } - - contextHandle = GL.createContext(canvas, contextAttributes); - if (contextHandle) { - ctx = GL.getContext(contextHandle).GLctx; - } - } else { - ctx = canvas.getContext('2d'); - } - - if (!ctx) return null; - - if (setInModule) { - if (!useWebGL) assert(typeof GLctx === 'undefined', 'cannot set in module if GLctx is used, but we are a non-GL context that would replace it'); - - Module.ctx = ctx; - if (useWebGL) GL.makeContextCurrent(contextHandle); - Module.useWebGL = useWebGL; - Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() }); - Browser.init(); - } - return ctx; - }, - - destroyContext: function(canvas, useWebGL, setInModule) {}, - - fullscreenHandlersInstalled: false, - lockPointer: undefined, - resizeCanvas: undefined, - requestFullscreen: function(lockPointer, resizeCanvas, vrDevice) { - Browser.lockPointer = lockPointer; - Browser.resizeCanvas = resizeCanvas; - Browser.vrDevice = vrDevice; - if (typeof Browser.lockPointer === 'undefined') Browser.lockPointer = true; - if (typeof Browser.resizeCanvas === 'undefined') Browser.resizeCanvas = false; - if (typeof Browser.vrDevice === 'undefined') Browser.vrDevice = null; - - var canvas = Module['canvas']; - function fullscreenChange() { - Browser.isFullscreen = false; - var canvasContainer = canvas.parentNode; - if ((document['fullscreenElement'] || document['mozFullScreenElement'] || - document['msFullscreenElement'] || document['webkitFullscreenElement'] || - document['webkitCurrentFullScreenElement']) === canvasContainer) { - canvas.exitFullscreen = document['exitFullscreen'] || - document['cancelFullScreen'] || - document['mozCancelFullScreen'] || - document['msExitFullscreen'] || - document['webkitCancelFullScreen'] || - function() {}; - canvas.exitFullscreen = canvas.exitFullscreen.bind(document); - if (Browser.lockPointer) canvas.requestPointerLock(); - Browser.isFullscreen = true; - if (Browser.resizeCanvas) { - Browser.setFullscreenCanvasSize(); - } else { - Browser.updateCanvasDimensions(canvas); - } - } else { - // remove the full screen specific parent of the canvas again to restore the HTML structure from before going full screen - canvasContainer.parentNode.insertBefore(canvas, canvasContainer); - canvasContainer.parentNode.removeChild(canvasContainer); - - if (Browser.resizeCanvas) { - Browser.setWindowedCanvasSize(); - } else { - Browser.updateCanvasDimensions(canvas); - } - } - if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullscreen); - if (Module['onFullscreen']) Module['onFullscreen'](Browser.isFullscreen); - } - - if (!Browser.fullscreenHandlersInstalled) { - Browser.fullscreenHandlersInstalled = true; - document.addEventListener('fullscreenchange', fullscreenChange, false); - document.addEventListener('mozfullscreenchange', fullscreenChange, false); - document.addEventListener('webkitfullscreenchange', fullscreenChange, false); - document.addEventListener('MSFullscreenChange', fullscreenChange, false); - } - - // create a new parent to ensure the canvas has no siblings. this allows browsers to optimize full screen performance when its parent is the full screen root - var canvasContainer = document.createElement("div"); - canvas.parentNode.insertBefore(canvasContainer, canvas); - canvasContainer.appendChild(canvas); - - // use parent of canvas as full screen root to allow aspect ratio correction (Firefox stretches the root to screen size) - canvasContainer.requestFullscreen = canvasContainer['requestFullscreen'] || - canvasContainer['mozRequestFullScreen'] || - canvasContainer['msRequestFullscreen'] || - (canvasContainer['webkitRequestFullscreen'] ? function() { canvasContainer['webkitRequestFullscreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null) || - (canvasContainer['webkitRequestFullScreen'] ? function() { canvasContainer['webkitRequestFullScreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null); - - if (vrDevice) { - canvasContainer.requestFullscreen({ vrDisplay: vrDevice }); - } else { - canvasContainer.requestFullscreen(); - } - }, - - requestFullScreen: function(lockPointer, resizeCanvas, vrDevice) { - Module.printErr('Browser.requestFullScreen() is deprecated. Please call Browser.requestFullscreen instead.'); - Browser.requestFullScreen = function(lockPointer, resizeCanvas, vrDevice) { - return Browser.requestFullscreen(lockPointer, resizeCanvas, vrDevice); - } - return Browser.requestFullscreen(lockPointer, resizeCanvas, vrDevice); - }, - - nextRAF: 0, - - fakeRequestAnimationFrame: function(func) { - // try to keep 60fps between calls to here - var now = Date.now(); - if (Browser.nextRAF === 0) { - Browser.nextRAF = now + 1000/60; - } else { - while (now + 2 >= Browser.nextRAF) { // fudge a little, to avoid timer jitter causing us to do lots of delay:0 - Browser.nextRAF += 1000/60; - } - } - var delay = Math.max(Browser.nextRAF - now, 0); - setTimeout(func, delay); - }, - - requestAnimationFrame: function requestAnimationFrame(func) { - if (typeof window === 'undefined') { // Provide fallback to setTimeout if window is undefined (e.g. in Node.js) - Browser.fakeRequestAnimationFrame(func); - } else { - if (!window.requestAnimationFrame) { - window.requestAnimationFrame = window['requestAnimationFrame'] || - window['mozRequestAnimationFrame'] || - window['webkitRequestAnimationFrame'] || - window['msRequestAnimationFrame'] || - window['oRequestAnimationFrame'] || - Browser.fakeRequestAnimationFrame; - } - window.requestAnimationFrame(func); - } - }, - - // generic abort-aware wrapper for an async callback - safeCallback: function(func) { - return function() { - if (!ABORT) return func.apply(null, arguments); - }; - }, - - // abort and pause-aware versions TODO: build main loop on top of this? - - allowAsyncCallbacks: true, - queuedAsyncCallbacks: [], - - pauseAsyncCallbacks: function() { - Browser.allowAsyncCallbacks = false; - }, - resumeAsyncCallbacks: function() { // marks future callbacks as ok to execute, and synchronously runs any remaining ones right now - Browser.allowAsyncCallbacks = true; - if (Browser.queuedAsyncCallbacks.length > 0) { - var callbacks = Browser.queuedAsyncCallbacks; - Browser.queuedAsyncCallbacks = []; - callbacks.forEach(function(func) { - func(); - }); - } - }, - - safeRequestAnimationFrame: function(func) { - return Browser.requestAnimationFrame(function() { - if (ABORT) return; - if (Browser.allowAsyncCallbacks) { - func(); - } else { - Browser.queuedAsyncCallbacks.push(func); - } - }); - }, - safeSetTimeout: function(func, timeout) { - Module['noExitRuntime'] = true; - return setTimeout(function() { - if (ABORT) return; - if (Browser.allowAsyncCallbacks) { - func(); - } else { - Browser.queuedAsyncCallbacks.push(func); - } - }, timeout); - }, - safeSetInterval: function(func, timeout) { - Module['noExitRuntime'] = true; - return setInterval(function() { - if (ABORT) return; - if (Browser.allowAsyncCallbacks) { - func(); - } // drop it on the floor otherwise, next interval will kick in - }, timeout); - }, - - getMimetype: function(name) { - return { - 'jpg': 'image/jpeg', - 'jpeg': 'image/jpeg', - 'png': 'image/png', - 'bmp': 'image/bmp', - 'ogg': 'audio/ogg', - 'wav': 'audio/wav', - 'mp3': 'audio/mpeg' - }[name.substr(name.lastIndexOf('.')+1)]; - }, - - getUserMedia: function(func) { - if(!window.getUserMedia) { - window.getUserMedia = navigator['getUserMedia'] || - navigator['mozGetUserMedia']; - } - window.getUserMedia(func); - }, - - - getMovementX: function(event) { - return event['movementX'] || - event['mozMovementX'] || - event['webkitMovementX'] || - 0; - }, - - getMovementY: function(event) { - return event['movementY'] || - event['mozMovementY'] || - event['webkitMovementY'] || - 0; - }, - - // Browsers specify wheel direction according to the page CSS pixel Y direction: - // Scrolling mouse wheel down (==towards user/away from screen) on Windows/Linux (and OSX without 'natural scroll' enabled) - // is the positive wheel direction. Scrolling mouse wheel up (towards the screen) is the negative wheel direction. - // This function returns the wheel direction in the browser page coordinate system (+: down, -: up). Note that this is often the - // opposite of native code: In native APIs the positive scroll direction is to scroll up (away from the user). - // NOTE: The mouse wheel delta is a decimal number, and can be a fractional value within -1 and 1. If you need to represent - // this as an integer, don't simply cast to int, or you may receive scroll events for wheel delta == 0. - getMouseWheelDelta: function(event) { - var delta = 0; - switch (event.type) { - case 'DOMMouseScroll': - delta = event.detail; - break; - case 'mousewheel': - delta = event.wheelDelta; - break; - case 'wheel': - delta = event['deltaY']; - break; - default: - throw 'unrecognized mouse wheel event: ' + event.type; - } - return delta; - }, - - mouseX: 0, - mouseY: 0, - mouseMovementX: 0, - mouseMovementY: 0, - touches: {}, - lastTouches: {}, - - calculateMouseEvent: function(event) { // event should be mousemove, mousedown or mouseup - if (Browser.pointerLock) { - // When the pointer is locked, calculate the coordinates - // based on the movement of the mouse. - // Workaround for Firefox bug 764498 - if (event.type != 'mousemove' && - ('mozMovementX' in event)) { - Browser.mouseMovementX = Browser.mouseMovementY = 0; - } else { - Browser.mouseMovementX = Browser.getMovementX(event); - Browser.mouseMovementY = Browser.getMovementY(event); - } - - // check if SDL is available - if (typeof SDL != "undefined") { - Browser.mouseX = SDL.mouseX + Browser.mouseMovementX; - Browser.mouseY = SDL.mouseY + Browser.mouseMovementY; - } else { - // just add the mouse delta to the current absolut mouse position - // FIXME: ideally this should be clamped against the canvas size and zero - Browser.mouseX += Browser.mouseMovementX; - Browser.mouseY += Browser.mouseMovementY; - } - } else { - // Otherwise, calculate the movement based on the changes - // in the coordinates. - var rect = Module["canvas"].getBoundingClientRect(); - var cw = Module["canvas"].width; - var ch = Module["canvas"].height; - - // Neither .scrollX or .pageXOffset are defined in a spec, but - // we prefer .scrollX because it is currently in a spec draft. - // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/) - var scrollX = ((typeof window.scrollX !== 'undefined') ? window.scrollX : window.pageXOffset); - var scrollY = ((typeof window.scrollY !== 'undefined') ? window.scrollY : window.pageYOffset); -#if ASSERTIONS - // If this assert lands, it's likely because the browser doesn't support scrollX or pageXOffset - // and we have no viable fallback. - assert((typeof scrollX !== 'undefined') && (typeof scrollY !== 'undefined'), 'Unable to retrieve scroll position, mouse positions likely broken.'); -#endif - - if (event.type === 'touchstart' || event.type === 'touchend' || event.type === 'touchmove') { - var touch = event.touch; - if (touch === undefined) { - return; // the "touch" property is only defined in SDL - - } - var adjustedX = touch.pageX - (scrollX + rect.left); - var adjustedY = touch.pageY - (scrollY + rect.top); - - adjustedX = adjustedX * (cw / rect.width); - adjustedY = adjustedY * (ch / rect.height); - - var coords = { x: adjustedX, y: adjustedY }; - - if (event.type === 'touchstart') { - Browser.lastTouches[touch.identifier] = coords; - Browser.touches[touch.identifier] = coords; - } else if (event.type === 'touchend' || event.type === 'touchmove') { - var last = Browser.touches[touch.identifier]; - if (!last) last = coords; - Browser.lastTouches[touch.identifier] = last; - Browser.touches[touch.identifier] = coords; - } - return; - } - - var x = event.pageX - (scrollX + rect.left); - var y = event.pageY - (scrollY + rect.top); - - // the canvas might be CSS-scaled compared to its backbuffer; - // SDL-using content will want mouse coordinates in terms - // of backbuffer units. - x = x * (cw / rect.width); - y = y * (ch / rect.height); - - Browser.mouseMovementX = x - Browser.mouseX; - Browser.mouseMovementY = y - Browser.mouseY; - Browser.mouseX = x; - Browser.mouseY = y; - } - }, - - asyncLoad: function(url, onload, onerror, noRunDep) { - var dep = !noRunDep ? getUniqueRunDependency('al ' + url) : ''; - Module['readAsync'](url, function(arrayBuffer) { - assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).'); - onload(new Uint8Array(arrayBuffer)); - if (dep) removeRunDependency(dep); - }, function(event) { - if (onerror) { - onerror(); - } else { - throw 'Loading data file "' + url + '" failed.'; - } - }); - if (dep) addRunDependency(dep); - }, - - resizeListeners: [], - - updateResizeListeners: function() { - var canvas = Module['canvas']; - Browser.resizeListeners.forEach(function(listener) { - listener(canvas.width, canvas.height); - }); - }, - - setCanvasSize: function(width, height, noUpdates) { - var canvas = Module['canvas']; - Browser.updateCanvasDimensions(canvas, width, height); - if (!noUpdates) Browser.updateResizeListeners(); - }, - - windowedWidth: 0, - windowedHeight: 0, - setFullscreenCanvasSize: function() { - // check if SDL is available - if (typeof SDL != "undefined") { - var flags = {{{ makeGetValue('SDL.screen', '0', 'i32', 0, 1) }}}; - flags = flags | 0x00800000; // set SDL_FULLSCREEN flag - {{{ makeSetValue('SDL.screen', '0', 'flags', 'i32') }}} - } - Browser.updateCanvasDimensions(Module['canvas']); - Browser.updateResizeListeners(); - }, - - setWindowedCanvasSize: function() { - // check if SDL is available - if (typeof SDL != "undefined") { - var flags = {{{ makeGetValue('SDL.screen', '0', 'i32', 0, 1) }}}; - flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag - {{{ makeSetValue('SDL.screen', '0', 'flags', 'i32') }}} - } - Browser.updateCanvasDimensions(Module['canvas']); - Browser.updateResizeListeners(); - }, - - updateCanvasDimensions : function(canvas, wNative, hNative) { - if (wNative && hNative) { - canvas.widthNative = wNative; - canvas.heightNative = hNative; - } else { - wNative = canvas.widthNative; - hNative = canvas.heightNative; - } - var w = wNative; - var h = hNative; - if (Module['forcedAspectRatio'] && Module['forcedAspectRatio'] > 0) { - if (w/h < Module['forcedAspectRatio']) { - w = Math.round(h * Module['forcedAspectRatio']); - } else { - h = Math.round(w / Module['forcedAspectRatio']); - } - } - if (((document['fullscreenElement'] || document['mozFullScreenElement'] || - document['msFullscreenElement'] || document['webkitFullscreenElement'] || - document['webkitCurrentFullScreenElement']) === canvas.parentNode) && (typeof screen != 'undefined')) { - var factor = Math.min(screen.width / w, screen.height / h); - w = Math.round(w * factor); - h = Math.round(h * factor); - } - if (Browser.resizeCanvas) { - if (canvas.width != w) canvas.width = w; - if (canvas.height != h) canvas.height = h; - if (typeof canvas.style != 'undefined') { - canvas.style.removeProperty( "width"); - canvas.style.removeProperty("height"); - } - } else { - if (canvas.width != wNative) canvas.width = wNative; - if (canvas.height != hNative) canvas.height = hNative; - if (typeof canvas.style != 'undefined') { - if (w != wNative || h != hNative) { - canvas.style.setProperty( "width", w + "px", "important"); - canvas.style.setProperty("height", h + "px", "important"); - } else { - canvas.style.removeProperty( "width"); - canvas.style.removeProperty("height"); - } - } - } - }, - - wgetRequests: {}, - nextWgetRequestHandle: 0, - - getNextWgetRequestHandle: function() { - var handle = Browser.nextWgetRequestHandle; - Browser.nextWgetRequestHandle++; - return handle; - } - }, - - emscripten_async_wget__deps: ['$PATH'], - emscripten_async_wget__proxy: 'sync', - emscripten_async_wget__sig: 'viiii', - emscripten_async_wget: function(url, file, onload, onerror) { - Module['noExitRuntime'] = true; - - var _url = Pointer_stringify(url); - var _file = Pointer_stringify(file); - _file = PATH.resolve(FS.cwd(), _file); - function doCallback(callback) { - if (callback) { - var stack = stackSave(); - Module['dynCall_vi'](callback, allocate(intArrayFromString(_file), 'i8', ALLOC_STACK)); - stackRestore(stack); - } - } - var destinationDirectory = PATH.dirname(_file); - FS.createPreloadedFile( - destinationDirectory, - PATH.basename(_file), - _url, true, true, - function() { - doCallback(onload); - }, - function() { - doCallback(onerror); - }, - false, // dontCreateFile - false, // canOwn - function() { // preFinish - // if a file exists there, we overwrite it - try { - FS.unlink(_file); - } catch (e) {} - // if the destination directory does not yet exist, create it - FS.mkdirTree(destinationDirectory); - } - ); - }, - - emscripten_async_wget_data__proxy: 'sync', - emscripten_async_wget_data__sig: 'viiii', - emscripten_async_wget_data: function(url, arg, onload, onerror) { - Browser.asyncLoad(Pointer_stringify(url), function(byteArray) { - var buffer = _malloc(byteArray.length); - HEAPU8.set(byteArray, buffer); - Module['dynCall_viii'](onload, arg, buffer, byteArray.length); - _free(buffer); - }, function() { - if (onerror) Module['dynCall_vi'](onerror, arg); - }, true /* no need for run dependency, this is async but will not do any prepare etc. step */ ); - }, - - emscripten_async_wget2__proxy: 'sync', - emscripten_async_wget2__sig: 'iiiiiiiii', - emscripten_async_wget2: function(url, file, request, param, arg, onload, onerror, onprogress) { - Module['noExitRuntime'] = true; - - var _url = Pointer_stringify(url); - var _file = Pointer_stringify(file); - _file = PATH.resolve(FS.cwd(), _file); - var _request = Pointer_stringify(request); - var _param = Pointer_stringify(param); - var index = _file.lastIndexOf('/'); - - var http = new XMLHttpRequest(); - http.open(_request, _url, true); - http.responseType = 'arraybuffer'; - - var handle = Browser.getNextWgetRequestHandle(); - - var destinationDirectory = PATH.dirname(_file); - - // LOAD - http.onload = function http_onload(e) { - if (http.status == 200) { - // if a file exists there, we overwrite it - try { - FS.unlink(_file); - } catch (e) {} - // if the destination directory does not yet exist, create it - FS.mkdirTree(destinationDirectory); - - FS.createDataFile( _file.substr(0, index), _file.substr(index + 1), new Uint8Array(http.response), true, true, false); - if (onload) { - var stack = stackSave(); - Module['dynCall_viii'](onload, handle, arg, allocate(intArrayFromString(_file), 'i8', ALLOC_STACK)); - stackRestore(stack); - } - } else { - if (onerror) Module['dynCall_viii'](onerror, handle, arg, http.status); - } - - delete Browser.wgetRequests[handle]; - }; - - // ERROR - http.onerror = function http_onerror(e) { - if (onerror) Module['dynCall_viii'](onerror, handle, arg, http.status); - delete Browser.wgetRequests[handle]; - }; - - // PROGRESS - http.onprogress = function http_onprogress(e) { - if (e.lengthComputable || (e.lengthComputable === undefined && e.total != 0)) { - var percentComplete = (e.loaded / e.total)*100; - if (onprogress) Module['dynCall_viii'](onprogress, handle, arg, percentComplete); - } - }; - - // ABORT - http.onabort = function http_onabort(e) { - delete Browser.wgetRequests[handle]; - }; - - if (_request == "POST") { - //Send the proper header information along with the request - http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); - http.send(_param); - } else { - http.send(null); - } - - Browser.wgetRequests[handle] = http; - - return handle; - }, - - emscripten_async_wget2_data__proxy: 'sync', - emscripten_async_wget2_data__sig: 'iiiiiiiii', - emscripten_async_wget2_data: function(url, request, param, arg, free, onload, onerror, onprogress) { - var _url = Pointer_stringify(url); - var _request = Pointer_stringify(request); - var _param = Pointer_stringify(param); - - var http = new XMLHttpRequest(); - http.open(_request, _url, true); - http.responseType = 'arraybuffer'; - - var handle = Browser.getNextWgetRequestHandle(); - - // LOAD - http.onload = function http_onload(e) { - if (http.status == 200 || _url.substr(0,4).toLowerCase() != "http") { - var byteArray = new Uint8Array(http.response); - var buffer = _malloc(byteArray.length); - HEAPU8.set(byteArray, buffer); - if (onload) Module['dynCall_viiii'](onload, handle, arg, buffer, byteArray.length); - if (free) _free(buffer); - } else { - if (onerror) Module['dynCall_viiii'](onerror, handle, arg, http.status, http.statusText); - } - delete Browser.wgetRequests[handle]; - }; - - // ERROR - http.onerror = function http_onerror(e) { - if (onerror) { - Module['dynCall_viiii'](onerror, handle, arg, http.status, http.statusText); - } - delete Browser.wgetRequests[handle]; - }; - - // PROGRESS - http.onprogress = function http_onprogress(e) { - if (onprogress) Module['dynCall_viiii'](onprogress, handle, arg, e.loaded, e.lengthComputable || e.lengthComputable === undefined ? e.total : 0); - }; - - // ABORT - http.onabort = function http_onabort(e) { - delete Browser.wgetRequests[handle]; - }; - - if (_request == "POST") { - //Send the proper header information along with the request - http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); - http.send(_param); - } else { - http.send(null); - } - - Browser.wgetRequests[handle] = http; - - return handle; - }, - - emscripten_async_wget2_abort__proxy: 'sync', - emscripten_async_wget2_abort__sig: 'vi', - emscripten_async_wget2_abort: function(handle) { - var http = Browser.wgetRequests[handle]; - if (http) { - http.abort(); - } - }, - - emscripten_run_preload_plugins__deps: ['$PATH'], - emscripten_run_preload_plugins__proxy: 'sync', - emscripten_run_preload_plugins__sig: 'iiii', - emscripten_run_preload_plugins: function(file, onload, onerror) { - Module['noExitRuntime'] = true; - - var _file = Pointer_stringify(file); - var data = FS.analyzePath(_file); - if (!data.exists) return -1; - FS.createPreloadedFile( - PATH.dirname(_file), - PATH.basename(_file), - new Uint8Array(data.object.contents), true, true, - function() { - if (onload) Module['dynCall_vi'](onload, file); - }, - function() { - if (onerror) Module['dynCall_vi'](onerror, file); - }, - true // don'tCreateFile - it's already there - ); - return 0; - }, - - emscripten_run_preload_plugins_data__proxy: 'sync', - emscripten_run_preload_plugins_data__sig: 'viiiiii', - emscripten_run_preload_plugins_data: function(data, size, suffix, arg, onload, onerror) { - Module['noExitRuntime'] = true; - - var _suffix = Pointer_stringify(suffix); - if (!Browser.asyncPrepareDataCounter) Browser.asyncPrepareDataCounter = 0; - var name = 'prepare_data_' + (Browser.asyncPrepareDataCounter++) + '.' + _suffix; - var lengthAsUTF8 = lengthBytesUTF8(name); - var cname = _malloc(lengthAsUTF8+1); - stringToUTF8(name, cname, lengthAsUTF8+1); - FS.createPreloadedFile( - '/', - name, - {{{ makeHEAPView('U8', 'data', 'data + size') }}}, - true, true, - function() { - if (onload) Module['dynCall_vii'](onload, arg, cname); - }, - function() { - if (onerror) Module['dynCall_vi'](onerror, arg); - }, - true // don'tCreateFile - it's already there - ); - }, - - // Callable from pthread, executes in pthread context. - emscripten_async_run_script__deps: ['emscripten_run_script'], - emscripten_async_run_script: function(script, millis) { - Module['noExitRuntime'] = true; - - // TODO: cache these to avoid generating garbage - Browser.safeSetTimeout(function() { - _emscripten_run_script(script); - }, millis); - }, - - // TODO: currently not callable from a pthread, but immediately calls onerror() if not on main thread. - emscripten_async_load_script: function(url, onload, onerror) { - onload = getFuncWrapper(onload, 'v'); - onerror = getFuncWrapper(onerror, 'v'); - -#if USE_PTHREADS - if (ENVIRONMENT_IS_PTHREAD) { - console.error('emscripten_async_load_script("' + Pointer_stringify(url) + '") failed, emscripten_async_load_script is currently not available in pthreads!'); - return onerror ? onerror() : undefined; - } -#endif - Module['noExitRuntime'] = true; - - assert(runDependencies === 0, 'async_load_script must be run when no other dependencies are active'); - var script = document.createElement('script'); - if (onload) { - script.onload = function script_onload() { - if (runDependencies > 0) { - dependenciesFulfilled = onload; - } else { - onload(); - } - }; - } - if (onerror) script.onerror = onerror; - script.src = Pointer_stringify(url); - document.body.appendChild(script); - }, - - // Runs natively in pthread, no __proxy needed. - emscripten_get_main_loop_timing: function(mode, value) { - if (mode) {{{ makeSetValue('mode', 0, 'Browser.mainLoop.timingMode', 'i32') }}}; - if (value) {{{ makeSetValue('value', 0, 'Browser.mainLoop.timingValue', 'i32') }}}; - }, - - // Runs natively in pthread, no __proxy needed. - emscripten_set_main_loop_timing: function(mode, value) { - Browser.mainLoop.timingMode = mode; - Browser.mainLoop.timingValue = value; - - if (!Browser.mainLoop.func) { -#if ASSERTIONS - console.error('emscripten_set_main_loop_timing: Cannot set timing mode for main loop since a main loop does not exist! Call emscripten_set_main_loop first to set one up.'); -#endif - return 1; // Return non-zero on failure, can't set timing mode when there is no main loop. - } - - if (mode == 0 /*EM_TIMING_SETTIMEOUT*/) { - Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_setTimeout() { - var timeUntilNextTick = Math.max(0, Browser.mainLoop.tickStartTime + value - _emscripten_get_now())|0; - setTimeout(Browser.mainLoop.runner, timeUntilNextTick); // doing this each time means that on exception, we stop - }; - Browser.mainLoop.method = 'timeout'; - } else if (mode == 1 /*EM_TIMING_RAF*/) { - Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_rAF() { - Browser.requestAnimationFrame(Browser.mainLoop.runner); - }; - Browser.mainLoop.method = 'rAF'; - } else if (mode == 2 /*EM_TIMING_SETIMMEDIATE*/) { - if (typeof setImmediate === 'undefined') { - // Emulate setImmediate. (note: not a complete polyfill, we don't emulate clearImmediate() to keep code size to minimum, since not needed) - var setImmediates = []; - var emscriptenMainLoopMessageId = 'setimmediate'; - function Browser_setImmediate_messageHandler(event) { - // When called in current thread or Worker, the main loop ID is structured slightly different to accommodate for --proxy-to-worker runtime listening to Worker events, - // so check for both cases. - if (event.data === emscriptenMainLoopMessageId || event.data.target === emscriptenMainLoopMessageId) { - event.stopPropagation(); - setImmediates.shift()(); - } - } - addEventListener("message", Browser_setImmediate_messageHandler, true); - setImmediate = function Browser_emulated_setImmediate(func) { - setImmediates.push(func); - if (ENVIRONMENT_IS_WORKER) { - if (Module['setImmediates'] === undefined) Module['setImmediates'] = []; - Module['setImmediates'].push(func); - postMessage({target: emscriptenMainLoopMessageId}); // In --proxy-to-worker, route the message via proxyClient.js - } else postMessage(emscriptenMainLoopMessageId, "*"); // On the main thread, can just send the message to itself. - } - } - Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_setImmediate() { - setImmediate(Browser.mainLoop.runner); - }; - Browser.mainLoop.method = 'immediate'; - } - return 0; - }, - - // Runs natively in pthread, no __proxy needed. - emscripten_set_main_loop__deps: ['emscripten_set_main_loop_timing', 'emscripten_get_now'], - emscripten_set_main_loop: function(func, fps, simulateInfiniteLoop, arg, noSetTiming) { - Module['noExitRuntime'] = true; - - assert(!Browser.mainLoop.func, 'emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.'); - - Browser.mainLoop.func = func; - Browser.mainLoop.arg = arg; - - var browserIterationFunc; - if (typeof arg !== 'undefined') { - browserIterationFunc = function() { - Module['dynCall_vi'](func, arg); - }; - } else { - browserIterationFunc = function() { - Module['dynCall_v'](func); - }; - } - - var thisMainLoopId = Browser.mainLoop.currentlyRunningMainloop; - - Browser.mainLoop.runner = function Browser_mainLoop_runner() { - if (ABORT) return; - if (Browser.mainLoop.queue.length > 0) { - var start = Date.now(); - var blocker = Browser.mainLoop.queue.shift(); - blocker.func(blocker.arg); - if (Browser.mainLoop.remainingBlockers) { - var remaining = Browser.mainLoop.remainingBlockers; - var next = remaining%1 == 0 ? remaining-1 : Math.floor(remaining); - if (blocker.counted) { - Browser.mainLoop.remainingBlockers = next; - } else { - // not counted, but move the progress along a tiny bit - next = next + 0.5; // do not steal all the next one's progress - Browser.mainLoop.remainingBlockers = (8*remaining + next)/9; - } - } - console.log('main loop blocker "' + blocker.name + '" took ' + (Date.now() - start) + ' ms'); //, left: ' + Browser.mainLoop.remainingBlockers); - Browser.mainLoop.updateStatus(); - - // catches pause/resume main loop from blocker execution - if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return; - - setTimeout(Browser.mainLoop.runner, 0); - return; - } - - // catch pauses from non-main loop sources - if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return; - - // Implement very basic swap interval control - Browser.mainLoop.currentFrameNumber = Browser.mainLoop.currentFrameNumber + 1 | 0; - if (Browser.mainLoop.timingMode == 1/*EM_TIMING_RAF*/ && Browser.mainLoop.timingValue > 1 && Browser.mainLoop.currentFrameNumber % Browser.mainLoop.timingValue != 0) { - // Not the scheduled time to render this frame - skip. - Browser.mainLoop.scheduler(); - return; - } else if (Browser.mainLoop.timingMode == 0/*EM_TIMING_SETTIMEOUT*/) { - Browser.mainLoop.tickStartTime = _emscripten_get_now(); - } - - // Signal GL rendering layer that processing of a new frame is about to start. This helps it optimize - // VBO double-buffering and reduce GPU stalls. -#if USES_GL_EMULATION - GL.newRenderingFrameStarted(); -#endif - -#if OFFSCREENCANVAS_SUPPORT - // If the current GL context is an OffscreenCanvas, but it was initialized with implicit swap mode, perform the swap - // in behalf of the user. - if (typeof GL !== 'undefined' && GL.currentContext && !GL.currentContext.attributes.explicitSwapControl && GL.currentContext.GLctx.commit) { - GL.currentContext.GLctx.commit(); - } -#endif - - if (Browser.mainLoop.method === 'timeout' && Module.ctx) { - Module.printErr('Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!'); - Browser.mainLoop.method = ''; // just warn once per call to set main loop - } - - Browser.mainLoop.runIter(browserIterationFunc); - -#if STACK_OVERFLOW_CHECK - checkStackCookie(); -#endif - - // catch pauses from the main loop itself - if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return; - - // Queue new audio data. This is important to be right after the main loop invocation, so that we will immediately be able - // to queue the newest produced audio samples. - // TODO: Consider adding pre- and post- rAF callbacks so that GL.newRenderingFrameStarted() and SDL.audio.queueNewAudioData() - // do not need to be hardcoded into this function, but can be more generic. - if (typeof SDL === 'object' && SDL.audio && SDL.audio.queueNewAudioData) SDL.audio.queueNewAudioData(); - - Browser.mainLoop.scheduler(); - } - - if (!noSetTiming) { - if (fps && fps > 0) _emscripten_set_main_loop_timing(0/*EM_TIMING_SETTIMEOUT*/, 1000.0 / fps); - else _emscripten_set_main_loop_timing(1/*EM_TIMING_RAF*/, 1); // Do rAF by rendering each frame (no decimating) - - Browser.mainLoop.scheduler(); - } - - if (simulateInfiniteLoop) { - throw 'SimulateInfiniteLoop'; - } - }, - - // Runs natively in pthread, no __proxy needed. - emscripten_set_main_loop_arg__deps: ['emscripten_set_main_loop'], - emscripten_set_main_loop_arg: function(func, arg, fps, simulateInfiniteLoop) { - _emscripten_set_main_loop(func, fps, simulateInfiniteLoop, arg); - }, - - // Runs natively in pthread, no __proxy needed. - emscripten_cancel_main_loop: function() { - Browser.mainLoop.pause(); - Browser.mainLoop.func = null; - }, - - // Runs natively in pthread, no __proxy needed. - emscripten_pause_main_loop: function() { - Browser.mainLoop.pause(); - }, - - // Runs natively in pthread, no __proxy needed. - emscripten_resume_main_loop: function() { - Browser.mainLoop.resume(); - }, - - // Runs natively in pthread, no __proxy needed. - _emscripten_push_main_loop_blocker: function(func, arg, name) { - Browser.mainLoop.queue.push({ func: function() { - Module['dynCall_vi'](func, arg); - }, name: Pointer_stringify(name), counted: true }); - Browser.mainLoop.updateStatus(); - }, - - // Runs natively in pthread, no __proxy needed. - _emscripten_push_uncounted_main_loop_blocker: function(func, arg, name) { - Browser.mainLoop.queue.push({ func: function() { - Module['dynCall_vi'](func, arg); - }, name: Pointer_stringify(name), counted: false }); - Browser.mainLoop.updateStatus(); - }, - - // Runs natively in pthread, no __proxy needed. - emscripten_set_main_loop_expected_blockers: function(num) { - Browser.mainLoop.expectedBlockers = num; - Browser.mainLoop.remainingBlockers = num; - Browser.mainLoop.updateStatus(); - }, - - // Runs natively in pthread, no __proxy needed. - emscripten_async_call: function(func, arg, millis) { - Module['noExitRuntime'] = true; - - function wrapper() { - getFuncWrapper(func, 'vi')(arg); - } - - if (millis >= 0) { - Browser.safeSetTimeout(wrapper, millis); - } else { - Browser.safeRequestAnimationFrame(wrapper); - } - }, - - // Callable in pthread without __proxy needed. - emscripten_exit_with_live_runtime: function() { - Module['noExitRuntime'] = true; - throw 'SimulateInfiniteLoop'; - }, - - emscripten_force_exit__proxy: 'sync', - emscripten_force_exit__sig: 'vi', - emscripten_force_exit: function(status) { -#if NO_EXIT_RUNTIME -#if ASSERTIONS - warnOnce('emscripten_force_exit cannot actually shut down the runtime, as the build has NO_EXIT_RUNTIME set'); -#endif -#endif - Module['noExitRuntime'] = false; - Module['exit'](status); - }, - - emscripten_get_device_pixel_ratio__proxy: 'sync', - emscripten_get_device_pixel_ratio__sig: 'd', - emscripten_get_device_pixel_ratio: function() { - return window.devicePixelRatio || 1.0; - }, - - emscripten_hide_mouse__proxy: 'sync', - emscripten_hide_mouse__sig: 'v', - emscripten_hide_mouse: function() { - var styleSheet = document.styleSheets[0]; - var rules = styleSheet.cssRules; - for (var i = 0; i < rules.length; i++) { - if (rules[i].cssText.substr(0, 6) == 'canvas') { - styleSheet.deleteRule(i); - i--; - } - } - styleSheet.insertRule('canvas.emscripten { border: 1px solid black; cursor: none; }', 0); - }, - - emscripten_set_canvas_size__proxy: 'sync', - emscripten_set_canvas_size__sig: 'vii', - emscripten_set_canvas_size: function(width, height) { - Browser.setCanvasSize(width, height); - }, - - emscripten_get_canvas_size__proxy: 'sync', - emscripten_get_canvas_size__sig: 'viii', - emscripten_get_canvas_size: function(width, height, isFullscreen) { - var canvas = Module['canvas']; - {{{ makeSetValue('width', '0', 'canvas.width', 'i32') }}}; - {{{ makeSetValue('height', '0', 'canvas.height', 'i32') }}}; - {{{ makeSetValue('isFullscreen', '0', 'Browser.isFullscreen ? 1 : 0', 'i32') }}}; - }, - - // To avoid creating worker parent->child chains, always proxies to execute on the main thread. - emscripten_create_worker__proxy: 'sync', - emscripten_create_worker__sig: 'ii', - emscripten_create_worker: function(url) { - url = Pointer_stringify(url); - var id = Browser.workers.length; - var info = { - worker: new Worker(url), - callbacks: [], - awaited: 0, - buffer: 0, - bufferSize: 0 - }; - info.worker.onmessage = function info_worker_onmessage(msg) { - if (ABORT) return; - var info = Browser.workers[id]; - if (!info) return; // worker was destroyed meanwhile - var callbackId = msg.data['callbackId']; - var callbackInfo = info.callbacks[callbackId]; - if (!callbackInfo) return; // no callback or callback removed meanwhile - // Don't trash our callback state if we expect additional calls. - if (msg.data['finalResponse']) { - info.awaited--; - info.callbacks[callbackId] = null; // TODO: reuse callbackIds, compress this - } - var data = msg.data['data']; - if (data) { - if (!data.byteLength) data = new Uint8Array(data); - if (!info.buffer || info.bufferSize < data.length) { - if (info.buffer) _free(info.buffer); - info.bufferSize = data.length; - info.buffer = _malloc(data.length); - } - HEAPU8.set(data, info.buffer); - callbackInfo.func(info.buffer, data.length, callbackInfo.arg); - } else { - callbackInfo.func(0, 0, callbackInfo.arg); - } - }; - Browser.workers.push(info); - return id; - }, - - emscripten_destroy_worker__proxy: 'sync', - emscripten_destroy_worker__sig: 'vi', - emscripten_destroy_worker: function(id) { - var info = Browser.workers[id]; - info.worker.terminate(); - if (info.buffer) _free(info.buffer); - Browser.workers[id] = null; - }, - - emscripten_call_worker__proxy: 'sync', - emscripten_call_worker__sig: 'viiiiii', - emscripten_call_worker: function(id, funcName, data, size, callback, arg) { - Module['noExitRuntime'] = true; // should we only do this if there is a callback? - - funcName = Pointer_stringify(funcName); - var info = Browser.workers[id]; - var callbackId = -1; - if (callback) { - callbackId = info.callbacks.length; - info.callbacks.push({ - func: getFuncWrapper(callback, 'viii'), - arg: arg - }); - info.awaited++; - } - var transferObject = { - 'funcName': funcName, - 'callbackId': callbackId, - 'data': data ? new Uint8Array({{{ makeHEAPView('U8', 'data', 'data + size') }}}) : 0 - }; - if (data) { - info.worker.postMessage(transferObject, [transferObject.data.buffer]); - } else { - info.worker.postMessage(transferObject); - } - }, - - emscripten_worker_respond_provisionally__proxy: 'sync', - emscripten_worker_respond_provisionally__sig: 'vii', - emscripten_worker_respond_provisionally: function(data, size) { - if (workerResponded) throw 'already responded with final response!'; - var transferObject = { - 'callbackId': workerCallbackId, - 'finalResponse': false, - 'data': data ? new Uint8Array({{{ makeHEAPView('U8', 'data', 'data + size') }}}) : 0 - }; - if (data) { - postMessage(transferObject, [transferObject.data.buffer]); - } else { - postMessage(transferObject); - } - }, - - emscripten_worker_respond__proxy: 'sync', - emscripten_worker_respond__sig: 'vii', - emscripten_worker_respond: function(data, size) { - if (workerResponded) throw 'already responded with final response!'; - workerResponded = true; - var transferObject = { - 'callbackId': workerCallbackId, - 'finalResponse': true, - 'data': data ? new Uint8Array({{{ makeHEAPView('U8', 'data', 'data + size') }}}) : 0 - }; - if (data) { - postMessage(transferObject, [transferObject.data.buffer]); - } else { - postMessage(transferObject); - } - }, - - emscripten_get_worker_queue_size__proxy: 'sync', - emscripten_get_worker_queue_size__sig: 'i', - emscripten_get_worker_queue_size: function(id) { - var info = Browser.workers[id]; - if (!info) return -1; - return info.awaited; - }, - - emscripten_get_preloaded_image_data__deps: ['$PATH'], - emscripten_get_preloaded_image_data__proxy: 'sync', - emscripten_get_preloaded_image_data__sig: 'iiii', - emscripten_get_preloaded_image_data: function(path, w, h) { - if (typeof path === "number") { - path = Pointer_stringify(path); - } - - path = PATH.resolve(path); - - var canvas = Module["preloadedImages"][path]; - if (canvas) { - var ctx = canvas.getContext("2d"); - var image = ctx.getImageData(0, 0, canvas.width, canvas.height); - var buf = _malloc(canvas.width * canvas.height * 4); - - HEAPU8.set(image.data, buf); - - {{{ makeSetValue('w', '0', 'canvas.width', 'i32') }}}; - {{{ makeSetValue('h', '0', 'canvas.height', 'i32') }}}; - return buf; - } - - return 0; - }, - - emscripten_get_preloaded_image_data_from_FILE__deps: ['emscripten_get_preloaded_image_data'], - emscripten_get_preloaded_image_data_from_FILE__proxy: 'sync', - emscripten_get_preloaded_image_data_from_FILE__sig: 'iiii', - emscripten_get_preloaded_image_data_from_FILE: function(file, w, h) { - var fd = Module['_fileno'](file); - var stream = FS.getStream(fd); - if (stream) { - return _emscripten_get_preloaded_image_data(stream.path, w, h); - } - - return 0; - } -}; - -autoAddDeps(LibraryBrowser, '$Browser'); - -mergeInto(LibraryManager.library, LibraryBrowser); - -/* Useful stuff for browser debugging - -function slowLog(label, text) { - if (!slowLog.labels) slowLog.labels = {}; - if (!slowLog.labels[label]) slowLog.labels[label] = 0; - var now = Date.now(); - if (now - slowLog.labels[label] > 1000) { - Module.print(label + ': ' + text); - slowLog.labels[label] = now; - } -} - -*/ - diff --git a/emsdk/files/preamble.js b/emsdk/files/preamble.js deleted file mode 100644 index bfc65f590..000000000 --- a/emsdk/files/preamble.js +++ /dev/null @@ -1,2482 +0,0 @@ -// === Preamble library stuff === - -// Documentation for the public APIs defined in this file must be updated in: -// site/source/docs/api_reference/preamble.js.rst -// A prebuilt local version of the documentation is available at: -// site/build/text/docs/api_reference/preamble.js.txt -// You can also build docs locally as HTML or other formats in site/ -// An online HTML version (which may be of a different version of Emscripten) -// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html - -#if BENCHMARK -Module.realPrint = Module.print; -Module.print = Module.printErr = function(){}; -#endif - -#if SAFE_HEAP -function getSafeHeapType(bytes, isFloat) { - switch (bytes) { - case 1: return 'i8'; - case 2: return 'i16'; - case 4: return isFloat ? 'float' : 'i32'; - case 8: return 'double'; - default: assert(0); - } -} - -#if SAFE_HEAP_LOG -var SAFE_HEAP_COUNTER = 0; -#endif - -function SAFE_HEAP_STORE(dest, value, bytes, isFloat) { -#if SAFE_HEAP_LOG - Module.print('SAFE_HEAP store: ' + [dest, value, bytes, isFloat, SAFE_HEAP_COUNTER++]); -#endif - if (dest <= 0) abort('segmentation fault storing ' + bytes + ' bytes to address ' + dest); - if (dest % bytes !== 0) abort('alignment error storing to address ' + dest + ', which was expected to be aligned to a multiple of ' + bytes); - if (staticSealed) { - if (dest + bytes > HEAP32[DYNAMICTOP_PTR>>2]) abort('segmentation fault, exceeded the top of the available dynamic heap when storing ' + bytes + ' bytes to address ' + dest + '. STATICTOP=' + STATICTOP + ', DYNAMICTOP=' + HEAP32[DYNAMICTOP_PTR>>2]); - assert(DYNAMICTOP_PTR); - assert(HEAP32[DYNAMICTOP_PTR>>2] <= TOTAL_MEMORY); - } else { - if (dest + bytes > STATICTOP) abort('segmentation fault, exceeded the top of the available static heap when storing ' + bytes + ' bytes to address ' + dest + '. STATICTOP=' + STATICTOP); - } - 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) { - if (dest <= 0) abort('segmentation fault loading ' + bytes + ' bytes from address ' + dest); - if (dest % bytes !== 0) abort('alignment error loading from address ' + dest + ', which was expected to be aligned to a multiple of ' + bytes); - if (staticSealed) { - if (dest + bytes > HEAP32[DYNAMICTOP_PTR>>2]) abort('segmentation fault, exceeded the top of the available dynamic heap when loading ' + bytes + ' bytes from address ' + dest + '. STATICTOP=' + STATICTOP + ', DYNAMICTOP=' + HEAP32[DYNAMICTOP_PTR>>2]); - assert(DYNAMICTOP_PTR); - assert(HEAP32[DYNAMICTOP_PTR>>2] <= TOTAL_MEMORY); - } else { - if (dest + bytes > STATICTOP) abort('segmentation fault, exceeded the top of the available static heap when loading ' + bytes + ' bytes from address ' + dest + '. STATICTOP=' + STATICTOP); - } - var type = getSafeHeapType(bytes, isFloat); - var ret = getValue(dest, type, 1); - if (unsigned) ret = unSign(ret, parseInt(type.substr(1)), 1); -#if SAFE_HEAP_LOG - Module.print('SAFE_HEAP load: ' + [dest, ret, bytes, isFloat, unsigned, SAFE_HEAP_COUNTER++]); -#endif - return ret; -} -function SAFE_HEAP_LOAD_D(dest, bytes, unsigned) { - return SAFE_HEAP_LOAD(dest, bytes, unsigned, true); -} - -function SAFE_FT_MASK(value, mask) { - var ret = value & mask; - if (ret !== value) { - abort('Function table mask error: function pointer is ' + value + ' which is masked by ' + mask + ', the likely cause of this is that the function pointer is being called by the wrong type.'); - } - return ret; -} - -function segfault() { - abort('segmentation fault'); -} -function alignfault() { - abort('alignment fault'); -} -function ftfault() { - abort('Function table mask error'); -} -#endif - -//======================================== -// Runtime essentials -//======================================== - -var ABORT = 0; // whether we are quitting the application. no code should run after this. set in exit() and abort() -var EXITSTATUS = 0; - -/** @type {function(*, string=)} */ -function assert(condition, text) { - if (!condition) { - abort('Assertion failed: ' + text); - } -} - -var globalScope = this; - -// Returns the C function with a specified identifier (for C++, you need to do manual name mangling) -function getCFunc(ident) { - var func = Module['_' + ident]; // closure exported function - assert(func, 'Cannot call unknown function ' + ident + ', make sure it is exported'); - return func; -} - -var JSfuncs = { - // Helpers for cwrap -- it can't refer to Runtime directly because it might - // be renamed by closure, instead it calls JSfuncs['stackSave'].body to find - // out what the minified function name is. - 'stackSave': function() { - stackSave() - }, - 'stackRestore': function() { - stackRestore() - }, - // type conversion from js to c - 'arrayToC' : function(arr) { - var ret = stackAlloc(arr.length); - writeArrayToMemory(arr, ret); - return ret; - }, - 'stringToC' : function(str) { - var ret = 0; - if (str !== null && str !== undefined && str !== 0) { // null string - // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0' - var len = (str.length << 2) + 1; - ret = stackAlloc(len); - stringToUTF8(str, ret, len); - } - return ret; - } -}; - -// For fast lookup of conversion functions -var toC = { - 'string': JSfuncs['stringToC'], 'array': JSfuncs['arrayToC'] -}; - -// C calling interface. -function ccall (ident, returnType, argTypes, args, opts) { - var func = getCFunc(ident); - var cArgs = []; - var stack = 0; -#if ASSERTIONS - assert(returnType !== 'array', 'Return type should not be "array".'); -#endif - if (args) { - for (var i = 0; i < args.length; i++) { - var converter = toC[argTypes[i]]; - if (converter) { - if (stack === 0) stack = stackSave(); - cArgs[i] = converter(args[i]); - } else { - cArgs[i] = args[i]; - } - } - } - var ret = func.apply(null, cArgs); -#if ASSERTIONS -#if EMTERPRETIFY_ASYNC - if ((!opts || !opts.async) && typeof EmterpreterAsync === 'object') { - assert(!EmterpreterAsync.state, 'cannot start async op with normal JS calling ccall'); - } - if (opts && opts.async) assert(!returnType, 'async ccalls cannot return values'); -#endif -#endif - if (returnType === 'string') ret = Pointer_stringify(ret); - else if (returnType === 'boolean') ret = Boolean(ret); - if (stack !== 0) { -#if EMTERPRETIFY_ASYNC - if (opts && opts.async) { - EmterpreterAsync.asyncFinalizers.push(function() { - stackRestore(stack); - }); - return; - } -#endif - stackRestore(stack); - } - return ret; -} - -function cwrap (ident, returnType, argTypes) { - argTypes = argTypes || []; - var cfunc = getCFunc(ident); - // When the function takes numbers and returns a number, we can just return - // the original function - var numericArgs = argTypes.every(function(type){ return type === 'number'}); - var numericRet = returnType !== 'string'; - if (numericRet && numericArgs) { - return cfunc; - } - return function() { - return ccall(ident, returnType, argTypes, arguments); - } -} - -/** @type {function(number, number, string, boolean=)} */ -function setValue(ptr, value, type, noSafe) { - type = type || 'i8'; - if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit -#if SAFE_HEAP - if (noSafe) { - switch(type) { - case 'i1': {{{ makeSetValue('ptr', '0', 'value', 'i1', undefined, undefined, undefined, '1') }}}; break; - case 'i8': {{{ makeSetValue('ptr', '0', 'value', 'i8', undefined, undefined, undefined, '1') }}}; break; - case 'i16': {{{ makeSetValue('ptr', '0', 'value', 'i16', undefined, undefined, undefined, '1') }}}; break; - case 'i32': {{{ makeSetValue('ptr', '0', 'value', 'i32', undefined, undefined, undefined, '1') }}}; break; - case 'i64': {{{ makeSetValue('ptr', '0', 'value', 'i64', undefined, undefined, undefined, '1') }}}; break; - case 'float': {{{ makeSetValue('ptr', '0', 'value', 'float', undefined, undefined, undefined, '1') }}}; break; - case 'double': {{{ makeSetValue('ptr', '0', 'value', 'double', undefined, undefined, undefined, '1') }}}; break; - default: abort('invalid type for setValue: ' + type); - } - } else { -#endif - switch(type) { - case 'i1': {{{ makeSetValue('ptr', '0', 'value', 'i1') }}}; break; - case 'i8': {{{ makeSetValue('ptr', '0', 'value', 'i8') }}}; break; - case 'i16': {{{ makeSetValue('ptr', '0', 'value', 'i16') }}}; break; - case 'i32': {{{ makeSetValue('ptr', '0', 'value', 'i32') }}}; break; - case 'i64': {{{ makeSetValue('ptr', '0', 'value', 'i64') }}}; break; - case 'float': {{{ makeSetValue('ptr', '0', 'value', 'float') }}}; break; - case 'double': {{{ makeSetValue('ptr', '0', 'value', 'double') }}}; break; - default: abort('invalid type for setValue: ' + type); - } -#if SAFE_HEAP - } -#endif -} - -/** @type {function(number, string, boolean=)} */ -function getValue(ptr, type, noSafe) { - type = type || 'i8'; - if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit -#if SAFE_HEAP - if (noSafe) { - switch(type) { - case 'i1': return {{{ makeGetValue('ptr', '0', 'i1', undefined, undefined, undefined, undefined, '1') }}}; - case 'i8': return {{{ makeGetValue('ptr', '0', 'i8', undefined, undefined, undefined, undefined, '1') }}}; - case 'i16': return {{{ makeGetValue('ptr', '0', 'i16', undefined, undefined, undefined, undefined, '1') }}}; - case 'i32': return {{{ makeGetValue('ptr', '0', 'i32', undefined, undefined, undefined, undefined, '1') }}}; - case 'i64': return {{{ makeGetValue('ptr', '0', 'i64', undefined, undefined, undefined, undefined, '1') }}}; - case 'float': return {{{ makeGetValue('ptr', '0', 'float', undefined, undefined, undefined, undefined, '1') }}}; - case 'double': return {{{ makeGetValue('ptr', '0', 'double', undefined, undefined, undefined, undefined, '1') }}}; - default: abort('invalid type for getValue: ' + type); - } - } else { -#endif - switch(type) { - case 'i1': return {{{ makeGetValue('ptr', '0', 'i1') }}}; - case 'i8': return {{{ makeGetValue('ptr', '0', 'i8') }}}; - case 'i16': return {{{ makeGetValue('ptr', '0', 'i16') }}}; - case 'i32': return {{{ makeGetValue('ptr', '0', 'i32') }}}; - case 'i64': return {{{ makeGetValue('ptr', '0', 'i64') }}}; - case 'float': return {{{ makeGetValue('ptr', '0', 'float') }}}; - case 'double': return {{{ makeGetValue('ptr', '0', 'double') }}}; - default: abort('invalid type for getValue: ' + type); - } -#if SAFE_HEAP - } -#endif - return null; -} - -var ALLOC_NORMAL = 0; // Tries to use _malloc() -var ALLOC_STACK = 1; // Lives for the duration of the current function call -var ALLOC_STATIC = 2; // Cannot be freed -var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk -var ALLOC_NONE = 4; // Do not allocate - -// allocate(): This is for internal use. You can use it yourself as well, but the interface -// is a little tricky (see docs right below). The reason is that it is optimized -// for multiple syntaxes to save space in generated code. So you should -// normally not use allocate(), and instead allocate memory using _malloc(), -// initialize it with setValue(), and so forth. -// @slab: An array of data, or a number. If a number, then the size of the block to allocate, -// in *bytes* (note that this is sometimes confusing: the next parameter does not -// affect this!) -// @types: Either an array of types, one for each byte (or 0 if no type at that position), -// or a single type which is used for the entire block. This only matters if there -// is initial data - if @slab is a number, then this does not matter at all and is -// ignored. -// @allocator: How to allocate memory, see ALLOC_* -/** @type {function((TypedArray|Array|number), string, number, number=)} */ -function allocate(slab, types, allocator, ptr) { - var zeroinit, size; - if (typeof slab === 'number') { - zeroinit = true; - size = slab; - } else { - zeroinit = false; - size = slab.length; - } - - var singleType = typeof types === 'string' ? types : null; - - var ret; - if (allocator == ALLOC_NONE) { - ret = ptr; - } else { - ret = [typeof _malloc === 'function' ? _malloc : staticAlloc, stackAlloc, staticAlloc, dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length)); - } - - if (zeroinit) { - var stop; - ptr = ret; - assert((ret & 3) == 0); - stop = ret + (size & ~3); - for (; ptr < stop; ptr += 4) { - {{{ makeSetValue('ptr', '0', '0', 'i32', null, true) }}}; - } - stop = ret + size; - while (ptr < stop) { - {{{ makeSetValue('ptr++', '0', '0', 'i8', null, true) }}}; - } - return ret; - } - - if (singleType === 'i8') { - if (slab.subarray || slab.slice) { - HEAPU8.set(/** @type {!Uint8Array} */ (slab), ret); - } else { - HEAPU8.set(new Uint8Array(slab), ret); - } - return ret; - } - - var i = 0, type, typeSize, previousType; - while (i < size) { - var curr = slab[i]; - - type = singleType || types[i]; - if (type === 0) { - i++; - continue; - } -#if ASSERTIONS - assert(type, 'Must know what type to store in allocate!'); -#endif - - if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later - - setValue(ret+i, curr, type); - - // no need to look up size unless type changes, so cache it - if (previousType !== type) { - typeSize = getNativeTypeSize(type); - previousType = type; - } - i += typeSize; - } - - return ret; -} - -// Allocate memory during any stage of startup - static memory early on, dynamic memory later, malloc when ready -function getMemory(size) { - if (!staticSealed) return staticAlloc(size); - if (!runtimeInitialized) return dynamicAlloc(size); - return _malloc(size); -} - -/** @type {function(number, number=)} */ -function Pointer_stringify(ptr, length) { - if (length === 0 || !ptr) return ''; - // Find the length, and check for UTF while doing so - var hasUtf = 0; - var t; - var i = 0; - while (1) { -#if ASSERTIONS - assert(ptr + i < TOTAL_MEMORY); -#endif - t = {{{ makeGetValue('ptr', 'i', 'i8', 0, 1) }}}; - hasUtf |= t; - if (t == 0 && !length) break; - i++; - if (length && i == length) break; - } - if (!length) length = i; - - var ret = ''; - - if (hasUtf < 128) { - var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack - var curr; - while (length > 0) { - curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK))); - ret = ret ? ret + curr : curr; - ptr += MAX_CHUNK; - length -= MAX_CHUNK; - } - return ret; - } - return UTF8ToString(ptr); -} - -// Given a pointer 'ptr' to a null-terminated ASCII-encoded string in the emscripten HEAP, returns -// a copy of that string as a Javascript String object. - -function AsciiToString(ptr) { - var str = ''; - while (1) { - var ch = {{{ makeGetValue('ptr++', 0, 'i8') }}}; - if (!ch) return str; - str += String.fromCharCode(ch); - } -} - -// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', -// null-terminated and encoded in ASCII form. The copy will require at most str.length+1 bytes of space in the HEAP. - -function stringToAscii(str, outPtr) { - return writeAsciiToMemory(str, outPtr, false); -} - -// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the given array that contains uint8 values, returns -// a copy of that string as a Javascript String object. - -#if TEXTDECODER -var UTF8Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf8') : undefined; -#endif -function UTF8ArrayToString(u8Array, idx) { -#if TEXTDECODER - var endPtr = idx; - // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself. - // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage. - while (u8Array[endPtr]) ++endPtr; - - if (endPtr - idx > 16 && u8Array.subarray && UTF8Decoder) { - return UTF8Decoder.decode(u8Array.subarray(idx, endPtr)); - } else { -#endif - var u0, u1, u2, u3, u4, u5; - - var str = ''; - while (1) { - // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629 - u0 = u8Array[idx++]; - if (!u0) return str; - if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; } - u1 = u8Array[idx++] & 63; - if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; } - u2 = u8Array[idx++] & 63; - if ((u0 & 0xF0) == 0xE0) { - u0 = ((u0 & 15) << 12) | (u1 << 6) | u2; - } else { - u3 = u8Array[idx++] & 63; - if ((u0 & 0xF8) == 0xF0) { - u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | u3; - } else { - u4 = u8Array[idx++] & 63; - if ((u0 & 0xFC) == 0xF8) { - u0 = ((u0 & 3) << 24) | (u1 << 18) | (u2 << 12) | (u3 << 6) | u4; - } else { - u5 = u8Array[idx++] & 63; - u0 = ((u0 & 1) << 30) | (u1 << 24) | (u2 << 18) | (u3 << 12) | (u4 << 6) | u5; - } - } - } - if (u0 < 0x10000) { - str += String.fromCharCode(u0); - } else { - var ch = u0 - 0x10000; - str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); - } - } -#if TEXTDECODER - } -#endif -} - -// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns -// a copy of that string as a Javascript String object. - -function UTF8ToString(ptr) { - return UTF8ArrayToString({{{ heapAndOffset('HEAPU8', 'ptr') }}}); -} - -// Copies the given Javascript String object 'str' to the given byte array at address 'outIdx', -// encoded in UTF8 form and null-terminated. The copy will require at most str.length*4+1 bytes of space in the HEAP. -// Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write. -// Parameters: -// str: the Javascript string to copy. -// outU8Array: the array to copy to. Each index in this array is assumed to be one 8-byte element. -// outIdx: The starting offset in the array to begin the copying. -// maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null -// terminator, i.e. if maxBytesToWrite=1, only the null terminator will be written and nothing else. -// maxBytesToWrite=0 does not write any bytes to the output, not even the null terminator. -// Returns the number of bytes written, EXCLUDING the null terminator. - -function stringToUTF8Array(str, outU8Array, outIdx, maxBytesToWrite) { - if (!(maxBytesToWrite > 0)) // Parameter maxBytesToWrite is not optional. Negative values, 0, null, undefined and false each don't write out any bytes. - return 0; - - var startIdx = outIdx; - var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator. - for (var i = 0; i < str.length; ++i) { - // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8. - // See http://unicode.org/faq/utf_bom.html#utf16-3 - // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629 - var u = str.charCodeAt(i); // possibly a lead surrogate - if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF); - if (u <= 0x7F) { - if (outIdx >= endIdx) break; - outU8Array[outIdx++] = u; - } else if (u <= 0x7FF) { - if (outIdx + 1 >= endIdx) break; - outU8Array[outIdx++] = 0xC0 | (u >> 6); - outU8Array[outIdx++] = 0x80 | (u & 63); - } else if (u <= 0xFFFF) { - if (outIdx + 2 >= endIdx) break; - outU8Array[outIdx++] = 0xE0 | (u >> 12); - outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); - outU8Array[outIdx++] = 0x80 | (u & 63); - } else if (u <= 0x1FFFFF) { - if (outIdx + 3 >= endIdx) break; - outU8Array[outIdx++] = 0xF0 | (u >> 18); - outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63); - outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); - outU8Array[outIdx++] = 0x80 | (u & 63); - } else if (u <= 0x3FFFFFF) { - if (outIdx + 4 >= endIdx) break; - outU8Array[outIdx++] = 0xF8 | (u >> 24); - outU8Array[outIdx++] = 0x80 | ((u >> 18) & 63); - outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63); - outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); - outU8Array[outIdx++] = 0x80 | (u & 63); - } else { - if (outIdx + 5 >= endIdx) break; - outU8Array[outIdx++] = 0xFC | (u >> 30); - outU8Array[outIdx++] = 0x80 | ((u >> 24) & 63); - outU8Array[outIdx++] = 0x80 | ((u >> 18) & 63); - outU8Array[outIdx++] = 0x80 | ((u >> 12) & 63); - outU8Array[outIdx++] = 0x80 | ((u >> 6) & 63); - outU8Array[outIdx++] = 0x80 | (u & 63); - } - } - // Null-terminate the pointer to the buffer. - outU8Array[outIdx] = 0; - return outIdx - startIdx; -} - -// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', -// null-terminated and encoded in UTF8 form. The copy will require at most str.length*4+1 bytes of space in the HEAP. -// Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write. -// Returns the number of bytes written, EXCLUDING the null terminator. - -function stringToUTF8(str, outPtr, maxBytesToWrite) { -#if ASSERTIONS - assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); -#endif - return stringToUTF8Array(str, {{{ heapAndOffset('HEAPU8', 'outPtr') }}}, maxBytesToWrite); -} - -// Returns the number of bytes the given Javascript string takes if encoded as a UTF8 byte array, EXCLUDING the null terminator byte. - -function lengthBytesUTF8(str) { - var len = 0; - for (var i = 0; i < str.length; ++i) { - // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8. - // See http://unicode.org/faq/utf_bom.html#utf16-3 - var u = str.charCodeAt(i); // possibly a lead surrogate - if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF); - if (u <= 0x7F) { - ++len; - } else if (u <= 0x7FF) { - len += 2; - } else if (u <= 0xFFFF) { - len += 3; - } else if (u <= 0x1FFFFF) { - len += 4; - } else if (u <= 0x3FFFFFF) { - len += 5; - } else { - len += 6; - } - } - return len; -} - -// Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns -// a copy of that string as a Javascript String object. - -var UTF16Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-16le') : undefined; -function UTF16ToString(ptr) { -#if ASSERTIONS - assert(ptr % 2 == 0, 'Pointer passed to UTF16ToString must be aligned to two bytes!'); -#endif -#if TEXTDECODER - var endPtr = ptr; - // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself. - // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage. - var idx = endPtr >> 1; - while (HEAP16[idx]) ++idx; - endPtr = idx << 1; - - if (endPtr - ptr > 32 && UTF16Decoder) { - return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr)); - } else { -#endif - var i = 0; - - var str = ''; - while (1) { - var codeUnit = {{{ makeGetValue('ptr', 'i*2', 'i16') }}}; - if (codeUnit == 0) return str; - ++i; - // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through. - str += String.fromCharCode(codeUnit); - } -#if TEXTDECODER - } -#endif -} - -// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', -// null-terminated and encoded in UTF16 form. The copy will require at most str.length*4+2 bytes of space in the HEAP. -// Use the function lengthBytesUTF16() to compute the exact number of bytes (excluding null terminator) that this function will write. -// Parameters: -// str: the Javascript string to copy. -// outPtr: Byte address in Emscripten HEAP where to write the string to. -// maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null -// terminator, i.e. if maxBytesToWrite=2, only the null terminator will be written and nothing else. -// maxBytesToWrite<2 does not write any bytes to the output, not even the null terminator. -// Returns the number of bytes written, EXCLUDING the null terminator. - -function stringToUTF16(str, outPtr, maxBytesToWrite) { -#if ASSERTIONS - assert(outPtr % 2 == 0, 'Pointer passed to stringToUTF16 must be aligned to two bytes!'); -#endif -#if ASSERTIONS - assert(typeof maxBytesToWrite == 'number', 'stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); -#endif - // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. - if (maxBytesToWrite === undefined) { - maxBytesToWrite = 0x7FFFFFFF; - } - if (maxBytesToWrite < 2) return 0; - maxBytesToWrite -= 2; // Null terminator. - var startPtr = outPtr; - var numCharsToWrite = (maxBytesToWrite < str.length*2) ? (maxBytesToWrite / 2) : str.length; - for (var i = 0; i < numCharsToWrite; ++i) { - // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP. - var codeUnit = str.charCodeAt(i); // possibly a lead surrogate - {{{ makeSetValue('outPtr', 0, 'codeUnit', 'i16') }}}; - outPtr += 2; - } - // Null-terminate the pointer to the HEAP. - {{{ makeSetValue('outPtr', 0, 0, 'i16') }}}; - return outPtr - startPtr; -} - -// Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte. - -function lengthBytesUTF16(str) { - return str.length*2; -} - -function UTF32ToString(ptr) { -#if ASSERTIONS - assert(ptr % 4 == 0, 'Pointer passed to UTF32ToString must be aligned to four bytes!'); -#endif - var i = 0; - - var str = ''; - while (1) { - var utf32 = {{{ makeGetValue('ptr', 'i*4', 'i32') }}}; - if (utf32 == 0) - return str; - ++i; - // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing. - // See http://unicode.org/faq/utf_bom.html#utf16-3 - if (utf32 >= 0x10000) { - var ch = utf32 - 0x10000; - str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF)); - } else { - str += String.fromCharCode(utf32); - } - } -} - -// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', -// null-terminated and encoded in UTF32 form. The copy will require at most str.length*4+4 bytes of space in the HEAP. -// Use the function lengthBytesUTF32() to compute the exact number of bytes (excluding null terminator) that this function will write. -// Parameters: -// str: the Javascript string to copy. -// outPtr: Byte address in Emscripten HEAP where to write the string to. -// maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null -// terminator, i.e. if maxBytesToWrite=4, only the null terminator will be written and nothing else. -// maxBytesToWrite<4 does not write any bytes to the output, not even the null terminator. -// Returns the number of bytes written, EXCLUDING the null terminator. - -function stringToUTF32(str, outPtr, maxBytesToWrite) { -#if ASSERTIONS - assert(outPtr % 4 == 0, 'Pointer passed to stringToUTF32 must be aligned to four bytes!'); -#endif -#if ASSERTIONS - assert(typeof maxBytesToWrite == 'number', 'stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); -#endif - // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed. - if (maxBytesToWrite === undefined) { - maxBytesToWrite = 0x7FFFFFFF; - } - if (maxBytesToWrite < 4) return 0; - var startPtr = outPtr; - var endPtr = startPtr + maxBytesToWrite - 4; - for (var i = 0; i < str.length; ++i) { - // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. - // See http://unicode.org/faq/utf_bom.html#utf16-3 - var codeUnit = str.charCodeAt(i); // possibly a lead surrogate - if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) { - var trailSurrogate = str.charCodeAt(++i); - codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF); - } - {{{ makeSetValue('outPtr', 0, 'codeUnit', 'i32') }}}; - outPtr += 4; - if (outPtr + 4 > endPtr) break; - } - // Null-terminate the pointer to the HEAP. - {{{ makeSetValue('outPtr', 0, 0, 'i32') }}}; - return outPtr - startPtr; -} - -// Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte. - -function lengthBytesUTF32(str) { - var len = 0; - for (var i = 0; i < str.length; ++i) { - // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap. - // See http://unicode.org/faq/utf_bom.html#utf16-3 - var codeUnit = str.charCodeAt(i); - if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) ++i; // possibly a lead surrogate, so skip over the tail surrogate. - len += 4; - } - - return len; -} - -// Allocate heap space for a JS string, and write it there. -// It is the responsibility of the caller to free() that memory. -function allocateUTF8(str) { - var size = lengthBytesUTF8(str) + 1; - var ret = _malloc(size); - if (ret) stringToUTF8Array(str, HEAP8, ret, size); - return ret; -} - -// Allocate stack space for a JS string, and write it there. -function allocateUTF8OnStack(str) { - var size = lengthBytesUTF8(str) + 1; - var ret = stackAlloc(size); - stringToUTF8Array(str, HEAP8, ret, size); - return ret; -} - -function demangle(func) { -#if DEMANGLE_SUPPORT - var __cxa_demangle_func = Module['___cxa_demangle'] || Module['__cxa_demangle']; - assert(__cxa_demangle_func); - try { - var s = -#if WASM_BACKEND - func; -#else - func.substr(1); -#endif - var len = lengthBytesUTF8(s)+1; - var buf = _malloc(len); - stringToUTF8(s, buf, len); - var status = _malloc(4); - var ret = __cxa_demangle_func(buf, 0, 0, status); - if ({{{ makeGetValue('status', '0', 'i32') }}} === 0 && ret) { - return Pointer_stringify(ret); - } - // otherwise, libcxxabi failed - } catch(e) { - // ignore problems here - } finally { - if (buf) _free(buf); - if (status) _free(status); - if (ret) _free(ret); - } - // failure when using libcxxabi, don't demangle - return func; -#else // DEMANGLE_SUPPORT -#if ASSERTIONS - warnOnce('warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling'); -#endif // ASSERTIONS - return func; -#endif // DEMANGLE_SUPPORT -} - -function demangleAll(text) { - var regex = -#if WASM_BACKEND - /_Z[\w\d_]+/g; -#else - /__Z[\w\d_]+/g; -#endif - return text.replace(regex, - function(x) { - var y = demangle(x); - return x === y ? x : (x + ' [' + y + ']'); - }); -} - -function jsStackTrace() { - var err = new Error(); - if (!err.stack) { - // IE10+ special cases: It does have callstack info, but it is only populated if an Error object is thrown, - // so try that as a special-case. - try { - throw new Error(0); - } catch(e) { - err = e; - } - if (!err.stack) { - return '(no stack trace available)'; - } - } - return err.stack.toString(); -} - -function stackTrace() { - var js = jsStackTrace(); - if (Module['extraStackTrace']) js += '\n' + Module['extraStackTrace'](); - return demangleAll(js); -} - -// Memory management - -var PAGE_SIZE = 16384; -var WASM_PAGE_SIZE = 65536; -var ASMJS_PAGE_SIZE = 16777216; -var MIN_TOTAL_MEMORY = 16777216; - -function alignUp(x, multiple) { - if (x % multiple > 0) { - x += multiple - (x % multiple); - } - return x; -} - -var HEAP, -/** @type {ArrayBuffer} */ - buffer, -/** @type {Int8Array} */ - HEAP8, -/** @type {Uint8Array} */ - HEAPU8, -/** @type {Int16Array} */ - HEAP16, -/** @type {Uint16Array} */ - HEAPU16, -/** @type {Int32Array} */ - HEAP32, -/** @type {Uint32Array} */ - HEAPU32, -/** @type {Float32Array} */ - HEAPF32, -/** @type {Float64Array} */ - HEAPF64; - -function updateGlobalBuffer(buf) { - Module['buffer'] = buffer = buf; -} - -function updateGlobalBufferViews() { - Module['HEAP8'] = HEAP8 = new Int8Array(buffer); - Module['HEAP16'] = HEAP16 = new Int16Array(buffer); - Module['HEAP32'] = HEAP32 = new Int32Array(buffer); - Module['HEAPU8'] = HEAPU8 = new Uint8Array(buffer); - Module['HEAPU16'] = HEAPU16 = new Uint16Array(buffer); - Module['HEAPU32'] = HEAPU32 = new Uint32Array(buffer); - Module['HEAPF32'] = HEAPF32 = new Float32Array(buffer); - Module['HEAPF64'] = HEAPF64 = new Float64Array(buffer); -} - -var STATIC_BASE, STATICTOP, staticSealed; // static area -var STACK_BASE, STACKTOP, STACK_MAX; // stack area -var DYNAMIC_BASE, DYNAMICTOP_PTR; // dynamic area handled by sbrk - -#if USE_PTHREADS -if (!ENVIRONMENT_IS_PTHREAD) { // Pthreads have already initialized these variables in src/pthread-main.js, where they were passed to the thread worker at startup time -#endif - STATIC_BASE = STATICTOP = STACK_BASE = STACKTOP = STACK_MAX = DYNAMIC_BASE = DYNAMICTOP_PTR = 0; - staticSealed = false; -#if USE_PTHREADS -} -#endif - -#if USE_PTHREADS -if (ENVIRONMENT_IS_PTHREAD) { - staticSealed = true; // The static memory area has been initialized already in the main thread, pthreads skip this. -#if SEPARATE_ASM != 0 - importScripts('{{{ SEPARATE_ASM }}}'); // load the separated-out asm.js -#endif -} -#endif - -#if STACK_OVERFLOW_CHECK -// Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode. -function writeStackCookie() { - assert((STACK_MAX & 3) == 0); - HEAPU32[(STACK_MAX >> 2)-1] = 0x02135467; - HEAPU32[(STACK_MAX >> 2)-2] = 0x89BACDFE; -} - -function checkStackCookie() { - if (HEAPU32[(STACK_MAX >> 2)-1] != 0x02135467 || HEAPU32[(STACK_MAX >> 2)-2] != 0x89BACDFE) { - abort('Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x02135467, but received 0x' + HEAPU32[(STACK_MAX >> 2)-2].toString(16) + ' ' + HEAPU32[(STACK_MAX >> 2)-1].toString(16)); - } -#if !SAFE_SPLIT_MEMORY - // Also test the global address 0 for integrity. This check is not compatible with SAFE_SPLIT_MEMORY though, since that mode already tests all address 0 accesses on its own. - if (HEAP32[0] !== 0x63736d65 /* 'emsc' */) throw 'Runtime error: The application has corrupted its heap memory area (address zero)!'; -#endif -} - -function abortStackOverflow(allocSize) { - abort('Stack overflow! Attempted to allocate ' + allocSize + ' bytes on the stack, but stack has only ' + (STACK_MAX - stackSave() + allocSize) + ' bytes available!'); -} -#endif - -#if ABORTING_MALLOC -function abortOnCannotGrowMemory() { -#if WASM - abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + TOTAL_MEMORY + ', (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 '); -#else - abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + TOTAL_MEMORY + ', (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or (4) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 '); -#endif -} -#endif - -#if ALLOW_MEMORY_GROWTH -if (!Module['reallocBuffer']) Module['reallocBuffer'] = function(size) { - var ret; - try { - if (ArrayBuffer.transfer) { - ret = ArrayBuffer.transfer(buffer, size); - } else { - var oldHEAP8 = HEAP8; - ret = new ArrayBuffer(size); - var temp = new Int8Array(ret); - temp.set(oldHEAP8); - } - } catch(e) { - return false; - } - var success = _emscripten_replace_memory(ret); - if (!success) return false; - return ret; -}; -#endif - -function enlargeMemory() { -#if USE_PTHREADS - abort('Cannot enlarge memory arrays, since compiling with pthreads support enabled (-s USE_PTHREADS=1).'); -#else -#if ALLOW_MEMORY_GROWTH == 0 -#if ABORTING_MALLOC - abortOnCannotGrowMemory(); -#else - return false; // malloc will report failure -#endif -#else - // TOTAL_MEMORY is the current size of the actual array, and DYNAMICTOP is the new top. -#if ASSERTIONS - assert(HEAP32[DYNAMICTOP_PTR>>2] > TOTAL_MEMORY); // This function should only ever be called after the ceiling of the dynamic heap has already been bumped to exceed the current total size of the asm.js heap. -#endif - -#if EMSCRIPTEN_TRACING - // Report old layout one last time - _emscripten_trace_report_memory_layout(); -#endif - - var PAGE_MULTIPLE = Module["usingWasm"] ? WASM_PAGE_SIZE : ASMJS_PAGE_SIZE; // In wasm, heap size must be a multiple of 64KB. In asm.js, they need to be multiples of 16MB. - var LIMIT = 2147483648 - PAGE_MULTIPLE; // We can do one page short of 2GB as theoretical maximum. - - if (HEAP32[DYNAMICTOP_PTR>>2] > LIMIT) { -#if ASSERTIONS - Module.printErr('Cannot enlarge memory, asked to go up to ' + HEAP32[DYNAMICTOP_PTR>>2] + ' bytes, but the limit is ' + LIMIT + ' bytes!'); -#endif - return false; - } - - var OLD_TOTAL_MEMORY = TOTAL_MEMORY; - TOTAL_MEMORY = Math.max(TOTAL_MEMORY, MIN_TOTAL_MEMORY); // So the loop below will not be infinite, and minimum asm.js memory size is 16MB. - - while (TOTAL_MEMORY < HEAP32[DYNAMICTOP_PTR>>2]) { // Keep incrementing the heap size as long as it's less than what is requested. - if (TOTAL_MEMORY <= 536870912) { - TOTAL_MEMORY = alignUp(2 * TOTAL_MEMORY, PAGE_MULTIPLE); // Simple heuristic: double until 1GB... - } else { - // ..., but after that, add smaller increments towards 2GB, which we cannot reach - TOTAL_MEMORY = Math.min(alignUp((3 * TOTAL_MEMORY + 2147483648) / 4, PAGE_MULTIPLE), LIMIT); -#if ASSERTIONS - if (TOTAL_MEMORY === OLD_TOTAL_MEMORY) { - warnOnce('Cannot ask for more memory since we reached the practical limit in browsers (which is just below 2GB), so the request would have failed. Requesting only ' + TOTAL_MEMORY); - } -#endif - } - } - -#if ASSERTIONS - var start = Date.now(); -#endif - - var replacement = Module['reallocBuffer'](TOTAL_MEMORY); - if (!replacement || replacement.byteLength != TOTAL_MEMORY) { -#if ASSERTIONS - Module.printErr('Failed to grow the heap from ' + OLD_TOTAL_MEMORY + ' bytes to ' + TOTAL_MEMORY + ' bytes, not enough memory!'); - if (replacement) { - Module.printErr('Expected to get back a buffer of size ' + TOTAL_MEMORY + ' bytes, but instead got back a buffer of size ' + replacement.byteLength); - } -#endif - // restore the state to before this call, we failed - TOTAL_MEMORY = OLD_TOTAL_MEMORY; - return false; - } - - // everything worked - - updateGlobalBuffer(replacement); - updateGlobalBufferViews(); - -#if ASSERTIONS - if (!Module["usingWasm"]) { - Module.printErr('Warning: Enlarging memory arrays, this is not fast! ' + [OLD_TOTAL_MEMORY, TOTAL_MEMORY]); - } -#endif - -#if EMSCRIPTEN_TRACING - _emscripten_trace_js_log_message("Emscripten", "Enlarging memory arrays from " + OLD_TOTAL_MEMORY + " to " + TOTAL_MEMORY); - // And now report the new layout - _emscripten_trace_report_memory_layout(); -#endif - - return true; -#endif // ALLOW_MEMORY_GROWTH -#endif // USE_PTHREADS -} - -#if ALLOW_MEMORY_GROWTH -var byteLength; -try { - byteLength = Function.prototype.call.bind(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, 'byteLength').get); - byteLength(new ArrayBuffer(4)); // can fail on older ie -} catch(e) { // can fail on older node/v8 - byteLength = function(buffer) { return buffer.byteLength; }; -} -#endif - -var TOTAL_STACK = Module['TOTAL_STACK'] || {{{ TOTAL_STACK }}}; -var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || {{{ TOTAL_MEMORY }}}; -if (TOTAL_MEMORY < TOTAL_STACK) Module.printErr('TOTAL_MEMORY should be larger than TOTAL_STACK, was ' + TOTAL_MEMORY + '! (TOTAL_STACK=' + TOTAL_STACK + ')'); - -// Initialize the runtime's memory -#if ASSERTIONS -// check for full engine support (use string 'subarray' to avoid closure compiler confusion) -assert(typeof Int32Array !== 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray !== undefined && Int32Array.prototype.set !== undefined, - 'JS engine does not provide full typed array support'); -#endif - -#if IN_TEST_HARNESS - -// Test runs in browsers should always be free from uncaught exceptions. If an uncaught exception is thrown, we fail browser test execution in the REPORT_RESULT() macro to output an error value. -if (ENVIRONMENT_IS_WEB) { - window.addEventListener('error', function(e) { - if (e.message.indexOf('SimulateInfiniteLoop') != -1) return; - console.error('Page threw an exception ' + e); - Module['pageThrewException'] = true; - }); -} - -#if USE_PTHREADS == 1 -if (typeof SharedArrayBuffer === 'undefined' || typeof Atomics === 'undefined') { - xhr = new XMLHttpRequest(); - xhr.open('GET', 'http://localhost:8888/report_result?skipped:%20SharedArrayBuffer%20is%20not%20supported!'); - xhr.send(); - setTimeout(function() { window.close() }, 2000); -} -#endif -#endif - -#if USE_PTHREADS -#if !WASM -if (typeof SharedArrayBuffer !== 'undefined') { - if (!ENVIRONMENT_IS_PTHREAD) buffer = new SharedArrayBuffer(TOTAL_MEMORY); - // Currently SharedArrayBuffer does not have a slice() operation, so polyfill it in. - // Adapted from https://github.com/ttaubert/node-arraybuffer-slice, (c) 2014 Tim Taubert - // arraybuffer-slice may be freely distributed under the MIT license. - (function (undefined) { - "use strict"; - function clamp(val, length) { - val = (val|0) || 0; - if (val < 0) return Math.max(val + length, 0); - return Math.min(val, length); - } - if (typeof SharedArrayBuffer !== 'undefined' && !SharedArrayBuffer.prototype.slice) { - SharedArrayBuffer.prototype.slice = function (from, to) { - var length = this.byteLength; - var begin = clamp(from, length); - var end = length; - if (to !== undefined) end = clamp(to, length); - if (begin > end) return new ArrayBuffer(0); - var num = end - begin; - var target = new ArrayBuffer(num); - var targetArray = new Uint8Array(target); - var sourceArray = new Uint8Array(this, begin, num); - targetArray.set(sourceArray); - return target; - }; - } - })(); -} else { - if (!ENVIRONMENT_IS_PTHREAD) buffer = new ArrayBuffer(TOTAL_MEMORY); -} -updateGlobalBufferViews(); - -if (typeof Atomics === 'undefined') { - // Polyfill singlethreaded atomics ops from http://lars-t-hansen.github.io/ecmascript_sharedmem/shmem.html#Atomics.add - // No thread-safety needed since we don't have multithreading support. - Atomics = {}; - Atomics['add'] = function(t, i, v) { var w = t[i]; t[i] += v; return w; } - Atomics['and'] = function(t, i, v) { var w = t[i]; t[i] &= v; return w; } - Atomics['compareExchange'] = function(t, i, e, r) { var w = t[i]; if (w == e) t[i] = r; return w; } - Atomics['exchange'] = function(t, i, v) { var w = t[i]; t[i] = v; return w; } - Atomics['wait'] = function(t, i, v, o) { if (t[i] != v) return 'not-equal'; else return 'timed-out'; } - Atomics['wake'] = function(t, i, c) { return 0; } - Atomics['wakeOrRequeue'] = function(t, i1, c, i2, v) { return 0; } - Atomics['isLockFree'] = function(s) { return true; } - Atomics['load'] = function(t, i) { return t[i]; } - Atomics['or'] = function(t, i, v) { var w = t[i]; t[i] |= v; return w; } - Atomics['store'] = function(t, i, v) { t[i] = v; return v; } - Atomics['sub'] = function(t, i, v) { var w = t[i]; t[i] -= v; return w; } - Atomics['xor'] = function(t, i, v) { var w = t[i]; t[i] ^= v; return w; } -} - -#else -if (!ENVIRONMENT_IS_PTHREAD) { -#if ALLOW_MEMORY_GROWTH - Module['wasmMemory'] = new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE , 'maximum': {{{ WASM_MEM_MAX }}} / WASM_PAGE_SIZE, 'shared': true }); -#else - Module['wasmMemory'] = new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE , 'maximum': TOTAL_MEMORY / WASM_PAGE_SIZE, 'shared': true }); -#endif - buffer = Module['wasmMemory'].buffer; -} - -updateGlobalBufferViews(); -#endif // !WASM -#else // USE_PTHREADS - -#if SPLIT_MEMORY == 0 -// Use a provided buffer, if there is one, or else allocate a new one -if (Module['buffer']) { - buffer = Module['buffer']; -#if ASSERTIONS - assert(buffer.byteLength === TOTAL_MEMORY, 'provided buffer should be ' + TOTAL_MEMORY + ' bytes, but it is ' + buffer.byteLength); -#endif -} else { - // Use a WebAssembly memory where available -#if WASM - if (typeof WebAssembly === 'object' && typeof WebAssembly.Memory === 'function') { -#if ASSERTIONS - assert(TOTAL_MEMORY % WASM_PAGE_SIZE === 0); -#endif // ASSERTIONS -#if ALLOW_MEMORY_GROWTH -#if WASM_MEM_MAX -#if ASSERTIONS - assert({{{ WASM_MEM_MAX }}} % WASM_PAGE_SIZE == 0); -#endif - Module['wasmMemory'] = new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE, 'maximum': {{{ WASM_MEM_MAX }}} / WASM_PAGE_SIZE }); -#else - Module['wasmMemory'] = new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE }); -#endif // BINARYEN_MEM_MAX -#else - Module['wasmMemory'] = new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE, 'maximum': TOTAL_MEMORY / WASM_PAGE_SIZE }); -#endif // ALLOW_MEMORY_GROWTH - buffer = Module['wasmMemory'].buffer; - } else -#endif // WASM - { - buffer = new ArrayBuffer(TOTAL_MEMORY); - } -#if ASSERTIONS - assert(buffer.byteLength === TOTAL_MEMORY); -#endif // ASSERTIONS - Module['buffer'] = buffer; -} -updateGlobalBufferViews(); -#else // SPLIT_MEMORY -// make sure total memory is a multiple of the split memory size -var SPLIT_MEMORY = {{{ SPLIT_MEMORY }}}; -var SPLIT_MEMORY_MASK = SPLIT_MEMORY - 1; -var SPLIT_MEMORY_BITS = -1; -var ALLOW_MEMORY_GROWTH = {{{ ALLOW_MEMORY_GROWTH }}}; -var ABORTING_MALLOC = {{{ ABORTING_MALLOC }}}; - -Module['SPLIT_MEMORY'] = SPLIT_MEMORY; - -totalMemory = TOTAL_MEMORY; -if (totalMemory % SPLIT_MEMORY) { - totalMemory += SPLIT_MEMORY - (totalMemory % SPLIT_MEMORY); -} -if (totalMemory === SPLIT_MEMORY) totalMemory *= 2; -if (totalMemory !== TOTAL_MEMORY) { - TOTAL_MEMORY = totalMemory; -#if ASSERTIONS == 2 - Module.printErr('increasing TOTAL_MEMORY to ' + TOTAL_MEMORY + ' to be a multiple>1 of the split memory size ' + SPLIT_MEMORY + ')'); -#endif -} - -var buffers = [], HEAP8s = [], HEAP16s = [], HEAP32s = [], HEAPU8s = [], HEAPU16s = [], HEAPU32s = [], HEAPF32s = [], HEAPF64s = []; - -// Allocates a split chunk, a range of memory of size SPLIT_MEMORY. Generally data is not provided, and a new -// buffer is allocated, this is what happens when malloc works. However, you can provide your own buffer, -// which then lets you access it at address [ i*SPLIT_MEMORY, (i+1)*SPLIT_MEMORY ). -// The function returns true if it succeeds. It can also throw an exception if no data is provided and -// the browser fails to allocate the buffer. -function allocateSplitChunk(i, data) { - if (buffers[i]) return false; // already taken - // any of these allocations might fail; do them all before writing anything to global state - var currBuffer = data ? data : new ArrayBuffer(SPLIT_MEMORY); -#if ASSERTIONS - assert(currBuffer instanceof ArrayBuffer); -#endif - var currHEAP8s = new Int8Array(currBuffer); - var currHEAP16s = new Int16Array(currBuffer); - var currHEAP32s = new Int32Array(currBuffer); - var currHEAPU8s = new Uint8Array(currBuffer); - var currHEAPU16s = new Uint16Array(currBuffer); - var currHEAPU32s = new Uint32Array(currBuffer); - var currHEAPF32s = new Float32Array(currBuffer); - var currHEAPF64s = new Float64Array(currBuffer); - buffers[i] = currBuffer; - HEAP8s[i] = currHEAP8s; - HEAP16s[i] = currHEAP16s; - HEAP32s[i] = currHEAP32s; - HEAPU8s[i] = currHEAPU8s; - HEAPU16s[i] = currHEAPU16s; - HEAPU32s[i] = currHEAPU32s; - HEAPF32s[i] = currHEAPF32s; - HEAPF64s[i] = currHEAPF64s; - return true; -} -function freeSplitChunk(i) { -#if ASSERTIONS - assert(buffers[i] && HEAP8s[i]); - assert(i > 0); // cannot free the first chunk -#endif - buffers[i] = HEAP8s[i] = HEAP16s[i] = HEAP32s[i] = HEAPU8s[i] = HEAPU16s[i] = HEAPU32s[i] = HEAPF32s[i] = HEAPF64s[i] = null; -} - -(function() { - for (var i = 0; i < TOTAL_MEMORY / SPLIT_MEMORY; i++) { - buffers[i] = HEAP8s[i] = HEAP16s[i] = HEAP32s[i] = HEAPU8s[i] = HEAPU16s[i] = HEAPU32s[i] = HEAPF32s[i] = HEAPF64s[i] = null; - } - - var temp = SPLIT_MEMORY; - while (temp) { - temp >>= 1; - SPLIT_MEMORY_BITS++; - } - - allocateSplitChunk(0); // first chunk is for core runtime, static, stack, etc., always must be initialized - - // support HEAP8.subarray etc. - var SHIFT_TABLE = [0, 0, 1, 0, 2, 0, 0, 0, 3]; - function fake(real) { - var bytes = real[0].BYTES_PER_ELEMENT; - var shifts = SHIFT_TABLE[bytes]; -#if ASSERTIONS - assert(shifts > 0 || bytes == 1); -#endif - var that = { - BYTES_PER_ELEMENT: bytes, - set: function(array, offset) { - if (offset === undefined) offset = 0; - // potentially split over multiple chunks - while (array.length > 0) { - var chunk = offset >> SPLIT_MEMORY_BITS; - var relative = offset & SPLIT_MEMORY_MASK; - if (relative + (array.length << shifts) < SPLIT_MEMORY) { - real[chunk].set(array, relative); // all fits in this chunk - break; - } else { - var currSize = SPLIT_MEMORY - relative; -#if ASSERTIONS - assert(currSize % that.BYTES_PER_ELEMENT === 0); -#endif - var lastIndex = currSize >> shifts; - real[chunk].set(array.subarray(0, lastIndex), relative); - // increments - array = array.subarray(lastIndex); - offset += currSize; - } - } - }, - subarray: function(from, to) { - from = from << shifts; - var start = from >> SPLIT_MEMORY_BITS; - if (to === undefined) { - to = (start + 1) << SPLIT_MEMORY_BITS; - } else { - to = to << shifts; - } - to = Math.max(from, to); // if to is smaller, we'll get nothing anyway, same as to == from - if (from < to) { - var end = (to - 1) >> SPLIT_MEMORY_BITS; // -1, since we do not actually read the last address -#if ASSERTIONS - assert(start === end, 'subarray cannot span split chunks'); -#endif - } - if (to > from && (to & SPLIT_MEMORY_MASK) == 0) { - // avoid the mask on the next line giving 0 for the end - return real[start].subarray((from & SPLIT_MEMORY_MASK) >> shifts); // just return to the end of the chunk - } - return real[start].subarray((from & SPLIT_MEMORY_MASK) >> shifts, (to & SPLIT_MEMORY_MASK) >> shifts); - }, - buffer: { - slice: function(from, to) { -#if ASSERTIONS - assert(to, 'TODO: this is an actual copy, so we could support a slice across multiple chunks'); -#endif - return new Uint8Array(HEAPU8.subarray(from, to)).buffer; - }, - }, - }; - return that; - } - HEAP8 = fake(HEAP8s); - HEAP16 = fake(HEAP16s); - HEAP32 = fake(HEAP32s); - HEAPU8 = fake(HEAPU8s); - HEAPU16 = fake(HEAPU16s); - HEAPU32 = fake(HEAPU32s); - HEAPF32 = fake(HEAPF32s); - HEAPF64 = fake(HEAPF64s); -})(); - -#if SAFE_SPLIT_MEMORY -function checkPtr(ptr, shifts) { - if (ptr <= 0) abort('segmentation fault storing to address ' + ptr); - if (ptr !== ((ptr >> shifts) << shifts)) abort('alignment error storing to address ' + ptr + ', which was expected to be aligned to a shift of ' + shifts); - if ((ptr >> SPLIT_MEMORY_BITS) !== (ptr + Math.pow(2, shifts) - 1 >> SPLIT_MEMORY_BITS)) abort('segmentation fault, write spans split chunks ' + [ptr, shifts]); -} -#endif - -function get8(ptr) { - ptr = ptr | 0; -#if SAFE_SPLIT_MEMORY - checkPtr(ptr, 0); -#endif - return HEAP8s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 0] | 0; -} -function get16(ptr) { - ptr = ptr | 0; -#if SAFE_SPLIT_MEMORY - checkPtr(ptr, 1); -#endif - return HEAP16s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 1] | 0; -} -function get32(ptr) { - ptr = ptr | 0; -#if SAFE_SPLIT_MEMORY - checkPtr(ptr, 2); -#endif - return HEAP32s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 2] | 0; -} -function getU8(ptr) { - ptr = ptr | 0; -#if SAFE_SPLIT_MEMORY - checkPtr(ptr, 0); -#endif - return HEAPU8s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 0] | 0; -} -function getU16(ptr) { - ptr = ptr | 0; -#if SAFE_SPLIT_MEMORY - checkPtr(ptr, 1); -#endif - return HEAPU16s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 1] | 0; -} -function getU32(ptr) { - ptr = ptr | 0; -#if SAFE_SPLIT_MEMORY - checkPtr(ptr, 2); -#endif - return HEAPU32s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 2] >>> 0; -} -function getF32(ptr) { - ptr = ptr | 0; -#if SAFE_SPLIT_MEMORY - checkPtr(ptr, 2); -#endif - return +HEAPF32s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 2]; -} -function getF64(ptr) { - ptr = ptr | 0; -#if SAFE_SPLIT_MEMORY - checkPtr(ptr, 3); -#endif - return +HEAPF64s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 3]; -} -function set8(ptr, value) { - ptr = ptr | 0; - value = value | 0; -#if SAFE_SPLIT_MEMORY - checkPtr(ptr, 0); -#endif - HEAP8s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 0] = value; -} -function set16(ptr, value) { - ptr = ptr | 0; - value = value | 0; -#if SAFE_SPLIT_MEMORY - checkPtr(ptr, 1); -#endif - HEAP16s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 1] = value; -} -function set32(ptr, value) { - ptr = ptr | 0; - value = value | 0; -#if SAFE_SPLIT_MEMORY - checkPtr(ptr, 2); -#endif - HEAP32s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 2] = value; -} -function setU8(ptr, value) { - ptr = ptr | 0; - value = value | 0; -#if SAFE_SPLIT_MEMORY - checkPtr(ptr, 0); -#endif - HEAPU8s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 0] = value; -} -function setU16(ptr, value) { - ptr = ptr | 0; - value = value | 0; -#if SAFE_SPLIT_MEMORY - checkPtr(ptr, 1); -#endif - HEAPU16s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 1] = value; -} -function setU32(ptr, value) { - ptr = ptr | 0; - value = value | 0; -#if SAFE_SPLIT_MEMORY - checkPtr(ptr, 2); -#endif - HEAPU32s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 2] = value; -} -function setF32(ptr, value) { - ptr = ptr | 0; - value = +value; -#if SAFE_SPLIT_MEMORY - checkPtr(ptr, 2); -#endif - HEAPF32s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 2] = value; -} -function setF64(ptr, value) { - ptr = ptr | 0; - value = +value; -#if SAFE_SPLIT_MEMORY - checkPtr(ptr, 3); -#endif - HEAPF64s[ptr >> SPLIT_MEMORY_BITS][(ptr & SPLIT_MEMORY_MASK) >> 3] = value; -} -#endif // SPLIT_MEMORY - -#endif // USE_PTHREADS - -function getTotalMemory() { - return TOTAL_MEMORY; -} - -// Endianness check (note: assumes compiler arch was little-endian) -#if SAFE_SPLIT_MEMORY == 0 -#if USE_PTHREADS -if (!ENVIRONMENT_IS_PTHREAD) { -#endif - HEAP32[0] = 0x63736d65; /* 'emsc' */ -#if USE_PTHREADS -} else { - if (HEAP32[0] !== 0x63736d65) throw 'Runtime error: The application has corrupted its heap memory area (address zero)!'; -} -#endif -HEAP16[1] = 0x6373; -if (HEAPU8[2] !== 0x73 || HEAPU8[3] !== 0x63) throw 'Runtime error: expected the system to be little-endian!'; -#endif - -function callRuntimeCallbacks(callbacks) { - while(callbacks.length > 0) { - var callback = callbacks.shift(); - if (typeof callback == 'function') { - callback(); - continue; - } - var func = callback.func; - if (typeof func === 'number') { - if (callback.arg === undefined) { - Module['dynCall_v'](func); - } else { - Module['dynCall_vi'](func, callback.arg); - } - } else { - func(callback.arg === undefined ? null : callback.arg); - } - } -} - -var __ATPRERUN__ = []; // functions called before the runtime is initialized -var __ATINIT__ = []; // functions called during startup -var __ATMAIN__ = []; // functions called when main() is to be run -var __ATEXIT__ = []; // functions called during shutdown -var __ATPOSTRUN__ = []; // functions called after the main() is called - -var runtimeInitialized = false; -var runtimeExited = false; - -#if USE_PTHREADS -if (ENVIRONMENT_IS_PTHREAD) runtimeInitialized = true; // The runtime is hosted in the main thread, and bits shared to pthreads via SharedArrayBuffer. No need to init again in pthread. -#endif - -function preRun() { -#if USE_PTHREADS - if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread. -#endif - // compatibility - merge in anything from Module['preRun'] at this time - if (Module['preRun']) { - if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; - while (Module['preRun'].length) { - addOnPreRun(Module['preRun'].shift()); - } - } - callRuntimeCallbacks(__ATPRERUN__); -} - -function ensureInitRuntime() { -#if STACK_OVERFLOW_CHECK - checkStackCookie(); -#endif -#if USE_PTHREADS - if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread. -#endif - if (runtimeInitialized) return; - runtimeInitialized = true; -#if USE_PTHREADS - // Pass the thread address inside the asm.js scope to store it for fast access that avoids the need for a FFI out. - __register_pthread_ptr(PThread.mainThreadBlock, /*isMainBrowserThread=*/!ENVIRONMENT_IS_WORKER, /*isMainRuntimeThread=*/1); -#endif - callRuntimeCallbacks(__ATINIT__); -} - -function preMain() { -#if STACK_OVERFLOW_CHECK - checkStackCookie(); -#endif -#if USE_PTHREADS - if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread. -#endif - callRuntimeCallbacks(__ATMAIN__); -} - -function exitRuntime() { -#if STACK_OVERFLOW_CHECK - checkStackCookie(); -#endif -#if USE_PTHREADS - if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread. -#endif - callRuntimeCallbacks(__ATEXIT__); - runtimeExited = true; -} - -function postRun() { -#if STACK_OVERFLOW_CHECK - checkStackCookie(); -#endif -#if USE_PTHREADS - if (ENVIRONMENT_IS_PTHREAD) return; // PThreads reuse the runtime from the main thread. -#endif - // compatibility - merge in anything from Module['postRun'] at this time - if (Module['postRun']) { - if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']]; - while (Module['postRun'].length) { - addOnPostRun(Module['postRun'].shift()); - } - } - callRuntimeCallbacks(__ATPOSTRUN__); -} - -function addOnPreRun(cb) { - __ATPRERUN__.unshift(cb); -} - -function addOnInit(cb) { - __ATINIT__.unshift(cb); -} - -function addOnPreMain(cb) { - __ATMAIN__.unshift(cb); -} - -function addOnExit(cb) { - __ATEXIT__.unshift(cb); -} - -function addOnPostRun(cb) { - __ATPOSTRUN__.unshift(cb); -} - -// Deprecated: This function should not be called because it is unsafe and does not provide -// a maximum length limit of how many bytes it is allowed to write. Prefer calling the -// function stringToUTF8Array() instead, which takes in a maximum length that can be used -// to be secure from out of bounds writes. -/** @deprecated */ -function writeStringToMemory(string, buffer, dontAddNull) { - warnOnce('writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!'); - - var /** @type {number} */ lastChar, /** @type {number} */ end; - if (dontAddNull) { - // stringToUTF8Array always appends null. If we don't want to do that, remember the - // character that existed at the location where the null will be placed, and restore - // that after the write (below). - end = buffer + lengthBytesUTF8(string); - lastChar = HEAP8[end]; - } - stringToUTF8(string, buffer, Infinity); - if (dontAddNull) HEAP8[end] = lastChar; // Restore the value under the null character. -} - -function writeArrayToMemory(array, buffer) { -#if ASSERTIONS - assert(array.length >= 0, 'writeArrayToMemory array must have a length (should be an array or typed array)') -#endif - HEAP8.set(array, buffer); -} - -function writeAsciiToMemory(str, buffer, dontAddNull) { - for (var i = 0; i < str.length; ++i) { -#if ASSERTIONS - assert(str.charCodeAt(i) === str.charCodeAt(i)&0xff); -#endif - {{{ makeSetValue('buffer++', 0, 'str.charCodeAt(i)', 'i8') }}}; - } - // Null-terminate the pointer to the HEAP. - if (!dontAddNull) {{{ makeSetValue('buffer', 0, 0, 'i8') }}}; -} - -{{{ unSign }}} -{{{ reSign }}} - -#if LEGACY_VM_SUPPORT -// check for imul support, and also for correctness ( https://bugs.webkit.org/show_bug.cgi?id=126345 ) -if (!Math['imul'] || Math['imul'](0xffffffff, 5) !== -5) Math['imul'] = function imul(a, b) { - var ah = a >>> 16; - var al = a & 0xffff; - var bh = b >>> 16; - var bl = b & 0xffff; - return (al*bl + ((ah*bl + al*bh) << 16))|0; -}; -Math.imul = Math['imul']; - -#if PRECISE_F32 -#if PRECISE_F32 == 1 -if (!Math['fround']) { - var froundBuffer = new Float32Array(1); - Math['fround'] = function(x) { froundBuffer[0] = x; return froundBuffer[0] }; -} -#else // 2 -if (!Math['fround']) Math['fround'] = function(x) { return x }; -#endif -Math.fround = Math['fround']; -#else -#if SIMD -if (!Math['fround']) Math['fround'] = function(x) { return x }; -#endif -#endif - -if (!Math['clz32']) Math['clz32'] = function(x) { - x = x >>> 0; - for (var i = 0; i < 32; i++) { - if (x & (1 << (31 - i))) return i; - } - return 32; -}; -Math.clz32 = Math['clz32'] - -if (!Math['trunc']) Math['trunc'] = function(x) { - return x < 0 ? Math.ceil(x) : Math.floor(x); -}; -Math.trunc = Math['trunc']; -#else // LEGACY_VM_SUPPORT -#if ASSERTIONS -assert(Math['imul'] && Math['fround'] && Math['clz32'] && Math['trunc'], 'this is a legacy browser, build with LEGACY_VM_SUPPORT'); -#endif -#endif // LEGACY_VM_SUPPORT - -var Math_abs = Math.abs; -var Math_cos = Math.cos; -var Math_sin = Math.sin; -var Math_tan = Math.tan; -var Math_acos = Math.acos; -var Math_asin = Math.asin; -var Math_atan = Math.atan; -var Math_atan2 = Math.atan2; -var Math_exp = Math.exp; -var Math_log = Math.log; -var Math_sqrt = Math.sqrt; -var Math_ceil = Math.ceil; -var Math_floor = Math.floor; -var Math_pow = Math.pow; -var Math_imul = Math.imul; -var Math_fround = Math.fround; -var Math_round = Math.round; -var Math_min = Math.min; -var Math_max = Math.max; -var Math_clz32 = Math.clz32; -var Math_trunc = Math.trunc; - -// A counter of dependencies for calling run(). If we need to -// do asynchronous work before running, increment this and -// decrement it. Incrementing must happen in a place like -// PRE_RUN_ADDITIONS (used by emcc to add file preloading). -// Note that you can add dependencies in preRun, even though -// it happens right before run - run will be postponed until -// the dependencies are met. -var runDependencies = 0; -var runDependencyWatcher = null; -var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled -#if ASSERTIONS -var runDependencyTracking = {}; -#endif - -function getUniqueRunDependency(id) { -#if ASSERTIONS - var orig = id; - while (1) { - if (!runDependencyTracking[id]) return id; - id = orig + Math.random(); - } -#endif - return id; -} - -function addRunDependency(id) { -#if USE_PTHREADS - // We should never get here in pthreads (could no-op this out if called in pthreads, but that might indicate a bug in caller side, - // so good to be very explicit) - assert(!ENVIRONMENT_IS_PTHREAD); -#endif - runDependencies++; - if (Module['monitorRunDependencies']) { - Module['monitorRunDependencies'](runDependencies); - } -#if ASSERTIONS - if (id) { - assert(!runDependencyTracking[id]); - runDependencyTracking[id] = 1; - if (runDependencyWatcher === null && typeof setInterval !== 'undefined') { - // Check for missing dependencies every few seconds - runDependencyWatcher = setInterval(function() { - if (ABORT) { - clearInterval(runDependencyWatcher); - runDependencyWatcher = null; - return; - } - var shown = false; - for (var dep in runDependencyTracking) { - if (!shown) { - shown = true; - Module.printErr('still waiting on run dependencies:'); - } - Module.printErr('dependency: ' + dep); - } - if (shown) { - Module.printErr('(end of list)'); - } - }, 10000); - } - } else { - Module.printErr('warning: run dependency added without ID'); - } -#endif -} - -function removeRunDependency(id) { - runDependencies--; - if (Module['monitorRunDependencies']) { - Module['monitorRunDependencies'](runDependencies); - } -#if ASSERTIONS - if (id) { - assert(runDependencyTracking[id]); - delete runDependencyTracking[id]; - } else { - Module.printErr('warning: run dependency removed without ID'); - } -#endif - if (runDependencies == 0) { - if (runDependencyWatcher !== null) { - clearInterval(runDependencyWatcher); - runDependencyWatcher = null; - } - if (dependenciesFulfilled) { - var callback = dependenciesFulfilled; - dependenciesFulfilled = null; - callback(); // can add another dependenciesFulfilled - } - } -} - -Module["preloadedImages"] = {}; // maps url to image data -Module["preloadedAudios"] = {}; // maps url to audio data -#if (WASM != 0) && (MAIN_MODULE != 0) -Module["preloadedWasm"] = {}; // maps url to wasm instance exports -#endif - -#if PGO -var PGOMonitor = { - called: {}, - dump: function() { - var dead = []; - for (var i = 0; i < this.allGenerated.length; i++) { - var func = this.allGenerated[i]; - if (!this.called[func]) dead.push(func); - } - Module.print('-s DEAD_FUNCTIONS=\'' + JSON.stringify(dead) + '\'\n'); - } -}; -Module['PGOMonitor'] = PGOMonitor; -__ATEXIT__.push(function() { PGOMonitor.dump() }); -addOnPreRun(function() { addRunDependency('pgo') }); -#endif - -#if RELOCATABLE -{{{ -(function() { - // add in RUNTIME_LINKED_LIBS, if provided - if (RUNTIME_LINKED_LIBS.length > 0) { - return "if (!Module['dynamicLibraries']) Module['dynamicLibraries'] = [];\n" + - "Module['dynamicLibraries'] = " + JSON.stringify(RUNTIME_LINKED_LIBS) + ".concat(Module['dynamicLibraries']);\n"; - } - return ''; -})() -}}} - -addOnPreRun(function() { - function loadDynamicLibraries(libs) { - if (libs) { - libs.forEach(function(lib) { - loadDynamicLibrary(lib); - }); - } - if (Module['asm']['runPostSets']) { - Module['asm']['runPostSets'](); - } - } - // if we can load dynamic libraries synchronously, do so, otherwise, preload -#if WASM - if (Module['dynamicLibraries'] && Module['dynamicLibraries'].length > 0 && !Module['readBinary']) { - // we can't read binary data synchronously, so preload - addRunDependency('preload_dynamicLibraries'); - var binaries = []; - Module['dynamicLibraries'].forEach(function(lib) { - fetch(lib, { credentials: 'same-origin' }).then(function(response) { - if (!response['ok']) { - throw "failed to load wasm binary file at '" + lib + "'"; - } - return response['arrayBuffer'](); - }).then(function(buffer) { - var binary = new Uint8Array(buffer); - binaries.push(binary); - if (binaries.length === Module['dynamicLibraries'].length) { - // we got them all, wonderful - loadDynamicLibraries(binaries); - removeRunDependency('preload_dynamicLibraries'); - } - }); - }); - return; - } -#endif - loadDynamicLibraries(Module['dynamicLibraries']); -}); - -#if ASSERTIONS -function lookupSymbol(ptr) { // for a pointer, print out all symbols that resolve to it - var ret = []; - for (var i in Module) { - if (Module[i] === ptr) ret.push(i); - } - print(ptr + ' is ' + ret); -} -#endif -#endif - -var memoryInitializer = null; - -#if USE_PTHREADS -#if PTHREAD_HINT_NUM_CORES < 0 -if (!ENVIRONMENT_IS_PTHREAD) addOnPreRun(function() { - addRunDependency('pthreads_querycores'); - - var bg = document.createElement('div'); - bg.style = "position: absolute; top: 0%; left: 0%; width: 100%; height: 100%; background-color: black; z-index:1001; -moz-opacity: 0.8; opacity:.80; filter: alpha(opacity=80);"; - var div = document.createElement('div'); - var default_num_cores = navigator.hardwareConcurrency || 4; - var hwConcurrency = navigator.hardwareConcurrency ? ("says " + navigator.hardwareConcurrency) : "is not available"; - var html = '
Thread setup

Number of logical cores:
(navigator.hardwareConcurrency ' - + hwConcurrency + ')
'; -#if PTHREAD_POOL_SIZE < 0 - html += 'PThread pool size:
'; -#endif - html += '
'; - div.innerHTML = html; - div.style = 'position: absolute; top: 35%; left: 35%; width: 30%; height: 150px; padding: 16px; border: 16px solid gray; background-color: white; z-index:1002; overflow: auto;'; - document.body.appendChild(bg); - document.body.appendChild(div); - var goButton = document.getElementById('thread_setup_button_go'); - goButton.onclick = function() { - var num_logical_cores = parseInt(document.getElementById('thread_setup_num_logical_cores').value); - _emscripten_force_num_logical_cores(num_logical_cores); -#if PTHREAD_POOL_SIZE < 0 - var pthread_pool_size = parseInt(document.getElementById('thread_setup_pthread_pool_size').value); - PThread.allocateUnusedWorkers(pthread_pool_size, function() { removeRunDependency('pthreads_querycores'); }); -#else - removeRunDependency('pthreads_querycores'); -#endif - document.body.removeChild(bg); - document.body.removeChild(div); - } -}); -#endif -#endif - -#if PTHREAD_POOL_SIZE > 0 -// To work around https://bugzilla.mozilla.org/show_bug.cgi?id=1049079, warm up a worker pool before starting up the application. -if (!ENVIRONMENT_IS_PTHREAD) addOnPreRun(function() { if (typeof SharedArrayBuffer !== 'undefined') { addRunDependency('pthreads'); PThread.allocateUnusedWorkers({{{PTHREAD_POOL_SIZE}}}, function() { removeRunDependency('pthreads'); }); }}); -#endif - -#if ASSERTIONS -#if NO_FILESYSTEM -var /* show errors on likely calls to FS when it was not included */ FS = { - error: function() { - abort('Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -s FORCE_FILESYSTEM=1'); - }, - init: function() { FS.error() }, - createDataFile: function() { FS.error() }, - createPreloadedFile: function() { FS.error() }, - createLazyFile: function() { FS.error() }, - open: function() { FS.error() }, - mkdev: function() { FS.error() }, - registerDevice: function() { FS.error() }, - analyzePath: function() { FS.error() }, - loadFilesFromDB: function() { FS.error() }, - - ErrnoError: function ErrnoError() { FS.error() }, -}; -Module['FS_createDataFile'] = FS.createDataFile; -Module['FS_createPreloadedFile'] = FS.createPreloadedFile; -#endif -#endif - -#if CYBERDWARF -var cyberDWARFFile = '{{{ BUNDLED_CD_DEBUG_FILE }}}'; -#endif - -#include "URIUtils.js" - -#if WASM -function integrateWasmJS() { - // wasm.js has several methods for creating the compiled code module here: - // * 'native-wasm' : use native WebAssembly support in the browser - // * 'interpret-s-expr': load s-expression code from a .wast and interpret - // * 'interpret-binary': load binary wasm and interpret - // * 'interpret-asm2wasm': load asm.js code, translate to wasm, and interpret - // * 'asmjs': no wasm, just load the asm.js code and use that (good for testing) - // The method is set at compile time (BINARYEN_METHOD) - // The method can be a comma-separated list, in which case, we will try the - // options one by one. Some of them can fail gracefully, and then we can try - // the next. - - // inputs - - var method = '{{{ BINARYEN_METHOD }}}'; - - var wasmTextFile = '{{{ WASM_TEXT_FILE }}}'; - var wasmBinaryFile = '{{{ WASM_BINARY_FILE }}}'; - var asmjsCodeFile = '{{{ ASMJS_CODE_FILE }}}'; - - if (typeof Module['locateFile'] === 'function') { - if (!isDataURI(wasmTextFile)) { - wasmTextFile = Module['locateFile'](wasmTextFile); - } - if (!isDataURI(wasmBinaryFile)) { - wasmBinaryFile = Module['locateFile'](wasmBinaryFile); - } - if (!isDataURI(asmjsCodeFile)) { - asmjsCodeFile = Module['locateFile'](asmjsCodeFile); - } - } - - // utilities - - var wasmPageSize = 64*1024; - - var info = { - 'global': null, - 'env': null, - 'asm2wasm': asm2wasmImports, - 'parent': Module // Module inside wasm-js.cpp refers to wasm-js.cpp; this allows access to the outside program. - }; - - var exports = null; - -#if BINARYEN_METHOD != 'native-wasm' - function lookupImport(mod, base) { - var lookup = info; - if (mod.indexOf('.') < 0) { - lookup = (lookup || {})[mod]; - } else { - var parts = mod.split('.'); - lookup = (lookup || {})[parts[0]]; - lookup = (lookup || {})[parts[1]]; - } - if (base) { - lookup = (lookup || {})[base]; - } - if (lookup === undefined) { - abort('bad lookupImport to (' + mod + ').' + base); - } - return lookup; - } -#endif // BINARYEN_METHOD != 'native-wasm' - - function mergeMemory(newBuffer) { - // The wasm instance creates its memory. But static init code might have written to - // buffer already, including the mem init file, and we must copy it over in a proper merge. - // TODO: avoid this copy, by avoiding such static init writes - // TODO: in shorter term, just copy up to the last static init write - var oldBuffer = Module['buffer']; - if (newBuffer.byteLength < oldBuffer.byteLength) { - Module['printErr']('the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here'); - } - var oldView = new Int8Array(oldBuffer); - var newView = new Int8Array(newBuffer); - -#if MEM_INIT_IN_WASM == 0 - // If we have a mem init file, do not trample it - if (!memoryInitializer) { - oldView.set(newView.subarray(Module['STATIC_BASE'], Module['STATIC_BASE'] + Module['STATIC_BUMP']), Module['STATIC_BASE']); - } -#endif - - newView.set(oldView); - updateGlobalBuffer(newBuffer); - updateGlobalBufferViews(); - } - - function fixImports(imports) { -#if WASM_BACKEND - var ret = {}; - for (var i in imports) { - var fixed = i; - if (fixed[0] == '_') fixed = fixed.substr(1); - ret[fixed] = imports[i]; - } - return ret; -#else - return imports; -#endif // WASM_BACKEND - } - - function getBinary() { - try { - if (Module['wasmBinary']) { - return new Uint8Array(Module['wasmBinary']); - } -#if SUPPORT_BASE64_EMBEDDING - var binary = tryParseAsDataURI(wasmBinaryFile); - if (binary) { - return binary; - } -#endif - if (Module['readBinary']) { - return Module['readBinary'](wasmBinaryFile); - } else { - throw "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)"; - } - } - catch (err) { - abort(err); - } - } - - function getBinaryPromise() { - // if we don't have the binary yet, and have the Fetch api, use that - // in some environments, like Electron's render process, Fetch api may be present, but have a different context than expected, let's only use it on the Web - if (!Module['wasmBinary'] && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && typeof fetch === 'function') { - return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) { - if (!response['ok']) { - throw "failed to load wasm binary file at '" + wasmBinaryFile + "'"; - } - return response['arrayBuffer'](); - }).catch(function () { - return getBinary(); - }); - } - // Otherwise, getBinary should be able to get it synchronously - return new Promise(function(resolve, reject) { - resolve(getBinary()); - }); - } - - // do-method functions - -#if BINARYEN_METHOD != 'native-wasm' - function doJustAsm(global, env, providedBuffer) { - // if no Module.asm, or it's the method handler helper (see below), then apply - // the asmjs - if (typeof Module['asm'] !== 'function' || Module['asm'] === methodHandler) { - if (!Module['asmPreload']) { - // you can load the .asm.js file before this, to avoid this sync xhr and eval - {{{ makeEval("eval(Module['read'](asmjsCodeFile));") }}} // set Module.asm - } else { - Module['asm'] = Module['asmPreload']; - } - } - if (typeof Module['asm'] !== 'function') { - Module['printErr']('asm evalling did not set the module properly'); - return false; - } - return Module['asm'](global, env, providedBuffer); - } -#endif // BINARYEN_METHOD != 'native-wasm' - - function doNativeWasm(global, env, providedBuffer) { - if (typeof WebAssembly !== 'object') { -#if BINARYEN_METHOD == 'native-wasm' -#if ASSERTIONS - // when the method is just native-wasm, our error message can be very specific - abort('No WebAssembly support found. Build with -s WASM=0 to target JavaScript instead.'); -#endif -#endif - Module['printErr']('no native wasm support detected'); - return false; - } - // prepare memory import - if (!(Module['wasmMemory'] instanceof WebAssembly.Memory)) { - Module['printErr']('no native wasm Memory in use'); - return false; - } - env['memory'] = Module['wasmMemory']; - // Load the wasm module and create an instance of using native support in the JS engine. - info['global'] = { - 'NaN': NaN, - 'Infinity': Infinity - }; - info['global.Math'] = Math; - info['env'] = env; - // handle a generated wasm instance, receiving its exports and - // performing other necessary setup - function receiveInstance(instance, module) { - exports = instance.exports; - if (exports.memory) mergeMemory(exports.memory); - Module['asm'] = exports; - Module["usingWasm"] = true; -#if WASM_BACKEND - // wasm backend stack goes down - STACKTOP = STACK_BASE + TOTAL_STACK; - STACK_MAX = STACK_BASE; - // can't call stackRestore() here since this function can be called - // synchronously before stackRestore() is declared. - Module["asm"]["stackRestore"](STACKTOP); -#endif -#if USE_PTHREADS - // Keep a reference to the compiled module so we can post it to the workers. - Module['wasmModule'] = module; - // Instantiation is synchronous in pthreads and we assert on run dependencies. - if(!ENVIRONMENT_IS_PTHREAD) removeRunDependency('wasm-instantiate'); -#else - removeRunDependency('wasm-instantiate'); -#endif - } -#if USE_PTHREADS - if (!ENVIRONMENT_IS_PTHREAD) { - addRunDependency('wasm-instantiate'); // we can't run yet (except in a pthread, where we have a custom sync instantiator) - } -#else - addRunDependency('wasm-instantiate'); -#endif - - // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback - // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel - // to any other async startup actions they are performing. - if (Module['instantiateWasm']) { - try { - return Module['instantiateWasm'](info, receiveInstance); - } catch(e) { - Module['printErr']('Module.instantiateWasm callback failed with error: ' + e); - return false; - } - } - -#if BINARYEN_ASYNC_COMPILATION -#if RUNTIME_LOGGING - Module['printErr']('asynchronously preparing wasm'); -#endif -#if ASSERTIONS - // Async compilation can be confusing when an error on the page overwrites Module - // (for example, if the order of elements is wrong, and the one defining Module is - // later), so we save Module and check it later. - var trueModule = Module; -#endif - function receiveInstantiatedSource(output) { - // 'output' is a WebAssemblyInstantiatedSource object which has both the module and instance. - // receiveInstance() will swap in the exports (to Module.asm) so they can be called -#if ASSERTIONS - assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?'); - trueModule = null; -#endif - receiveInstance(output['instance'], output['module']); - } - function instantiateArrayBuffer(receiver) { - getBinaryPromise().then(function(binary) { - return WebAssembly.instantiate(binary, info); - }).then(receiver).catch(function(reason) { - Module['printErr']('failed to asynchronously prepare wasm: ' + reason); - abort(reason); - }); - } - // Prefer streaming instantiation if available. - if (!Module['wasmBinary'] && - typeof WebAssembly.instantiateStreaming === 'function' && - !isDataURI(wasmBinaryFile) && - typeof fetch === 'function') { - WebAssembly.instantiateStreaming(fetch(wasmBinaryFile, { credentials: 'same-origin' }), info) - .then(receiveInstantiatedSource) - .catch(function(reason) { - // We expect the most common failure cause to be a bad MIME type for the binary, - // in which case falling back to ArrayBuffer instantiation should work. - Module['printErr']('wasm streaming compile failed: ' + reason); - Module['printErr']('falling back to ArrayBuffer instantiation'); - instantiateArrayBuffer(receiveInstantiatedSource); - }); - } else { - instantiateArrayBuffer(receiveInstantiatedSource); - } - return {}; // no exports yet; we'll fill them in later -#else - var instance; - try { - instance = new WebAssembly.Instance(new WebAssembly.Module(getBinary()), info) - } catch (e) { - Module['printErr']('failed to compile wasm module: ' + e); - if (e.toString().indexOf('imported Memory with incompatible size') >= 0) { - 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).'); - } - return false; - } - receiveInstance(instance); - return exports; -#endif - } - -#if BINARYEN_METHOD != 'native-wasm' - function doWasmPolyfill(global, env, providedBuffer, method) { - if (typeof WasmJS !== 'function') { - Module['printErr']('WasmJS not detected - polyfill not bundled?'); - return false; - } - - // Use wasm.js to polyfill and execute code in a wasm interpreter. - var wasmJS = WasmJS({}); - - // XXX don't be confused. Module here is in the outside program. wasmJS is the inner wasm-js.cpp. - wasmJS['outside'] = Module; // Inside wasm-js.cpp, Module['outside'] reaches the outside module. - - // Information for the instance of the module. - wasmJS['info'] = info; - - wasmJS['lookupImport'] = lookupImport; - - 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. - - info.global = global; - info.env = env; - - // polyfill interpreter expects an ArrayBuffer - assert(providedBuffer === Module['buffer']); - env['memory'] = providedBuffer; - assert(env['memory'] instanceof ArrayBuffer); - - wasmJS['providedTotalMemory'] = Module['buffer'].byteLength; - - // Prepare to generate wasm, using either asm2wasm or s-exprs - var code; - if (method === 'interpret-binary') { - code = getBinary(); - } else { - code = Module['read'](method == 'interpret-asm2wasm' ? asmjsCodeFile : wasmTextFile); - } - var temp; - if (method == 'interpret-asm2wasm') { - temp = wasmJS['_malloc'](code.length + 1); - wasmJS['writeAsciiToMemory'](code, temp); - wasmJS['_load_asm2wasm'](temp); - } else if (method === 'interpret-s-expr') { - temp = wasmJS['_malloc'](code.length + 1); - wasmJS['writeAsciiToMemory'](code, temp); - wasmJS['_load_s_expr2wasm'](temp); - } else if (method === 'interpret-binary') { - temp = wasmJS['_malloc'](code.length); - wasmJS['HEAPU8'].set(code, temp); - wasmJS['_load_binary2wasm'](temp, code.length); - } else { - throw 'what? ' + method; - } - wasmJS['_free'](temp); - - wasmJS['_instantiate'](temp); - - if (Module['newBuffer']) { - mergeMemory(Module['newBuffer']); - Module['newBuffer'] = null; - } - - exports = wasmJS['asmExports']; - - return exports; - } -#endif // BINARYEN_METHOD != 'native-wasm' - - // We may have a preloaded value in Module.asm, save it - Module['asmPreload'] = Module['asm']; - - // Memory growth integration code - - var asmjsReallocBuffer = Module['reallocBuffer']; - - var wasmReallocBuffer = function(size) { - var PAGE_MULTIPLE = Module["usingWasm"] ? WASM_PAGE_SIZE : ASMJS_PAGE_SIZE; // In wasm, heap size must be a multiple of 64KB. In asm.js, they need to be multiples of 16MB. - size = alignUp(size, PAGE_MULTIPLE); // round up to wasm page size - var old = Module['buffer']; - var oldSize = old.byteLength; - if (Module["usingWasm"]) { - // native wasm support - try { - var result = Module['wasmMemory'].grow((size - oldSize) / wasmPageSize); // .grow() takes a delta compared to the previous size - if (result !== (-1 | 0)) { - // success in native wasm memory growth, get the buffer from the memory - return Module['buffer'] = Module['wasmMemory'].buffer; - } else { - return null; - } - } catch(e) { -#if ASSERTIONS - console.error('Module.reallocBuffer: Attempted to grow from ' + oldSize + ' bytes to ' + size + ' bytes, but got error: ' + e); -#endif - return null; - } - } -#if BINARYEN_METHOD != 'native-wasm' - else { - // wasm interpreter support - exports['__growWasmMemory']((size - oldSize) / wasmPageSize); // tiny wasm method that just does grow_memory - // in interpreter, we replace Module.buffer if we allocate - return Module['buffer'] !== old ? Module['buffer'] : null; // if it was reallocated, it changed - } -#endif // BINARYEN_METHOD != 'native-wasm' - }; - - Module['reallocBuffer'] = function(size) { - if (finalMethod === 'asmjs') { - return asmjsReallocBuffer(size); - } else { - return wasmReallocBuffer(size); - } - }; - - // we may try more than one; this is the final one, that worked and we are using - var finalMethod = ''; - - // Provide an "asm.js function" for the application, called to "link" the asm.js module. We instantiate - // the wasm module at that time, and it receives imports and provides exports and so forth, the app - // doesn't need to care that it is wasm or olyfilled wasm or asm.js. - - Module['asm'] = function(global, env, providedBuffer) { -#if BINARYEN_METHOD != 'native-wasm' - global = fixImports(global); -#endif - env = fixImports(env); - - // import table - if (!env['table']) { - var TABLE_SIZE = Module['wasmTableSize']; - if (TABLE_SIZE === undefined) TABLE_SIZE = 1024; // works in binaryen interpreter at least - var MAX_TABLE_SIZE = Module['wasmMaxTableSize']; - if (typeof WebAssembly === 'object' && typeof WebAssembly.Table === 'function') { - if (MAX_TABLE_SIZE !== undefined) { - env['table'] = new WebAssembly.Table({ 'initial': TABLE_SIZE, 'maximum': MAX_TABLE_SIZE, 'element': 'anyfunc' }); - } else { - env['table'] = new WebAssembly.Table({ 'initial': TABLE_SIZE, element: 'anyfunc' }); - } - } else { - env['table'] = new Array(TABLE_SIZE); // works in binaryen interpreter at least - } - Module['wasmTable'] = env['table']; - } - - if (!env['memoryBase']) { - env['memoryBase'] = Module['STATIC_BASE']; // tell the memory segments where to place themselves - } - if (!env['tableBase']) { - env['tableBase'] = 0; // table starts at 0 by default, in dynamic linking this will change - } - - // try the methods. each should return the exports if it succeeded - - var exports; -#if BINARYEN_METHOD == 'native-wasm' - exports = doNativeWasm(global, env, providedBuffer); -#else // native-wasm -#if BINARYEN_METHOD == 'asmjs' - exports = doJustAsm(global, env, providedBuffer); -#else - var methods = method.split(','); - - for (var i = 0; i < methods.length; i++) { - var curr = methods[i]; - -#if RUNTIME_LOGGING - Module['printErr']('trying binaryen method: ' + curr); -#endif - - finalMethod = curr; - - if (curr === 'native-wasm') { - if (exports = doNativeWasm(global, env, providedBuffer)) break; - } else if (curr === 'asmjs') { - if (exports = doJustAsm(global, env, providedBuffer)) break; - } else if (curr === 'interpret-asm2wasm' || curr === 'interpret-s-expr' || curr === 'interpret-binary') { - if (exports = doWasmPolyfill(global, env, providedBuffer, curr)) break; - } else { - abort('bad method: ' + curr); - } - } -#endif // asmjs -#endif // native-wasm - -#if ASSERTIONS - assert(exports, 'no binaryen method succeeded. consider enabling more options, like interpreting, if you want that: https://github.com/kripken/emscripten/wiki/WebAssembly#binaryen-methods'); -#else - assert(exports, 'no binaryen method succeeded.'); -#endif - -#if RUNTIME_LOGGING - Module['printErr']('binaryen method succeeded.'); -#endif - - return exports; - }; - - var methodHandler = Module['asm']; // note our method handler, as we may modify Module['asm'] later -} - -integrateWasmJS(); -#endif - -// === Body === diff --git a/emsdk/files/support.js b/emsdk/files/support.js deleted file mode 100644 index 59641a1cc..000000000 --- a/emsdk/files/support.js +++ /dev/null @@ -1,546 +0,0 @@ -// {{PREAMBLE_ADDITIONS}} - -var STACK_ALIGN = {{{ STACK_ALIGN }}}; - -#if ASSERTIONS -// stack management, and other functionality that is provided by the compiled code, -// should not be used before it is ready -stackSave = stackRestore = stackAlloc = setTempRet0 = getTempRet0 = function() { - abort('cannot use the stack before compiled code is ready to run, and has provided stack access'); -}; -#endif - -function staticAlloc(size) { - assert(!staticSealed); - var ret = STATICTOP; - STATICTOP = (STATICTOP + size + 15) & -16; - return ret; -} - -function dynamicAlloc(size) { - assert(DYNAMICTOP_PTR); - var ret = HEAP32[DYNAMICTOP_PTR>>2]; - var end = (ret + size + 15) & -16; - HEAP32[DYNAMICTOP_PTR>>2] = end; - if (end >= TOTAL_MEMORY) { - var success = enlargeMemory(); - if (!success) { - HEAP32[DYNAMICTOP_PTR>>2] = ret; - return 0; - } - } - return ret; -} - -{{{ alignMemory }}} - -{{{ getNativeTypeSize }}} - -function warnOnce(text) { - if (!warnOnce.shown) warnOnce.shown = {}; - if (!warnOnce.shown[text]) { - warnOnce.shown[text] = 1; - Module.printErr(text); - } -} - -var asm2wasmImports = { // special asm2wasm imports - "f64-rem": function(x, y) { - return x % y; - }, - "debugger": function() { - debugger; - } -#if NEED_ALL_ASM2WASM_IMPORTS - , - "f64-to-int": function(x) { - return x | 0; - }, - "i32s-div": function(x, y) { - return ((x | 0) / (y | 0)) | 0; - }, - "i32u-div": function(x, y) { - return ((x >>> 0) / (y >>> 0)) >>> 0; - }, - "i32s-rem": function(x, y) { - return ((x | 0) % (y | 0)) | 0; - }, - "i32u-rem": function(x, y) { - return ((x >>> 0) % (y >>> 0)) >>> 0; - } -#endif // NEED_ALL_ASM2WASM_IMPORTS -}; - -#if RELOCATABLE -var loadedDynamicLibraries = []; - -function loadDynamicLibrary(lib) { - var libModule; -#if WASM - var bin; - if (lib.buffer) { - // we were provided the binary, in a typed array - bin = lib; - } else { - // load the binary synchronously - bin = Module['readBinary'](lib); - } - libModule = loadWebAssemblyModule(bin); -#else - var src = Module['read'](lib); - libModule = eval(src)( - alignFunctionTables(), - Module - ); -#endif - // add symbols into global namespace TODO: weak linking etc. - for (var sym in libModule) { - if (!Module.hasOwnProperty(sym)) { - Module[sym] = libModule[sym]; - } -#if ASSERTIONS == 2 - else if (sym[0] === '_') { - var curr = Module[sym], next = libModule[sym]; - // don't warn on functions - might be odr, linkonce_odr, etc. - if (!(typeof curr === 'function' && typeof next === 'function')) { - Module.printErr("warning: trying to dynamically load symbol '" + sym + "' (from '" + lib + "') that already exists (duplicate symbol? or weak linking, which isn't supported yet?)"); // + [curr, ' vs ', next]); - } - } -#endif - } - loadedDynamicLibraries.push(libModule); -} - -#if WASM -// Loads a side module from binary data -function loadWebAssemblyModule(binary, loadAsync) { - var int32View = new Uint32Array(new Uint8Array(binary.subarray(0, 24)).buffer); - assert(int32View[0] == 0x6d736100, 'need to see wasm magic number'); // \0wasm - // we should see the dylink section right after the magic number and wasm version - assert(binary[8] === 0, 'need the dylink section to be first') - var next = 9; - function getLEB() { - var ret = 0; - var mul = 1; - while (1) { - var byte = binary[next++]; - ret += ((byte & 0x7f) * mul); - mul *= 0x80; - if (!(byte & 0x80)) break; - } - return ret; - } - var sectionSize = getLEB(); - assert(binary[next] === 6); next++; // size of "dylink" string - assert(binary[next] === 'd'.charCodeAt(0)); next++; - assert(binary[next] === 'y'.charCodeAt(0)); next++; - assert(binary[next] === 'l'.charCodeAt(0)); next++; - assert(binary[next] === 'i'.charCodeAt(0)); next++; - assert(binary[next] === 'n'.charCodeAt(0)); next++; - assert(binary[next] === 'k'.charCodeAt(0)); next++; - var memorySize = getLEB(); - var memoryAlign = getLEB(); - var tableSize = getLEB(); - var tableAlign = getLEB(); - // alignments are powers of 2 - memoryAlign = Math.pow(2, memoryAlign); - tableAlign = Math.pow(2, tableAlign); - // finalize alignments and verify them - memoryAlign = Math.max(memoryAlign, STACK_ALIGN); // we at least need stack alignment - assert(tableAlign === 1); - // prepare memory - var memoryStart = alignMemory(getMemory(memorySize + memoryAlign), memoryAlign); // TODO: add to cleanups - // The static area consists of explicitly initialized data, followed by zero-initialized data. - // The latter may need zeroing out if the MAIN_MODULE has already used this memory area before - // dlopen'ing the SIDE_MODULE. Since we don't know the size of the explicitly initialized data - // here, we just zero the whole thing, which is suboptimal, but should at least resolve bugs - // from uninitialized memory. - for (var i = memoryStart; i < memoryStart + memorySize; ++i) HEAP8[i] = 0; - // prepare env imports - var env = Module['asmLibraryArg']; - // TODO: use only memoryBase and tableBase, need to update asm.js backend - var table = Module['wasmTable']; - var oldTableSize = table.length; - env['memoryBase'] = env['gb'] = memoryStart; - env['tableBase'] = env['fb'] = oldTableSize; - var originalTable = table; - table.grow(tableSize); - assert(table === originalTable); - // zero-initialize memory and table TODO: in some cases we can tell it is already zero initialized - for (var i = env['memoryBase']; i < env['memoryBase'] + memorySize; i++) { - HEAP8[i] = 0; - } - for (var i = env['tableBase']; i < env['tableBase'] + tableSize; i++) { - table.set(i, null); - } - // copy currently exported symbols so the new module can import them - for (var x in Module) { - if (!(x in env)) { - env[x] = Module[x]; - } - } - var info = { - global: { - 'NaN': NaN, - 'Infinity': Infinity, - }, - 'global.Math': Math, - env: env, - 'asm2wasm': asm2wasmImports - }; -#if ASSERTIONS - var oldTable = []; - for (var i = 0; i < oldTableSize; i++) { - oldTable.push(table.get(i)); - } -#endif - - function postInstantiation(instance) { - var exports = {}; -#if ASSERTIONS - // the table should be unchanged - assert(table === originalTable); - assert(table === Module['wasmTable']); - if (instance.exports['table']) { - assert(table === instance.exports['table']); - } - // the old part of the table should be unchanged - for (var i = 0; i < oldTableSize; i++) { - assert(table.get(i) === oldTable[i], 'old table entries must remain the same'); - } - // verify that the new table region was filled in - for (var i = 0; i < tableSize; i++) { - assert(table.get(oldTableSize + i) !== undefined, 'table entry was not filled in'); - } -#endif - for (var e in instance.exports) { - var value = instance.exports[e]; - if (typeof value === 'object') { - // a breaking change in the wasm spec, globals are now objects - // https://github.com/WebAssembly/mutable-global/issues/1 - value = value.value; - } - if (typeof value === 'number') { - // relocate it - modules export the absolute value, they can't relocate before they export -#if EMULATED_FUNCTION_POINTERS - // it may be a function pointer - if (e.substr(0, 3) == 'fp$' && typeof instance.exports[e.substr(3)] === 'function') { - value = value + env['tableBase']; - } else { -#endif - value = value + env['memoryBase']; -#if EMULATED_FUNCTION_POINTERS - } -#endif - } - exports[e] = value; - } - // initialize the module - var init = exports['__post_instantiate']; - if (init) { - if (runtimeInitialized) { - init(); - } else { - // we aren't ready to run compiled code yet - __ATINIT__.push(init); - } - } - return exports; - } - - if (loadAsync) { - return WebAssembly.instantiate(binary, info).then(function(result) { - return postInstantiation(result.instance); - }); - } else { - var instance = new WebAssembly.Instance(new WebAssembly.Module(binary), info); - return postInstantiation(instance); - } -} -Module['loadWebAssemblyModule'] = loadWebAssemblyModule; - -#endif // WASM -#endif // RELOCATABLE - -#if EMULATED_FUNCTION_POINTERS -function getFunctionTables(module) { - if (!module) module = Module; - var tables = {}; - for (var t in module) { - if (/^FUNCTION_TABLE_.*/.test(t)) { - var table = module[t]; - if (typeof table === 'object') tables[t.substr('FUNCTION_TABLE_'.length)] = table; - } - } - return tables; -} - -function alignFunctionTables(module) { - var tables = getFunctionTables(module); - var maxx = 0; - for (var sig in tables) { - maxx = Math.max(maxx, tables[sig].length); - } - assert(maxx >= 0); - for (var sig in tables) { - var table = tables[sig]; - while (table.length < maxx) table.push(0); - } - return maxx; -} - -#if RELOCATABLE -// register functions from a new module being loaded -function registerFunctions(sigs, newModule) { - sigs.forEach(function(sig) { - if (!Module['FUNCTION_TABLE_' + sig]) { - Module['FUNCTION_TABLE_' + sig] = []; - } - }); - var oldMaxx = alignFunctionTables(); // align the new tables we may have just added - var newMaxx = alignFunctionTables(newModule); - var maxx = oldMaxx + newMaxx; - sigs.forEach(function(sig) { - var newTable = newModule['FUNCTION_TABLE_' + sig]; - var oldTable = Module['FUNCTION_TABLE_' + sig]; - assert(newTable !== oldTable); - assert(oldTable.length === oldMaxx); - for (var i = 0; i < newTable.length; i++) { - oldTable.push(newTable[i]); - } - assert(oldTable.length === maxx); - }); - assert(maxx === alignFunctionTables()); // align the ones we didn't touch -} -// export this so side modules can use it -Module['registerFunctions'] = registerFunctions; -#endif // RELOCATABLE -#endif // EMULATED_FUNCTION_POINTERS - -#if WASM_BACKEND_WITH_RESERVED_FUNCTION_POINTERS -var jsCallStartIndex = {{{ JSCALL_START_INDEX }}}; -var jsCallSigOrder = {{{ JSON.stringify(JSCALL_SIG_ORDER) }}}; -var jsCallNumSigs = Object.keys(jsCallSigOrder).length; -var functionPointers = new Array(jsCallNumSigs * {{{ RESERVED_FUNCTION_POINTERS }}}); -#else // WASM_BACKEND_WITH_RESERVED_FUNCTION_POINTERS == 0 -var jsCallStartIndex = 1; -var functionPointers = new Array({{{ RESERVED_FUNCTION_POINTERS }}}); -#endif // WASM_BACKEND_WITH_RESERVED_FUNCTION_POINTERS - -// 'sig' parameter is only used on LLVM wasm backend -function addFunction(func, sig) { -#if WASM_BACKEND - assert(typeof sig !== 'undefined', - 'Second argument of addFunction should be a wasm function signature ' + - 'string'); -#endif // WASM_BACKEND -#if ASSERTIONS - if (typeof sig === 'undefined') { - Module.printErr('warning: addFunction(): You should provide a wasm function signature string as a second argument. This is not necessary for asm.js and asm2wasm, but is required for the LLVM wasm backend, so it is recommended for full portability.'); - } -#endif // ASSERTIONS -#if EMULATED_FUNCTION_POINTERS == 0 -#if WASM_BACKEND_WITH_RESERVED_FUNCTION_POINTERS - var base = jsCallSigOrder[sig] * {{{ RESERVED_FUNCTION_POINTERS }}}; -#else // WASM_BACKEND_WITH_RESERVED_FUNCTION_POINTERS == 0 - var base = 0; -#endif // WASM_BACKEND_WITH_RESERVED_FUNCTION_POINTERS - for (var i = base; i < base + {{{ RESERVED_FUNCTION_POINTERS }}}; i++) { - if (!functionPointers[i]) { - functionPointers[i] = func; - return jsCallStartIndex + i; - } - } - throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.'; -#else -#if WASM - // we can simply append to the wasm table - var table = Module['wasmTable']; - var ret = table.length; - table.grow(1); - table.set(ret, func); - return ret; -#else - alignFunctionTables(); // XXX we should rely on this being an invariant - var tables = getFunctionTables(); - var ret = -1; - for (var sig in tables) { - var table = tables[sig]; - if (ret < 0) ret = table.length; - else assert(ret === table.length); - table.push(func); - } - return ret; -#endif -#endif -} - -function removeFunction(index) { -#if EMULATED_FUNCTION_POINTERS == 0 - functionPointers[index-jsCallStartIndex] = null; -#else - alignFunctionTables(); // XXX we should rely on this being an invariant - var tables = getFunctionTables(); - for (var sig in tables) { - tables[sig][index] = null; - } -#endif -} - -var funcWrappers = {}; - -function getFuncWrapper(func, sig) { - if (!func) return; // on null pointer, return undefined - assert(sig); - if (!funcWrappers[sig]) { - funcWrappers[sig] = {}; - } - var sigCache = funcWrappers[sig]; - if (!sigCache[func]) { - // optimize away arguments usage in common cases - if (sig.length === 1) { - sigCache[func] = function dynCall_wrapper() { - return dynCall(sig, func); - }; - } else if (sig.length === 2) { - sigCache[func] = function dynCall_wrapper(arg) { - return dynCall(sig, func, [arg]); - }; - } else { - // general case - sigCache[func] = function dynCall_wrapper() { - return dynCall(sig, func, Array.prototype.slice.call(arguments)); - }; - } - } - return sigCache[func]; -} - -#if RUNTIME_DEBUG -var runtimeDebug = true; // Switch to false at runtime to disable logging at the right times - -var printObjectList = []; - -function prettyPrint(arg) { - if (typeof arg == 'undefined') return '!UNDEFINED!'; - if (typeof arg == 'boolean') arg = arg + 0; - if (!arg) return arg; - var index = printObjectList.indexOf(arg); - if (index >= 0) return '<' + arg + '|' + index + '>'; - if (arg.toString() == '[object HTMLImageElement]') { - return arg + '\n\n'; - } - if (arg.byteLength) { - return '{' + Array.prototype.slice.call(arg, 0, Math.min(arg.length, 400)) + '}'; // Useful for correct arrays, less so for compiled arrays, see the code below for that - var buf = new ArrayBuffer(32); - var i8buf = new Int8Array(buf); - var i16buf = new Int16Array(buf); - var f32buf = new Float32Array(buf); - switch(arg.toString()) { - case '[object Uint8Array]': - i8buf.set(arg.subarray(0, 32)); - break; - case '[object Float32Array]': - f32buf.set(arg.subarray(0, 5)); - break; - case '[object Uint16Array]': - i16buf.set(arg.subarray(0, 16)); - break; - default: - alert('unknown array for debugging: ' + arg); - throw 'see alert'; - } - var ret = '{' + arg.byteLength + ':\n'; - var arr = Array.prototype.slice.call(i8buf); - ret += 'i8:' + arr.toString().replace(/,/g, ',') + '\n'; - arr = Array.prototype.slice.call(f32buf, 0, 8); - ret += 'f32:' + arr.toString().replace(/,/g, ',') + '}'; - return ret; - } - if (typeof arg == 'object') { - printObjectList.push(arg); - return '<' + arg + '|' + (printObjectList.length-1) + '>'; - } - if (typeof arg == 'number') { - if (arg > 0) return '0x' + arg.toString(16) + ' (' + arg + ')'; - } - return arg; -} -#endif - -function makeBigInt(low, high, unsigned) { - return unsigned ? ((+((low>>>0)))+((+((high>>>0)))*4294967296.0)) : ((+((low>>>0)))+((+((high|0)))*4294967296.0)); -} - -function dynCall(sig, ptr, args) { - if (args && args.length) { -#if ASSERTIONS - assert(args.length == sig.length-1); -#endif -#if ASSERTIONS - assert(('dynCall_' + sig) in Module, 'bad function pointer type - no table for sig \'' + sig + '\''); -#endif - return Module['dynCall_' + sig].apply(null, [ptr].concat(args)); - } else { -#if ASSERTIONS - assert(sig.length == 1); -#endif -#if ASSERTIONS - assert(('dynCall_' + sig) in Module, 'bad function pointer type - no table for sig \'' + sig + '\''); -#endif - return Module['dynCall_' + sig].call(null, ptr); - } -} - -#if RELOCATABLE -// tempRet0 is normally handled in the module. but in relocatable code, -// we need to share a single one among all the modules, so they all call -// out. -var tempRet0 = 0; - -var setTempRet0 = function(value) { - tempRet0 = value; -} - -var getTempRet0 = function() { - return tempRet0; -} -#endif // RELOCATABLE - -#if RETAIN_COMPILER_SETTINGS -var compilerSettings = {{{ JSON.stringify(makeRetainedCompilerSettings()) }}} ; - -function getCompilerSetting(name) { - if (!(name in compilerSettings)) return 'invalid compiler setting: ' + name; - return compilerSettings[name]; -} -#else // RETAIN_COMPILER_SETTINGS -#if ASSERTIONS -function getCompilerSetting(name) { - throw 'You must build with -s RETAIN_COMPILER_SETTINGS=1 for getCompilerSetting or emscripten_get_compiler_setting to work'; -} -#endif // ASSERTIONS -#endif // RETAIN_COMPILER_SETTINGS - -var Runtime = { - // FIXME backwards compatibility layer for ports. Support some Runtime.* - // for now, fix it there, then remove it from here. That way we - // can minimize any period of breakage. - dynCall: dynCall, // for SDL2 port -#if ASSERTIONS - // helpful errors - getTempRet0: function() { abort('getTempRet0() is now a top-level function, after removing the Runtime object. Remove "Runtime."') }, - staticAlloc: function() { abort('staticAlloc() is now a top-level function, after removing the Runtime object. Remove "Runtime."') }, - stackAlloc: function() { abort('stackAlloc() is now a top-level function, after removing the Runtime object. Remove "Runtime."') }, -#endif -}; - -// The address globals begin at. Very low in memory, for code size and optimization opportunities. -// Above 0 is static memory, starting with globals. -// Then the stack. -// Then 'dynamic' memory for sbrk. -var GLOBAL_BASE = {{{ GLOBAL_BASE }}}; - -#if RELOCATABLE -GLOBAL_BASE = alignMemory(GLOBAL_BASE, {{{ MAX_GLOBAL_ALIGN || 1 }}}); -#endif diff --git a/emsdk/patches/float-remainder-in-side-module.patch b/emsdk/patches/float-remainder-in-side-module.patch deleted file mode 100644 index 945e28f2f..000000000 --- a/emsdk/patches/float-remainder-in-side-module.patch +++ /dev/null @@ -1,38 +0,0 @@ -index f6c9842ff..9f83181eb 100644 ---- a/emsdk/emscripten/tag-1.38.4/src/support.js -+++ b/emsdk/emscripten/tag-1.38.4/src/support.js -@@ -158,7 +158,33 @@ function loadWebAssemblyModule(binary) { - 'Infinity': Infinity, - }, - 'global.Math': Math, -- env: env -+ env: env, -+ 'asm2wasm': { // special asm2wasm imports -+ "f64-rem": function(x, y) { -+ return x % y; -+ }, -+ "debugger": function() { -+ debugger; -+ } -+#if NEED_ALL_ASM2WASM_IMPORTS -+ , -+ "f64-to-int": function(x) { -+ return x | 0; -+ }, -+ "i32s-div": function(x, y) { -+ return ((x | 0) / (y | 0)) | 0; -+ }, -+ "i32u-div": function(x, y) { -+ return ((x >>> 0) / (y >>> 0)) >>> 0; -+ }, -+ "i32s-rem": function(x, y) { -+ return ((x | 0) % (y | 0)) | 0; -+ }, -+ "i32u-rem": function(x, y) { -+ return ((x >>> 0) % (y >>> 0)) >>> 0; -+ } -+#endif // NEED_ALL_ASM2WASM_IMPORTS -+ }, - }; - #if ASSERTIONS - var oldTable = []; From 3c08f1541de7078df5198e01a61ba4e03f522e34 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Tue, 24 Jul 2018 12:27:34 -0400 Subject: [PATCH 2/4] Fix emsdk build --- emsdk/Makefile | 1 - emsdk/patches/num_params.patch | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/emsdk/Makefile b/emsdk/Makefile index 1c7164ab1..dfd1cdbd7 100644 --- a/emsdk/Makefile +++ b/emsdk/Makefile @@ -15,7 +15,6 @@ emsdk/.complete: cd emsdk/binaryen/tag-1.38.10_64bit_binaryen/ ; \ make ; \ cd ../.. ; \ - cp binaryen/tag-1.38.10/bin/binaryen.js binaryen/tag-1.38.10_64bit_binaryen/bin ; \ ./emsdk activate --embedded --build=Release sdk-tag-1.38.10-64bit binaryen-tag-1.38.10-64bit ; \ touch .complete \ ) diff --git a/emsdk/patches/num_params.patch b/emsdk/patches/num_params.patch index da53a234e..e46c966d0 100644 --- a/emsdk/patches/num_params.patch +++ b/emsdk/patches/num_params.patch @@ -1,7 +1,7 @@ diff --git a/emsdk/binaryen/master/src/passes/FuncCastEmulation.cpp b/emsdk/binaryen/master/src/passes/FuncCastEmulation.cpp index 013e9403..d95fc282 100644 ---- a/emsdk/binaryen/tag-1.38.4/src/passes/FuncCastEmulation.cpp -+++ b/emsdk/binaryen/tag-1.38.4/src/passes/FuncCastEmulation.cpp +--- a/emsdk/binaryen/tag-1.38.10/src/passes/FuncCastEmulation.cpp ++++ b/emsdk/binaryen/tag-1.38.10/src/passes/FuncCastEmulation.cpp @@ -39,7 +39,7 @@ namespace wasm { // This should be enough for everybody. (As described above, we need this // to match when dynamically linking, and also dynamic linking is why we @@ -10,4 +10,4 @@ index 013e9403..d95fc282 100644 +static const int NUM_PARAMS = 32; // Converts a value to the ABI type of i64. - static Expression* toABI(Expression* value, Module* module) { \ No newline at end of file + static Expression* toABI(Expression* value, Module* module) { From a02c2de983f9719bcee1550ed9c08b9d5fc7c3a5 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Tue, 24 Jul 2018 12:41:08 -0400 Subject: [PATCH 3/4] Fix paths --- Makefile | 2 +- Makefile.envs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 7009df95e..220a2328f 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ PYODIDE_ROOT=$(abspath .) include Makefile.envs -FILEPACKAGER=emsdk/emsdk/emscripten/tag-1.38.4/tools/file_packager.py +FILEPACKAGER=emsdk/emsdk/emscripten/tag-1.38.10/tools/file_packager.py CPYTHONROOT=cpython CPYTHONLIB=$(CPYTHONROOT)/installs/python-$(PYVERSION)/lib/python$(PYMINOR) diff --git a/Makefile.envs b/Makefile.envs index 419fd8252..20307504b 100644 --- a/Makefile.envs +++ b/Makefile.envs @@ -1,4 +1,4 @@ -export PATH := $(PYODIDE_ROOT)/ccache:$(PYODIDE_ROOT)/emsdk/emsdk:$(PYODIDE_ROOT)/emsdk/emsdk/clang/tag-e-1.38.4/build_tag-e1.38.10_64/bin:$(PYODIDE_ROOT)/emsdk/emsdk/node/8.9.1_64bit/bin:$(PYODIDE_ROOT)/emsdk/emsdk/emscripten/tag-1.38.10:$(PYODIDE_ROOT)/emsdk/emsdk/binaryen/tag-1.38.10_64bit_binaryen/bin:$(PATH) +export PATH := $(PYODIDE_ROOT)/ccache:$(PYODIDE_ROOT)/emsdk/emsdk:$(PYODIDE_ROOT)/emsdk/emsdk/clang/tag-e-1.38.10/build_tag-e1.38.10_64/bin:$(PYODIDE_ROOT)/emsdk/emsdk/node/8.9.1_64bit/bin:$(PYODIDE_ROOT)/emsdk/emsdk/emscripten/tag-1.38.10:$(PYODIDE_ROOT)/emsdk/emsdk/binaryen/tag-1.38.10_64bit_binaryen/bin:$(PATH) export EMSDK = $(PYODIDE_ROOT)/emsdk/emsdk export EM_CONFIG = $(PYODIDE_ROOT)/emsdk/emsdk/.emscripten From b3d8e4c2a7973792d98fd3f0790684a127a29d1c Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Tue, 24 Jul 2018 12:53:17 -0400 Subject: [PATCH 4/4] Add another symbol to force inclusion of C++ exceptions --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 220a2328f..4094398ec 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ LDFLAGS=\ -s MAIN_MODULE=1 \ -s EMULATED_FUNCTION_POINTERS=1 \ -s EMULATE_FUNCTION_POINTER_CASTS=1 \ - -s EXPORTED_FUNCTIONS='["_main", "__ZNKSt3__220__vector_base_commonILb1EE20__throw_length_errorEv"]' \ + -s EXPORTED_FUNCTIONS='["_main", "__ZNKSt3__220__vector_base_commonILb1EE20__throw_length_errorEv", "__ZNSt11logic_errorC2EPKc"]' \ -s WASM=1 \ -s SWAPPABLE_ASM_MODULE=1 \ -s USE_FREETYPE=1 \