Summary
The codegen arms for Math.tan, Math.asin, Math.acos, Math.atan, and Math.atan2 lower to return the argument unchanged. Programs calling these get a silent identity function with zero diagnostic.
Math.sin / Math.cos are correctly wired to llvm.sin.f64 / llvm.cos.f64 intrinsics — the bug is specific to the five trig functions above.
Evidence
crates/perry-codegen/src/expr.rs:5389-5397:
// tan/asin/acos/atan: still stubs returning input (runtime has no wrappers yet, no LLVM intrinsics for these).
Expr::MathTan(o)
| Expr::MathAsin(o)
| Expr::MathAcos(o)
| Expr::MathAtan(o) => lower_expr(ctx, o),
Expr::MathAtan2(y, x) => {
let _ = lower_expr(ctx, y)?;
lower_expr(ctx, x)
}
The real implementations already exist in crates/perry-runtime/src/math.rs:46-62 (js_math_tan, js_math_asin, js_math_acos, js_math_atan, js_math_atan2, each calling f64::tan() etc.), but nothing calls them.
Impact
Math.tan(x) === x for any x
Math.atan2(y, x) === x (y is evaluated and discarded)
- No warning, no error — the program compiles and runs with wrong numbers
- Any graphics / geometry / physics code relying on these is silently incorrect
Suggested fix
Wire the existing runtime functions through codegen the same way other Math.* helpers are called (extern decl in runtime_decls.rs + a ctx.block().call(DOUBLE, "js_math_tan", &[arg]) in the codegen arm). Or, where applicable, use llvm.* intrinsics — LLVM has no tan/asin/acos/atan intrinsics on all targets, so runtime calls are the safer path.
Reproducer
console.log(Math.tan(0)); // expected 0, got 0 (lucky)
console.log(Math.tan(1)); // expected ~1.557, got 1
console.log(Math.atan2(1,1)); // expected ~0.785, got 1
Summary
The codegen arms for
Math.tan,Math.asin,Math.acos,Math.atan, andMath.atan2lower to return the argument unchanged. Programs calling these get a silent identity function with zero diagnostic.Math.sin/Math.cosare correctly wired tollvm.sin.f64/llvm.cos.f64intrinsics — the bug is specific to the five trig functions above.Evidence
crates/perry-codegen/src/expr.rs:5389-5397:The real implementations already exist in
crates/perry-runtime/src/math.rs:46-62(js_math_tan,js_math_asin,js_math_acos,js_math_atan,js_math_atan2, each callingf64::tan()etc.), but nothing calls them.Impact
Math.tan(x) === xfor anyxMath.atan2(y, x) === x(y is evaluated and discarded)Suggested fix
Wire the existing runtime functions through codegen the same way other
Math.*helpers are called (extern decl inruntime_decls.rs+ actx.block().call(DOUBLE, "js_math_tan", &[arg])in the codegen arm). Or, where applicable, usellvm.*intrinsics — LLVM has notan/asin/acos/atanintrinsics on all targets, so runtime calls are the safer path.Reproducer