Skip to content

Commit 8759033

Browse files
authored
Consider NaN falseish (#933)
Also makes isNaN and isFinite builtins again
1 parent 145d8ac commit 8759033

38 files changed

+4028
-3680
lines changed

src/builtins.ts

Lines changed: 253 additions & 73 deletions
Large diffs are not rendered by default.

src/compiler.ts

Lines changed: 101 additions & 94 deletions
Large diffs are not rendered by default.

src/flow.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -401,13 +401,6 @@ export class Flow {
401401
temps.push(local);
402402
}
403403

404-
/** Gets and immediately frees a temporary local of the specified type. */
405-
getAndFreeTempLocal(type: Type, except: Set<i32> | null = null): Local {
406-
var local = this.getTempLocal(type, except);
407-
this.freeTempLocal(local);
408-
return local;
409-
}
410-
411404
/** Gets the scoped local of the specified name. */
412405
getScopedLocal(name: string): Local | null {
413406
var scopedLocals = this.scopedLocals;

src/module.ts

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1755,44 +1755,44 @@ export class Relooper {
17551755
}
17561756
}
17571757

1758-
// export function hasSideEffects(expr: ExpressionRef): bool {
1759-
// // TODO: there's more
1760-
// switch (_BinaryenExpressionGetId(expr)) {
1761-
// case ExpressionId.LocalGet:
1762-
// case ExpressionId.GlobalGet:
1763-
// case ExpressionId.Const:
1764-
// case ExpressionId.Nop: {
1765-
// return false;
1766-
// }
1767-
// case ExpressionId.Block: {
1768-
// for (let i = 0, k = _BinaryenBlockGetNumChildren(expr); i < k; ++i) {
1769-
// if (hasSideEffects(_BinaryenBlockGetChild(expr, i))) return true;
1770-
// }
1771-
// return false;
1772-
// }
1773-
// case ExpressionId.If: {
1774-
// return hasSideEffects(_BinaryenIfGetCondition(expr))
1775-
// || hasSideEffects(_BinaryenIfGetIfTrue(expr))
1776-
// || hasSideEffects(_BinaryenIfGetIfFalse(expr));
1777-
// }
1778-
// case ExpressionId.Unary: {
1779-
// return hasSideEffects(_BinaryenUnaryGetValue(expr));
1780-
// }
1781-
// case ExpressionId.Binary: {
1782-
// return hasSideEffects(_BinaryenBinaryGetLeft(expr))
1783-
// || hasSideEffects(_BinaryenBinaryGetRight(expr));
1784-
// }
1785-
// case ExpressionId.Drop: {
1786-
// return hasSideEffects(_BinaryenDropGetValue(expr));
1787-
// }
1788-
// case ExpressionId.Select: {
1789-
// return hasSideEffects(_BinaryenSelectGetIfTrue(expr))
1790-
// || hasSideEffects(_BinaryenSelectGetIfFalse(expr))
1791-
// || hasSideEffects(_BinaryenSelectGetCondition(expr));
1792-
// }
1793-
// }
1794-
// return true;
1795-
// }
1758+
export function hasSideEffects(expr: ExpressionRef): bool {
1759+
// TODO: there's more
1760+
switch (_BinaryenExpressionGetId(expr)) {
1761+
case ExpressionId.LocalGet:
1762+
case ExpressionId.GlobalGet:
1763+
case ExpressionId.Const:
1764+
case ExpressionId.Nop: {
1765+
return false;
1766+
}
1767+
case ExpressionId.Block: {
1768+
for (let i = 0, k = _BinaryenBlockGetNumChildren(expr); i < k; ++i) {
1769+
if (hasSideEffects(_BinaryenBlockGetChild(expr, i))) return true;
1770+
}
1771+
return false;
1772+
}
1773+
case ExpressionId.If: {
1774+
return hasSideEffects(_BinaryenIfGetCondition(expr))
1775+
|| hasSideEffects(_BinaryenIfGetIfTrue(expr))
1776+
|| hasSideEffects(_BinaryenIfGetIfFalse(expr));
1777+
}
1778+
case ExpressionId.Unary: {
1779+
return hasSideEffects(_BinaryenUnaryGetValue(expr));
1780+
}
1781+
case ExpressionId.Binary: {
1782+
return hasSideEffects(_BinaryenBinaryGetLeft(expr))
1783+
|| hasSideEffects(_BinaryenBinaryGetRight(expr));
1784+
}
1785+
case ExpressionId.Drop: {
1786+
return hasSideEffects(_BinaryenDropGetValue(expr));
1787+
}
1788+
case ExpressionId.Select: {
1789+
return hasSideEffects(_BinaryenSelectGetIfTrue(expr))
1790+
|| hasSideEffects(_BinaryenSelectGetIfFalse(expr))
1791+
|| hasSideEffects(_BinaryenSelectGetCondition(expr));
1792+
}
1793+
}
1794+
return true;
1795+
}
17961796

17971797
// helpers
17981798
// can't do stack allocation here: STACKTOP is a global in WASM but a hidden variable in asm.js

src/program.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -999,10 +999,10 @@ export class Program extends DiagnosticEmitter {
999999
return this.resolver.resolveFunction(<FunctionPrototype>prototype, null);
10001000
}
10011001

1002-
/** Requires that a non-generic global function is present and returns it. */
1003-
private requireFunction(name: string): Function {
1002+
/** Requires that a global function is present and returns it. */
1003+
private requireFunction(name: string, typeArguments: Type[] | null = null): Function {
10041004
var prototype = this.require(name, ElementKind.FUNCTION_PROTOTYPE);
1005-
var resolved = this.resolver.resolveFunction(<FunctionPrototype>prototype, null);
1005+
var resolved = this.resolver.resolveFunction(<FunctionPrototype>prototype, typeArguments);
10061006
if (!resolved) throw new Error("invalid " + name);
10071007
return resolved;
10081008
}

std/assembly/number.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,13 @@ export const NaN: f64 = 0 / 0;
99
@builtin @inline
1010
export const Infinity: f64 = 1 / 0;
1111

12-
export function isNaN<T extends number>(value: T): bool {
13-
if (!isFloat<T>()) {
14-
if (!isInteger<T>()) ERROR("numeric type expected");
15-
}
16-
return value != value;
17-
}
12+
// @ts-ignore: decorator
13+
@builtin
14+
export declare function isNaN<T extends number>(value: T): bool;
1815

19-
export function isFinite<T extends number>(value: T): bool {
20-
if (!isFloat<T>()) {
21-
if (!isInteger<T>()) ERROR("numeric type expected");
22-
}
23-
return value - value == 0;
24-
}
16+
// @ts-ignore: decorator
17+
@builtin
18+
export declare function isFinite<T extends number>(value: T): bool;
2519

2620
@sealed @unmanaged
2721
export abstract class I8 {

0 commit comments

Comments
 (0)