| ... | @@ -2565,37 +2565,55 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError! | ... | @@ -2565,37 +2565,55 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError! |
| 2565 | | 2565 | |
| 2566 | fn binOpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue { | 2566 | fn binOpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue { |
| 2567 | if (ty.intInfo(func.target).bits > 128) { | 2567 | if (ty.intInfo(func.target).bits > 128) { |
| 2568 | return func.fail("TODO: Implement binary operation for big integer", .{}); | 2568 | return func.fail("TODO: Implement binary operation for big integers larger than 128 bits", .{}); |
| 2569 | } | 2569 | } |
| 2570 | | 2570 | |
| 2571 | if (op != .add and op != .sub) { | 2571 | switch (op) { |
| 2572 | return func.fail("TODO: Implement binary operation for big integers", .{}); | 2572 | .mul => return func.callIntrinsic("__multi3", &.{ ty, ty }, ty, &.{ lhs, rhs }), |
| 2573 | } | 2573 | .shr => return func.callIntrinsic("__lshrti3", &.{ ty, Type.i32 }, ty, &.{ lhs, rhs }), |
| 2574 | | 2574 | .xor => { |
| 2575 | const result = try func.allocStack(ty); | 2575 | const result = try func.allocStack(ty); |
| 2576 | var lhs_high_bit = try (try func.load(lhs, Type.u64, 0)).toLocal(func, Type.u64); | 2576 | try func.emitWValue(result); |
| 2577 | defer lhs_high_bit.free(func); | 2577 | const lhs_high_bit = try func.load(lhs, Type.u64, 0); |
| 2578 | var rhs_high_bit = try (try func.load(rhs, Type.u64, 0)).toLocal(func, Type.u64); | 2578 | const rhs_high_bit = try func.load(rhs, Type.u64, 0); |
| 2579 | defer rhs_high_bit.free(func); | 2579 | const xor_high_bit = try func.binOp(lhs_high_bit, rhs_high_bit, Type.u64, .xor); |
| 2580 | var high_op_res = try (try func.binOp(lhs_high_bit, rhs_high_bit, Type.u64, op)).toLocal(func, Type.u64); | 2580 | try func.store(.stack, xor_high_bit, Type.u64, result.offset()); |
| 2581 | defer high_op_res.free(func); | | |
| 2582 | | | |
| 2583 | const lhs_low_bit = try func.load(lhs, Type.u64, 8); | | |
| 2584 | const rhs_low_bit = try func.load(rhs, Type.u64, 8); | | |
| 2585 | const low_op_res = try func.binOp(lhs_low_bit, rhs_low_bit, Type.u64, op); | | |
| 2586 | | 2581 | |
| 2587 | const lt = if (op == .add) blk: { | 2582 | try func.emitWValue(result); |
| 2588 | break :blk try func.cmp(high_op_res, rhs_high_bit, Type.u64, .lt); | 2583 | const lhs_low_bit = try func.load(lhs, Type.u64, 8); |
| 2589 | } else if (op == .sub) blk: { | 2584 | const rhs_low_bit = try func.load(rhs, Type.u64, 8); |
| 2590 | break :blk try func.cmp(lhs_high_bit, rhs_high_bit, Type.u64, .lt); | 2585 | const xor_low_bit = try func.binOp(lhs_low_bit, rhs_low_bit, Type.u64, .xor); |
| 2591 | } else unreachable; | 2586 | try func.store(.stack, xor_low_bit, Type.u64, result.offset() + 8); |
| 2592 | const tmp = try func.intcast(lt, Type.u32, Type.u64); | 2587 | return result; |
| 2593 | var tmp_op = try (try func.binOp(low_op_res, tmp, Type.u64, op)).toLocal(func, Type.u64); | 2588 | }, |
| 2594 | defer tmp_op.free(func); | 2589 | .add, .sub => { |
| | 2590 | const result = try func.allocStack(ty); |
| | 2591 | var lhs_high_bit = try (try func.load(lhs, Type.u64, 0)).toLocal(func, Type.u64); |
| | 2592 | defer lhs_high_bit.free(func); |
| | 2593 | var rhs_high_bit = try (try func.load(rhs, Type.u64, 0)).toLocal(func, Type.u64); |
| | 2594 | defer rhs_high_bit.free(func); |
| | 2595 | var high_op_res = try (try func.binOp(lhs_high_bit, rhs_high_bit, Type.u64, op)).toLocal(func, Type.u64); |
| | 2596 | defer high_op_res.free(func); |
| 2595 | | 2597 | |
| 2596 | try func.store(result, high_op_res, Type.u64, 0); | 2598 | const lhs_low_bit = try func.load(lhs, Type.u64, 8); |
| 2597 | try func.store(result, tmp_op, Type.u64, 8); | 2599 | const rhs_low_bit = try func.load(rhs, Type.u64, 8); |
| 2598 | return result; | 2600 | const low_op_res = try func.binOp(lhs_low_bit, rhs_low_bit, Type.u64, op); |
| | 2601 | |
| | 2602 | const lt = if (op == .add) blk: { |
| | 2603 | break :blk try func.cmp(high_op_res, rhs_high_bit, Type.u64, .lt); |
| | 2604 | } else if (op == .sub) blk: { |
| | 2605 | break :blk try func.cmp(lhs_high_bit, rhs_high_bit, Type.u64, .lt); |
| | 2606 | } else unreachable; |
| | 2607 | const tmp = try func.intcast(lt, Type.u32, Type.u64); |
| | 2608 | var tmp_op = try (try func.binOp(low_op_res, tmp, Type.u64, op)).toLocal(func, Type.u64); |
| | 2609 | defer tmp_op.free(func); |
| | 2610 | |
| | 2611 | try func.store(result, high_op_res, Type.u64, 0); |
| | 2612 | try func.store(result, tmp_op, Type.u64, 8); |
| | 2613 | return result; |
| | 2614 | }, |
| | 2615 | else => return func.fail("TODO: Implement binary operation for big integers: '{s}'", .{@tagName(op)}), |
| | 2616 | } |
| 2599 | } | 2617 | } |
| 2600 | | 2618 | |
| 2601 | const FloatOp = enum { | 2619 | const FloatOp = enum { |