@@ -101,7 +101,8 @@ import {
101101 getBlockName ,
102102 getConstValueF32 ,
103103 getConstValueF64 ,
104- getConstValueI64Low
104+ getConstValueI64Low ,
105+ getGetGlobalName
105106} from "./module" ;
106107
107108import {
@@ -3314,7 +3315,7 @@ export class Flow {
33143315 /**
33153316 * Tests if an expression can possibly overflow in the context of this flow. Assumes that the
33163317 * expression might already have overflown and returns `false` only if the operation neglects
3317- * any possibly combination of garbage bits being present.
3318+ * any possible combination of garbage bits being present.
33183319 */
33193320 canOverflow ( expr : ExpressionRef , type : Type ) : bool {
33203321 // TODO: the following catches most common and a few uncommon cases, but there are additional
@@ -3336,13 +3337,18 @@ export class Flow {
33363337 }
33373338
33383339 // overflows if the value does
3339- case ExpressionId . SetLocal : {
3340+ case ExpressionId . SetLocal : { // tee
33403341 assert ( isTeeLocal ( expr ) ) ;
33413342 return this . canOverflow ( getSetLocalValue ( expr ) , type ) ;
33423343 }
33433344
3344- // never overflows because globals are wrapped on set
3345- case ExpressionId . GetGlobal : return false ;
3345+ // overflows if the conversion does (globals are wrapped on set)
3346+ case ExpressionId . GetGlobal : {
3347+ // TODO: this is inefficient because it has to read a string
3348+ let global = assert ( this . currentFunction . program . elementsLookup . get ( assert ( getGetGlobalName ( expr ) ) ) ) ;
3349+ assert ( global . kind == ElementKind . GLOBAL ) ;
3350+ return canConversionOverflow ( assert ( ( < Global > global ) . type ) , type ) ;
3351+ }
33463352
33473353 case ExpressionId . Binary : {
33483354 switch ( getBinaryOp ( expr ) ) {
@@ -3567,9 +3573,7 @@ export class Flow {
35673573
35683574/** Tests if a conversion from one type to another can technically overflow. */
35693575function canConversionOverflow ( fromType : Type , toType : Type ) : bool {
3570- var fromSize = fromType . byteSize ;
3571- var toSize = toType . byteSize ;
35723576 return ! fromType . is ( TypeFlags . INTEGER ) // non-i32 locals or returns
3573- || fromSize > toSize
3577+ || fromType . size > toType . size
35743578 || fromType . is ( TypeFlags . SIGNED ) != toType . is ( TypeFlags . SIGNED ) ;
35753579}
0 commit comments