aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-11-17 10:20:45 -0800
committerAlon Zakai <alonzakai@gmail.com>2013-11-17 10:20:45 -0800
commita4e9c38c371360b3cc652f1fcd11974d0476b54a (patch)
tree64c386bc57cbc117a371b173666d4ded9defcde9
parentdddebe080f0792b1df14c1dbb596961f108cc3b5 (diff)
EM_ASM_INT and EM_ASM_DOUBLE, which allow input and output values from EM_ASM; fixes #1819
-rw-r--r--src/library.js19
-rw-r--r--src/runtime.js12
-rw-r--r--system/include/emscripten/emscripten.h31
-rw-r--r--tests/test_core.py12
4 files changed, 62 insertions, 12 deletions
diff --git a/src/library.js b/src/library.js
index 9db99c6c..066a060f 100644
--- a/src/library.js
+++ b/src/library.js
@@ -8676,12 +8676,19 @@ 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() {
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')