aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/intertyper.js3
-rw-r--r--src/library.js51
-rw-r--r--src/library_browser.js4
-rw-r--r--src/library_sdl.js2
-rw-r--r--src/preamble.js2
-rw-r--r--src/runtime.js12
-rw-r--r--system/include/emscripten/emscripten.h31
-rw-r--r--tests/test_core.py12
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')