@@ -191,22 +191,6 @@ function isPointerType(type) {
191
191
return type [ type . length - 1 ] == '*' ;
192
192
}
193
193
194
- function isIntImplemented ( type ) {
195
- return type [ 0 ] == 'i' || type [ 0 ] == 'u' || isPointerType ( type ) ;
196
- }
197
-
198
- // Note: works for iX types and structure types, not pointers (even though they are implemented as ints)
199
- function getBits ( type , allowPointers ) {
200
- if ( allowPointers && isPointerType ( type ) ) return POINTER_SIZE ;
201
- if ( ! type ) return 0 ;
202
- if ( type [ 0 ] == 'i' || type [ 0 ] == 'u' ) {
203
- const left = type . substr ( 1 ) ;
204
- if ( ! isNumber ( left ) ) return 0 ;
205
- return parseInt ( left ) ;
206
- }
207
- return 0 ;
208
- }
209
-
210
194
// Given an expression like (VALUE=VALUE*2,VALUE<10?VALUE:t+1) , this will
211
195
// replace VALUE with value. If value is not a simple identifier of a variable,
212
196
// value will be replaced with tempVar.
@@ -405,12 +389,13 @@ function makeHEAPView(which, start, end) {
405
389
return `HEAP${ which } .subarray((${ start } )${ mod } , (${ end } )${ mod } )` ;
406
390
}
407
391
408
- const TWO_TWENTY = Math . pow ( 2 , 20 ) ;
409
-
410
392
// Given two values and an operation, returns the result of that operation.
411
393
// Tries to do as much as possible at compile time.
412
- // Leaves overflows etc. unhandled, *except* for integer multiply, in order to be efficient with Math.imul
413
- function getFastValue ( a , op , b , type ) {
394
+ function getFastValue ( a , op , b ) {
395
+ // In the past we supported many operations, but today we only use addition.
396
+ assert ( op == '+' ) ;
397
+
398
+ // Convert 'true' and 'false' to '1' and '0'.
414
399
a = a === 'true' ? '1' : ( a === 'false' ? '0' : a ) ;
415
400
b = b === 'true' ? '1' : ( b === 'false' ? '0' : b ) ;
416
401
@@ -419,95 +404,47 @@ function getFastValue(a, op, b, type) {
419
404
if ( typeof a == 'number' ) {
420
405
aNumber = a ;
421
406
a = a . toString ( ) ;
422
- } else if ( isNumber ( a ) ) aNumber = parseFloat ( a ) ;
407
+ } else if ( isNumber ( a ) ) {
408
+ aNumber = parseFloat ( a ) ;
409
+ }
423
410
if ( typeof b == 'number' ) {
424
411
bNumber = b ;
425
412
b = b . toString ( ) ;
426
- } else if ( isNumber ( b ) ) bNumber = parseFloat ( b ) ;
413
+ } else if ( isNumber ( b ) ) {
414
+ bNumber = parseFloat ( b ) ;
415
+ }
427
416
417
+ // First check if we can do the addition at compile time
428
418
if ( aNumber !== null && bNumber !== null ) {
429
- switch ( op ) {
430
- case '+' : return ( aNumber + bNumber ) . toString ( ) ;
431
- case '-' : return ( aNumber - bNumber ) . toString ( ) ;
432
- case '*' : return ( aNumber * bNumber ) . toString ( ) ;
433
- case '/' : {
434
- if ( type [ 0 ] === 'i' ) {
435
- return ( ( aNumber / bNumber ) | 0 ) . toString ( ) ;
436
- }
437
- return ( aNumber / bNumber ) . toString ( ) ;
438
- }
439
- case '%' : return ( aNumber % bNumber ) . toString ( ) ;
440
- case '|' : return ( aNumber | bNumber ) . toString ( ) ;
441
- case '>>>' : return ( aNumber >>> bNumber ) . toString ( ) ;
442
- case '&' : return ( aNumber & bNumber ) . toString ( ) ;
443
- case 'pow' : return Math . pow ( aNumber , bNumber ) . toString ( ) ;
444
- default : assert ( false , 'need to implement getFastValue pn ' + op ) ;
445
- }
419
+ return ( aNumber + bNumber ) . toString ( ) ;
446
420
}
447
- if ( op === 'pow' ) {
448
- if ( a === '2' && isIntImplemented ( type ) ) {
449
- return `(1 << (${ b } ))` ;
450
- }
451
- return `Math.pow(${ a } , ${ b } )` ;
452
- }
453
- if ( ( op === '+' || op === '*' ) && aNumber !== null ) { // if one of them is a number, keep it last
421
+
422
+ // If one of them is a number, keep it last
423
+ if ( aNumber !== null ) {
454
424
const c = b ;
455
425
b = a ;
456
426
a = c ;
457
427
const cNumber = bNumber ;
458
428
bNumber = aNumber ;
459
429
aNumber = cNumber ;
460
430
}
461
- if ( op === '*' ) {
462
- // We can't eliminate where a or b are 0 as that would break things for creating
463
- // a negative 0.
464
- if ( ( aNumber === 0 || bNumber === 0 ) && ! FLOAT_TYPES . has ( type ) ) {
465
- return '0' ;
466
- } else if ( aNumber === 1 ) {
467
- return b ;
468
- } else if ( bNumber === 1 ) {
469
- return a ;
470
- } else if ( bNumber !== null && type && isIntImplemented ( type ) && Runtime . getNativeTypeSize ( type ) <= 32 ) {
471
- const shifts = Math . log ( bNumber ) / Math . LN2 ;
472
- if ( shifts % 1 === 0 ) {
473
- return `(${ a } <<${ shifts } )` ;
474
- }
475
- }
476
- if ( ! FLOAT_TYPES . has ( type ) ) {
477
- // if guaranteed small enough to not overflow into a double, do a normal multiply
478
- // default is 32-bit multiply for things like getelementptr indexes
479
- const bits = getBits ( type ) || 32 ;
480
- // Note that we can emit simple multiple in non-asm.js mode, but asm.js
481
- // will not parse "16-bit" multiple, so must do imul there
482
- if ( ( aNumber !== null && Math . abs ( a ) < TWO_TWENTY ) || ( bNumber !== null && Math . abs ( b ) < TWO_TWENTY ) ) {
483
- // keep a non-eliminatable coercion directly on this
484
- return `(((${ a } )*(${ b } ))&${ ( Math . pow ( 2 , bits ) - 1 ) | 0 } )` ;
485
- }
486
- return `(Math.imul(${ a } , ${ b } )|0)` ;
487
- }
488
- } else if ( op === '/' ) {
489
- // careful on floats, since 0*NaN is not 0
490
- if ( a === '0' && ! FLOAT_TYPES . has ( type ) ) {
491
- return '0' ;
492
- } else if ( b === 1 ) {
493
- return a ;
494
- } // Doing shifts for division is problematic, as getting the rounding right on negatives is tricky
495
- } else if ( op === '+' || op === '-' ) {
496
- if ( b [ 0 ] === '-' ) {
497
- op = op === '+' ? '-' : '+' ;
498
- b = b . substr ( 1 ) ;
499
- }
500
- if ( aNumber === 0 ) {
501
- return op === '+' ? b : `(-${ b } )` ;
502
- } else if ( bNumber === 0 ) {
503
- return a ;
504
- }
431
+
432
+ if ( aNumber === 0 ) {
433
+ return b ;
434
+ } else if ( bNumber === 0 ) {
435
+ return a ;
505
436
}
437
+
438
+ if ( b [ 0 ] === '-' ) {
439
+ op = '-'
440
+ b = b . substr ( 1 ) ;
441
+ }
442
+
506
443
return `(${ a } )${ op } (${ b } )` ;
507
444
}
508
445
509
446
function calcFastOffset ( ptr , pos ) {
510
- return getFastValue ( ptr , '+' , pos , 'i32' ) ;
447
+ return getFastValue ( ptr , '+' , pos ) ;
511
448
}
512
449
513
450
function getHeapForType ( type ) {
0 commit comments