diff options
Diffstat (limited to 'src/arch/wasm/CodeGen.zig')
| -rw-r--r-- | src/arch/wasm/CodeGen.zig | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index cd1aa286e1..f52506c393 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1317,6 +1317,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { .mul_with_overflow => 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; +} |
