~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to src/parseTools.js

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-09-20 22:44:35 UTC
  • mfrom: (4.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20130920224435-apuwj4fsl3fqv1a6
Tags: 1.5.6~20130920~6010666-1
* New snapshot release
* Update the list of supported architectures to the same as libv8
  (Closes: #723129)
* emlibtool has been removed from upstream.
* Fix warning syntax-error-in-dep5-copyright
* Refresh of the patches

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
        var op = parts[2];
36
36
        var value = parts[3];
37
37
        if (op) {
38
 
          assert(op === '==')
39
 
          showStack.push(ident in this && this[ident] == value);
 
38
          if (op === '==') {
 
39
            showStack.push(ident in this && this[ident] == value);
 
40
          } else if (op === '!=') {
 
41
            showStack.push(!(ident in this && this[ident] == value));
 
42
          } else {
 
43
            error('unsupported preprecessor op ' + op);
 
44
          }
40
45
        } else {
41
46
          showStack.push(ident in this && this[ident] > 0);
42
47
        }
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);
 
406
      }
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);
403
411
      }
404
412
    }
 
413
    if (segment[1] && segment[1].text === 'nocapture') {
 
414
      segment.splice(1, 1);
 
415
    }
405
416
    if (segment.length == 1) {
406
417
      if (segment[0].text == '...') {
407
418
        ret.push({
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));
427
440
    } else {
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;
468
481
}
469
482
 
 
483
function isBSS(item) {
 
484
  if (!USE_BSS) {
 
485
    return false;
 
486
  }
 
487
 
 
488
  if (item.external) return false; // externals are typically implemented in a JS library, and must be accessed by name, explicitly
 
489
 
 
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');
 
493
}
 
494
 
470
495
function makeGlobalDef(ident) {
471
496
  if (!NAMED_GLOBALS && isIndexableGlobal(ident)) return '';
472
497
  return 'var ' + ident + ';';
480
505
      UNINDEXABLE_GLOBALS[ident] = 1;
481
506
      return ident;
482
507
    }
483
 
    return (Runtime.GLOBAL_BASE + index).toString();
 
508
    var ret = (Runtime.GLOBAL_BASE + index).toString();
 
509
    if (SIDE_MODULE) ret = '(H_BASE+' + ret + ')';
 
510
    return ret;
484
511
  }
485
512
  return ident;
486
513
}
490
517
  ks.sort();
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]);
494
524
  });
495
525
}
496
526
 
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
 
737
  // general idea:
 
738
  //
 
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)
 
743
  //  ) : 0;
 
744
  //
 
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.
 
748
  //
 
749
  // For negatives, we need to ensure a -1 if the value is overall negative, even if not significant negative component
 
750
 
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' + 
 
759
      ')' +
 
760
    ' : 0',
 
761
    value,
 
762
    'tempDouble'
 
763
  );
712
764
  if (legalizedI64s) {
713
 
    return [lowInput + '>>>0', 'Math.min(Math.floor((' + value + ')/' + asmEnsureFloat(4294967296, 'float') + '), ' + asmEnsureFloat(4294967295, 'float') + ')>>>0'];
 
765
    return [low, high];
714
766
  } else {
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);
716
768
  }
717
769
}
718
770
function mergeI64(value, unsigned) {
952
1004
        }
953
1005
        ret[index++] = type;
954
1006
      } else {
 
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);
 
1010
          continue;
 
1011
        }
955
1012
        add(Types.types[type]);
956
1013
      }
957
1014
      var more = (i+1 < typeData.fields.length ? typeData.flatIndexes[i+1] : typeData.flatSize) - (index - start);
1049
1106
  offset = '(' + offset + ')';
1050
1107
  if (shifts != 0) {
1051
1108
    if (CHECK_HEAP_ALIGN) {
1052
 
      return '(CHECK_ALIGN_' + sz + '(' + offset + '|0)>>' + shifts + ')';
 
1109
      return '((CHECK_ALIGN_' + sz + '(' + offset + '|0)|0)>>' + shifts + ')';
1053
1110
    } else {
1054
1111
      return '(' + offset + '>>' + shifts + ')';
1055
1112
    }
1212
1269
  var out = {};
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 }) : []);
1217
 
    }
1218
 
 
1219
 
    if (BUILD_AS_SHARED_LIB) {
1220
 
      return '(FUNCTION_TABLE_OFFSET + ' + Functions.getIndex(value) + ')';
1221
 
    } else {
1222
 
      return Functions.getIndex(value);
1223
 
    }
 
1272
    var sig = Functions.implementedFunctions[value] || Functions.unimplementedFunctions[value];
 
1273
    if (!sig) {
 
1274
      sig = Functions.unimplementedFunctions[value] = Functions.getSignature(out.returnType, out.segments ? out.segments.map(function(segment) { return segment[0].text }) : [], isVarArgsFunctionType(type));
 
1275
    }
 
1276
    return Functions.getIndex(value, sig);
1224
1277
  }
1225
1278
  return value;
1226
1279
}
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)';
1387
1440
    }
1388
1441
    num = parseInt(num);
1389
1442
    if (ASM_JS) {
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
1467
1520
        }
1468
 
        return 'Math.imul(' + a + ',' + b + ')';
 
1521
        return '(Math.imul(' + a + ',' + b + ')|0)';
1469
1522
      }
1470
1523
    } else {
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)
 
1670
      }
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];
1678
1734
      }
1679
1735
      case 'float': return ['HEAPF32'];
1680
1736
      default: {
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];
1682
1738
      }
1683
1739
    }
1684
1740
  }
1993
2049
  return 'isNaN(' + value + ')';
1994
2050
}
1995
2051
 
 
2052
function makeFloat(value, type) {
 
2053
  if (TO_FLOAT32 && type == 'float') {
 
2054
    return 'Math.toFloat32(' + value + ')';
 
2055
  }
 
2056
  return value;
 
2057
}
 
2058
 
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');
2131
2194
      }
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
 
2197
      case 'inttoptr': {
 
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
 
2201
      }
2135
2202
      // Dangerous, rounded operations. TODO: Fully emulate
2136
2203
      case 'add': {
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);
2208
2275
    case 'or': {
2209
2276
      if (bits > 32) {
2210
2277
        assert(bits === 64, 'Too many bits for or: ' + bits);
2244
2311
      return idents[0] + ' >>> ' + idents[1];
2245
2312
    }
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);
2254
2321