Cast to bool by comparing to zero (#343)

This commit is contained in:
Daniel Wirtz
2018-11-23 15:20:52 +01:00
committed by GitHub
parent b723ff3e88
commit c30c62e383
38 changed files with 1072 additions and 1023 deletions

View File

@ -7516,9 +7516,10 @@ export class Compiler extends DiagnosticEmitter {
}
case TypeKind.BOOL: {
if (flow.canOverflow(expr, type)) {
expr = module.createBinary(BinaryOp.AndI32,
// bool is special in that it compares to 0 instead of masking with 0x1
expr = module.createBinary(BinaryOp.NeI32,
expr,
module.createI32(0x1)
module.createI32(0)
);
}
break;

View File

@ -1169,6 +1169,10 @@ export function isTeeLocal(expr: ExpressionRef): bool {
return _BinaryenSetLocalIsTee(expr);
}
export function getGetGlobalName(expr: ExpressionRef): string | null {
return readString(_BinaryenGetGlobalGetName(expr));
}
export function getBinaryOp(expr: ExpressionRef): BinaryOp {
return _BinaryenBinaryGetOp(expr);
}

View File

@ -101,7 +101,8 @@ import {
getBlockName,
getConstValueF32,
getConstValueF64,
getConstValueI64Low
getConstValueI64Low,
getGetGlobalName
} from "./module";
import {
@ -3314,7 +3315,7 @@ export class Flow {
/**
* Tests if an expression can possibly overflow in the context of this flow. Assumes that the
* expression might already have overflown and returns `false` only if the operation neglects
* any possibly combination of garbage bits being present.
* any possible combination of garbage bits being present.
*/
canOverflow(expr: ExpressionRef, type: Type): bool {
// TODO: the following catches most common and a few uncommon cases, but there are additional
@ -3336,13 +3337,18 @@ export class Flow {
}
// overflows if the value does
case ExpressionId.SetLocal: {
case ExpressionId.SetLocal: { // tee
assert(isTeeLocal(expr));
return this.canOverflow(getSetLocalValue(expr), type);
}
// never overflows because globals are wrapped on set
case ExpressionId.GetGlobal: return false;
// overflows if the conversion does (globals are wrapped on set)
case ExpressionId.GetGlobal: {
// TODO: this is inefficient because it has to read a string
let global = assert(this.currentFunction.program.elementsLookup.get(assert(getGetGlobalName(expr))));
assert(global.kind == ElementKind.GLOBAL);
return canConversionOverflow(assert((<Global>global).type), type);
}
case ExpressionId.Binary: {
switch (getBinaryOp(expr)) {
@ -3567,9 +3573,7 @@ export class Flow {
/** Tests if a conversion from one type to another can technically overflow. */
function canConversionOverflow(fromType: Type, toType: Type): bool {
var fromSize = fromType.byteSize;
var toSize = toType.byteSize;
return !fromType.is(TypeFlags.INTEGER) // non-i32 locals or returns
|| fromSize > toSize
|| fromType.size > toType.size
|| fromType.is(TypeFlags.SIGNED) != toType.is(TypeFlags.SIGNED);
}