mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-18 09:21:35 +00:00
Cast to bool by comparing to zero (#343)
This commit is contained in:
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user