diff options
| author | antlilja <liljaanton2001@gmail.com> | 2023-07-17 00:16:49 +0200 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-09-27 11:15:53 -0700 |
| commit | 6a29646a553a93fc6a4cbf0fee5fa5362483c326 (patch) | |
| tree | f19368082978b5004e65707cdf4c60c786617db0 /src/arch/wasm/CodeGen.zig | |
| parent | 1606717b5fed83ee64ba1a91e55248e07a51afa6 (diff) | |
| download | zig-6a29646a553a93fc6a4cbf0fee5fa5362483c326.tar.gz zig-6a29646a553a93fc6a4cbf0fee5fa5362483c326.zip | |
Rename `@fabs` to `@abs` and accept integers
Replaces the @fabs builtin with a new @abs builtins which accepts
floats, signed integers and vectors of said types.
Diffstat (limited to 'src/arch/wasm/CodeGen.zig')
| -rw-r--r-- | src/arch/wasm/CodeGen.zig | 79 |
1 files changed, 78 insertions, 1 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 76a27ec718..850e08a6bc 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1866,13 +1866,14 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { .log => func.airUnaryFloatOp(inst, .log), .log2 => func.airUnaryFloatOp(inst, .log2), .log10 => func.airUnaryFloatOp(inst, .log10), - .fabs => func.airUnaryFloatOp(inst, .fabs), .floor => func.airUnaryFloatOp(inst, .floor), .ceil => func.airUnaryFloatOp(inst, .ceil), .round => func.airUnaryFloatOp(inst, .round), .trunc_float => func.airUnaryFloatOp(inst, .trunc), .neg => func.airUnaryFloatOp(inst, .neg), + .abs => func.airAbs(inst), + .add_with_overflow => func.airAddSubWithOverflow(inst, .add), .sub_with_overflow => func.airAddSubWithOverflow(inst, .sub), .shl_with_overflow => func.airShlWithOverflow(inst), @@ -2786,6 +2787,82 @@ const FloatOp = enum { } }; +fn airAbs(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { + const mod = func.bin_file.base.options.module.?; + const ty_op = func.air.instructions.items(.data)[inst].ty_op; + const operand = try func.resolveInst(ty_op.operand); + const ty = func.typeOf(ty_op.operand); + const scalar_ty = ty.scalarType(mod); + + switch (scalar_ty.zigTypeTag(mod)) { + .Int => if (ty.zigTypeTag(mod) == .Vector) { + return func.fail("TODO implement airAbs for {}", .{ty.fmt(mod)}); + } else { + const int_bits = ty.intInfo(mod).bits; + const wasm_bits = toWasmBits(int_bits) orelse { + return func.fail("TODO: airAbs for signed integers larger than '{d}' bits", .{int_bits}); + }; + + const op = try operand.toLocal(func, ty); + + try func.emitWValue(op); + switch (wasm_bits) { + 32 => { + if (wasm_bits != int_bits) { + try func.addImm32(wasm_bits - int_bits); + try func.addTag(.i32_shl); + } + try func.addImm32(31); + try func.addTag(.i32_shr_s); + + const tmp = try func.allocLocal(ty); + try func.addLabel(.local_tee, tmp.local.value); + + try func.emitWValue(op); + try func.addTag(.i32_xor); + try func.emitWValue(tmp); + try func.addTag(.i32_sub); + + if (int_bits != wasm_bits) { + try func.emitWValue(WValue{ .imm32 = (@as(u32, 1) << @intCast(int_bits)) - 1 }); + try func.addTag(.i32_and); + } + }, + 64 => { + if (wasm_bits != int_bits) { + try func.addImm64(wasm_bits - int_bits); + try func.addTag(.i64_shl); + } + try func.addImm64(63); + try func.addTag(.i64_shr_s); + + const tmp = try func.allocLocal(ty); + try func.addLabel(.local_tee, tmp.local.value); + + try func.emitWValue(op); + try func.addTag(.i64_xor); + try func.emitWValue(tmp); + try func.addTag(.i64_sub); + + if (int_bits != wasm_bits) { + try func.emitWValue(WValue{ .imm64 = (@as(u64, 1) << @intCast(int_bits)) - 1 }); + try func.addTag(.i64_and); + } + }, + else => return func.fail("TODO: Implement airAbs for {}", .{ty.fmt(mod)}), + } + + const result = try (WValue{ .stack = {} }).toLocal(func, ty); + func.finishAir(inst, result, &.{ty_op.operand}); + }, + .Float => { + const result = try (try func.floatOp(.fabs, ty, &.{operand})).toLocal(func, ty); + func.finishAir(inst, result, &.{ty_op.operand}); + }, + else => unreachable, + } +} + fn airUnaryFloatOp(func: *CodeGen, inst: Air.Inst.Index, op: FloatOp) InnerError!void { const un_op = func.air.instructions.items(.data)[inst].un_op; const operand = try func.resolveInst(un_op); |
