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)
|
||||
|
||||
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
|
||||
|
|
|
@ -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 (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 (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) {
|
||||
print('if (!ENVIRONMENT_IS_WEB) {');
|
||||
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']) }}};
|
||||
},
|
||||
|
||||
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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
Загрузка…
Ссылка в новой задаче