36
36
var value = parts[3];
39
showStack.push(ident in this && this[ident] == value);
39
showStack.push(ident in this && this[ident] == value);
40
} else if (op === '!=') {
41
showStack.push(!(ident in this && this[ident] == value));
43
error('unsupported preprecessor op ' + op);
41
46
showStack.push(ident in this && this[ident] > 0);
396
401
// handle 'byval' and 'byval align X'. We store the alignment in 'byVal'
397
402
byVal = QUANTUM_SIZE;
398
403
segment.splice(1, 1);
404
if (segment[1] && segment[1].text === 'nocapture') {
405
segment.splice(1, 1);
399
407
if (segment[1] && segment[1].text === 'align') {
400
408
assert(isNumber(segment[2].text));
401
409
byVal = parseInt(segment[2].text);
402
410
segment.splice(1, 2);
413
if (segment[1] && segment[1].text === 'nocapture') {
414
segment.splice(1, 1);
405
416
if (segment.length == 1) {
406
417
if (segment[0].text == '...') {
424
435
ret.push(parseLLVMFunctionCall(segment));
425
436
} else if (segment[1].text === 'blockaddress') {
426
437
ret.push(parseBlockAddress(segment));
438
} else if (segment[1].type && segment[1].type == '{') {
439
ret.push(parseLLVMSegment(segment));
428
441
if (segment[2] && segment[2].text == 'to') { // part of bitcast params
429
442
segment = segment.slice(0, 2);
467
480
return !data.alias && !data.external;
483
function isBSS(item) {
488
if (item.external) return false; // externals are typically implemented in a JS library, and must be accessed by name, explicitly
490
// return true if a global is uninitialized or initialized to 0
491
return (item.value && item.value.intertype === 'emptystruct') ||
492
(item.value && item.value.value !== undefined && item.value.value === '0');
470
495
function makeGlobalDef(ident) {
471
496
if (!NAMED_GLOBALS && isIndexableGlobal(ident)) return '';
472
497
return 'var ' + ident + ';';
491
518
var inv = invertArray(ks);
492
519
return values(globals).sort(function(a, b) {
493
return inv[b.ident] - inv[a.ident];
520
// sort globals based on if they need to be explicitly initialized or not (moving
521
// values that don't need to be to the end of the array). if equal, sort by name.
522
return (Number(isBSS(a)) - Number(isBSS(b))) ||
523
(inv[b.ident] - inv[a.ident]);
704
734
// Splits a number (an integer in a double, possibly > 32 bits) into an USE_TYPED_ARRAYS == 2 i64 value.
705
735
// Will suffer from rounding. mergeI64 does the opposite.
706
736
function splitI64(value, floatConversion) {
707
// We need to min here, since our input might be a double, and large values are rounded, so they can
739
// $1$0 = ~~$d >>> 0;
740
// $1$1 = Math_abs($d) >= 1 ? (
741
// $d > 0 ? Math.min(Math_floor(($d)/ 4294967296.0), 4294967295.0)
742
// : Math_ceil(Math.min(-4294967296.0, $d - $1$0)/ 4294967296.0)
745
// We need to min on positive values here, since our input might be a double, and large values are rounded, so they can
708
746
// be slightly higher than expected. And if we get 4294967296, that will turn into a 0 if put into a
709
747
// HEAP32 or |0'd, etc.
749
// For negatives, we need to ensure a -1 if the value is overall negative, even if not significant negative component
710
751
var lowInput = legalizedI64s ? value : 'VALUE';
711
752
if (floatConversion && ASM_JS) lowInput = asmFloatToInt(lowInput);
753
var low = lowInput + '>>>0';
754
var high = makeInlineCalculation(
755
asmCoercion('Math.abs(VALUE)', 'double') + ' >= ' + asmEnsureFloat('1', 'double') + ' ? ' +
756
'(VALUE > ' + asmEnsureFloat('0', 'double') + ' ? ' +
757
asmCoercion('Math.min(' + asmCoercion('Math.floor((VALUE)/' + asmEnsureFloat(4294967296, 'float') + ')', 'double') + ', ' + asmEnsureFloat(4294967295, 'float') + ')', 'i32') + '>>>0' +
758
' : ' + asmFloatToInt(asmCoercion('Math.ceil((VALUE - +((' + asmFloatToInt('VALUE') + ')>>>0))/' + asmEnsureFloat(4294967296, 'float') + ')', 'double')) + '>>>0' +
712
764
if (legalizedI64s) {
713
return [lowInput + '>>>0', 'Math.min(Math.floor((' + value + ')/' + asmEnsureFloat(4294967296, 'float') + '), ' + asmEnsureFloat(4294967295, 'float') + ')>>>0'];
715
return makeInlineCalculation(makeI64(lowInput + '>>>0', 'Math.min(Math.floor(VALUE/' + asmEnsureFloat(4294967296, 'float') + '), ' + asmEnsureFloat(4294967295, 'float') + ')>>>0'), value, 'tempBigIntP');
767
return makeI64(low, high);
718
770
function mergeI64(value, unsigned) {
953
1005
ret[index++] = type;
1007
if (Runtime.isStructType(type) && type[1] === '0') {
1008
// this is [0 x something], which does nothing
1009
// XXX this happens in java_nbody... assert(i === typeData.fields.length-1);
955
1012
add(Types.types[type]);
957
1014
var more = (i+1 < typeData.fields.length ? typeData.flatIndexes[i+1] : typeData.flatSize) - (index - start);
1213
1270
if (type && isFunctionType(type, out) && value[0] === '_') { // checking for _ differentiates from $ (local vars)
1214
1271
// add signature to library functions that we now know need indexing
1215
if (!(value in Functions.implementedFunctions) && !(value in Functions.unimplementedFunctions)) {
1216
Functions.unimplementedFunctions[value] = Functions.getSignature(out.returnType, out.segments ? out.segments.map(function(segment) { return segment[0].text }) : []);
1219
if (BUILD_AS_SHARED_LIB) {
1220
return '(FUNCTION_TABLE_OFFSET + ' + Functions.getIndex(value) + ')';
1222
return Functions.getIndex(value);
1272
var sig = Functions.implementedFunctions[value] || Functions.unimplementedFunctions[value];
1274
sig = Functions.unimplementedFunctions[value] = Functions.getSignature(out.returnType, out.segments ? out.segments.map(function(segment) { return segment[0].text }) : [], isVarArgsFunctionType(type));
1276
return Functions.getIndex(value, sig);
1383
1436
if (!isNumber(num)) num = stripCorrections(num);
1384
1437
if (!isNumber(align)) align = stripCorrections(align);
1385
1438
if (!isNumber(num) || (parseInt(num)/align >= UNROLL_LOOP_MAX)) {
1386
return '_memcpy(' + dest + ', ' + src + ', ' + num + ')';
1439
return '(_memcpy(' + dest + ', ' + src + ', ' + num + ')|0)';
1388
1441
num = parseInt(num);
1465
1518
if ((isNumber(a) && Math.abs(a) < TWO_TWENTY) || (isNumber(b) && Math.abs(b) < TWO_TWENTY) || (bits < 32 && !ASM_JS)) {
1466
1519
return '(((' + a + ')*(' + b + '))&' + ((Math.pow(2, bits)-1)|0) + ')'; // keep a non-eliminatable coercion directly on this
1468
return 'Math.imul(' + a + ',' + b + ')';
1521
return '(Math.imul(' + a + ',' + b + ')|0)';
1471
1524
if (a == '0') {
1612
1665
// writing out into memory, without a normal allocation. We put all of these into a single big chunk.
1613
1666
assert(typeof slab == 'object');
1614
1667
assert(slab.length % QUANTUM_SIZE == 0, slab.length); // must be aligned already
1668
if (SIDE_MODULE && typeof ptr == 'string') {
1669
ptr = parseInt(ptr.substring(ptr.indexOf('+'), ptr.length-1)); // parse into (H_BASE+X)
1615
1671
var offset = ptr - Runtime.GLOBAL_BASE;
1616
1672
for (var i = 0; i < slab.length; i++) {
1617
1673
memoryInitialization[offset + i] = slab[i];
1679
1735
case 'float': return ['HEAPF32'];
1681
throw 'what, exactly, can we do for unknown types in TA2?! ' + new Error().stack;
1737
throw 'what, exactly, can we do for unknown types in TA2?! ' + [new Error().stack, ptr, type, allowMultiple, unsigned];
1993
2049
return 'isNaN(' + value + ')';
2052
function makeFloat(value, type) {
2053
if (TO_FLOAT32 && type == 'float') {
2054
return 'Math.toFloat32(' + value + ')';
1996
2059
// fptoui and fptosi are not in these, because we need to be careful about what we do there. We can't
1997
2060
// just sign/unsign the input first.
1998
2061
var UNSIGNED_OP = set('udiv', 'urem', 'uitofp', 'zext', 'lshr');
2132
2195
case 'select': return idents[0] + ' ? ' + makeCopyI64(idents[1]) + ' : ' + makeCopyI64(idents[2]);
2133
2196
case 'ptrtoint': return makeI64(idents[0], 0);
2134
case 'inttoptr': return '(' + idents[0] + '[0])'; // just directly truncate the i64 to a 'pointer', which is an i32
2198
var m = /\(?\[(\d+),\d+\]\)?/.exec(idents[0]);
2199
if (m) return m[1]; // constant, can just parse it right now
2200
return '(' + idents[0] + '[0])'; // just directly truncate the i64 to a 'pointer', which is an i32
2135
2202
// Dangerous, rounded operations. TODO: Fully emulate
2137
2204
if (PRECISE_I64_MATH) {
2202
2269
// basic integer ops
2203
2270
case 'add': return handleOverflow(getFastValue(idents[0], '+', idents[1], item.type), bits);
2204
2271
case 'sub': return handleOverflow(getFastValue(idents[0], '-', idents[1], item.type), bits);
2205
case 'sdiv': case 'udiv': return makeRounding(getFastValue(idents[0], '/', idents[1], item.type), bits, op[0] === 's');
2272
case 'sdiv': case 'udiv': return makeRounding(getFastValue(idents[0], '/', idents[1], item.type), bits, true);
2206
2273
case 'mul': return getFastValue(idents[0], '*', idents[1], item.type); // overflow handling is already done in getFastValue for '*'
2207
case 'urem': case 'srem': return makeRounding(getFastValue(idents[0], '%', idents[1], item.type), bits, op[0] === 's');
2274
case 'urem': case 'srem': return makeRounding(getFastValue(idents[0], '%', idents[1], item.type), bits, true);
2209
2276
if (bits > 32) {
2210
2277
assert(bits === 64, 'Too many bits for or: ' + bits);
2244
2311
return idents[0] + ' >>> ' + idents[1];
2246
2313
// basic float ops
2247
case 'fadd': return getFastValue(idents[0], '+', idents[1], item.type);
2248
case 'fsub': return getFastValue(idents[0], '-', idents[1], item.type);
2249
case 'fdiv': return getFastValue(idents[0], '/', idents[1], item.type);
2250
case 'fmul': return getFastValue(idents[0], '*', idents[1], item.type);
2251
case 'frem': return getFastValue(idents[0], '%', idents[1], item.type);
2314
case 'fadd': return makeFloat(getFastValue(idents[0], '+', idents[1], item.type), item.type);
2315
case 'fsub': return makeFloat(getFastValue(idents[0], '-', idents[1], item.type), item.type);
2316
case 'fdiv': return makeFloat(getFastValue(idents[0], '/', idents[1], item.type), item.type);
2317
case 'fmul': return makeFloat(getFastValue(idents[0], '*', idents[1], item.type), item.type);
2318
case 'frem': return makeFloat(getFastValue(idents[0], '%', idents[1], item.type), item.type);
2252
2319
case 'uitofp': case 'sitofp': return asmCoercion(idents[0], 'double', op[0]);
2253
2320
case 'fptoui': case 'fptosi': return makeRounding(idents[0], bitsLeft, op === 'fptosi', true);