diff options
-rw-r--r-- | src/intertyper.js | 3 | ||||
-rw-r--r-- | src/library.js | 51 | ||||
-rw-r--r-- | src/library_browser.js | 4 | ||||
-rw-r--r-- | src/library_sdl.js | 2 | ||||
-rw-r--r-- | src/preamble.js | 2 | ||||
-rw-r--r-- | src/runtime.js | 12 | ||||
-rw-r--r-- | system/include/emscripten/emscripten.h | 31 | ||||
-rw-r--r-- | tests/test_core.py | 12 |
8 files changed, 94 insertions, 23 deletions
diff --git a/src/intertyper.js b/src/intertyper.js index f92a04db..940c677f 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -660,9 +660,10 @@ function intertyper(lines, sidePass, baseLineNums) { var tokensLeft = item.tokens.slice(2); item.ident = eatLLVMIdent(tokensLeft); if (item.ident == 'asm') { + warnOnce('inline JavaScript using asm() has some oddities due to how gcc asm() syntax works. use EM_ASM where possible (see emscripten.h)'); if (ASM_JS) { Types.hasInlineJS = true; - warnOnce('inline JavaScript (asm, EM_ASM) will cause the code to no longer fall in the asm.js subset of JavaScript, which can reduce performance - consider using emscripten_run_script'); + warnOnce('inline JavaScript using asm() will cause the code to no longer fall in the asm.js subset of JavaScript, which can reduce performance - consider using emscripten_run_script'); } assert(TARGET_LE32, 'inline js is only supported in le32'); // Inline assembly is just JavaScript that we paste into the code diff --git a/src/library.js b/src/library.js index 6d821bfc..16089bc4 100644 --- a/src/library.js +++ b/src/library.js @@ -3193,7 +3193,7 @@ LibraryManager.library = { } } if (!finalBase) finalBase = 10; - start = str; + var start = str; // Get digits. var chr; @@ -6122,7 +6122,7 @@ LibraryManager.library = { clock_gettime: function(clk_id, tp) { // int clock_gettime(clockid_t clk_id, struct timespec *tp); var now; - if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) { + if (clk_id === {{{ cDefine('CLOCK_REALTIME') }}}) { now = Date.now(); } else { now = _emscripten_get_now(); @@ -6136,10 +6136,17 @@ LibraryManager.library = { // Nothing. return 0; }, + clock_getres__deps: ['emscripten_get_now_res'], 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; + } else { + nsec = _emscripten_get_now_res(); + } {{{ makeSetValue('res', C_STRUCTS.timespec.tv_sec, '1', 'i32') }}} - {{{ makeSetValue('res', C_STRUCTS.timespec.tv_nsec, '1000 * 1000', 'i32') }}} // resolution is milliseconds + {{{ makeSetValue('res', C_STRUCTS.timespec.tv_nsec, 'nsec', 'i32') }}} // resolution is milliseconds return 0; }, @@ -8669,21 +8676,28 @@ LibraryManager.library = { }, emscripten_asm_const: function(code) { - // code is a constant string on the heap, so we can cache these - if (!Runtime.asmConstCache) Runtime.asmConstCache = {}; - var func = Runtime.asmConstCache[code]; - if (func) return func(); - func = Runtime.asmConstCache[code] = eval('(function(){ ' + Pointer_stringify(code) + ' })'); // new Function does not allow upvars in node - return func(); + Runtime.getAsmConst(code, 0)(); + }, + + emscripten_asm_const_int__jsargs: true, + emscripten_asm_const_int: function(code) { + var args = Array.prototype.slice.call(arguments, 1); + return Runtime.getAsmConst(code, args.length).apply(null, args) | 0; + }, + + emscripten_asm_const_double__jsargs: true, + emscripten_asm_const_double: function(code) { + var args = Array.prototype.slice.call(arguments, 1); + return +Runtime.getAsmConst(code, args.length).apply(null, args); }, emscripten_get_now: function() { if (!_emscripten_get_now.actual) { if (ENVIRONMENT_IS_NODE) { - _emscripten_get_now.actual = function _emscripten_get_now_actual() { - var t = process['hrtime'](); - return t[0] * 1e3 + t[1] / 1e6; - } + _emscripten_get_now.actual = function _emscripten_get_now_actual() { + var t = process['hrtime'](); + return t[0] * 1e3 + t[1] / 1e6; + } } else if (typeof dateNow !== 'undefined') { _emscripten_get_now.actual = dateNow; } else if (ENVIRONMENT_IS_WEB && window['performance'] && window['performance']['now']) { @@ -8695,6 +8709,17 @@ LibraryManager.library = { return _emscripten_get_now.actual(); }, + 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 && window['performance'] && window['performance']['now'])) { + return 1000; // microseconds (1/1000 of a millisecond) + } else { + return 1000*1000; // milliseconds + } + }, + //============================ // emscripten vector ops //============================ diff --git a/src/library_browser.js b/src/library_browser.js index 1883c3be..8444fb73 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -250,7 +250,9 @@ mergeInto(LibraryManager.library, { contextAttributes.preserveDrawingBuffer = true; #endif - ctx = canvas.getContext('experimental-webgl', contextAttributes); + ['experimental-webgl', 'webgl'].some(function(webglId) { + return ctx = canvas.getContext(webglId, contextAttributes); + }); } else { ctx = canvas.getContext('2d'); } diff --git a/src/library_sdl.js b/src/library_sdl.js index f780e15a..eb8eea97 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -2675,7 +2675,7 @@ var LibrarySDL = { SDL_WaitThread: function() { throw 'SDL_WaitThread' }, SDL_GetThreadID: function() { throw 'SDL_GetThreadID' }, - SDL_ThreadID: function() { throw 'SDL_ThreadID' }, + SDL_ThreadID: function() { return 0; }, SDL_AllocRW: function() { throw 'SDL_AllocRW: TODO' }, SDL_CondBroadcast: function() { throw 'SDL_CondBroadcast: TODO' }, SDL_CondWaitTimeout: function() { throw 'SDL_CondWaitTimeout: TODO' }, diff --git a/src/preamble.js b/src/preamble.js index 27016c14..ff9200fc 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -246,7 +246,7 @@ var EXITSTATUS = 0; var undef = 0; // tempInt is used for 32-bit signed values or smaller. tempBigInt is used // for 32-bit unsigned values or more than 32 bits. TODO: audit all uses of tempInt -var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD; +var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD, tempDouble, tempFloat; #if USE_TYPED_ARRAYS == 2 var tempI64, tempI64b; var tempRet0, tempRet1, tempRet2, tempRet3, tempRet4, tempRet5, tempRet6, tempRet7, tempRet8, tempRet9; diff --git a/src/runtime.js b/src/runtime.js index 786ae021..dedaf5ea 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -381,6 +381,18 @@ var Runtime = { #endif }, + getAsmConst: function(code, numArgs) { + // code is a constant string on the heap, so we can cache these + if (!Runtime.asmConstCache) Runtime.asmConstCache = {}; + var func = Runtime.asmConstCache[code]; + if (func) return func; + var args = []; + for (var i = 0; i < numArgs; i++) { + args.push(String.fromCharCode(36) + i); // $0, $1 etc + } + return Runtime.asmConstCache[code] = eval('(function(' + args.join(',') + '){ ' + Pointer_stringify(code) + ' })'); // new Function does not allow upvars in node + }, + warnOnce: function(text) { if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {}; if (!Runtime.warnOnce.shown[text]) { diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h index ac880981..ddcbc43a 100644 --- a/system/include/emscripten/emscripten.h +++ b/system/include/emscripten/emscripten.h @@ -24,17 +24,38 @@ extern "C" { * EM_ASM(window.alert('hai')); * * This also works with asm.js, as it outlines the code (it - * does a function call to reach it). + * does a function call to reach it). It supports newlines, * - * Notes: double-quotes (") are not supported, but you can use + * EM_ASM( + * window.alert('hai')); + * window.alert('bai')); + * ) + * + * Notes: Double-quotes (") are not supported, but you can use * single-quotes (') in js anyhow. * - * you can't access C variables with EM_ASM, use gcc - * inline asm for that, asm("code" : .. etc.) + * You can't access C variables with EM_ASM, nor receive + * a value back. use EM_ASM_INT or EM_ASM_DOUBLE for that */ #define EM_ASM(...) emscripten_asm_const(#__VA_ARGS__) /* + * Input-output versions of EM_ASM. EM_ASM_INT receives arguments of + * either int or double type and returns an int; EM_ASM_DOUBLE + * receives similar arguments (int or double) but returns a double. + * Arguments arrive as $0, $1 etc; output value should be returned: + * + * int x = EM_ASM_INT({ + * console.log('I received: ' + [$0, $1]); + * return $0 + $1; + * }, calc(), otherCalc()); + * + * Note the {,} + */ +#define EM_ASM_INT(code, ...) emscripten_asm_const_int(#code, __VA_ARGS__) +#define EM_ASM_DOUBLE(code, ...) emscripten_asm_const_double(#code, __VA_ARGS__) + +/* * Forces LLVM to not dead-code-eliminate a function. Note that * you still need to use EXPORTED_FUNCTIONS so it stays alive * in JS, e.g. @@ -423,6 +444,8 @@ void emscripten_jcache_printf_(...); /* internal use */ /* Helper API for EM_ASM - do not call this yourself */ void emscripten_asm_const(const char *code); +int emscripten_asm_const_int(const char *code, ...); +double emscripten_asm_const_double(const char *code, ...); #ifdef __cplusplus } diff --git a/tests/test_core.py b/tests/test_core.py index d7b6cf53..67e316e4 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -3970,7 +3970,7 @@ def process(filename): #include <stdio.h> #include <emscripten.h> - int main() { + int main(int argc, char **argv) { EM_ASM(Module.print('hello dere1')); EM_ASM( Module.print('hello dere2'); @@ -3981,11 +3981,19 @@ def process(filename): Module.print('hello dere' + 4); ); } + int sum = 0; + for (int i = 0; i < argc*3; i++) { + sum += EM_ASM_INT({ + Module.print('i: ' + [$0, ($1).toFixed(2)]); + return $0*2; + }, i, double(i)/12); + } + printf("sum: %d\n", sum); return 0; } ''' - self.do_run(src, 'hello dere1\nhello dere2\nhello dere3\nhello dere4\nhello dere3\nhello dere4\nhello dere3\nhello dere4\n') + self.do_run(src, 'hello dere1\nhello dere2\nhello dere3\nhello dere4\nhello dere3\nhello dere4\nhello dere3\nhello dere4\ni: 0,0.00\ni: 1,0.08\ni: 2,0.17\nsum: 6\n') def test_memorygrowth(self): if Settings.USE_TYPED_ARRAYS == 0: return self.skip('memory growth is only supported with typed arrays') |