mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 13:58:27 +00:00
wasm: implement mul, shl and xor for big ints
Uses compiler-rt for multiplication and shifting left, while lowers it down using regular instructions for xor.
This commit is contained in:
parent
eb77e3381f
commit
8236a26c60
@ -2565,37 +2565,55 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!
|
||||
|
||||
fn binOpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue {
|
||||
if (ty.intInfo(func.target).bits > 128) {
|
||||
return func.fail("TODO: Implement binary operation for big integer", .{});
|
||||
return func.fail("TODO: Implement binary operation for big integers larger than 128 bits", .{});
|
||||
}
|
||||
|
||||
if (op != .add and op != .sub) {
|
||||
return func.fail("TODO: Implement binary operation for big integers", .{});
|
||||
switch (op) {
|
||||
.mul => return func.callIntrinsic("__multi3", &.{ ty, ty }, ty, &.{ lhs, rhs }),
|
||||
.shr => return func.callIntrinsic("__lshrti3", &.{ ty, Type.i32 }, ty, &.{ lhs, rhs }),
|
||||
.xor => {
|
||||
const result = try func.allocStack(ty);
|
||||
try func.emitWValue(result);
|
||||
const lhs_high_bit = try func.load(lhs, Type.u64, 0);
|
||||
const rhs_high_bit = try func.load(rhs, Type.u64, 0);
|
||||
const xor_high_bit = try func.binOp(lhs_high_bit, rhs_high_bit, Type.u64, .xor);
|
||||
try func.store(.stack, xor_high_bit, Type.u64, result.offset());
|
||||
|
||||
try func.emitWValue(result);
|
||||
const lhs_low_bit = try func.load(lhs, Type.u64, 8);
|
||||
const rhs_low_bit = try func.load(rhs, Type.u64, 8);
|
||||
const xor_low_bit = try func.binOp(lhs_low_bit, rhs_low_bit, Type.u64, .xor);
|
||||
try func.store(.stack, xor_low_bit, Type.u64, result.offset() + 8);
|
||||
return result;
|
||||
},
|
||||
.add, .sub => {
|
||||
const result = try func.allocStack(ty);
|
||||
var lhs_high_bit = try (try func.load(lhs, Type.u64, 0)).toLocal(func, Type.u64);
|
||||
defer lhs_high_bit.free(func);
|
||||
var rhs_high_bit = try (try func.load(rhs, Type.u64, 0)).toLocal(func, Type.u64);
|
||||
defer rhs_high_bit.free(func);
|
||||
var high_op_res = try (try func.binOp(lhs_high_bit, rhs_high_bit, Type.u64, op)).toLocal(func, Type.u64);
|
||||
defer high_op_res.free(func);
|
||||
|
||||
const lhs_low_bit = try func.load(lhs, Type.u64, 8);
|
||||
const rhs_low_bit = try func.load(rhs, Type.u64, 8);
|
||||
const low_op_res = try func.binOp(lhs_low_bit, rhs_low_bit, Type.u64, op);
|
||||
|
||||
const lt = if (op == .add) blk: {
|
||||
break :blk try func.cmp(high_op_res, rhs_high_bit, Type.u64, .lt);
|
||||
} else if (op == .sub) blk: {
|
||||
break :blk try func.cmp(lhs_high_bit, rhs_high_bit, Type.u64, .lt);
|
||||
} else unreachable;
|
||||
const tmp = try func.intcast(lt, Type.u32, Type.u64);
|
||||
var tmp_op = try (try func.binOp(low_op_res, tmp, Type.u64, op)).toLocal(func, Type.u64);
|
||||
defer tmp_op.free(func);
|
||||
|
||||
try func.store(result, high_op_res, Type.u64, 0);
|
||||
try func.store(result, tmp_op, Type.u64, 8);
|
||||
return result;
|
||||
},
|
||||
else => return func.fail("TODO: Implement binary operation for big integers: '{s}'", .{@tagName(op)}),
|
||||
}
|
||||
|
||||
const result = try func.allocStack(ty);
|
||||
var lhs_high_bit = try (try func.load(lhs, Type.u64, 0)).toLocal(func, Type.u64);
|
||||
defer lhs_high_bit.free(func);
|
||||
var rhs_high_bit = try (try func.load(rhs, Type.u64, 0)).toLocal(func, Type.u64);
|
||||
defer rhs_high_bit.free(func);
|
||||
var high_op_res = try (try func.binOp(lhs_high_bit, rhs_high_bit, Type.u64, op)).toLocal(func, Type.u64);
|
||||
defer high_op_res.free(func);
|
||||
|
||||
const lhs_low_bit = try func.load(lhs, Type.u64, 8);
|
||||
const rhs_low_bit = try func.load(rhs, Type.u64, 8);
|
||||
const low_op_res = try func.binOp(lhs_low_bit, rhs_low_bit, Type.u64, op);
|
||||
|
||||
const lt = if (op == .add) blk: {
|
||||
break :blk try func.cmp(high_op_res, rhs_high_bit, Type.u64, .lt);
|
||||
} else if (op == .sub) blk: {
|
||||
break :blk try func.cmp(lhs_high_bit, rhs_high_bit, Type.u64, .lt);
|
||||
} else unreachable;
|
||||
const tmp = try func.intcast(lt, Type.u32, Type.u64);
|
||||
var tmp_op = try (try func.binOp(low_op_res, tmp, Type.u64, op)).toLocal(func, Type.u64);
|
||||
defer tmp_op.free(func);
|
||||
|
||||
try func.store(result, high_op_res, Type.u64, 0);
|
||||
try func.store(result, tmp_op, Type.u64, 8);
|
||||
return result;
|
||||
}
|
||||
|
||||
const FloatOp = enum {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user