infrastructure for implementing i64 math in asm.js, and implement i64Add and llvm_uadd_with_overflow_i64 that way
This commit is contained in:
Родитель
1706d67834
Коммит
9483f8b998
|
@ -313,6 +313,10 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
|
||||||
last_forwarded_json = json.loads(last_forwarded_data)
|
last_forwarded_json = json.loads(last_forwarded_data)
|
||||||
|
|
||||||
if settings.get('ASM_JS'):
|
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')
|
simple = os.environ.get('EMCC_SIMPLE_ASM')
|
||||||
class Counter:
|
class Counter:
|
||||||
i = 0
|
i = 0
|
||||||
|
|
|
@ -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
|
// functionStub
|
||||||
substrate.addActor('FunctionStub', {
|
substrate.addActor('FunctionStub', {
|
||||||
processItem: function(item) {
|
processItem: function(item) {
|
||||||
|
@ -434,16 +448,7 @@ function JSify(data, functionsOnly, givenFunctions) {
|
||||||
snippet = stringifyWithFunctions(snippet);
|
snippet = stringifyWithFunctions(snippet);
|
||||||
} else if (typeof snippet === 'function') {
|
} else if (typeof snippet === 'function') {
|
||||||
isFunction = true;
|
isFunction = true;
|
||||||
snippet = snippet.toString();
|
snippet = processLibraryFunction(snippet, ident);
|
||||||
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}';
|
|
||||||
}
|
|
||||||
if (ASM_JS) Functions.libraryFunctions[ident] = 1;
|
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
|
// 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
|
// rest of the output that we started to print out earlier (see comment on the
|
||||||
// "Final shape that will be created").
|
// "Final shape that will be created").
|
||||||
|
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) {
|
if (CORRUPTION_CHECK) {
|
||||||
assert(!ASM_JS); // cannot monkeypatch asm!
|
assert(!ASM_JS); // cannot monkeypatch asm!
|
||||||
print(processMacros(read('corruptionCheck.js')));
|
print(processMacros(read('corruptionCheck.js')));
|
||||||
}
|
}
|
||||||
if (PRECISE_I64_MATH && Types.preciseI64MathUsed) {
|
|
||||||
print(read('long.js'));
|
|
||||||
} else {
|
|
||||||
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 (HEADLESS) {
|
if (HEADLESS) {
|
||||||
print('if (!ENVIRONMENT_IS_WEB) {');
|
print('if (!ENVIRONMENT_IS_WEB) {');
|
||||||
print(read('headless.js').replace("'%s'", "'http://emscripten.org'").replace("'?%s'", "''").replace('%s,', 'null,').replace('%d', '0'));
|
print(read('headless.js').replace("'%s'", "'http://emscripten.org'").replace("'?%s'", "''").replace('%s,', 'null,').replace('%d', '0'));
|
||||||
|
|
|
@ -5206,13 +5206,6 @@ LibraryManager.library = {
|
||||||
{{{ makeStructuralReturn(['(x*y)>>>0', 'x*y > 4294967295']) }}};
|
{{{ 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__deps: [function() { Types.preciseI64MathUsed = 1 }],
|
||||||
llvm_umul_with_overflow_i64: function(xl, xh, yl, yh) {
|
llvm_umul_with_overflow_i64: function(xl, xh, yl, yh) {
|
||||||
i64Math.multiply(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', ''));
|
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
|
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) {
|
function autoAddDeps(object, name) {
|
||||||
|
|
|
@ -1530,13 +1530,6 @@ var i64Math = (function() { // Emscripten wrapper
|
||||||
|
|
||||||
// Emscripten wrapper
|
// Emscripten wrapper
|
||||||
var 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) {
|
subtract: function(xl, xh, yl, yh) {
|
||||||
var x = new goog.math.Long(xl, xh);
|
var x = new goog.math.Long(xl, xh);
|
||||||
var y = new goog.math.Long(yl, yh);
|
var y = new goog.math.Long(yl, yh);
|
||||||
|
|
|
@ -1724,13 +1724,14 @@ function makeLLVMStruct(values) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeStructuralReturn(values) {
|
function makeStructuralReturn(values, inAsm) {
|
||||||
if (USE_TYPED_ARRAYS == 2) {
|
if (USE_TYPED_ARRAYS == 2) {
|
||||||
var i = 0;
|
var i = -1;
|
||||||
return 'return (' + values.slice(1).map(function(value) {
|
return 'return ' + asmCoercion(values.slice(1).map(function(value) {
|
||||||
return ASM_JS ? 'asm.setTempRet' + (i++) + '(' + value + ')'
|
i++;
|
||||||
|
return ASM_JS ? (inAsm ? 'tempRet' + i + ' = ' + value : 'asm.setTempRet' + i + '(' + value + ')')
|
||||||
: 'tempRet' + (i++) + ' = ' + value;
|
: 'tempRet' + (i++) + ' = ' + value;
|
||||||
}).concat([values[0]]).join(',') + ')';
|
}).concat([values[0]]).join(','), 'i32');
|
||||||
} else {
|
} else {
|
||||||
var i = 0;
|
var i = 0;
|
||||||
return 'return { ' + values.map(function(value) {
|
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') +
|
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')]);
|
(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) {
|
switch (op) {
|
||||||
// basic integer ops
|
// basic integer ops
|
||||||
case 'or': {
|
case 'or': {
|
||||||
|
@ -2059,7 +2064,7 @@ function processMathop(item) {
|
||||||
// Dangerous, rounded operations. TODO: Fully emulate
|
// Dangerous, rounded operations. TODO: Fully emulate
|
||||||
case 'add': {
|
case 'add': {
|
||||||
if (PRECISE_I64_MATH) {
|
if (PRECISE_I64_MATH) {
|
||||||
return i64PreciseOp('add');
|
return i64PreciseLib('add');
|
||||||
} else {
|
} else {
|
||||||
warnI64_1();
|
warnI64_1();
|
||||||
return finish(splitI64(mergeI64(idents[0]) + '+' + mergeI64(idents[1]), true));
|
return finish(splitI64(mergeI64(idents[0]) + '+' + mergeI64(idents[1]), true));
|
||||||
|
|
Загрузка…
Ссылка в новой задаче