mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
wasm: signed integer division (non-floor)
Implements the non-floor variants of signed integer division.
This commit is contained in:
parent
9b84f29503
commit
3011ef2d82
@ -1444,7 +1444,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
|
||||
.div_float,
|
||||
.div_exact,
|
||||
.div_trunc,
|
||||
=> self.airBinOp(inst, .div),
|
||||
=> self.airDiv(inst),
|
||||
.div_floor => self.airDivFloor(inst),
|
||||
.bit_and => self.airBinOp(inst, .@"and"),
|
||||
.bit_or => self.airBinOp(inst, .@"or"),
|
||||
@ -4759,6 +4759,20 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
|
||||
}
|
||||
}
|
||||
|
||||
fn airDiv(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
|
||||
if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
|
||||
|
||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||
const ty = self.air.typeOfIndex(inst);
|
||||
const lhs = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
|
||||
if (ty.isSignedInt()) {
|
||||
return self.divSigned(lhs, rhs, ty);
|
||||
}
|
||||
return self.binOp(lhs, rhs, ty, .div);
|
||||
}
|
||||
|
||||
fn airDivFloor(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
|
||||
if (self.liveness.isUnused(inst)) return WValue{ .none = {} };
|
||||
|
||||
@ -4785,3 +4799,36 @@ fn airDivFloor(self: *Self, inst: Air.Inst.Index) InnerError!WValue {
|
||||
try self.addLabel(.local_set, result.local);
|
||||
return result;
|
||||
}
|
||||
|
||||
fn divSigned(self: *Self, lhs: WValue, rhs: WValue, ty: Type) InnerError!WValue {
|
||||
const int_bits = ty.intInfo(self.target).bits;
|
||||
const wasm_bits = toWasmBits(int_bits) orelse {
|
||||
return self.fail("TODO: Implement signed division for integers with bitsize '{d}'", .{int_bits});
|
||||
};
|
||||
|
||||
if (wasm_bits == 128) {
|
||||
return self.fail("TODO: Implement signed division for 128-bit integerrs", .{});
|
||||
}
|
||||
|
||||
if (wasm_bits != int_bits) {
|
||||
const shift_val = switch (wasm_bits) {
|
||||
32 => WValue{ .imm32 = wasm_bits - int_bits },
|
||||
64 => WValue{ .imm64 = wasm_bits - int_bits },
|
||||
else => unreachable,
|
||||
};
|
||||
const shl_lhs = try self.binOp(lhs, shift_val, ty, .shl);
|
||||
const shr_lhs = try self.binOp(shl_lhs, shift_val, ty, .shr);
|
||||
const shl_rhs = try self.binOp(rhs, shift_val, ty, .shl);
|
||||
const shr_rhs = try self.binOp(shl_rhs, shift_val, ty, .shr);
|
||||
try self.emitWValue(shr_lhs);
|
||||
try self.emitWValue(shr_rhs);
|
||||
} else {
|
||||
try self.emitWValue(lhs);
|
||||
try self.emitWValue(rhs);
|
||||
}
|
||||
try self.addTag(.i32_div_s);
|
||||
|
||||
const result = try self.allocLocal(ty);
|
||||
try self.addLabel(.local_set, result.local);
|
||||
return result;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user