mirror of
https://github.com/ziglang/zig.git
synced 2026-01-03 20:13:21 +00:00
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<<bitsize) to set the right bits and ensure we will only count the trailing zeroes of the integer with the correct bitsize.
This commit is contained in:
parent
bd27fe2bf5
commit
2c40b37f79
@ -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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user