Commit 8236a26c60
Changed files (1)
src
arch
wasm
src/arch/wasm/CodeGen.zig
@@ -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", .{});
- }
-
- 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);
+ 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());
- 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.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);
- try func.store(result, high_op_res, Type.u64, 0);
- try func.store(result, tmp_op, Type.u64, 8);
- return result;
+ 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 FloatOp = enum {