| ... | ... | @@ -1317,6 +1317,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1317 | 1317 | .mul_with_overflow => self.airBinOpOverflow(inst, .mul), |
| 1318 | 1318 | |
| 1319 | 1319 | .clz => self.airClz(inst), |
| 1320 | .ctz => self.airCtz(inst), |
| 1320 | 1321 | |
| 1321 | 1322 | .cmp_eq => self.airCmp(inst, .eq), |
| 1322 | 1323 | .cmp_gte => self.airCmp(inst, .gte), |
| ... | ... | @@ -1440,7 +1441,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1440 | 1441 | .shl_sat, |
| 1441 | 1442 | .ret_addr, |
| 1442 | 1443 | .frame_addr, |
| 1443 | | .ctz, |
| 1444 | 1444 | .byte_swap, |
| 1445 | 1445 | .bit_reverse, |
| 1446 | 1446 | .is_err_ptr, |
| ... | ... | @@ -3978,3 +3978,44 @@ fn airClz(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3978 | 3978 | try self.addLabel(.local_set, result.local); |
| 3979 | 3979 | return result; |
| 3980 | 3980 | } |
| 3981 | |
| 3982 | fn airCtz(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3983 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; |
| 3984 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3985 | const ty = self.air.typeOf(ty_op.operand); |
| 3986 | const result_ty = self.air.typeOfIndex(inst); |
| 3987 | |
| 3988 | if (ty.zigTypeTag() == .Vector) { |
| 3989 | return self.fail("TODO: `@ctz` for vectors", .{}); |
| 3990 | } |
| 3991 | |
| 3992 | const operand = try self.resolveInst(ty_op.operand); |
| 3993 | const int_info = ty.intInfo(self.target); |
| 3994 | const wasm_bits = toWasmBits(int_info.bits) orelse { |
| 3995 | return self.fail("TODO: `@clz` for integers with bitsize '{d}'", .{int_info.bits}); |
| 3996 | }; |
| 3997 | |
| 3998 | switch (wasm_bits) { |
| 3999 | 32 => { |
| 4000 | if (wasm_bits != int_info.bits) { |
| 4001 | const val: u32 = @as(u32, 1) << @intCast(u5, int_info.bits); |
| 4002 | const bin_op = try self.binOp(operand, .{ .imm32 = val }, ty, .@"or"); |
| 4003 | try self.emitWValue(bin_op); |
| 4004 | } else try self.emitWValue(operand); |
| 4005 | try self.addTag(.i32_ctz); |
| 4006 | }, |
| 4007 | 64 => { |
| 4008 | if (wasm_bits != int_info.bits) { |
| 4009 | const val: u64 = @as(u64, 1) << @intCast(u6, int_info.bits); |
| 4010 | const bin_op = try self.binOp(operand, .{ .imm64 = val }, ty, .@"or"); |
| 4011 | try self.emitWValue(bin_op); |
| 4012 | } else try self.emitWValue(operand); |
| 4013 | try self.addTag(.i64_ctz); |
| 4014 | }, |
| 4015 | else => unreachable, |
| 4016 | } |
| 4017 | |
| 4018 | const result = try self.allocLocal(result_ty); |
| 4019 | try self.addLabel(.local_set, result.local); |
| 4020 | return result; |
| 4021 | } |