From 2c40b37f79b1b40b5f22e13131064bcab2191f64 Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Sat, 2 Apr 2022 17:56:11 +0200 Subject: [PATCH] wasm: Implement `@ctz` for bitsize <= 64 Implements the `ctz` AIR instruction for integers with bitsize <= 64. When the bitsize of the integer does not match the bitsize of a wasm type, we first XOR the value with the value of (1< self.airBinOpOverflow(inst, .mul), .clz => self.airClz(inst), + .ctz => self.airCtz(inst), .cmp_eq => self.airCmp(inst, .eq), .cmp_gte => self.airCmp(inst, .gte), @@ -1440,7 +1441,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { .shl_sat, .ret_addr, .frame_addr, - .ctz, .byte_swap, .bit_reverse, .is_err_ptr, @@ -3978,3 +3978,44 @@ fn airClz(self: *Self, inst: Air.Inst.Index) InnerError!WValue { try self.addLabel(.local_set, result.local); return result; } + +fn airCtz(self: *Self, inst: Air.Inst.Index) InnerError!WValue { + if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const ty = self.air.typeOf(ty_op.operand); + const result_ty = self.air.typeOfIndex(inst); + + if (ty.zigTypeTag() == .Vector) { + return self.fail("TODO: `@ctz` for vectors", .{}); + } + + const operand = try self.resolveInst(ty_op.operand); + const int_info = ty.intInfo(self.target); + const wasm_bits = toWasmBits(int_info.bits) orelse { + return self.fail("TODO: `@clz` for integers with bitsize '{d}'", .{int_info.bits}); + }; + + switch (wasm_bits) { + 32 => { + if (wasm_bits != int_info.bits) { + const val: u32 = @as(u32, 1) << @intCast(u5, int_info.bits); + const bin_op = try self.binOp(operand, .{ .imm32 = val }, ty, .@"or"); + try self.emitWValue(bin_op); + } else try self.emitWValue(operand); + try self.addTag(.i32_ctz); + }, + 64 => { + if (wasm_bits != int_info.bits) { + const val: u64 = @as(u64, 1) << @intCast(u6, int_info.bits); + const bin_op = try self.binOp(operand, .{ .imm64 = val }, ty, .@"or"); + try self.emitWValue(bin_op); + } else try self.emitWValue(operand); + try self.addTag(.i64_ctz); + }, + else => unreachable, + } + + const result = try self.allocLocal(result_ty); + try self.addLabel(.local_set, result.local); + return result; +}