| ... | @@ -37,6 +37,10 @@ prologue: Section = .{}, | ... | @@ -37,6 +37,10 @@ prologue: Section = .{}, |
| 37 | body: Section = .{}, | 37 | body: Section = .{}, |
| 38 | args: std.ArrayList(Id) = .empty, | 38 | args: std.ArrayList(Id) = .empty, |
| 39 | next_arg_index: u32 = 0, | 39 | next_arg_index: u32 = 0, |
| | 40 | /// Caches the limb extractions for composite integer values so repeated |
| | 41 | /// arithmetic on the same operand doesn't re-emit `OpCompositeExtract` per |
| | 42 | /// limb per use. Slices are owned by `cg.arena`. |
| | 43 | composite_limbs: std.AutoHashMapUnmanaged(Id, []const Id) = .empty, |
| 40 | block_stack: std.ArrayList(*Block) = .empty, | 44 | block_stack: std.ArrayList(*Block) = .empty, |
| 41 | block_label: Id = .none, | 45 | block_label: Id = .none, |
| 42 | /// Whether the current block has been terminated by a terminator | 46 | /// Whether the current block has been terminated by a terminator |
| ... | @@ -49,7 +53,18 @@ tracked_allocas: std.AutoHashMapUnmanaged(Id, ?Id) = .empty, | ... | @@ -49,7 +53,18 @@ tracked_allocas: std.AutoHashMapUnmanaged(Id, ?Id) = .empty, |
| 49 | loop_switches: std.AutoHashMapUnmanaged(Air.Inst.Index, LoopSwitch) = .empty, | 53 | loop_switches: std.AutoHashMapUnmanaged(Air.Inst.Index, LoopSwitch) = .empty, |
| 50 | id_scratch: std.ArrayList(Id) = .empty, | 54 | id_scratch: std.ArrayList(Id) = .empty, |
| 51 | | 55 | |
| 52 | const big_int_bits = @bitSizeOf(u32); | 56 | fn bigIntBits(cg: *const CodeGen) u16 { |
| | 57 | const target = cg.zcu.getTarget(); |
| | 58 | return if (target.cpu.has(.spirv, .int64)) 64 else 32; |
| | 59 | } |
| | 60 | |
| | 61 | fn limbType(cg: *const CodeGen) Type { |
| | 62 | return if (cg.bigIntBits() == 64) .u64 else .u32; |
| | 63 | } |
| | 64 | |
| | 65 | fn limbTypeId(cg: *CodeGen) !Id { |
| | 66 | return cg.resolveType(cg.limbType(), .direct); |
| | 67 | } |
| 53 | | 68 | |
| 54 | /// Data can be lowered into in two basic representations: indirect, which is when | 69 | /// Data can be lowered into in two basic representations: indirect, which is when |
| 55 | /// a type is stored in memory, and direct, which is how a type is stored when its | 70 | /// a type is stored in memory, and direct, which is how a type is stored when its |
| ... | @@ -163,6 +178,7 @@ pub fn deinit(cg: *CodeGen) void { | ... | @@ -163,6 +178,7 @@ pub fn deinit(cg: *CodeGen) void { |
| 163 | cg.block_stack.deinit(gpa); | 178 | cg.block_stack.deinit(gpa); |
| 164 | cg.block_results.deinit(gpa); | 179 | cg.block_results.deinit(gpa); |
| 165 | cg.args.deinit(gpa); | 180 | cg.args.deinit(gpa); |
| | 181 | cg.composite_limbs.deinit(gpa); |
| 166 | cg.tracked_allocas.deinit(gpa); | 182 | cg.tracked_allocas.deinit(gpa); |
| 167 | cg.inst_results.deinit(gpa); | 183 | cg.inst_results.deinit(gpa); |
| 168 | cg.loop_switches.deinit(gpa); | 184 | cg.loop_switches.deinit(gpa); |
| ... | @@ -478,7 +494,7 @@ pub fn backingIntBits(cg: *const CodeGen, bits: u16) struct { u16, bool } { | ... | @@ -478,7 +494,7 @@ pub fn backingIntBits(cg: *const CodeGen, bits: u16) struct { u16, bool } { |
| 478 | if (bits <= int.bits and int.enabled) return .{ int.bits, false }; | 494 | if (bits <= int.bits and int.enabled) return .{ int.bits, false }; |
| 479 | } | 495 | } |
| 480 | | 496 | |
| 481 | return .{ std.mem.alignForward(u16, bits, big_int_bits), true }; | 497 | return .{ std.mem.alignForward(u16, bits, cg.bigIntBits()), true }; |
| 482 | } | 498 | } |
| 483 | | 499 | |
| 484 | pub fn intType(cg: *CodeGen, signedness: std.lang.Signedness, bits: u16) !Id { | 500 | pub fn intType(cg: *CodeGen, signedness: std.lang.Signedness, bits: u16) !Id { |
| ... | @@ -492,14 +508,16 @@ pub fn intType(cg: *CodeGen, signedness: std.lang.Signedness, bits: u16) !Id { | ... | @@ -492,14 +508,16 @@ pub fn intType(cg: *CodeGen, signedness: std.lang.Signedness, bits: u16) !Id { |
| 492 | }; | 508 | }; |
| 493 | const backing_bits, const big_int = cg.backingIntBits(bits); | 509 | const backing_bits, const big_int = cg.backingIntBits(bits); |
| 494 | if (big_int) { | 510 | if (big_int) { |
| 495 | const u32_ty = try cg.intType(.unsigned, 32); | 511 | const limb_bits = cg.bigIntBits(); |
| | 512 | const limb_ty = try cg.intType(.unsigned, limb_bits); |
| | 513 | const len_ty = try cg.intType(.unsigned, 32); |
| 496 | const len_id = cg.allocId(); | 514 | const len_id = cg.allocId(); |
| 497 | try cg.sections.globals.emit(cg.gpa, .OpConstant, .{ | 515 | try cg.sections.globals.emit(cg.gpa, .OpConstant, .{ |
| 498 | .id_result_type = u32_ty, | 516 | .id_result_type = len_ty, |
| 499 | .id_result = len_id, | 517 | .id_result = len_id, |
| 500 | .value = .{ .uint32 = backing_bits / big_int_bits }, | 518 | .value = .{ .uint32 = backing_bits / limb_bits }, |
| 501 | }); | 519 | }); |
| 502 | return cg.arrayType(len_id, u32_ty); | 520 | return cg.arrayType(len_id, limb_ty); |
| 503 | } | 521 | } |
| 504 | | 522 | |
| 505 | const result_id = cg.allocId(); | 523 | const result_id = cg.allocId(); |
| ... | @@ -1443,7 +1461,7 @@ fn constInt(cg: *CodeGen, ty: Type, value: anytype) !Id { | ... | @@ -1443,7 +1461,7 @@ fn constInt(cg: *CodeGen, ty: Type, value: anytype) !Id { |
| 1443 | .signed => @bitCast(@as(i64, @intCast(value))), | 1461 | .signed => @bitCast(@as(i64, @intCast(value))), |
| 1444 | .unsigned => @as(u64, @intCast(value)), | 1462 | .unsigned => @as(u64, @intCast(value)), |
| 1445 | }; | 1463 | }; |
| 1446 | const n_limbs = backing_bits / big_int_bits; | 1464 | const n_limbs = backing_bits / cg.bigIntBits(); |
| 1447 | const fill: u32 = if (signedness == .signed and value < 0) 0xFFFFFFFF else 0; | 1465 | const fill: u32 = if (signedness == .signed and value < 0) 0xFFFFFFFF else 0; |
| 1448 | const scratch_top = cg.id_scratch.items.len; | 1466 | const scratch_top = cg.id_scratch.items.len; |
| 1449 | defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); | 1467 | defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); |
| ... | @@ -1616,21 +1634,33 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { | ... | @@ -1616,21 +1634,33 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { |
| 1616 | const int_info = ty.intInfo(zcu); | 1634 | const int_info = ty.intInfo(zcu); |
| 1617 | const backing_bits, const is_big_int = cg.backingIntBits(int_info.bits); | 1635 | const backing_bits, const is_big_int = cg.backingIntBits(int_info.bits); |
| 1618 | if (is_big_int) { | 1636 | if (is_big_int) { |
| 1619 | const n_limbs = backing_bits / big_int_bits; | 1637 | const limb_bits = cg.bigIntBits(); |
| | 1638 | const n_limbs = backing_bits / limb_bits; |
| 1620 | const big_result_ty_id = try cg.resolveType(ty, .indirect); | 1639 | const big_result_ty_id = try cg.resolveType(ty, .indirect); |
| 1621 | var bigint_space: Value.BigIntSpace = undefined; | 1640 | var bigint_space: Value.BigIntSpace = undefined; |
| 1622 | const bigint = val.toBigInt(&bigint_space, zcu); | 1641 | const bigint = val.toBigInt(&bigint_space, zcu); |
| 1623 | const limb_values = try gpa.alloc(u32, n_limbs); | 1642 | const limb_bytes = try gpa.alloc(u8, backing_bits / 8); |
| 1624 | defer gpa.free(limb_values); | 1643 | defer gpa.free(limb_bytes); |
| 1625 | bigint.writeTwosComplement(std.mem.sliceAsBytes(limb_values), .little); | 1644 | bigint.writeTwosComplement(limb_bytes, .little); |
| 1626 | if (builtin.cpu.arch.endian() == .big) { | | |
| 1627 | for (limb_values) |*limb| limb.* = @byteSwap(limb.*); | | |
| 1628 | } | | |
| 1629 | const scratch_top = cg.id_scratch.items.len; | 1645 | const scratch_top = cg.id_scratch.items.len; |
| 1630 | defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); | 1646 | defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); |
| 1631 | const constituents = try cg.id_scratch.addManyAsSlice(gpa, n_limbs); | 1647 | const constituents = try cg.id_scratch.addManyAsSlice(gpa, n_limbs); |
| 1632 | for (constituents, 0..) |*c, i| { | 1648 | switch (limb_bits) { |
| 1633 | c.* = try cg.constInt(.u32, limb_values[i]); | 1649 | 32 => { |
| | 1650 | const limbs_u32: []u32 = @ptrCast(@alignCast(limb_bytes)); |
| | 1651 | for (constituents, limbs_u32) |*c, v| { |
| | 1652 | const host_v = if (builtin.cpu.arch.endian() == .big) @byteSwap(v) else v; |
| | 1653 | c.* = try cg.constInt(.u32, host_v); |
| | 1654 | } |
| | 1655 | }, |
| | 1656 | 64 => { |
| | 1657 | const limbs_u64: []u64 = @ptrCast(@alignCast(limb_bytes)); |
| | 1658 | for (constituents, limbs_u64) |*c, v| { |
| | 1659 | const host_v = if (builtin.cpu.arch.endian() == .big) @byteSwap(v) else v; |
| | 1660 | c.* = try cg.constInt(.u64, host_v); |
| | 1661 | } |
| | 1662 | }, |
| | 1663 | else => unreachable, |
| 1634 | } | 1664 | } |
| 1635 | break :cache try cg.constructComposite(big_result_ty_id, constituents); | 1665 | break :cache try cg.constructComposite(big_result_ty_id, constituents); |
| 1636 | } | 1666 | } |
| ... | @@ -2766,20 +2796,28 @@ const CompositeInt = struct { | ... | @@ -2766,20 +2796,28 @@ const CompositeInt = struct { |
| 2766 | info: ArithmeticTypeInfo, | 2796 | info: ArithmeticTypeInfo, |
| 2767 | | 2797 | |
| 2768 | fn init(cg: *CodeGen, composite_id: Id, info: ArithmeticTypeInfo) !CompositeInt { | 2798 | fn init(cg: *CodeGen, composite_id: Id, info: ArithmeticTypeInfo) !CompositeInt { |
| 2769 | const n_limbs: u16 = info.backing_bits / big_int_bits; | 2799 | const n_limbs: u16 = info.backing_bits / cg.bigIntBits(); |
| 2770 | const gpa = cg.gpa; | 2800 | const gpa = cg.gpa; |
| 2771 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 2801 | if (cg.composite_limbs.get(composite_id)) |cached| { |
| | 2802 | assert(cached.len == n_limbs); |
| | 2803 | const limbs = try cg.id_scratch.addManyAsSlice(gpa, n_limbs); |
| | 2804 | @memcpy(limbs, cached); |
| | 2805 | return .{ .cg = cg, .limbs = limbs, .n_limbs = n_limbs, .info = info }; |
| | 2806 | } |
| | 2807 | const limb_ty_id = try cg.limbTypeId(); |
| 2772 | const limbs = try cg.id_scratch.addManyAsSlice(gpa, n_limbs); | 2808 | const limbs = try cg.id_scratch.addManyAsSlice(gpa, n_limbs); |
| 2773 | for (limbs, 0..) |*limb, i| { | 2809 | for (limbs, 0..) |*limb, i| { |
| 2774 | const result_id = cg.allocId(); | 2810 | const result_id = cg.allocId(); |
| 2775 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 2811 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 2776 | .id_result_type = u32_ty_id, | 2812 | .id_result_type = limb_ty_id, |
| 2777 | .id_result = result_id, | 2813 | .id_result = result_id, |
| 2778 | .composite = composite_id, | 2814 | .composite = composite_id, |
| 2779 | .indexes = &.{@as(u32, @intCast(i))}, | 2815 | .indexes = &.{@as(u32, @intCast(i))}, |
| 2780 | }); | 2816 | }); |
| 2781 | limb.* = result_id; | 2817 | limb.* = result_id; |
| 2782 | } | 2818 | } |
| | 2819 | const cached = try cg.arena.dupe(Id, limbs); |
| | 2820 | try cg.composite_limbs.put(gpa, composite_id, cached); |
| 2783 | return .{ .cg = cg, .limbs = limbs, .n_limbs = n_limbs, .info = info }; | 2821 | return .{ .cg = cg, .limbs = limbs, .n_limbs = n_limbs, .info = info }; |
| 2784 | } | 2822 | } |
| 2785 | | 2823 | |
| ... | @@ -2793,9 +2831,9 @@ const CompositeInt = struct { | ... | @@ -2793,9 +2831,9 @@ const CompositeInt = struct { |
| 2793 | } | 2831 | } |
| 2794 | | 2832 | |
| 2795 | fn zero(cg: *CodeGen, info: ArithmeticTypeInfo) !CompositeInt { | 2833 | fn zero(cg: *CodeGen, info: ArithmeticTypeInfo) !CompositeInt { |
| 2796 | const n_limbs: u16 = info.backing_bits / big_int_bits; | 2834 | const n_limbs: u16 = info.backing_bits / cg.bigIntBits(); |
| 2797 | const limbs = try cg.id_scratch.addManyAsSlice(cg.gpa, n_limbs); | 2835 | const limbs = try cg.id_scratch.addManyAsSlice(cg.gpa, n_limbs); |
| 2798 | const zero_id = try cg.constInt(.u32, @as(u32, 0)); | 2836 | const zero_id = try cg.constInt(cg.limbType(), @as(u64, 0)); |
| 2799 | for (limbs) |*limb| limb.* = zero_id; | 2837 | for (limbs) |*limb| limb.* = zero_id; |
| 2800 | return .{ .cg = cg, .limbs = limbs, .n_limbs = n_limbs, .info = info }; | 2838 | return .{ .cg = cg, .limbs = limbs, .n_limbs = n_limbs, .info = info }; |
| 2801 | } | 2839 | } |
| ... | @@ -2808,10 +2846,10 @@ const CompositeInt = struct { | ... | @@ -2808,10 +2846,10 @@ const CompositeInt = struct { |
| 2808 | fn limbBinOp(ci: CompositeInt, opcode: Opcode, lhs: Id, rhs: Id) !Id { | 2846 | fn limbBinOp(ci: CompositeInt, opcode: Opcode, lhs: Id, rhs: Id) !Id { |
| 2809 | const cg = ci.cg; | 2847 | const cg = ci.cg; |
| 2810 | const gpa = cg.gpa; | 2848 | const gpa = cg.gpa; |
| 2811 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 2849 | const limb_ty_id = try cg.limbTypeId(); |
| 2812 | const result_id = cg.allocId(); | 2850 | const result_id = cg.allocId(); |
| 2813 | try cg.body.emitRaw(gpa, opcode, 4); | 2851 | try cg.body.emitRaw(gpa, opcode, 4); |
| 2814 | cg.body.writeOperand(Id, u32_ty_id); | 2852 | cg.body.writeOperand(Id, limb_ty_id); |
| 2815 | cg.body.writeOperand(Id, result_id); | 2853 | cg.body.writeOperand(Id, result_id); |
| 2816 | cg.body.writeOperand(Id, lhs); | 2854 | cg.body.writeOperand(Id, lhs); |
| 2817 | cg.body.writeOperand(Id, rhs); | 2855 | cg.body.writeOperand(Id, rhs); |
| ... | @@ -2821,10 +2859,10 @@ const CompositeInt = struct { | ... | @@ -2821,10 +2859,10 @@ const CompositeInt = struct { |
| 2821 | fn limbUnOp(ci: CompositeInt, opcode: Opcode, operand: Id) !Id { | 2859 | fn limbUnOp(ci: CompositeInt, opcode: Opcode, operand: Id) !Id { |
| 2822 | const cg = ci.cg; | 2860 | const cg = ci.cg; |
| 2823 | const gpa = cg.gpa; | 2861 | const gpa = cg.gpa; |
| 2824 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 2862 | const limb_ty_id = try cg.limbTypeId(); |
| 2825 | const result_id = cg.allocId(); | 2863 | const result_id = cg.allocId(); |
| 2826 | try cg.body.emitRaw(gpa, opcode, 3); | 2864 | try cg.body.emitRaw(gpa, opcode, 3); |
| 2827 | cg.body.writeOperand(Id, u32_ty_id); | 2865 | cg.body.writeOperand(Id, limb_ty_id); |
| 2828 | cg.body.writeOperand(Id, result_id); | 2866 | cg.body.writeOperand(Id, result_id); |
| 2829 | cg.body.writeOperand(Id, operand); | 2867 | cg.body.writeOperand(Id, operand); |
| 2830 | return result_id; | 2868 | return result_id; |
| ... | @@ -2916,16 +2954,17 @@ const CompositeInt = struct { | ... | @@ -2916,16 +2954,17 @@ const CompositeInt = struct { |
| 2916 | var cmp_l = l; | 2954 | var cmp_l = l; |
| 2917 | var cmp_r = r; | 2955 | var cmp_r = r; |
| 2918 | if (use_signed) { | 2956 | if (use_signed) { |
| 2919 | const i32_ty_id = try cg.resolveType(.i32, .direct); | 2957 | const signed_limb_ty: Type = if (cg.bigIntBits() == 64) .i64 else .i32; |
| | 2958 | const signed_limb_ty_id = try cg.resolveType(signed_limb_ty, .direct); |
| 2920 | const sl = cg.allocId(); | 2959 | const sl = cg.allocId(); |
| 2921 | try cg.body.emit(gpa, .OpBitcast, .{ | 2960 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 2922 | .id_result_type = i32_ty_id, | 2961 | .id_result_type = signed_limb_ty_id, |
| 2923 | .id_result = sl, | 2962 | .id_result = sl, |
| 2924 | .operand = l, | 2963 | .operand = l, |
| 2925 | }); | 2964 | }); |
| 2926 | const sr = cg.allocId(); | 2965 | const sr = cg.allocId(); |
| 2927 | try cg.body.emit(gpa, .OpBitcast, .{ | 2966 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 2928 | .id_result_type = i32_ty_id, | 2967 | .id_result_type = signed_limb_ty_id, |
| 2929 | .id_result = sr, | 2968 | .id_result = sr, |
| 2930 | .operand = r, | 2969 | .operand = r, |
| 2931 | }); | 2970 | }); |
| ... | @@ -2969,16 +3008,17 @@ const CompositeInt = struct { | ... | @@ -2969,16 +3008,17 @@ const CompositeInt = struct { |
| 2969 | const comp = zcu.comp; | 3008 | const comp = zcu.comp; |
| 2970 | const io = comp.io; | 3009 | const io = comp.io; |
| 2971 | | 3010 | |
| 2972 | const u32_zig = try pt.intType(.unsigned, 32); | 3011 | const limb_bits = cg.bigIntBits(); |
| 2973 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 3012 | const limb_zig = try pt.intType(.unsigned, limb_bits); |
| | 3013 | const limb_ty_id = try cg.limbTypeId(); |
| 2974 | const carry_struct_ty: Type = .fromInterned(try ip.getTupleType(gpa, io, pt.tid, .{ | 3014 | const carry_struct_ty: Type = .fromInterned(try ip.getTupleType(gpa, io, pt.tid, .{ |
| 2975 | .types = &.{ u32_zig.toIntern(), u32_zig.toIntern() }, | 3015 | .types = &.{ limb_zig.toIntern(), limb_zig.toIntern() }, |
| 2976 | .values = &.{ .none, .none }, | 3016 | .values = &.{ .none, .none }, |
| 2977 | })); | 3017 | })); |
| 2978 | const carry_struct_ty_id = try cg.resolveType(carry_struct_ty, .direct); | 3018 | const carry_struct_ty_id = try cg.resolveType(carry_struct_ty, .direct); |
| 2979 | | 3019 | |
| 2980 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs); | 3020 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs); |
| 2981 | var carry_id = try cg.constInt(.u32, @as(u32, 0)); | 3021 | var carry_id = try cg.constInt(cg.limbType(), @as(u64, 0)); |
| 2982 | | 3022 | |
| 2983 | const opcode: Opcode = if (is_add) .OpIAddCarry else .OpISubBorrow; | 3023 | const opcode: Opcode = if (is_add) .OpIAddCarry else .OpISubBorrow; |
| 2984 | | 3024 | |
| ... | @@ -2992,14 +3032,14 @@ const CompositeInt = struct { | ... | @@ -2992,14 +3032,14 @@ const CompositeInt = struct { |
| 2992 | | 3032 | |
| 2993 | const sum1 = cg.allocId(); | 3033 | const sum1 = cg.allocId(); |
| 2994 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3034 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 2995 | .id_result_type = u32_ty_id, | 3035 | .id_result_type = limb_ty_id, |
| 2996 | .id_result = sum1, | 3036 | .id_result = sum1, |
| 2997 | .composite = op1, | 3037 | .composite = op1, |
| 2998 | .indexes = &.{0}, | 3038 | .indexes = &.{0}, |
| 2999 | }); | 3039 | }); |
| 3000 | const carry1 = cg.allocId(); | 3040 | const carry1 = cg.allocId(); |
| 3001 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3041 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3002 | .id_result_type = u32_ty_id, | 3042 | .id_result_type = limb_ty_id, |
| 3003 | .id_result = carry1, | 3043 | .id_result = carry1, |
| 3004 | .composite = op1, | 3044 | .composite = op1, |
| 3005 | .indexes = &.{1}, | 3045 | .indexes = &.{1}, |
| ... | @@ -3014,14 +3054,14 @@ const CompositeInt = struct { | ... | @@ -3014,14 +3054,14 @@ const CompositeInt = struct { |
| 3014 | | 3054 | |
| 3015 | result_limbs[i] = cg.allocId(); | 3055 | result_limbs[i] = cg.allocId(); |
| 3016 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3056 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3017 | .id_result_type = u32_ty_id, | 3057 | .id_result_type = limb_ty_id, |
| 3018 | .id_result = result_limbs[i], | 3058 | .id_result = result_limbs[i], |
| 3019 | .composite = op2, | 3059 | .composite = op2, |
| 3020 | .indexes = &.{0}, | 3060 | .indexes = &.{0}, |
| 3021 | }); | 3061 | }); |
| 3022 | const carry2 = cg.allocId(); | 3062 | const carry2 = cg.allocId(); |
| 3023 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3063 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3024 | .id_result_type = u32_ty_id, | 3064 | .id_result_type = limb_ty_id, |
| 3025 | .id_result = carry2, | 3065 | .id_result = carry2, |
| 3026 | .composite = op2, | 3066 | .composite = op2, |
| 3027 | .indexes = &.{1}, | 3067 | .indexes = &.{1}, |
| ... | @@ -3036,16 +3076,18 @@ const CompositeInt = struct { | ... | @@ -3036,16 +3076,18 @@ const CompositeInt = struct { |
| 3036 | fn shl(ci: CompositeInt, shift_amt_id: Id) !CompositeInt { | 3076 | fn shl(ci: CompositeInt, shift_amt_id: Id) !CompositeInt { |
| 3037 | const cg = ci.cg; | 3077 | const cg = ci.cg; |
| 3038 | const gpa = cg.gpa; | 3078 | const gpa = cg.gpa; |
| 3039 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 3079 | const limb_bits = cg.bigIntBits(); |
| | 3080 | const limb_ty = cg.limbType(); |
| | 3081 | const limb_ty_id = try cg.limbTypeId(); |
| 3040 | const bool_ty_id = try cg.resolveType(.bool, .direct); | 3082 | const bool_ty_id = try cg.resolveType(.bool, .direct); |
| 3041 | const zero_id = try cg.constInt(.u32, @as(u32, 0)); | 3083 | const zero_id = try cg.constInt(limb_ty, @as(u64, 0)); |
| 3042 | const five_id = try cg.constInt(.u32, @as(u32, 5)); | 3084 | const log2_bits_id = try cg.constInt(limb_ty, @as(u64, std.math.log2_int(u16, limb_bits))); |
| 3043 | const thirty_one_id = try cg.constInt(.u32, @as(u32, 31)); | 3085 | const bits_minus_1_id = try cg.constInt(limb_ty, @as(u64, limb_bits - 1)); |
| 3044 | const thirty_two_id = try cg.constInt(.u32, @as(u32, 32)); | 3086 | const bits_id = try cg.constInt(limb_ty, @as(u64, limb_bits)); |
| 3045 | | 3087 | |
| 3046 | const whole = try ci.limbBinOp(.OpShiftRightLogical, shift_amt_id, five_id); | 3088 | const whole = try ci.limbBinOp(.OpShiftRightLogical, shift_amt_id, log2_bits_id); |
| 3047 | const frac = try ci.limbBinOp(.OpBitwiseAnd, shift_amt_id, thirty_one_id); | 3089 | const frac = try ci.limbBinOp(.OpBitwiseAnd, shift_amt_id, bits_minus_1_id); |
| 3048 | const comp_frac = try ci.limbBinOp(.OpISub, thirty_two_id, frac); | 3090 | const comp_frac = try ci.limbBinOp(.OpISub, bits_id, frac); |
| 3049 | const frac_is_zero = blk: { | 3091 | const frac_is_zero = blk: { |
| 3050 | const r = cg.allocId(); | 3092 | const r = cg.allocId(); |
| 3051 | try cg.body.emit(gpa, .OpIEqual, .{ | 3093 | try cg.body.emit(gpa, .OpIEqual, .{ |
| ... | @@ -3060,12 +3102,12 @@ const CompositeInt = struct { | ... | @@ -3060,12 +3102,12 @@ const CompositeInt = struct { |
| 3060 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs); | 3102 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs); |
| 3061 | | 3103 | |
| 3062 | for (0..ci.n_limbs) |i| { | 3104 | for (0..ci.n_limbs) |i| { |
| 3063 | const i_id = try cg.constInt(.u32, @as(u32, @intCast(i))); | 3105 | const i_id = try cg.constInt(limb_ty, @as(u64, @intCast(i))); |
| 3064 | var main_val = zero_id; | 3106 | var main_val = zero_id; |
| 3065 | var carry_val = zero_id; | 3107 | var carry_val = zero_id; |
| 3066 | | 3108 | |
| 3067 | for (0..ci.n_limbs) |j| { | 3109 | for (0..ci.n_limbs) |j| { |
| 3068 | const j_id = try cg.constInt(.u32, @as(u32, @intCast(j))); | 3110 | const j_id = try cg.constInt(limb_ty, @as(u64, @intCast(j))); |
| 3069 | const j_plus_whole = try ci.limbBinOp(.OpIAdd, j_id, whole); | 3111 | const j_plus_whole = try ci.limbBinOp(.OpIAdd, j_id, whole); |
| 3070 | | 3112 | |
| 3071 | const is_main = blk: { | 3113 | const is_main = blk: { |
| ... | @@ -3082,7 +3124,7 @@ const CompositeInt = struct { | ... | @@ -3082,7 +3124,7 @@ const CompositeInt = struct { |
| 3082 | main_val = blk: { | 3124 | main_val = blk: { |
| 3083 | const r = cg.allocId(); | 3125 | const r = cg.allocId(); |
| 3084 | try cg.body.emit(gpa, .OpSelect, .{ | 3126 | try cg.body.emit(gpa, .OpSelect, .{ |
| 3085 | .id_result_type = u32_ty_id, | 3127 | .id_result_type = limb_ty_id, |
| 3086 | .id_result = r, | 3128 | .id_result = r, |
| 3087 | .condition = is_main, | 3129 | .condition = is_main, |
| 3088 | .object_1 = shifted, | 3130 | .object_1 = shifted, |
| ... | @@ -3091,7 +3133,7 @@ const CompositeInt = struct { | ... | @@ -3091,7 +3133,7 @@ const CompositeInt = struct { |
| 3091 | break :blk r; | 3133 | break :blk r; |
| 3092 | }; | 3134 | }; |
| 3093 | | 3135 | |
| 3094 | const one_id = try cg.constInt(.u32, @as(u32, 1)); | 3136 | const one_id = try cg.constInt(limb_ty, @as(u64, 1)); |
| 3095 | const j_plus_whole_plus_1 = try ci.limbBinOp(.OpIAdd, j_plus_whole, one_id); | 3137 | const j_plus_whole_plus_1 = try ci.limbBinOp(.OpIAdd, j_plus_whole, one_id); |
| 3096 | const is_carry = blk: { | 3138 | const is_carry = blk: { |
| 3097 | const r = cg.allocId(); | 3139 | const r = cg.allocId(); |
| ... | @@ -3107,7 +3149,7 @@ const CompositeInt = struct { | ... | @@ -3107,7 +3149,7 @@ const CompositeInt = struct { |
| 3107 | const guarded_carry = blk: { | 3149 | const guarded_carry = blk: { |
| 3108 | const r = cg.allocId(); | 3150 | const r = cg.allocId(); |
| 3109 | try cg.body.emit(gpa, .OpSelect, .{ | 3151 | try cg.body.emit(gpa, .OpSelect, .{ |
| 3110 | .id_result_type = u32_ty_id, | 3152 | .id_result_type = limb_ty_id, |
| 3111 | .id_result = r, | 3153 | .id_result = r, |
| 3112 | .condition = frac_is_zero, | 3154 | .condition = frac_is_zero, |
| 3113 | .object_1 = zero_id, | 3155 | .object_1 = zero_id, |
| ... | @@ -3118,7 +3160,7 @@ const CompositeInt = struct { | ... | @@ -3118,7 +3160,7 @@ const CompositeInt = struct { |
| 3118 | carry_val = blk: { | 3160 | carry_val = blk: { |
| 3119 | const r = cg.allocId(); | 3161 | const r = cg.allocId(); |
| 3120 | try cg.body.emit(gpa, .OpSelect, .{ | 3162 | try cg.body.emit(gpa, .OpSelect, .{ |
| 3121 | .id_result_type = u32_ty_id, | 3163 | .id_result_type = limb_ty_id, |
| 3122 | .id_result = r, | 3164 | .id_result = r, |
| 3123 | .condition = is_carry, | 3165 | .condition = is_carry, |
| 3124 | .object_1 = guarded_carry, | 3166 | .object_1 = guarded_carry, |
| ... | @@ -3137,16 +3179,18 @@ const CompositeInt = struct { | ... | @@ -3137,16 +3179,18 @@ const CompositeInt = struct { |
| 3137 | fn shr(ci: CompositeInt, shift_amt_id: Id, comptime is_arithmetic: bool) !CompositeInt { | 3179 | fn shr(ci: CompositeInt, shift_amt_id: Id, comptime is_arithmetic: bool) !CompositeInt { |
| 3138 | const cg = ci.cg; | 3180 | const cg = ci.cg; |
| 3139 | const gpa = cg.gpa; | 3181 | const gpa = cg.gpa; |
| 3140 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 3182 | const limb_bits = cg.bigIntBits(); |
| | 3183 | const limb_ty = cg.limbType(); |
| | 3184 | const limb_ty_id = try cg.limbTypeId(); |
| 3141 | const bool_ty_id = try cg.resolveType(.bool, .direct); | 3185 | const bool_ty_id = try cg.resolveType(.bool, .direct); |
| 3142 | const zero_id = try cg.constInt(.u32, @as(u32, 0)); | 3186 | const zero_id = try cg.constInt(limb_ty, @as(u64, 0)); |
| 3143 | const five_id = try cg.constInt(.u32, @as(u32, 5)); | 3187 | const log2_bits_id = try cg.constInt(limb_ty, @as(u64, std.math.log2_int(u16, limb_bits))); |
| 3144 | const thirty_one_id = try cg.constInt(.u32, @as(u32, 31)); | 3188 | const bits_minus_1_id = try cg.constInt(limb_ty, @as(u64, limb_bits - 1)); |
| 3145 | const thirty_two_id = try cg.constInt(.u32, @as(u32, 32)); | 3189 | const bits_id = try cg.constInt(limb_ty, @as(u64, limb_bits)); |
| 3146 | | 3190 | |
| 3147 | const whole = try ci.limbBinOp(.OpShiftRightLogical, shift_amt_id, five_id); | 3191 | const whole = try ci.limbBinOp(.OpShiftRightLogical, shift_amt_id, log2_bits_id); |
| 3148 | const frac = try ci.limbBinOp(.OpBitwiseAnd, shift_amt_id, thirty_one_id); | 3192 | const frac = try ci.limbBinOp(.OpBitwiseAnd, shift_amt_id, bits_minus_1_id); |
| 3149 | const comp_frac = try ci.limbBinOp(.OpISub, thirty_two_id, frac); | 3193 | const comp_frac = try ci.limbBinOp(.OpISub, bits_id, frac); |
| 3150 | const frac_is_zero = blk: { | 3194 | const frac_is_zero = blk: { |
| 3151 | const r = cg.allocId(); | 3195 | const r = cg.allocId(); |
| 3152 | try cg.body.emit(gpa, .OpIEqual, .{ | 3196 | try cg.body.emit(gpa, .OpIEqual, .{ |
| ... | @@ -3159,24 +3203,25 @@ const CompositeInt = struct { | ... | @@ -3159,24 +3203,25 @@ const CompositeInt = struct { |
| 3159 | }; | 3203 | }; |
| 3160 | | 3204 | |
| 3161 | const fill_id = if (is_arithmetic) blk: { | 3205 | const fill_id = if (is_arithmetic) blk: { |
| 3162 | const i32_ty_id = try cg.resolveType(.i32, .direct); | 3206 | const signed_limb_ty: Type = if (limb_bits == 64) .i64 else .i32; |
| | 3207 | const signed_limb_ty_id = try cg.resolveType(signed_limb_ty, .direct); |
| 3163 | const msb_signed = cg.allocId(); | 3208 | const msb_signed = cg.allocId(); |
| 3164 | try cg.body.emit(gpa, .OpBitcast, .{ | 3209 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 3165 | .id_result_type = i32_ty_id, | 3210 | .id_result_type = signed_limb_ty_id, |
| 3166 | .id_result = msb_signed, | 3211 | .id_result = msb_signed, |
| 3167 | .operand = ci.limbs[ci.n_limbs - 1], | 3212 | .operand = ci.limbs[ci.n_limbs - 1], |
| 3168 | }); | 3213 | }); |
| 3169 | const shift31 = try cg.constInt(.i32, @as(i32, 31)); | 3214 | const shift_amt = try cg.constInt(signed_limb_ty, @as(u64, limb_bits - 1)); |
| 3170 | const sign_ext = cg.allocId(); | 3215 | const sign_ext = cg.allocId(); |
| 3171 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ | 3216 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ |
| 3172 | .id_result_type = i32_ty_id, | 3217 | .id_result_type = signed_limb_ty_id, |
| 3173 | .id_result = sign_ext, | 3218 | .id_result = sign_ext, |
| 3174 | .base = msb_signed, | 3219 | .base = msb_signed, |
| 3175 | .shift = shift31, | 3220 | .shift = shift_amt, |
| 3176 | }); | 3221 | }); |
| 3177 | const back = cg.allocId(); | 3222 | const back = cg.allocId(); |
| 3178 | try cg.body.emit(gpa, .OpBitcast, .{ | 3223 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 3179 | .id_result_type = u32_ty_id, | 3224 | .id_result_type = limb_ty_id, |
| 3180 | .id_result = back, | 3225 | .id_result = back, |
| 3181 | .operand = sign_ext, | 3226 | .operand = sign_ext, |
| 3182 | }); | 3227 | }); |
| ... | @@ -3189,7 +3234,7 @@ const CompositeInt = struct { | ... | @@ -3189,7 +3234,7 @@ const CompositeInt = struct { |
| 3189 | const shifted_fill = try ci.limbBinOp(.OpShiftLeftLogical, fill_id, comp_frac); | 3234 | const shifted_fill = try ci.limbBinOp(.OpShiftLeftLogical, fill_id, comp_frac); |
| 3190 | const guarded = cg.allocId(); | 3235 | const guarded = cg.allocId(); |
| 3191 | try cg.body.emit(gpa, .OpSelect, .{ | 3236 | try cg.body.emit(gpa, .OpSelect, .{ |
| 3192 | .id_result_type = u32_ty_id, | 3237 | .id_result_type = limb_ty_id, |
| 3193 | .id_result = guarded, | 3238 | .id_result = guarded, |
| 3194 | .condition = frac_is_zero, | 3239 | .condition = frac_is_zero, |
| 3195 | .object_1 = zero_id, | 3240 | .object_1 = zero_id, |
| ... | @@ -3199,12 +3244,12 @@ const CompositeInt = struct { | ... | @@ -3199,12 +3244,12 @@ const CompositeInt = struct { |
| 3199 | } else zero_id; | 3244 | } else zero_id; |
| 3200 | | 3245 | |
| 3201 | for (0..ci.n_limbs) |i| { | 3246 | for (0..ci.n_limbs) |i| { |
| 3202 | const i_id = try cg.constInt(.u32, @as(u32, @intCast(i))); | 3247 | const i_id = try cg.constInt(limb_ty, @as(u64, @intCast(i))); |
| 3203 | var main_val = fill_id; | 3248 | var main_val = fill_id; |
| 3204 | var carry_val = arith_carry_init; | 3249 | var carry_val = arith_carry_init; |
| 3205 | | 3250 | |
| 3206 | for (0..ci.n_limbs) |j| { | 3251 | for (0..ci.n_limbs) |j| { |
| 3207 | const j_id = try cg.constInt(.u32, @as(u32, @intCast(j))); | 3252 | const j_id = try cg.constInt(limb_ty, @as(u64, @intCast(j))); |
| 3208 | const i_plus_whole = try ci.limbBinOp(.OpIAdd, i_id, whole); | 3253 | const i_plus_whole = try ci.limbBinOp(.OpIAdd, i_id, whole); |
| 3209 | const is_main = blk: { | 3254 | const is_main = blk: { |
| 3210 | const r = cg.allocId(); | 3255 | const r = cg.allocId(); |
| ... | @@ -3220,7 +3265,7 @@ const CompositeInt = struct { | ... | @@ -3220,7 +3265,7 @@ const CompositeInt = struct { |
| 3220 | main_val = blk: { | 3265 | main_val = blk: { |
| 3221 | const r = cg.allocId(); | 3266 | const r = cg.allocId(); |
| 3222 | try cg.body.emit(gpa, .OpSelect, .{ | 3267 | try cg.body.emit(gpa, .OpSelect, .{ |
| 3223 | .id_result_type = u32_ty_id, | 3268 | .id_result_type = limb_ty_id, |
| 3224 | .id_result = r, | 3269 | .id_result = r, |
| 3225 | .condition = is_main, | 3270 | .condition = is_main, |
| 3226 | .object_1 = shifted, | 3271 | .object_1 = shifted, |
| ... | @@ -3229,7 +3274,7 @@ const CompositeInt = struct { | ... | @@ -3229,7 +3274,7 @@ const CompositeInt = struct { |
| 3229 | break :blk r; | 3274 | break :blk r; |
| 3230 | }; | 3275 | }; |
| 3231 | | 3276 | |
| 3232 | const one_id = try cg.constInt(.u32, @as(u32, 1)); | 3277 | const one_id = try cg.constInt(limb_ty, @as(u64, 1)); |
| 3233 | const i_plus_whole_plus_1 = try ci.limbBinOp(.OpIAdd, i_plus_whole, one_id); | 3278 | const i_plus_whole_plus_1 = try ci.limbBinOp(.OpIAdd, i_plus_whole, one_id); |
| 3234 | const is_carry = blk: { | 3279 | const is_carry = blk: { |
| 3235 | const r = cg.allocId(); | 3280 | const r = cg.allocId(); |
| ... | @@ -3245,7 +3290,7 @@ const CompositeInt = struct { | ... | @@ -3245,7 +3290,7 @@ const CompositeInt = struct { |
| 3245 | const guarded_carry = blk: { | 3290 | const guarded_carry = blk: { |
| 3246 | const r = cg.allocId(); | 3291 | const r = cg.allocId(); |
| 3247 | try cg.body.emit(gpa, .OpSelect, .{ | 3292 | try cg.body.emit(gpa, .OpSelect, .{ |
| 3248 | .id_result_type = u32_ty_id, | 3293 | .id_result_type = limb_ty_id, |
| 3249 | .id_result = r, | 3294 | .id_result = r, |
| 3250 | .condition = frac_is_zero, | 3295 | .condition = frac_is_zero, |
| 3251 | .object_1 = zero_id, | 3296 | .object_1 = zero_id, |
| ... | @@ -3256,7 +3301,7 @@ const CompositeInt = struct { | ... | @@ -3256,7 +3301,7 @@ const CompositeInt = struct { |
| 3256 | carry_val = blk: { | 3301 | carry_val = blk: { |
| 3257 | const r = cg.allocId(); | 3302 | const r = cg.allocId(); |
| 3258 | try cg.body.emit(gpa, .OpSelect, .{ | 3303 | try cg.body.emit(gpa, .OpSelect, .{ |
| 3259 | .id_result_type = u32_ty_id, | 3304 | .id_result_type = limb_ty_id, |
| 3260 | .id_result = r, | 3305 | .id_result = r, |
| 3261 | .condition = is_carry, | 3306 | .condition = is_carry, |
| 3262 | .object_1 = guarded_carry, | 3307 | .object_1 = guarded_carry, |
| ... | @@ -3284,17 +3329,18 @@ const CompositeInt = struct { | ... | @@ -3284,17 +3329,18 @@ const CompositeInt = struct { |
| 3284 | | 3329 | |
| 3285 | const n: usize = ci.n_limbs; | 3330 | const n: usize = ci.n_limbs; |
| 3286 | const total: usize = if (wide) 2 * n else n; | 3331 | const total: usize = if (wide) 2 * n else n; |
| 3287 | const u32_zig = try pt.intType(.unsigned, 32); | 3332 | const limb_bits = cg.bigIntBits(); |
| 3288 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 3333 | const limb_zig = try pt.intType(.unsigned, limb_bits); |
| | 3334 | const limb_ty_id = try cg.limbTypeId(); |
| 3289 | | 3335 | |
| 3290 | const pair_struct_ty: Type = .fromInterned(try ip.getTupleType(gpa, io, pt.tid, .{ | 3336 | const pair_struct_ty: Type = .fromInterned(try ip.getTupleType(gpa, io, pt.tid, .{ |
| 3291 | .types = &.{ u32_zig.toIntern(), u32_zig.toIntern() }, | 3337 | .types = &.{ limb_zig.toIntern(), limb_zig.toIntern() }, |
| 3292 | .values = &.{ .none, .none }, | 3338 | .values = &.{ .none, .none }, |
| 3293 | })); | 3339 | })); |
| 3294 | const pair_struct_ty_id = try cg.resolveType(pair_struct_ty, .direct); | 3340 | const pair_struct_ty_id = try cg.resolveType(pair_struct_ty, .direct); |
| 3295 | | 3341 | |
| 3296 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, total); | 3342 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, total); |
| 3297 | const zero_id = try cg.constInt(.u32, @as(u32, 0)); | 3343 | const zero_id = try cg.constInt(cg.limbType(), @as(u64, 0)); |
| 3298 | for (result_limbs) |*r| r.* = zero_id; | 3344 | for (result_limbs) |*r| r.* = zero_id; |
| 3299 | | 3345 | |
| 3300 | for (0..n) |i| { | 3346 | for (0..n) |i| { |
| ... | @@ -3309,7 +3355,7 @@ const CompositeInt = struct { | ... | @@ -3309,7 +3355,7 @@ const CompositeInt = struct { |
| 3309 | .opencl => { | 3355 | .opencl => { |
| 3310 | lo = cg.allocId(); | 3356 | lo = cg.allocId(); |
| 3311 | try cg.body.emit(gpa, .OpIMul, .{ | 3357 | try cg.body.emit(gpa, .OpIMul, .{ |
| 3312 | .id_result_type = u32_ty_id, | 3358 | .id_result_type = limb_ty_id, |
| 3313 | .id_result = lo, | 3359 | .id_result = lo, |
| 3314 | .operand_1 = ci.limbs[i], | 3360 | .operand_1 = ci.limbs[i], |
| 3315 | .operand_2 = other.limbs[j], | 3361 | .operand_2 = other.limbs[j], |
| ... | @@ -3318,7 +3364,7 @@ const CompositeInt = struct { | ... | @@ -3318,7 +3364,7 @@ const CompositeInt = struct { |
| 3318 | const set = try cg.importExtendedSet(); | 3364 | const set = try cg.importExtendedSet(); |
| 3319 | hi = cg.allocId(); | 3365 | hi = cg.allocId(); |
| 3320 | try cg.body.emit(gpa, .OpExtInst, .{ | 3366 | try cg.body.emit(gpa, .OpExtInst, .{ |
| 3321 | .id_result_type = u32_ty_id, | 3367 | .id_result_type = limb_ty_id, |
| 3322 | .id_result = hi, | 3368 | .id_result = hi, |
| 3323 | .set = set, | 3369 | .set = set, |
| 3324 | .instruction = .{ .inst = @intFromEnum(spec.OpenClOpcode.u_mul_hi) }, | 3370 | .instruction = .{ .inst = @intFromEnum(spec.OpenClOpcode.u_mul_hi) }, |
| ... | @@ -3336,14 +3382,14 @@ const CompositeInt = struct { | ... | @@ -3336,14 +3382,14 @@ const CompositeInt = struct { |
| 3336 | | 3382 | |
| 3337 | lo = cg.allocId(); | 3383 | lo = cg.allocId(); |
| 3338 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3384 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3339 | .id_result_type = u32_ty_id, | 3385 | .id_result_type = limb_ty_id, |
| 3340 | .id_result = lo, | 3386 | .id_result = lo, |
| 3341 | .composite = mul_result, | 3387 | .composite = mul_result, |
| 3342 | .indexes = &.{0}, | 3388 | .indexes = &.{0}, |
| 3343 | }); | 3389 | }); |
| 3344 | hi = cg.allocId(); | 3390 | hi = cg.allocId(); |
| 3345 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3391 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3346 | .id_result_type = u32_ty_id, | 3392 | .id_result_type = limb_ty_id, |
| 3347 | .id_result = hi, | 3393 | .id_result = hi, |
| 3348 | .composite = mul_result, | 3394 | .composite = mul_result, |
| 3349 | .indexes = &.{1}, | 3395 | .indexes = &.{1}, |
| ... | @@ -3361,14 +3407,14 @@ const CompositeInt = struct { | ... | @@ -3361,14 +3407,14 @@ const CompositeInt = struct { |
| 3361 | | 3407 | |
| 3362 | const sum1 = cg.allocId(); | 3408 | const sum1 = cg.allocId(); |
| 3363 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3409 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3364 | .id_result_type = u32_ty_id, | 3410 | .id_result_type = limb_ty_id, |
| 3365 | .id_result = sum1, | 3411 | .id_result = sum1, |
| 3366 | .composite = add1, | 3412 | .composite = add1, |
| 3367 | .indexes = &.{0}, | 3413 | .indexes = &.{0}, |
| 3368 | }); | 3414 | }); |
| 3369 | const c1 = cg.allocId(); | 3415 | const c1 = cg.allocId(); |
| 3370 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3416 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3371 | .id_result_type = u32_ty_id, | 3417 | .id_result_type = limb_ty_id, |
| 3372 | .id_result = c1, | 3418 | .id_result = c1, |
| 3373 | .composite = add1, | 3419 | .composite = add1, |
| 3374 | .indexes = &.{1}, | 3420 | .indexes = &.{1}, |
| ... | @@ -3384,14 +3430,14 @@ const CompositeInt = struct { | ... | @@ -3384,14 +3430,14 @@ const CompositeInt = struct { |
| 3384 | | 3430 | |
| 3385 | result_limbs[k] = cg.allocId(); | 3431 | result_limbs[k] = cg.allocId(); |
| 3386 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3432 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3387 | .id_result_type = u32_ty_id, | 3433 | .id_result_type = limb_ty_id, |
| 3388 | .id_result = result_limbs[k], | 3434 | .id_result = result_limbs[k], |
| 3389 | .composite = add2, | 3435 | .composite = add2, |
| 3390 | .indexes = &.{0}, | 3436 | .indexes = &.{0}, |
| 3391 | }); | 3437 | }); |
| 3392 | const c2 = cg.allocId(); | 3438 | const c2 = cg.allocId(); |
| 3393 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3439 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3394 | .id_result_type = u32_ty_id, | 3440 | .id_result_type = limb_ty_id, |
| 3395 | .id_result = c2, | 3441 | .id_result = c2, |
| 3396 | .composite = add2, | 3442 | .composite = add2, |
| 3397 | .indexes = &.{1}, | 3443 | .indexes = &.{1}, |
| ... | @@ -3412,7 +3458,8 @@ const CompositeInt = struct { | ... | @@ -3412,7 +3458,8 @@ const CompositeInt = struct { |
| 3412 | if (ci.info.bits == ci.info.backing_bits) return ci; | 3458 | if (ci.info.bits == ci.info.backing_bits) return ci; |
| 3413 | const cg = ci.cg; | 3459 | const cg = ci.cg; |
| 3414 | const gpa = cg.gpa; | 3460 | const gpa = cg.gpa; |
| 3415 | const top_bits: u16 = ci.info.bits % big_int_bits; | 3461 | const limb_bits = cg.bigIntBits(); |
| | 3462 | const top_bits: u16 = ci.info.bits % limb_bits; |
| 3416 | assert(top_bits != 0); | 3463 | assert(top_bits != 0); |
| 3417 | | 3464 | |
| 3418 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs); | 3465 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs); |
| ... | @@ -3421,41 +3468,43 @@ const CompositeInt = struct { | ... | @@ -3421,41 +3468,43 @@ const CompositeInt = struct { |
| 3421 | } | 3468 | } |
| 3422 | | 3469 | |
| 3423 | const top_limb = ci.limbs[ci.n_limbs - 1]; | 3470 | const top_limb = ci.limbs[ci.n_limbs - 1]; |
| | 3471 | const limb_ty = cg.limbType(); |
| | 3472 | const limb_signed_ty: Type = if (limb_bits == 64) .i64 else .i32; |
| 3424 | switch (ci.info.signedness) { | 3473 | switch (ci.info.signedness) { |
| 3425 | .unsigned => { | 3474 | .unsigned => { |
| 3426 | const mask_val: u32 = (@as(u32, 1) << @as(u5, @intCast(top_bits))) - 1; | 3475 | const mask_val: u64 = (@as(u64, 1) << @as(u6, @intCast(top_bits))) - 1; |
| 3427 | const mask_id = try cg.constInt(.u32, mask_val); | 3476 | const mask_id = try cg.constInt(limb_ty, mask_val); |
| 3428 | result_limbs[ci.n_limbs - 1] = try ci.limbBinOp(.OpBitwiseAnd, top_limb, mask_id); | 3477 | result_limbs[ci.n_limbs - 1] = try ci.limbBinOp(.OpBitwiseAnd, top_limb, mask_id); |
| 3429 | }, | 3478 | }, |
| 3430 | .signed => { | 3479 | .signed => { |
| 3431 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 3480 | const limb_ty_id = try cg.limbTypeId(); |
| 3432 | const i32_ty_id = try cg.resolveType(.i32, .direct); | 3481 | const signed_ty_id = try cg.resolveType(limb_signed_ty, .direct); |
| 3433 | const shift_amt: u32 = 32 - top_bits; | 3482 | const shift_amt: u32 = @intCast(limb_bits - top_bits); |
| 3434 | const shift_id = try cg.constInt(.u32, shift_amt); | 3483 | const shift_id = try cg.constInt(limb_ty, shift_amt); |
| 3435 | | 3484 | |
| 3436 | const as_signed = cg.allocId(); | 3485 | const as_signed = cg.allocId(); |
| 3437 | try cg.body.emit(gpa, .OpBitcast, .{ | 3486 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 3438 | .id_result_type = i32_ty_id, | 3487 | .id_result_type = signed_ty_id, |
| 3439 | .id_result = as_signed, | 3488 | .id_result = as_signed, |
| 3440 | .operand = top_limb, | 3489 | .operand = top_limb, |
| 3441 | }); | 3490 | }); |
| 3442 | const shifted_left = cg.allocId(); | 3491 | const shifted_left = cg.allocId(); |
| 3443 | try cg.body.emit(gpa, .OpShiftLeftLogical, .{ | 3492 | try cg.body.emit(gpa, .OpShiftLeftLogical, .{ |
| 3444 | .id_result_type = i32_ty_id, | 3493 | .id_result_type = signed_ty_id, |
| 3445 | .id_result = shifted_left, | 3494 | .id_result = shifted_left, |
| 3446 | .base = as_signed, | 3495 | .base = as_signed, |
| 3447 | .shift = shift_id, | 3496 | .shift = shift_id, |
| 3448 | }); | 3497 | }); |
| 3449 | const shifted_right = cg.allocId(); | 3498 | const shifted_right = cg.allocId(); |
| 3450 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ | 3499 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ |
| 3451 | .id_result_type = i32_ty_id, | 3500 | .id_result_type = signed_ty_id, |
| 3452 | .id_result = shifted_right, | 3501 | .id_result = shifted_right, |
| 3453 | .base = shifted_left, | 3502 | .base = shifted_left, |
| 3454 | .shift = shift_id, | 3503 | .shift = shift_id, |
| 3455 | }); | 3504 | }); |
| 3456 | const back = cg.allocId(); | 3505 | const back = cg.allocId(); |
| 3457 | try cg.body.emit(gpa, .OpBitcast, .{ | 3506 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 3458 | .id_result_type = u32_ty_id, | 3507 | .id_result_type = limb_ty_id, |
| 3459 | .id_result = back, | 3508 | .id_result = back, |
| 3460 | .operand = shifted_right, | 3509 | .operand = shifted_right, |
| 3461 | }); | 3510 | }); |
| ... | @@ -4552,13 +4601,14 @@ fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode | ... | @@ -4552,13 +4601,14 @@ fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode |
| 4552 | switch (info.class) { | 4601 | switch (info.class) { |
| 4553 | .composite_integer => { | 4602 | .composite_integer => { |
| 4554 | const shift_info = cg.arithmeticTypeInfo(shift.ty); | 4603 | const shift_info = cg.arithmeticTypeInfo(shift.ty); |
| | 4604 | const limb_ty = cg.limbType(); |
| 4555 | const shift_amt_id = switch (shift_info.class) { | 4605 | const shift_amt_id = switch (shift_info.class) { |
| 4556 | .composite_integer => blk: { | 4606 | .composite_integer => blk: { |
| 4557 | const shift_id = try shift.materialize(cg); | 4607 | const shift_id = try shift.materialize(cg); |
| 4558 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 4608 | const limb_ty_id = try cg.limbTypeId(); |
| 4559 | const result_id = cg.allocId(); | 4609 | const result_id = cg.allocId(); |
| 4560 | try cg.body.emit(cg.gpa, .OpCompositeExtract, .{ | 4610 | try cg.body.emit(cg.gpa, .OpCompositeExtract, .{ |
| 4561 | .id_result_type = u32_ty_id, | 4611 | .id_result_type = limb_ty_id, |
| 4562 | .id_result = result_id, | 4612 | .id_result = result_id, |
| 4563 | .composite = shift_id, | 4613 | .composite = shift_id, |
| 4564 | .indexes = &.{@as(u32, 0)}, | 4614 | .indexes = &.{@as(u32, 0)}, |
| ... | @@ -4566,7 +4616,7 @@ fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode | ... | @@ -4566,7 +4616,7 @@ fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode |
| 4566 | break :blk result_id; | 4616 | break :blk result_id; |
| 4567 | }, | 4617 | }, |
| 4568 | else => blk: { | 4618 | else => blk: { |
| 4569 | const converted = try cg.buildConvert(.u32, shift); | 4619 | const converted = try cg.buildConvert(limb_ty, shift); |
| 4570 | break :blk try converted.materialize(cg); | 4620 | break :blk try converted.materialize(cg); |
| 4571 | }, | 4621 | }, |
| 4572 | }; | 4622 | }; |
| ... | @@ -4887,12 +4937,12 @@ fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -4887,12 +4937,12 @@ fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4887 | const is_neg = try ci.cmp(ci_z, .lt); | 4937 | const is_neg = try ci.cmp(ci_z, .lt); |
| 4888 | const ci_neg = try ci_z.addSub(ci, false); | 4938 | const ci_neg = try ci_z.addSub(ci, false); |
| 4889 | const result_info = cg.arithmeticTypeInfo(result_ty); | 4939 | const result_info = cg.arithmeticTypeInfo(result_ty); |
| 4890 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 4940 | const limb_ty_id = try cg.limbTypeId(); |
| 4891 | const result_limbs = try cg.id_scratch.addManyAsSlice(cg.gpa, ci.n_limbs); | 4941 | const result_limbs = try cg.id_scratch.addManyAsSlice(cg.gpa, ci.n_limbs); |
| 4892 | for (0..ci.n_limbs) |i| { | 4942 | for (0..ci.n_limbs) |i| { |
| 4893 | result_limbs[i] = cg.allocId(); | 4943 | result_limbs[i] = cg.allocId(); |
| 4894 | try cg.body.emit(cg.gpa, .OpSelect, .{ | 4944 | try cg.body.emit(cg.gpa, .OpSelect, .{ |
| 4895 | .id_result_type = u32_ty_id, | 4945 | .id_result_type = limb_ty_id, |
| 4896 | .id_result = result_limbs[i], | 4946 | .id_result = result_limbs[i], |
| 4897 | .condition = is_neg, | 4947 | .condition = is_neg, |
| 4898 | .object_1 = ci_neg.limbs[i], | 4948 | .object_1 = ci_neg.limbs[i], |
| ... | @@ -5066,12 +5116,13 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -5066,12 +5116,13 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 5066 | const high_limbs = wide_limbs[ci_lhs2.n_limbs..]; | 5116 | const high_limbs = wide_limbs[ci_lhs2.n_limbs..]; |
| 5067 | | 5117 | |
| 5068 | const bool_ty_id = try cg.resolveType(.bool, .direct); | 5118 | const bool_ty_id = try cg.resolveType(.bool, .direct); |
| 5069 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 5119 | const limb_ty_id = try cg.limbTypeId(); |
| 5070 | const n: usize = info.backing_bits / big_int_bits; | 5120 | const limb_ty = cg.limbType(); |
| | 5121 | const n: usize = info.backing_bits / cg.bigIntBits(); |
| 5071 | | 5122 | |
| 5072 | const ov_bool = switch (info.signedness) { | 5123 | const ov_bool = switch (info.signedness) { |
| 5073 | .unsigned => blk: { | 5124 | .unsigned => blk: { |
| 5074 | const zero_id = try cg.constInt(.u32, @as(u32, 0)); | 5125 | const zero_id = try cg.constInt(limb_ty, @as(u64, 0)); |
| 5075 | var any_nonzero = cg.allocId(); | 5126 | var any_nonzero = cg.allocId(); |
| 5076 | try cg.body.emit(gpa, .OpINotEqual, .{ | 5127 | try cg.body.emit(gpa, .OpINotEqual, .{ |
| 5077 | .id_result_type = bool_ty_id, | 5128 | .id_result_type = bool_ty_id, |
| ... | @@ -5104,32 +5155,33 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -5104,32 +5155,33 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 5104 | .signed => blk: { | 5155 | .signed => blk: { |
| 5105 | const ci_res = try CompositeInt.init(cg, result_val_id, info); | 5156 | const ci_res = try CompositeInt.init(cg, result_val_id, info); |
| 5106 | const top_limb = ci_res.limbs[n - 1]; | 5157 | const top_limb = ci_res.limbs[n - 1]; |
| 5107 | const i32_ty_id = try cg.resolveType(.i32, .direct); | 5158 | const signed_limb_ty: Type = if (cg.bigIntBits() == 64) .i64 else .i32; |
| | 5159 | const signed_limb_ty_id = try cg.resolveType(signed_limb_ty, .direct); |
| 5108 | | 5160 | |
| 5109 | const top_bits: u16 = if (info.bits % big_int_bits == 0) | 5161 | const top_bits: u16 = if (info.bits % cg.bigIntBits() == 0) |
| 5110 | big_int_bits | 5162 | cg.bigIntBits() |
| 5111 | else | 5163 | else |
| 5112 | info.bits % big_int_bits; | 5164 | info.bits % cg.bigIntBits(); |
| 5113 | | 5165 | |
| 5114 | const shift_amt: u32 = top_bits - 1; | 5166 | const shift_amt: u64 = top_bits - 1; |
| 5115 | const shift_id = try cg.constInt(.u32, shift_amt); | 5167 | const shift_id = try cg.constInt(limb_ty, shift_amt); |
| 5116 | | 5168 | |
| 5117 | const as_signed = cg.allocId(); | 5169 | const as_signed = cg.allocId(); |
| 5118 | try cg.body.emit(gpa, .OpBitcast, .{ | 5170 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 5119 | .id_result_type = i32_ty_id, | 5171 | .id_result_type = signed_limb_ty_id, |
| 5120 | .id_result = as_signed, | 5172 | .id_result = as_signed, |
| 5121 | .operand = top_limb, | 5173 | .operand = top_limb, |
| 5122 | }); | 5174 | }); |
| 5123 | const sign_ext = cg.allocId(); | 5175 | const sign_ext = cg.allocId(); |
| 5124 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ | 5176 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ |
| 5125 | .id_result_type = i32_ty_id, | 5177 | .id_result_type = signed_limb_ty_id, |
| 5126 | .id_result = sign_ext, | 5178 | .id_result = sign_ext, |
| 5127 | .base = as_signed, | 5179 | .base = as_signed, |
| 5128 | .shift = shift_id, | 5180 | .shift = shift_id, |
| 5129 | }); | 5181 | }); |
| 5130 | const expected = cg.allocId(); | 5182 | const expected = cg.allocId(); |
| 5131 | try cg.body.emit(gpa, .OpBitcast, .{ | 5183 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 5132 | .id_result_type = u32_ty_id, | 5184 | .id_result_type = limb_ty_id, |
| 5133 | .id_result = expected, | 5185 | .id_result = expected, |
| 5134 | .operand = sign_ext, | 5186 | .operand = sign_ext, |
| 5135 | }); | 5187 | }); |
| ... | @@ -5162,25 +5214,25 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -5162,25 +5214,25 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 5162 | } | 5214 | } |
| 5163 | | 5215 | |
| 5164 | if (info.bits != info.backing_bits) { | 5216 | if (info.bits != info.backing_bits) { |
| 5165 | const top_bits_s: u16 = info.bits % big_int_bits; | 5217 | const top_bits_s: u16 = info.bits % cg.bigIntBits(); |
| 5166 | const s_shift_id = try cg.constInt(.u32, top_bits_s - 1); | 5218 | const s_shift_id = try cg.constInt(limb_ty, @as(u64, top_bits_s - 1)); |
| 5167 | | 5219 | |
| 5168 | const top_as_signed = cg.allocId(); | 5220 | const top_as_signed = cg.allocId(); |
| 5169 | try cg.body.emit(gpa, .OpBitcast, .{ | 5221 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 5170 | .id_result_type = i32_ty_id, | 5222 | .id_result_type = signed_limb_ty_id, |
| 5171 | .id_result = top_as_signed, | 5223 | .id_result = top_as_signed, |
| 5172 | .operand = top_limb, | 5224 | .operand = top_limb, |
| 5173 | }); | 5225 | }); |
| 5174 | const top_sign_ext = cg.allocId(); | 5226 | const top_sign_ext = cg.allocId(); |
| 5175 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ | 5227 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ |
| 5176 | .id_result_type = i32_ty_id, | 5228 | .id_result_type = signed_limb_ty_id, |
| 5177 | .id_result = top_sign_ext, | 5229 | .id_result = top_sign_ext, |
| 5178 | .base = top_as_signed, | 5230 | .base = top_as_signed, |
| 5179 | .shift = s_shift_id, | 5231 | .shift = s_shift_id, |
| 5180 | }); | 5232 | }); |
| 5181 | const top_expected = cg.allocId(); | 5233 | const top_expected = cg.allocId(); |
| 5182 | try cg.body.emit(gpa, .OpBitcast, .{ | 5234 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 5183 | .id_result_type = u32_ty_id, | 5235 | .id_result_type = limb_ty_id, |
| 5184 | .id_result = top_expected, | 5236 | .id_result = top_expected, |
| 5185 | .operand = top_sign_ext, | 5237 | .operand = top_sign_ext, |
| 5186 | }); | 5238 | }); |
| ... | @@ -6117,15 +6169,17 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -6117,15 +6169,17 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 6117 | | 6169 | |
| 6118 | if (src_composite and dst_composite) { | 6170 | if (src_composite and dst_composite) { |
| 6119 | const src_id = try src.materialize(cg); | 6171 | const src_id = try src.materialize(cg); |
| 6120 | const src_n: u16 = src_info.backing_bits / big_int_bits; | 6172 | const limb_bits = cg.bigIntBits(); |
| 6121 | const dst_n: u16 = dst_info.backing_bits / big_int_bits; | 6173 | const limb_ty = cg.limbType(); |
| | 6174 | const limb_ty_id = try cg.limbTypeId(); |
| | 6175 | const src_n: u16 = src_info.backing_bits / limb_bits; |
| | 6176 | const dst_n: u16 = dst_info.backing_bits / limb_bits; |
| 6122 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, dst_n); | 6177 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, dst_n); |
| 6123 | const min_n = @min(src_n, dst_n); | 6178 | const min_n = @min(src_n, dst_n); |
| 6124 | const u32_ty_id = try cg.resolveType(.u32, .direct); | | |
| 6125 | for (0..min_n) |i| { | 6179 | for (0..min_n) |i| { |
| 6126 | result_limbs[i] = cg.allocId(); | 6180 | result_limbs[i] = cg.allocId(); |
| 6127 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 6181 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 6128 | .id_result_type = u32_ty_id, | 6182 | .id_result_type = limb_ty_id, |
| 6129 | .id_result = result_limbs[i], | 6183 | .id_result = result_limbs[i], |
| 6130 | .composite = src_id, | 6184 | .composite = src_id, |
| 6131 | .indexes = &.{@as(u32, @intCast(i))}, | 6185 | .indexes = &.{@as(u32, @intCast(i))}, |
| ... | @@ -6133,30 +6187,31 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -6133,30 +6187,31 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 6133 | } | 6187 | } |
| 6134 | if (dst_n > src_n) { | 6188 | if (dst_n > src_n) { |
| 6135 | const fill = if (src_info.signedness == .signed) blk: { | 6189 | const fill = if (src_info.signedness == .signed) blk: { |
| 6136 | const i32_ty_id = try cg.resolveType(.i32, .direct); | 6190 | const signed_limb_ty: Type = if (limb_bits == 64) .i64 else .i32; |
| | 6191 | const signed_limb_ty_id = try cg.resolveType(signed_limb_ty, .direct); |
| 6137 | const msb = result_limbs[src_n - 1]; | 6192 | const msb = result_limbs[src_n - 1]; |
| 6138 | const msb_signed = cg.allocId(); | 6193 | const msb_signed = cg.allocId(); |
| 6139 | try cg.body.emit(gpa, .OpBitcast, .{ | 6194 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 6140 | .id_result_type = i32_ty_id, | 6195 | .id_result_type = signed_limb_ty_id, |
| 6141 | .id_result = msb_signed, | 6196 | .id_result = msb_signed, |
| 6142 | .operand = msb, | 6197 | .operand = msb, |
| 6143 | }); | 6198 | }); |
| 6144 | const shift31 = try cg.constInt(.i32, @as(i32, 31)); | 6199 | const shift_amt = try cg.constInt(signed_limb_ty, @as(u64, limb_bits - 1)); |
| 6145 | const sign_ext = cg.allocId(); | 6200 | const sign_ext = cg.allocId(); |
| 6146 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ | 6201 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ |
| 6147 | .id_result_type = i32_ty_id, | 6202 | .id_result_type = signed_limb_ty_id, |
| 6148 | .id_result = sign_ext, | 6203 | .id_result = sign_ext, |
| 6149 | .base = msb_signed, | 6204 | .base = msb_signed, |
| 6150 | .shift = shift31, | 6205 | .shift = shift_amt, |
| 6151 | }); | 6206 | }); |
| 6152 | const back = cg.allocId(); | 6207 | const back = cg.allocId(); |
| 6153 | try cg.body.emit(gpa, .OpBitcast, .{ | 6208 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 6154 | .id_result_type = u32_ty_id, | 6209 | .id_result_type = limb_ty_id, |
| 6155 | .id_result = back, | 6210 | .id_result = back, |
| 6156 | .operand = sign_ext, | 6211 | .operand = sign_ext, |
| 6157 | }); | 6212 | }); |
| 6158 | break :blk back; | 6213 | break :blk back; |
| 6159 | } else try cg.constInt(.u32, @as(u32, 0)); | 6214 | } else try cg.constInt(limb_ty, @as(u64, 0)); |
| 6160 | for (min_n..dst_n) |i| { | 6215 | for (min_n..dst_n) |i| { |
| 6161 | result_limbs[i] = fill; | 6216 | result_limbs[i] = fill; |
| 6162 | } | 6217 | } |
| ... | @@ -6166,16 +6221,18 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -6166,16 +6221,18 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 6166 | return try normalized.materialize(dst_ty); | 6221 | return try normalized.materialize(dst_ty); |
| 6167 | } else if (src_composite and !dst_composite) { | 6222 | } else if (src_composite and !dst_composite) { |
| 6168 | const src_id = try src.materialize(cg); | 6223 | const src_id = try src.materialize(cg); |
| 6169 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 6224 | const limb_bits = cg.bigIntBits(); |
| 6170 | if (dst_info.backing_bits <= 32) { | 6225 | const limb_ty = cg.limbType(); |
| | 6226 | const limb_ty_id = try cg.limbTypeId(); |
| | 6227 | if (dst_info.backing_bits <= limb_bits) { |
| 6171 | const limb0 = cg.allocId(); | 6228 | const limb0 = cg.allocId(); |
| 6172 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 6229 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 6173 | .id_result_type = u32_ty_id, | 6230 | .id_result_type = limb_ty_id, |
| 6174 | .id_result = limb0, | 6231 | .id_result = limb0, |
| 6175 | .composite = src_id, | 6232 | .composite = src_id, |
| 6176 | .indexes = &.{@as(u32, 0)}, | 6233 | .indexes = &.{@as(u32, 0)}, |
| 6177 | }); | 6234 | }); |
| 6178 | const tmp: Temporary = .init(.u32, limb0); | 6235 | const tmp: Temporary = .init(limb_ty, limb0); |
| 6179 | const converted = try cg.buildConvert(dst_ty, tmp); | 6236 | const converted = try cg.buildConvert(dst_ty, tmp); |
| 6180 | const result = if (dst_info.bits < src_info.bits) | 6237 | const result = if (dst_info.bits < src_info.bits) |
| 6181 | try cg.normalize(converted, dst_info) | 6238 | try cg.normalize(converted, dst_info) |
| ... | @@ -6183,16 +6240,17 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -6183,16 +6240,17 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 6183 | converted; | 6240 | converted; |
| 6184 | return try result.materialize(cg); | 6241 | return try result.materialize(cg); |
| 6185 | } else { | 6242 | } else { |
| | 6243 | assert(limb_bits == 32); // dst > 64 while limbs are 64 shouldn't happen — dst fits in one 64-bit limb. |
| 6186 | const limb0 = cg.allocId(); | 6244 | const limb0 = cg.allocId(); |
| 6187 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 6245 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 6188 | .id_result_type = u32_ty_id, | 6246 | .id_result_type = limb_ty_id, |
| 6189 | .id_result = limb0, | 6247 | .id_result = limb0, |
| 6190 | .composite = src_id, | 6248 | .composite = src_id, |
| 6191 | .indexes = &.{@as(u32, 0)}, | 6249 | .indexes = &.{@as(u32, 0)}, |
| 6192 | }); | 6250 | }); |
| 6193 | const limb1 = cg.allocId(); | 6251 | const limb1 = cg.allocId(); |
| 6194 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 6252 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 6195 | .id_result_type = u32_ty_id, | 6253 | .id_result_type = limb_ty_id, |
| 6196 | .id_result = limb1, | 6254 | .id_result = limb1, |
| 6197 | .composite = src_id, | 6255 | .composite = src_id, |
| 6198 | .indexes = &.{@as(u32, 1)}, | 6256 | .indexes = &.{@as(u32, 1)}, |
| ... | @@ -6234,19 +6292,21 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -6234,19 +6292,21 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 6234 | return try result.materialize(cg); | 6292 | return try result.materialize(cg); |
| 6235 | } | 6293 | } |
| 6236 | } else { | 6294 | } else { |
| 6237 | const dst_n: u16 = dst_info.backing_bits / big_int_bits; | 6295 | const limb_bits = cg.bigIntBits(); |
| | 6296 | const limb_ty = cg.limbType(); |
| | 6297 | const limb_ty_id = try cg.limbTypeId(); |
| | 6298 | const dst_n: u16 = dst_info.backing_bits / limb_bits; |
| 6238 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, dst_n); | 6299 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, dst_n); |
| 6239 | const u32_ty_id = try cg.resolveType(.u32, .direct); | | |
| 6240 | | 6300 | |
| 6241 | if (src_info.backing_bits <= 32) { | 6301 | if (src_info.backing_bits <= limb_bits) { |
| 6242 | const converted = try cg.buildConvert(.u32, src); | 6302 | const converted = try cg.buildConvert(limb_ty, src); |
| 6243 | result_limbs[0] = try converted.materialize(cg); | 6303 | result_limbs[0] = try converted.materialize(cg); |
| 6244 | } else { | 6304 | } else { |
| 6245 | const src_as_u64 = try cg.buildConvert(.u64, src); | 6305 | const src_as_u64 = try cg.buildConvert(.u64, src); |
| 6246 | const src_id = try src_as_u64.materialize(cg); | 6306 | const src_id = try src_as_u64.materialize(cg); |
| 6247 | result_limbs[0] = cg.allocId(); | 6307 | result_limbs[0] = cg.allocId(); |
| 6248 | try cg.body.emit(gpa, .OpUConvert, .{ | 6308 | try cg.body.emit(gpa, .OpUConvert, .{ |
| 6249 | .id_result_type = u32_ty_id, | 6309 | .id_result_type = limb_ty_id, |
| 6250 | .id_result = result_limbs[0], | 6310 | .id_result = result_limbs[0], |
| 6251 | .unsigned_value = src_id, | 6311 | .unsigned_value = src_id, |
| 6252 | }); | 6312 | }); |
| ... | @@ -6261,38 +6321,39 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -6261,38 +6321,39 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 6261 | }); | 6321 | }); |
| 6262 | result_limbs[1] = cg.allocId(); | 6322 | result_limbs[1] = cg.allocId(); |
| 6263 | try cg.body.emit(gpa, .OpUConvert, .{ | 6323 | try cg.body.emit(gpa, .OpUConvert, .{ |
| 6264 | .id_result_type = u32_ty_id, | 6324 | .id_result_type = limb_ty_id, |
| 6265 | .id_result = result_limbs[1], | 6325 | .id_result = result_limbs[1], |
| 6266 | .unsigned_value = hi, | 6326 | .unsigned_value = hi, |
| 6267 | }); | 6327 | }); |
| 6268 | } | 6328 | } |
| 6269 | // Sign/zero-extend remaining limbs. | 6329 | // Sign/zero-extend remaining limbs. |
| 6270 | const fill_start: u16 = if (src_info.backing_bits <= 32) 1 else 2; | 6330 | const fill_start: u16 = if (src_info.backing_bits <= limb_bits) 1 else 2; |
| 6271 | const fill = if (src_info.signedness == .signed) blk: { | 6331 | const fill = if (src_info.signedness == .signed) blk: { |
| 6272 | const i32_ty_id = try cg.resolveType(.i32, .direct); | 6332 | const signed_limb_ty: Type = if (limb_bits == 64) .i64 else .i32; |
| | 6333 | const signed_limb_ty_id = try cg.resolveType(signed_limb_ty, .direct); |
| 6273 | const msb = result_limbs[fill_start - 1]; | 6334 | const msb = result_limbs[fill_start - 1]; |
| 6274 | const msb_signed = cg.allocId(); | 6335 | const msb_signed = cg.allocId(); |
| 6275 | try cg.body.emit(gpa, .OpBitcast, .{ | 6336 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 6276 | .id_result_type = i32_ty_id, | 6337 | .id_result_type = signed_limb_ty_id, |
| 6277 | .id_result = msb_signed, | 6338 | .id_result = msb_signed, |
| 6278 | .operand = msb, | 6339 | .operand = msb, |
| 6279 | }); | 6340 | }); |
| 6280 | const shift31 = try cg.constInt(.i32, @as(i32, 31)); | 6341 | const shift_amt = try cg.constInt(signed_limb_ty, @as(u64, limb_bits - 1)); |
| 6281 | const sign_ext = cg.allocId(); | 6342 | const sign_ext = cg.allocId(); |
| 6282 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ | 6343 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ |
| 6283 | .id_result_type = i32_ty_id, | 6344 | .id_result_type = signed_limb_ty_id, |
| 6284 | .id_result = sign_ext, | 6345 | .id_result = sign_ext, |
| 6285 | .base = msb_signed, | 6346 | .base = msb_signed, |
| 6286 | .shift = shift31, | 6347 | .shift = shift_amt, |
| 6287 | }); | 6348 | }); |
| 6288 | const back = cg.allocId(); | 6349 | const back = cg.allocId(); |
| 6289 | try cg.body.emit(gpa, .OpBitcast, .{ | 6350 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 6290 | .id_result_type = u32_ty_id, | 6351 | .id_result_type = limb_ty_id, |
| 6291 | .id_result = back, | 6352 | .id_result = back, |
| 6292 | .operand = sign_ext, | 6353 | .operand = sign_ext, |
| 6293 | }); | 6354 | }); |
| 6294 | break :blk back; | 6355 | break :blk back; |
| 6295 | } else try cg.constInt(.u32, @as(u32, 0)); | 6356 | } else try cg.constInt(limb_ty, @as(u64, 0)); |
| 6296 | for (fill_start..dst_n) |i| { | 6357 | for (fill_start..dst_n) |i| { |
| 6297 | result_limbs[i] = fill; | 6358 | result_limbs[i] = fill; |
| 6298 | } | 6359 | } |