| ... | @@ -1316,6 +1316,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1316,6 +1316,8 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1316 | .shl_with_overflow => self.airBinOpOverflow(inst, .shl), | 1316 | .shl_with_overflow => self.airBinOpOverflow(inst, .shl), |
| 1317 | .mul_with_overflow => self.airBinOpOverflow(inst, .mul), | 1317 | .mul_with_overflow => self.airBinOpOverflow(inst, .mul), |
| 1318 | | 1318 | |
| | 1319 | .clz => self.airClz(inst), |
| | 1320 | |
| 1319 | .cmp_eq => self.airCmp(inst, .eq), | 1321 | .cmp_eq => self.airCmp(inst, .eq), |
| 1320 | .cmp_gte => self.airCmp(inst, .gte), | 1322 | .cmp_gte => self.airCmp(inst, .gte), |
| 1321 | .cmp_gt => self.airCmp(inst, .gt), | 1323 | .cmp_gt => self.airCmp(inst, .gt), |
| ... | @@ -1438,7 +1440,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { | ... | @@ -1438,7 +1440,6 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue { |
| 1438 | .shl_sat, | 1440 | .shl_sat, |
| 1439 | .ret_addr, | 1441 | .ret_addr, |
| 1440 | .frame_addr, | 1442 | .frame_addr, |
| 1441 | .clz, | | |
| 1442 | .ctz, | 1443 | .ctz, |
| 1443 | .byte_swap, | 1444 | .byte_swap, |
| 1444 | .bit_reverse, | 1445 | .bit_reverse, |
| ... | @@ -3932,3 +3933,48 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) InnerError!WValue { | ... | @@ -3932,3 +3933,48 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3932 | const mul_result = try self.binOp(lhs, rhs, ty, .mul); | 3933 | const mul_result = try self.binOp(lhs, rhs, ty, .mul); |
| 3933 | return self.binOp(mul_result, addend, ty, .add); | 3934 | return self.binOp(mul_result, addend, ty, .add); |
| 3934 | } | 3935 | } |
| | 3936 | |
| | 3937 | fn airClz(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| | 3938 | if (self.liveness.isUnused(inst)) return WValue{ .none = {} }; |
| | 3939 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| | 3940 | const ty = self.air.typeOf(ty_op.operand); |
| | 3941 | const result_ty = self.air.typeOfIndex(inst); |
| | 3942 | if (ty.zigTypeTag() == .Vector) { |
| | 3943 | return self.fail("TODO: `@clz` for vectors", .{}); |
| | 3944 | } |
| | 3945 | |
| | 3946 | const operand = try self.resolveInst(ty_op.operand); |
| | 3947 | const int_info = ty.intInfo(self.target); |
| | 3948 | const wasm_bits = toWasmBits(int_info.bits) orelse { |
| | 3949 | return self.fail("TODO: `@clz` for integers with bitsize '{d}'", .{int_info.bits}); |
| | 3950 | }; |
| | 3951 | |
| | 3952 | try self.emitWValue(operand); |
| | 3953 | switch (wasm_bits) { |
| | 3954 | 32 => { |
| | 3955 | try self.addTag(.i32_clz); |
| | 3956 | |
| | 3957 | if (wasm_bits != int_info.bits) { |
| | 3958 | const tmp = try self.allocLocal(ty); |
| | 3959 | try self.addLabel(.local_set, tmp.local); |
| | 3960 | const val: i32 = -@intCast(i32, wasm_bits - int_info.bits); |
| | 3961 | return self.wrapBinOp(tmp, .{ .imm32 = @bitCast(u32, val) }, ty, .add); |
| | 3962 | } |
| | 3963 | }, |
| | 3964 | 64 => { |
| | 3965 | try self.addTag(.i64_clz); |
| | 3966 | |
| | 3967 | if (wasm_bits != int_info.bits) { |
| | 3968 | const tmp = try self.allocLocal(ty); |
| | 3969 | try self.addLabel(.local_set, tmp.local); |
| | 3970 | const val: i64 = -@intCast(i64, wasm_bits - int_info.bits); |
| | 3971 | return self.wrapBinOp(tmp, .{ .imm64 = @bitCast(u64, val) }, ty, .add); |
| | 3972 | } |
| | 3973 | }, |
| | 3974 | else => unreachable, |
| | 3975 | } |
| | 3976 | |
| | 3977 | const result = try self.allocLocal(result_ty); |
| | 3978 | try self.addLabel(.local_set, result.local); |
| | 3979 | return result; |
| | 3980 | } |