aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-03-12 17:14:07 -0700
committerAlon Zakai <alonzakai@gmail.com>2013-03-12 17:14:07 -0700
commit9483f8b998df9c49a4122d163e0e2ef92bf7a1c1 (patch)
tree7c4aeafedf48aabf05cd9648995fed1a995ad702
parent1706d678343c3bcf4abc911a5228fa2911d90eb6 (diff)
infrastructure for implementing i64 math in asm.js, and implement i64Add and llvm_uadd_with_overflow_i64 that way
-rwxr-xr-xemscripten.py4
-rw-r--r--src/jsifier.js40
-rw-r--r--src/library.js42
-rw-r--r--src/long.js7
-rw-r--r--src/parseTools.js17
5 files changed, 76 insertions, 34 deletions
diff --git a/emscripten.py b/emscripten.py
index bbc4f76d..d7a24fbc 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -313,6 +313,10 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
last_forwarded_json = json.loads(last_forwarded_data)
if settings.get('ASM_JS'):
+ post_funcs, post_rest = post.split('// EMSCRIPTEN_END_FUNCS\n')
+ post = post_rest
+ funcs_js += '\n' + post_funcs + '// EMSCRIPTEN_END_FUNCS\n'
+
simple = os.environ.get('EMCC_SIMPLE_ASM')
class Counter:
i = 0
diff --git a/src/jsifier.js b/src/jsifier.js
index 3cb5c23e..e7e4706b 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -397,6 +397,20 @@ function JSify(data, functionsOnly, givenFunctions) {
}
});
+ function processLibraryFunction(snippet, ident) {
+ snippet = snippet.toString();
+ assert(snippet.indexOf('XXX missing C define') == -1,
+ 'Trying to include a library function with missing C defines: ' + ident + ' | ' + snippet);
+
+ // name the function; overwrite if it's already named
+ snippet = snippet.replace(/function(?:\s+([^(]+))?\s*\(/, 'function _' + ident + '(');
+ if (LIBRARY_DEBUG) {
+ snippet = snippet.replace('{', '{ var ret = (function() { if (Runtime.debug) Module.printErr("[library call:' + ident + ': " + Array.prototype.slice.call(arguments).map(Runtime.prettyPrint) + "]"); ');
+ snippet = snippet.substr(0, snippet.length-1) + '}).apply(this, arguments); if (Runtime.debug && typeof ret !== "undefined") Module.printErr(" [ return:" + Runtime.prettyPrint(ret)); return ret; \n}';
+ }
+ return snippet;
+ }
+
// functionStub
substrate.addActor('FunctionStub', {
processItem: function(item) {
@@ -434,16 +448,7 @@ function JSify(data, functionsOnly, givenFunctions) {
snippet = stringifyWithFunctions(snippet);
} else if (typeof snippet === 'function') {
isFunction = true;
- snippet = snippet.toString();
- assert(snippet.indexOf('XXX missing C define') == -1,
- 'Trying to include a library function with missing C defines: ' + ident + ' | ' + snippet);
-
- // name the function; overwrite if it's already named
- snippet = snippet.replace(/function(?:\s+([^(]+))?\s*\(/, 'function _' + ident + '(');
- if (LIBRARY_DEBUG) {
- snippet = snippet.replace('{', '{ var ret = (function() { if (Runtime.debug) Module.printErr("[library call:' + ident + ': " + Array.prototype.slice.call(arguments).map(Runtime.prettyPrint) + "]"); ');
- snippet = snippet.substr(0, snippet.length-1) + '}).apply(this, arguments); if (Runtime.debug && typeof ret !== "undefined") Module.printErr(" [ return:" + Runtime.prettyPrint(ret)); return ret; \n}';
- }
+ snippet = processLibraryFunction(snippet, ident);
if (ASM_JS) Functions.libraryFunctions[ident] = 1;
}
@@ -1563,16 +1568,23 @@ function JSify(data, functionsOnly, givenFunctions) {
// This is the main 'post' pass. Print out the generated code that we have here, together with the
// rest of the output that we started to print out earlier (see comment on the
// "Final shape that will be created").
- if (CORRUPTION_CHECK) {
- assert(!ASM_JS); // cannot monkeypatch asm!
- print(processMacros(read('corruptionCheck.js')));
- }
if (PRECISE_I64_MATH && Types.preciseI64MathUsed) {
+ ['i64Add'].forEach(function(func) {
+ print(processLibraryFunction(LibraryManager.library[func], func)); // must be first to be close to generated code
+ Functions.implementedFunctions['_' + func] = LibraryManager.library[func + '__sig'];
+ });
+ print('// EMSCRIPTEN_END_FUNCS\n');
print(read('long.js'));
} else {
+ print('// EMSCRIPTEN_END_FUNCS\n');
print('// Warning: printing of i64 values may be slightly rounded! No deep i64 math used, so precise i64 code not included');
print('var i64Math = null;');
}
+
+ if (CORRUPTION_CHECK) {
+ assert(!ASM_JS); // cannot monkeypatch asm!
+ print(processMacros(read('corruptionCheck.js')));
+ }
if (HEADLESS) {
print('if (!ENVIRONMENT_IS_WEB) {');
print(read('headless.js').replace("'%s'", "'http://emscripten.org'").replace("'?%s'", "''").replace('%s,', 'null,').replace('%d', '0'));
diff --git a/src/library.js b/src/library.js
index 12e550ff..0f8b0af5 100644
--- a/src/library.js
+++ b/src/library.js
@@ -5206,13 +5206,6 @@ LibraryManager.library = {
{{{ makeStructuralReturn(['(x*y)>>>0', 'x*y > 4294967295']) }}};
},
- llvm_uadd_with_overflow_i64__deps: [function() { Types.preciseI64MathUsed = 1 }],
- llvm_uadd_with_overflow_i64: function(xl, xh, yl, yh) {
- i64Math.add(xl, xh, yl, yh);
- {{{ makeStructuralReturn([makeGetTempDouble(0, 'i32'), makeGetTempDouble(1, 'i32'), '0']) }}};
- // XXX Need to hack support for second param in long.js
- },
-
llvm_umul_with_overflow_i64__deps: [function() { Types.preciseI64MathUsed = 1 }],
llvm_umul_with_overflow_i64: function(xl, xh, yl, yh) {
i64Math.multiply(xl, xh, yl, yh);
@@ -7352,6 +7345,41 @@ LibraryManager.library = {
Module.print(intArrayToString(__formatString(_emscripten_jcache_printf_.buffer, varargs + i*4)).replace('\\n', ''));
Runtime.stackAlloc(-4*i); // free up the stack space we know is ok to free
},
+
+ //============================
+ // 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)>>>0;
+ if ((l>>>0) < (a>>>0)) { // iff we overflowed
+ h = (h+1)>>>0;
+ }
+ {{{ makeStructuralReturn(['l|0', 'h'], true) }}};
+ },
+ llvm_uadd_with_overflow_i64__asm: 'true',
+ llvm_uadd_with_overflow_i64__sig: 'iiiii',
+ llvm_uadd_with_overflow_i64: function(a, b, c, d) {
+ a = a|0; b = b|0; c = c|0; d = d|0;
+ var l = 0, h = 0, overflow = 0;
+ l = (a + c)>>>0;
+ h = (b + d)>>>0;
+ if ((l>>>0) < (a>>>0)) { // iff we overflowed
+ h = (h+1)>>>0;
+ overflow = 1;
+ }
+ {{{ makeStructuralReturn(['l|0', 'h', 'overflow'], true) }}};
+ },
};
function autoAddDeps(object, name) {
diff --git a/src/long.js b/src/long.js
index c3651bd9..6d0e873d 100644
--- a/src/long.js
+++ b/src/long.js
@@ -1530,13 +1530,6 @@ var i64Math = (function() { // Emscripten wrapper
// Emscripten wrapper
var Wrapper = {
- add: function(xl, xh, yl, yh) {
- var x = new goog.math.Long(xl, xh);
- var y = new goog.math.Long(yl, yh);
- var ret = x.add(y);
- HEAP32[tempDoublePtr>>2] = ret.low_;
- HEAP32[tempDoublePtr+4>>2] = ret.high_;
- },
subtract: function(xl, xh, yl, yh) {
var x = new goog.math.Long(xl, xh);
var y = new goog.math.Long(yl, yh);
diff --git a/src/parseTools.js b/src/parseTools.js
index 48274cd5..9a91070c 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -1724,13 +1724,14 @@ function makeLLVMStruct(values) {
}
}
-function makeStructuralReturn(values) {
+function makeStructuralReturn(values, inAsm) {
if (USE_TYPED_ARRAYS == 2) {
- var i = 0;
- return 'return (' + values.slice(1).map(function(value) {
- return ASM_JS ? 'asm.setTempRet' + (i++) + '(' + value + ')'
+ var i = -1;
+ return 'return ' + asmCoercion(values.slice(1).map(function(value) {
+ i++;
+ return ASM_JS ? (inAsm ? 'tempRet' + i + ' = ' + value : 'asm.setTempRet' + i + '(' + value + ')')
: 'tempRet' + (i++) + ' = ' + value;
- }).concat([values[0]]).join(',') + ')';
+ }).concat([values[0]]).join(','), 'i32');
} else {
var i = 0;
return 'return { ' + values.map(function(value) {
@@ -1971,6 +1972,10 @@ function processMathop(item) {
return finish(['(i64Math' + (ASM_JS ? '_' : '.') + type + '(' + asmCoercion(low1, 'i32') + ',' + asmCoercion(high1, 'i32') + ',' + asmCoercion(low2, 'i32') + ',' + asmCoercion(high2, 'i32') +
(lastArg ? ',' + asmCoercion(+lastArg, 'i32') : '') + '),' + makeGetValue('tempDoublePtr', 0, 'i32') + ')', makeGetValue('tempDoublePtr', Runtime.getNativeTypeSize('i32'), 'i32')]);
}
+ function i64PreciseLib(type) {
+ Types.preciseI64MathUsed = true;
+ return finish(['_i64' + type[0].toUpperCase() + type.substr(1) + '(' + low1 + ',' + high1 + ',' + low2 + ',' + high2 + ')', 'tempRet0']);
+ }
switch (op) {
// basic integer ops
case 'or': {
@@ -2059,7 +2064,7 @@ function processMathop(item) {
// Dangerous, rounded operations. TODO: Fully emulate
case 'add': {
if (PRECISE_I64_MATH) {
- return i64PreciseOp('add');
+ return i64PreciseLib('add');
} else {
warnI64_1();
return finish(splitI64(mergeI64(idents[0]) + '+' + mergeI64(idents[1]), true));