| ... | @@ -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,21 @@ tracked_allocas: std.AutoHashMapUnmanaged(Id, ?Id) = .empty, | ... | @@ -49,7 +53,21 @@ 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 hasInt64(target: *const std.Target) bool { |
| | 57 | return target.cpu.arch == .spirv64 or target.cpu.has(.spirv, .int64); |
| | 58 | } |
| | 59 | |
| | 60 | fn bigIntBits(cg: *const CodeGen) u16 { |
| | 61 | return if (hasInt64(cg.zcu.getTarget())) 64 else 32; |
| | 62 | } |
| | 63 | |
| | 64 | fn limbType(cg: *const CodeGen) Type { |
| | 65 | return if (cg.bigIntBits() == 64) .u64 else .u32; |
| | 66 | } |
| | 67 | |
| | 68 | fn limbTypeId(cg: *CodeGen) !Id { |
| | 69 | return cg.resolveType(cg.limbType(), .direct); |
| | 70 | } |
| 53 | | 71 | |
| 54 | /// Data can be lowered into in two basic representations: indirect, which is when | 72 | /// 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 | 73 | /// a type is stored in memory, and direct, which is how a type is stored when its |
| ... | @@ -163,6 +181,7 @@ pub fn deinit(cg: *CodeGen) void { | ... | @@ -163,6 +181,7 @@ pub fn deinit(cg: *CodeGen) void { |
| 163 | cg.block_stack.deinit(gpa); | 181 | cg.block_stack.deinit(gpa); |
| 164 | cg.block_results.deinit(gpa); | 182 | cg.block_results.deinit(gpa); |
| 165 | cg.args.deinit(gpa); | 183 | cg.args.deinit(gpa); |
| | 184 | cg.composite_limbs.deinit(gpa); |
| 166 | cg.tracked_allocas.deinit(gpa); | 185 | cg.tracked_allocas.deinit(gpa); |
| 167 | cg.inst_results.deinit(gpa); | 186 | cg.inst_results.deinit(gpa); |
| 168 | cg.loop_switches.deinit(gpa); | 187 | cg.loop_switches.deinit(gpa); |
| ... | @@ -407,7 +426,7 @@ pub fn addEntryPointDeps( | ... | @@ -407,7 +426,7 @@ pub fn addEntryPointDeps( |
| 407 | cg: *CodeGen, | 426 | cg: *CodeGen, |
| 408 | decl_index: Decl.Index, | 427 | decl_index: Decl.Index, |
| 409 | seen: *std.bit_set.Dynamic, | 428 | seen: *std.bit_set.Dynamic, |
| 410 | interface: *std.array_list.Managed(Id), | 429 | interface: *std.ArrayList(Id), |
| 411 | ) !void { | 430 | ) !void { |
| 412 | const decl = cg.declPtr(decl_index); | 431 | const decl = cg.declPtr(decl_index); |
| 413 | const deps = cg.decl_deps.items[decl.begin_dep..decl.end_dep]; | 432 | const deps = cg.decl_deps.items[decl.begin_dep..decl.end_dep]; |
| ... | @@ -419,7 +438,7 @@ pub fn addEntryPointDeps( | ... | @@ -419,7 +438,7 @@ pub fn addEntryPointDeps( |
| 419 | seen.set(@intFromEnum(decl_index)); | 438 | seen.set(@intFromEnum(decl_index)); |
| 420 | | 439 | |
| 421 | if (decl.kind == .global) { | 440 | if (decl.kind == .global) { |
| 422 | try interface.append(decl.result_id); | 441 | try interface.append(cg.gpa, decl.result_id); |
| 423 | } | 442 | } |
| 424 | | 443 | |
| 425 | for (deps) |dep| { | 444 | for (deps) |dep| { |
| ... | @@ -471,14 +490,14 @@ pub fn backingIntBits(cg: *const CodeGen, bits: u16) struct { u16, bool } { | ... | @@ -471,14 +490,14 @@ pub fn backingIntBits(cg: *const CodeGen, bits: u16) struct { u16, bool } { |
| 471 | .{ .bits = 8, .enabled = target.cpu.has(.spirv, .int8) }, | 490 | .{ .bits = 8, .enabled = target.cpu.has(.spirv, .int8) }, |
| 472 | .{ .bits = 16, .enabled = target.cpu.has(.spirv, .int16) }, | 491 | .{ .bits = 16, .enabled = target.cpu.has(.spirv, .int16) }, |
| 473 | .{ .bits = 32, .enabled = true }, | 492 | .{ .bits = 32, .enabled = true }, |
| 474 | .{ .bits = 64, .enabled = target.cpu.has(.spirv, .int64) or target.cpu.arch == .spirv64 }, | 493 | .{ .bits = 64, .enabled = hasInt64(target) }, |
| 475 | }; | 494 | }; |
| 476 | | 495 | |
| 477 | for (ints) |int| { | 496 | for (ints) |int| { |
| 478 | if (bits <= int.bits and int.enabled) return .{ int.bits, false }; | 497 | if (bits <= int.bits and int.enabled) return .{ int.bits, false }; |
| 479 | } | 498 | } |
| 480 | | 499 | |
| 481 | return .{ std.mem.alignForward(u16, bits, big_int_bits), true }; | 500 | return .{ std.mem.alignForward(u16, bits, cg.bigIntBits()), true }; |
| 482 | } | 501 | } |
| 483 | | 502 | |
| 484 | pub fn intType(cg: *CodeGen, signedness: std.lang.Signedness, bits: u16) !Id { | 503 | pub fn intType(cg: *CodeGen, signedness: std.lang.Signedness, bits: u16) !Id { |
| ... | @@ -492,14 +511,16 @@ pub fn intType(cg: *CodeGen, signedness: std.lang.Signedness, bits: u16) !Id { | ... | @@ -492,14 +511,16 @@ pub fn intType(cg: *CodeGen, signedness: std.lang.Signedness, bits: u16) !Id { |
| 492 | }; | 511 | }; |
| 493 | const backing_bits, const big_int = cg.backingIntBits(bits); | 512 | const backing_bits, const big_int = cg.backingIntBits(bits); |
| 494 | if (big_int) { | 513 | if (big_int) { |
| 495 | const u32_ty = try cg.intType(.unsigned, 32); | 514 | const limb_bits = cg.bigIntBits(); |
| | 515 | const limb_ty = try cg.intType(.unsigned, limb_bits); |
| | 516 | const len_ty = try cg.intType(.unsigned, 32); |
| 496 | const len_id = cg.allocId(); | 517 | const len_id = cg.allocId(); |
| 497 | try cg.sections.globals.emit(cg.gpa, .OpConstant, .{ | 518 | try cg.sections.globals.emit(cg.gpa, .OpConstant, .{ |
| 498 | .id_result_type = u32_ty, | 519 | .id_result_type = len_ty, |
| 499 | .id_result = len_id, | 520 | .id_result = len_id, |
| 500 | .value = .{ .uint32 = backing_bits / big_int_bits }, | 521 | .value = .{ .uint32 = backing_bits / limb_bits }, |
| 501 | }); | 522 | }); |
| 502 | return cg.arrayType(len_id, u32_ty); | 523 | return cg.arrayType(len_id, limb_ty); |
| 503 | } | 524 | } |
| 504 | | 525 | |
| 505 | const result_id = cg.allocId(); | 526 | const result_id = cg.allocId(); |
| ... | @@ -1443,7 +1464,7 @@ fn constInt(cg: *CodeGen, ty: Type, value: anytype) !Id { | ... | @@ -1443,7 +1464,7 @@ fn constInt(cg: *CodeGen, ty: Type, value: anytype) !Id { |
| 1443 | .signed => @bitCast(@as(i64, @intCast(value))), | 1464 | .signed => @bitCast(@as(i64, @intCast(value))), |
| 1444 | .unsigned => @as(u64, @intCast(value)), | 1465 | .unsigned => @as(u64, @intCast(value)), |
| 1445 | }; | 1466 | }; |
| 1446 | const n_limbs = backing_bits / big_int_bits; | 1467 | const n_limbs = backing_bits / cg.bigIntBits(); |
| 1447 | const fill: u32 = if (signedness == .signed and value < 0) 0xFFFFFFFF else 0; | 1468 | const fill: u32 = if (signedness == .signed and value < 0) 0xFFFFFFFF else 0; |
| 1448 | const scratch_top = cg.id_scratch.items.len; | 1469 | const scratch_top = cg.id_scratch.items.len; |
| 1449 | defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); | 1470 | defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); |
| ... | @@ -1616,21 +1637,33 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { | ... | @@ -1616,21 +1637,33 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { |
| 1616 | const int_info = ty.intInfo(zcu); | 1637 | const int_info = ty.intInfo(zcu); |
| 1617 | const backing_bits, const is_big_int = cg.backingIntBits(int_info.bits); | 1638 | const backing_bits, const is_big_int = cg.backingIntBits(int_info.bits); |
| 1618 | if (is_big_int) { | 1639 | if (is_big_int) { |
| 1619 | const n_limbs = backing_bits / big_int_bits; | 1640 | const limb_bits = cg.bigIntBits(); |
| | 1641 | const n_limbs = backing_bits / limb_bits; |
| 1620 | const big_result_ty_id = try cg.resolveType(ty, .indirect); | 1642 | const big_result_ty_id = try cg.resolveType(ty, .indirect); |
| 1621 | var bigint_space: Value.BigIntSpace = undefined; | 1643 | var bigint_space: Value.BigIntSpace = undefined; |
| 1622 | const bigint = val.toBigInt(&bigint_space, zcu); | 1644 | const bigint = val.toBigInt(&bigint_space, zcu); |
| 1623 | const limb_values = try gpa.alloc(u32, n_limbs); | 1645 | const limb_bytes = try gpa.alloc(u8, backing_bits / 8); |
| 1624 | defer gpa.free(limb_values); | 1646 | defer gpa.free(limb_bytes); |
| 1625 | bigint.writeTwosComplement(std.mem.sliceAsBytes(limb_values), .little); | 1647 | 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; | 1648 | const scratch_top = cg.id_scratch.items.len; |
| 1630 | defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); | 1649 | defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); |
| 1631 | const constituents = try cg.id_scratch.addManyAsSlice(gpa, n_limbs); | 1650 | const constituents = try cg.id_scratch.addManyAsSlice(gpa, n_limbs); |
| 1632 | for (constituents, 0..) |*c, i| { | 1651 | switch (limb_bits) { |
| 1633 | c.* = try cg.constInt(.u32, limb_values[i]); | 1652 | 32 => { |
| | 1653 | const limbs_u32: []u32 = @ptrCast(@alignCast(limb_bytes)); |
| | 1654 | for (constituents, limbs_u32) |*c, v| { |
| | 1655 | const host_v = if (builtin.cpu.arch.endian() == .big) @byteSwap(v) else v; |
| | 1656 | c.* = try cg.constInt(.u32, host_v); |
| | 1657 | } |
| | 1658 | }, |
| | 1659 | 64 => { |
| | 1660 | const limbs_u64: []u64 = @ptrCast(@alignCast(limb_bytes)); |
| | 1661 | for (constituents, limbs_u64) |*c, v| { |
| | 1662 | const host_v = if (builtin.cpu.arch.endian() == .big) @byteSwap(v) else v; |
| | 1663 | c.* = try cg.constInt(.u64, host_v); |
| | 1664 | } |
| | 1665 | }, |
| | 1666 | else => unreachable, |
| 1634 | } | 1667 | } |
| 1635 | break :cache try cg.constructComposite(big_result_ty_id, constituents); | 1668 | break :cache try cg.constructComposite(big_result_ty_id, constituents); |
| 1636 | } | 1669 | } |
| ... | @@ -1776,11 +1809,11 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { | ... | @@ -1776,11 +1809,11 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { |
| 1776 | const struct_type = zcu.typeToStruct(ty).?; | 1809 | const struct_type = zcu.typeToStruct(ty).?; |
| 1777 | assert(struct_type.layout != .@"packed"); // packed structs use `bitpack` | 1810 | assert(struct_type.layout != .@"packed"); // packed structs use `bitpack` |
| 1778 | | 1811 | |
| 1779 | var types = std.array_list.Managed(Type).init(gpa); | 1812 | var types: std.ArrayList(Type) = .empty; |
| 1780 | defer types.deinit(); | 1813 | defer types.deinit(gpa); |
| 1781 | | 1814 | |
| 1782 | var constituents = std.array_list.Managed(Id).init(gpa); | 1815 | var constituents: std.ArrayList(Id) = .empty; |
| 1783 | defer constituents.deinit(); | 1816 | defer constituents.deinit(gpa); |
| 1784 | | 1817 | |
| 1785 | var it = struct_type.iterateRuntimeOrder(ip); | 1818 | var it = struct_type.iterateRuntimeOrder(ip); |
| 1786 | while (it.next()) |field_index| { | 1819 | while (it.next()) |field_index| { |
| ... | @@ -1794,8 +1827,8 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { | ... | @@ -1794,8 +1827,8 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { |
| 1794 | const field_val = try val.fieldValue(pt, field_index); | 1827 | const field_val = try val.fieldValue(pt, field_index); |
| 1795 | const field_id = try cg.constant(field_ty, field_val, .indirect); | 1828 | const field_id = try cg.constant(field_ty, field_val, .indirect); |
| 1796 | | 1829 | |
| 1797 | try types.append(field_ty); | 1830 | try types.append(gpa, field_ty); |
| 1798 | try constituents.append(field_id); | 1831 | try constituents.append(gpa, field_id); |
| 1799 | } | 1832 | } |
| 1800 | | 1833 | |
| 1801 | const comp_ty_id = try cg.resolveType(ty, .direct); | 1834 | const comp_ty_id = try cg.resolveType(ty, .direct); |
| ... | @@ -2189,14 +2222,10 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { | ... | @@ -2189,14 +2222,10 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { |
| 2189 | 64 => target.cpu.has(.spirv, .float64), | 2222 | 64 => target.cpu.has(.spirv, .float64), |
| 2190 | else => false, | 2223 | else => false, |
| 2191 | }; | 2224 | }; |
| 2192 | | 2225 | if (!supported) return cg.fail( |
| 2193 | if (!supported) { | 2226 | "'{f}' is not supported on the current SPIR-V feature set", |
| 2194 | return cg.fail( | 2227 | .{ty.fmt(cg.pt)}, |
| 2195 | "floating point width of {} bits is not supported for the current SPIR-V feature set", | 2228 | ); |
| 2196 | .{bits}, | | |
| 2197 | ); | | |
| 2198 | } | | |
| 2199 | | | |
| 2200 | return try cg.floatType(bits); | 2229 | return try cg.floatType(bits); |
| 2201 | }, | 2230 | }, |
| 2202 | .array => { | 2231 | .array => { |
| ... | @@ -2288,7 +2317,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { | ... | @@ -2288,7 +2317,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { |
| 2288 | }), | 2317 | }), |
| 2289 | }, | 2318 | }, |
| 2290 | }; | 2319 | }; |
| 2291 | const child_ty_id = try cg.resolveType(child_ty, .indirect); | 2320 | const child_ty_id = try cg.pointeeType(ptr_info.flags.address_space, child_ty, false); |
| 2292 | const storage_class = cg.storageClass(ptr_info.flags.address_space); | 2321 | const storage_class = cg.storageClass(ptr_info.flags.address_space); |
| 2293 | const ptr_ty_id = try cg.ptrType(child_ty_id, storage_class); | 2322 | const ptr_ty_id = try cg.ptrType(child_ty_id, storage_class); |
| 2294 | | 2323 | |
| ... | @@ -2336,11 +2365,11 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { | ... | @@ -2336,11 +2365,11 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { |
| 2336 | return try cg.resolveType(.fromInterned(struct_type.packed_backing_int_type), .direct); | 2365 | return try cg.resolveType(.fromInterned(struct_type.packed_backing_int_type), .direct); |
| 2337 | } | 2366 | } |
| 2338 | | 2367 | |
| 2339 | var member_types = std.array_list.Managed(Id).init(gpa); | 2368 | var member_types: std.ArrayList(Id) = .empty; |
| 2340 | defer member_types.deinit(); | 2369 | defer member_types.deinit(gpa); |
| 2341 | | 2370 | |
| 2342 | var member_names = std.array_list.Managed([]const u8).init(gpa); | 2371 | var member_names: std.ArrayList([]const u8) = .empty; |
| 2343 | defer member_names.deinit(); | 2372 | defer member_names.deinit(gpa); |
| 2344 | | 2373 | |
| 2345 | var it = struct_type.iterateRuntimeOrder(ip); | 2374 | var it = struct_type.iterateRuntimeOrder(ip); |
| 2346 | while (it.next()) |field_index| { | 2375 | while (it.next()) |field_index| { |
| ... | @@ -2348,8 +2377,8 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { | ... | @@ -2348,8 +2377,8 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { |
| 2348 | if (!field_ty.hasRuntimeBits(zcu)) continue; | 2377 | if (!field_ty.hasRuntimeBits(zcu)) continue; |
| 2349 | | 2378 | |
| 2350 | const field_name = struct_type.field_names.get(ip)[field_index]; | 2379 | const field_name = struct_type.field_names.get(ip)[field_index]; |
| 2351 | try member_types.append(try cg.resolveType(field_ty, .indirect)); | 2380 | try member_types.append(gpa, try cg.resolveType(field_ty, .indirect)); |
| 2352 | try member_names.append(field_name.toSlice(ip)); | 2381 | try member_names.append(gpa, field_name.toSlice(ip)); |
| 2353 | } | 2382 | } |
| 2354 | | 2383 | |
| 2355 | const result_id = try cg.structType( | 2384 | const result_id = try cg.structType( |
| ... | @@ -2766,20 +2795,28 @@ const CompositeInt = struct { | ... | @@ -2766,20 +2795,28 @@ const CompositeInt = struct { |
| 2766 | info: ArithmeticTypeInfo, | 2795 | info: ArithmeticTypeInfo, |
| 2767 | | 2796 | |
| 2768 | fn init(cg: *CodeGen, composite_id: Id, info: ArithmeticTypeInfo) !CompositeInt { | 2797 | fn init(cg: *CodeGen, composite_id: Id, info: ArithmeticTypeInfo) !CompositeInt { |
| 2769 | const n_limbs: u16 = info.backing_bits / big_int_bits; | 2798 | const n_limbs: u16 = info.backing_bits / cg.bigIntBits(); |
| 2770 | const gpa = cg.gpa; | 2799 | const gpa = cg.gpa; |
| 2771 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 2800 | if (cg.composite_limbs.get(composite_id)) |cached| { |
| | 2801 | assert(cached.len == n_limbs); |
| | 2802 | const limbs = try cg.id_scratch.addManyAsSlice(gpa, n_limbs); |
| | 2803 | @memcpy(limbs, cached); |
| | 2804 | return .{ .cg = cg, .limbs = limbs, .n_limbs = n_limbs, .info = info }; |
| | 2805 | } |
| | 2806 | const limb_ty_id = try cg.limbTypeId(); |
| 2772 | const limbs = try cg.id_scratch.addManyAsSlice(gpa, n_limbs); | 2807 | const limbs = try cg.id_scratch.addManyAsSlice(gpa, n_limbs); |
| 2773 | for (limbs, 0..) |*limb, i| { | 2808 | for (limbs, 0..) |*limb, i| { |
| 2774 | const result_id = cg.allocId(); | 2809 | const result_id = cg.allocId(); |
| 2775 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 2810 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 2776 | .id_result_type = u32_ty_id, | 2811 | .id_result_type = limb_ty_id, |
| 2777 | .id_result = result_id, | 2812 | .id_result = result_id, |
| 2778 | .composite = composite_id, | 2813 | .composite = composite_id, |
| 2779 | .indexes = &.{@as(u32, @intCast(i))}, | 2814 | .indexes = &.{@as(u32, @intCast(i))}, |
| 2780 | }); | 2815 | }); |
| 2781 | limb.* = result_id; | 2816 | limb.* = result_id; |
| 2782 | } | 2817 | } |
| | 2818 | const cached = try cg.arena.dupe(Id, limbs); |
| | 2819 | try cg.composite_limbs.put(gpa, composite_id, cached); |
| 2783 | return .{ .cg = cg, .limbs = limbs, .n_limbs = n_limbs, .info = info }; | 2820 | return .{ .cg = cg, .limbs = limbs, .n_limbs = n_limbs, .info = info }; |
| 2784 | } | 2821 | } |
| 2785 | | 2822 | |
| ... | @@ -2793,9 +2830,9 @@ const CompositeInt = struct { | ... | @@ -2793,9 +2830,9 @@ const CompositeInt = struct { |
| 2793 | } | 2830 | } |
| 2794 | | 2831 | |
| 2795 | fn zero(cg: *CodeGen, info: ArithmeticTypeInfo) !CompositeInt { | 2832 | fn zero(cg: *CodeGen, info: ArithmeticTypeInfo) !CompositeInt { |
| 2796 | const n_limbs: u16 = info.backing_bits / big_int_bits; | 2833 | const n_limbs: u16 = info.backing_bits / cg.bigIntBits(); |
| 2797 | const limbs = try cg.id_scratch.addManyAsSlice(cg.gpa, n_limbs); | 2834 | const limbs = try cg.id_scratch.addManyAsSlice(cg.gpa, n_limbs); |
| 2798 | const zero_id = try cg.constInt(.u32, @as(u32, 0)); | 2835 | const zero_id = try cg.constInt(cg.limbType(), @as(u64, 0)); |
| 2799 | for (limbs) |*limb| limb.* = zero_id; | 2836 | for (limbs) |*limb| limb.* = zero_id; |
| 2800 | return .{ .cg = cg, .limbs = limbs, .n_limbs = n_limbs, .info = info }; | 2837 | return .{ .cg = cg, .limbs = limbs, .n_limbs = n_limbs, .info = info }; |
| 2801 | } | 2838 | } |
| ... | @@ -2808,10 +2845,10 @@ const CompositeInt = struct { | ... | @@ -2808,10 +2845,10 @@ const CompositeInt = struct { |
| 2808 | fn limbBinOp(ci: CompositeInt, opcode: Opcode, lhs: Id, rhs: Id) !Id { | 2845 | fn limbBinOp(ci: CompositeInt, opcode: Opcode, lhs: Id, rhs: Id) !Id { |
| 2809 | const cg = ci.cg; | 2846 | const cg = ci.cg; |
| 2810 | const gpa = cg.gpa; | 2847 | const gpa = cg.gpa; |
| 2811 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 2848 | const limb_ty_id = try cg.limbTypeId(); |
| 2812 | const result_id = cg.allocId(); | 2849 | const result_id = cg.allocId(); |
| 2813 | try cg.body.emitRaw(gpa, opcode, 4); | 2850 | try cg.body.emitRaw(gpa, opcode, 4); |
| 2814 | cg.body.writeOperand(Id, u32_ty_id); | 2851 | cg.body.writeOperand(Id, limb_ty_id); |
| 2815 | cg.body.writeOperand(Id, result_id); | 2852 | cg.body.writeOperand(Id, result_id); |
| 2816 | cg.body.writeOperand(Id, lhs); | 2853 | cg.body.writeOperand(Id, lhs); |
| 2817 | cg.body.writeOperand(Id, rhs); | 2854 | cg.body.writeOperand(Id, rhs); |
| ... | @@ -2821,10 +2858,10 @@ const CompositeInt = struct { | ... | @@ -2821,10 +2858,10 @@ const CompositeInt = struct { |
| 2821 | fn limbUnOp(ci: CompositeInt, opcode: Opcode, operand: Id) !Id { | 2858 | fn limbUnOp(ci: CompositeInt, opcode: Opcode, operand: Id) !Id { |
| 2822 | const cg = ci.cg; | 2859 | const cg = ci.cg; |
| 2823 | const gpa = cg.gpa; | 2860 | const gpa = cg.gpa; |
| 2824 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 2861 | const limb_ty_id = try cg.limbTypeId(); |
| 2825 | const result_id = cg.allocId(); | 2862 | const result_id = cg.allocId(); |
| 2826 | try cg.body.emitRaw(gpa, opcode, 3); | 2863 | try cg.body.emitRaw(gpa, opcode, 3); |
| 2827 | cg.body.writeOperand(Id, u32_ty_id); | 2864 | cg.body.writeOperand(Id, limb_ty_id); |
| 2828 | cg.body.writeOperand(Id, result_id); | 2865 | cg.body.writeOperand(Id, result_id); |
| 2829 | cg.body.writeOperand(Id, operand); | 2866 | cg.body.writeOperand(Id, operand); |
| 2830 | return result_id; | 2867 | return result_id; |
| ... | @@ -2916,16 +2953,17 @@ const CompositeInt = struct { | ... | @@ -2916,16 +2953,17 @@ const CompositeInt = struct { |
| 2916 | var cmp_l = l; | 2953 | var cmp_l = l; |
| 2917 | var cmp_r = r; | 2954 | var cmp_r = r; |
| 2918 | if (use_signed) { | 2955 | if (use_signed) { |
| 2919 | const i32_ty_id = try cg.resolveType(.i32, .direct); | 2956 | const signed_limb_ty: Type = if (cg.bigIntBits() == 64) .i64 else .i32; |
| | 2957 | const signed_limb_ty_id = try cg.resolveType(signed_limb_ty, .direct); |
| 2920 | const sl = cg.allocId(); | 2958 | const sl = cg.allocId(); |
| 2921 | try cg.body.emit(gpa, .OpBitcast, .{ | 2959 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 2922 | .id_result_type = i32_ty_id, | 2960 | .id_result_type = signed_limb_ty_id, |
| 2923 | .id_result = sl, | 2961 | .id_result = sl, |
| 2924 | .operand = l, | 2962 | .operand = l, |
| 2925 | }); | 2963 | }); |
| 2926 | const sr = cg.allocId(); | 2964 | const sr = cg.allocId(); |
| 2927 | try cg.body.emit(gpa, .OpBitcast, .{ | 2965 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 2928 | .id_result_type = i32_ty_id, | 2966 | .id_result_type = signed_limb_ty_id, |
| 2929 | .id_result = sr, | 2967 | .id_result = sr, |
| 2930 | .operand = r, | 2968 | .operand = r, |
| 2931 | }); | 2969 | }); |
| ... | @@ -2969,16 +3007,17 @@ const CompositeInt = struct { | ... | @@ -2969,16 +3007,17 @@ const CompositeInt = struct { |
| 2969 | const comp = zcu.comp; | 3007 | const comp = zcu.comp; |
| 2970 | const io = comp.io; | 3008 | const io = comp.io; |
| 2971 | | 3009 | |
| 2972 | const u32_zig = try pt.intType(.unsigned, 32); | 3010 | const limb_bits = cg.bigIntBits(); |
| 2973 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 3011 | const limb_zig = try pt.intType(.unsigned, limb_bits); |
| | 3012 | const limb_ty_id = try cg.limbTypeId(); |
| 2974 | const carry_struct_ty: Type = .fromInterned(try ip.getTupleType(gpa, io, pt.tid, .{ | 3013 | const carry_struct_ty: Type = .fromInterned(try ip.getTupleType(gpa, io, pt.tid, .{ |
| 2975 | .types = &.{ u32_zig.toIntern(), u32_zig.toIntern() }, | 3014 | .types = &.{ limb_zig.toIntern(), limb_zig.toIntern() }, |
| 2976 | .values = &.{ .none, .none }, | 3015 | .values = &.{ .none, .none }, |
| 2977 | })); | 3016 | })); |
| 2978 | const carry_struct_ty_id = try cg.resolveType(carry_struct_ty, .direct); | 3017 | const carry_struct_ty_id = try cg.resolveType(carry_struct_ty, .direct); |
| 2979 | | 3018 | |
| 2980 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs); | 3019 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs); |
| 2981 | var carry_id = try cg.constInt(.u32, @as(u32, 0)); | 3020 | var carry_id = try cg.constInt(cg.limbType(), @as(u64, 0)); |
| 2982 | | 3021 | |
| 2983 | const opcode: Opcode = if (is_add) .OpIAddCarry else .OpISubBorrow; | 3022 | const opcode: Opcode = if (is_add) .OpIAddCarry else .OpISubBorrow; |
| 2984 | | 3023 | |
| ... | @@ -2992,14 +3031,14 @@ const CompositeInt = struct { | ... | @@ -2992,14 +3031,14 @@ const CompositeInt = struct { |
| 2992 | | 3031 | |
| 2993 | const sum1 = cg.allocId(); | 3032 | const sum1 = cg.allocId(); |
| 2994 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3033 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 2995 | .id_result_type = u32_ty_id, | 3034 | .id_result_type = limb_ty_id, |
| 2996 | .id_result = sum1, | 3035 | .id_result = sum1, |
| 2997 | .composite = op1, | 3036 | .composite = op1, |
| 2998 | .indexes = &.{0}, | 3037 | .indexes = &.{0}, |
| 2999 | }); | 3038 | }); |
| 3000 | const carry1 = cg.allocId(); | 3039 | const carry1 = cg.allocId(); |
| 3001 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3040 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3002 | .id_result_type = u32_ty_id, | 3041 | .id_result_type = limb_ty_id, |
| 3003 | .id_result = carry1, | 3042 | .id_result = carry1, |
| 3004 | .composite = op1, | 3043 | .composite = op1, |
| 3005 | .indexes = &.{1}, | 3044 | .indexes = &.{1}, |
| ... | @@ -3014,14 +3053,14 @@ const CompositeInt = struct { | ... | @@ -3014,14 +3053,14 @@ const CompositeInt = struct { |
| 3014 | | 3053 | |
| 3015 | result_limbs[i] = cg.allocId(); | 3054 | result_limbs[i] = cg.allocId(); |
| 3016 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3055 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3017 | .id_result_type = u32_ty_id, | 3056 | .id_result_type = limb_ty_id, |
| 3018 | .id_result = result_limbs[i], | 3057 | .id_result = result_limbs[i], |
| 3019 | .composite = op2, | 3058 | .composite = op2, |
| 3020 | .indexes = &.{0}, | 3059 | .indexes = &.{0}, |
| 3021 | }); | 3060 | }); |
| 3022 | const carry2 = cg.allocId(); | 3061 | const carry2 = cg.allocId(); |
| 3023 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3062 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3024 | .id_result_type = u32_ty_id, | 3063 | .id_result_type = limb_ty_id, |
| 3025 | .id_result = carry2, | 3064 | .id_result = carry2, |
| 3026 | .composite = op2, | 3065 | .composite = op2, |
| 3027 | .indexes = &.{1}, | 3066 | .indexes = &.{1}, |
| ... | @@ -3036,16 +3075,18 @@ const CompositeInt = struct { | ... | @@ -3036,16 +3075,18 @@ const CompositeInt = struct { |
| 3036 | fn shl(ci: CompositeInt, shift_amt_id: Id) !CompositeInt { | 3075 | fn shl(ci: CompositeInt, shift_amt_id: Id) !CompositeInt { |
| 3037 | const cg = ci.cg; | 3076 | const cg = ci.cg; |
| 3038 | const gpa = cg.gpa; | 3077 | const gpa = cg.gpa; |
| 3039 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 3078 | const limb_bits = cg.bigIntBits(); |
| | 3079 | const limb_ty = cg.limbType(); |
| | 3080 | const limb_ty_id = try cg.limbTypeId(); |
| 3040 | const bool_ty_id = try cg.resolveType(.bool, .direct); | 3081 | const bool_ty_id = try cg.resolveType(.bool, .direct); |
| 3041 | const zero_id = try cg.constInt(.u32, @as(u32, 0)); | 3082 | const zero_id = try cg.constInt(limb_ty, @as(u64, 0)); |
| 3042 | const five_id = try cg.constInt(.u32, @as(u32, 5)); | 3083 | 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)); | 3084 | 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)); | 3085 | const bits_id = try cg.constInt(limb_ty, @as(u64, limb_bits)); |
| 3045 | | 3086 | |
| 3046 | const whole = try ci.limbBinOp(.OpShiftRightLogical, shift_amt_id, five_id); | 3087 | 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); | 3088 | 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); | 3089 | const comp_frac = try ci.limbBinOp(.OpISub, bits_id, frac); |
| 3049 | const frac_is_zero = blk: { | 3090 | const frac_is_zero = blk: { |
| 3050 | const r = cg.allocId(); | 3091 | const r = cg.allocId(); |
| 3051 | try cg.body.emit(gpa, .OpIEqual, .{ | 3092 | try cg.body.emit(gpa, .OpIEqual, .{ |
| ... | @@ -3060,12 +3101,12 @@ const CompositeInt = struct { | ... | @@ -3060,12 +3101,12 @@ const CompositeInt = struct { |
| 3060 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs); | 3101 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs); |
| 3061 | | 3102 | |
| 3062 | for (0..ci.n_limbs) |i| { | 3103 | for (0..ci.n_limbs) |i| { |
| 3063 | const i_id = try cg.constInt(.u32, @as(u32, @intCast(i))); | 3104 | const i_id = try cg.constInt(limb_ty, @as(u64, @intCast(i))); |
| 3064 | var main_val = zero_id; | 3105 | var main_val = zero_id; |
| 3065 | var carry_val = zero_id; | 3106 | var carry_val = zero_id; |
| 3066 | | 3107 | |
| 3067 | for (0..ci.n_limbs) |j| { | 3108 | for (0..ci.n_limbs) |j| { |
| 3068 | const j_id = try cg.constInt(.u32, @as(u32, @intCast(j))); | 3109 | const j_id = try cg.constInt(limb_ty, @as(u64, @intCast(j))); |
| 3069 | const j_plus_whole = try ci.limbBinOp(.OpIAdd, j_id, whole); | 3110 | const j_plus_whole = try ci.limbBinOp(.OpIAdd, j_id, whole); |
| 3070 | | 3111 | |
| 3071 | const is_main = blk: { | 3112 | const is_main = blk: { |
| ... | @@ -3082,7 +3123,7 @@ const CompositeInt = struct { | ... | @@ -3082,7 +3123,7 @@ const CompositeInt = struct { |
| 3082 | main_val = blk: { | 3123 | main_val = blk: { |
| 3083 | const r = cg.allocId(); | 3124 | const r = cg.allocId(); |
| 3084 | try cg.body.emit(gpa, .OpSelect, .{ | 3125 | try cg.body.emit(gpa, .OpSelect, .{ |
| 3085 | .id_result_type = u32_ty_id, | 3126 | .id_result_type = limb_ty_id, |
| 3086 | .id_result = r, | 3127 | .id_result = r, |
| 3087 | .condition = is_main, | 3128 | .condition = is_main, |
| 3088 | .object_1 = shifted, | 3129 | .object_1 = shifted, |
| ... | @@ -3091,7 +3132,7 @@ const CompositeInt = struct { | ... | @@ -3091,7 +3132,7 @@ const CompositeInt = struct { |
| 3091 | break :blk r; | 3132 | break :blk r; |
| 3092 | }; | 3133 | }; |
| 3093 | | 3134 | |
| 3094 | const one_id = try cg.constInt(.u32, @as(u32, 1)); | 3135 | 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); | 3136 | const j_plus_whole_plus_1 = try ci.limbBinOp(.OpIAdd, j_plus_whole, one_id); |
| 3096 | const is_carry = blk: { | 3137 | const is_carry = blk: { |
| 3097 | const r = cg.allocId(); | 3138 | const r = cg.allocId(); |
| ... | @@ -3107,7 +3148,7 @@ const CompositeInt = struct { | ... | @@ -3107,7 +3148,7 @@ const CompositeInt = struct { |
| 3107 | const guarded_carry = blk: { | 3148 | const guarded_carry = blk: { |
| 3108 | const r = cg.allocId(); | 3149 | const r = cg.allocId(); |
| 3109 | try cg.body.emit(gpa, .OpSelect, .{ | 3150 | try cg.body.emit(gpa, .OpSelect, .{ |
| 3110 | .id_result_type = u32_ty_id, | 3151 | .id_result_type = limb_ty_id, |
| 3111 | .id_result = r, | 3152 | .id_result = r, |
| 3112 | .condition = frac_is_zero, | 3153 | .condition = frac_is_zero, |
| 3113 | .object_1 = zero_id, | 3154 | .object_1 = zero_id, |
| ... | @@ -3118,7 +3159,7 @@ const CompositeInt = struct { | ... | @@ -3118,7 +3159,7 @@ const CompositeInt = struct { |
| 3118 | carry_val = blk: { | 3159 | carry_val = blk: { |
| 3119 | const r = cg.allocId(); | 3160 | const r = cg.allocId(); |
| 3120 | try cg.body.emit(gpa, .OpSelect, .{ | 3161 | try cg.body.emit(gpa, .OpSelect, .{ |
| 3121 | .id_result_type = u32_ty_id, | 3162 | .id_result_type = limb_ty_id, |
| 3122 | .id_result = r, | 3163 | .id_result = r, |
| 3123 | .condition = is_carry, | 3164 | .condition = is_carry, |
| 3124 | .object_1 = guarded_carry, | 3165 | .object_1 = guarded_carry, |
| ... | @@ -3137,16 +3178,18 @@ const CompositeInt = struct { | ... | @@ -3137,16 +3178,18 @@ const CompositeInt = struct { |
| 3137 | fn shr(ci: CompositeInt, shift_amt_id: Id, comptime is_arithmetic: bool) !CompositeInt { | 3178 | fn shr(ci: CompositeInt, shift_amt_id: Id, comptime is_arithmetic: bool) !CompositeInt { |
| 3138 | const cg = ci.cg; | 3179 | const cg = ci.cg; |
| 3139 | const gpa = cg.gpa; | 3180 | const gpa = cg.gpa; |
| 3140 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 3181 | const limb_bits = cg.bigIntBits(); |
| | 3182 | const limb_ty = cg.limbType(); |
| | 3183 | const limb_ty_id = try cg.limbTypeId(); |
| 3141 | const bool_ty_id = try cg.resolveType(.bool, .direct); | 3184 | const bool_ty_id = try cg.resolveType(.bool, .direct); |
| 3142 | const zero_id = try cg.constInt(.u32, @as(u32, 0)); | 3185 | const zero_id = try cg.constInt(limb_ty, @as(u64, 0)); |
| 3143 | const five_id = try cg.constInt(.u32, @as(u32, 5)); | 3186 | 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)); | 3187 | 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)); | 3188 | const bits_id = try cg.constInt(limb_ty, @as(u64, limb_bits)); |
| 3146 | | 3189 | |
| 3147 | const whole = try ci.limbBinOp(.OpShiftRightLogical, shift_amt_id, five_id); | 3190 | 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); | 3191 | 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); | 3192 | const comp_frac = try ci.limbBinOp(.OpISub, bits_id, frac); |
| 3150 | const frac_is_zero = blk: { | 3193 | const frac_is_zero = blk: { |
| 3151 | const r = cg.allocId(); | 3194 | const r = cg.allocId(); |
| 3152 | try cg.body.emit(gpa, .OpIEqual, .{ | 3195 | try cg.body.emit(gpa, .OpIEqual, .{ |
| ... | @@ -3159,24 +3202,25 @@ const CompositeInt = struct { | ... | @@ -3159,24 +3202,25 @@ const CompositeInt = struct { |
| 3159 | }; | 3202 | }; |
| 3160 | | 3203 | |
| 3161 | const fill_id = if (is_arithmetic) blk: { | 3204 | const fill_id = if (is_arithmetic) blk: { |
| 3162 | const i32_ty_id = try cg.resolveType(.i32, .direct); | 3205 | const signed_limb_ty: Type = if (limb_bits == 64) .i64 else .i32; |
| | 3206 | const signed_limb_ty_id = try cg.resolveType(signed_limb_ty, .direct); |
| 3163 | const msb_signed = cg.allocId(); | 3207 | const msb_signed = cg.allocId(); |
| 3164 | try cg.body.emit(gpa, .OpBitcast, .{ | 3208 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 3165 | .id_result_type = i32_ty_id, | 3209 | .id_result_type = signed_limb_ty_id, |
| 3166 | .id_result = msb_signed, | 3210 | .id_result = msb_signed, |
| 3167 | .operand = ci.limbs[ci.n_limbs - 1], | 3211 | .operand = ci.limbs[ci.n_limbs - 1], |
| 3168 | }); | 3212 | }); |
| 3169 | const shift31 = try cg.constInt(.i32, @as(i32, 31)); | 3213 | const shift_amt = try cg.constInt(signed_limb_ty, @as(u64, limb_bits - 1)); |
| 3170 | const sign_ext = cg.allocId(); | 3214 | const sign_ext = cg.allocId(); |
| 3171 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ | 3215 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ |
| 3172 | .id_result_type = i32_ty_id, | 3216 | .id_result_type = signed_limb_ty_id, |
| 3173 | .id_result = sign_ext, | 3217 | .id_result = sign_ext, |
| 3174 | .base = msb_signed, | 3218 | .base = msb_signed, |
| 3175 | .shift = shift31, | 3219 | .shift = shift_amt, |
| 3176 | }); | 3220 | }); |
| 3177 | const back = cg.allocId(); | 3221 | const back = cg.allocId(); |
| 3178 | try cg.body.emit(gpa, .OpBitcast, .{ | 3222 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 3179 | .id_result_type = u32_ty_id, | 3223 | .id_result_type = limb_ty_id, |
| 3180 | .id_result = back, | 3224 | .id_result = back, |
| 3181 | .operand = sign_ext, | 3225 | .operand = sign_ext, |
| 3182 | }); | 3226 | }); |
| ... | @@ -3189,7 +3233,7 @@ const CompositeInt = struct { | ... | @@ -3189,7 +3233,7 @@ const CompositeInt = struct { |
| 3189 | const shifted_fill = try ci.limbBinOp(.OpShiftLeftLogical, fill_id, comp_frac); | 3233 | const shifted_fill = try ci.limbBinOp(.OpShiftLeftLogical, fill_id, comp_frac); |
| 3190 | const guarded = cg.allocId(); | 3234 | const guarded = cg.allocId(); |
| 3191 | try cg.body.emit(gpa, .OpSelect, .{ | 3235 | try cg.body.emit(gpa, .OpSelect, .{ |
| 3192 | .id_result_type = u32_ty_id, | 3236 | .id_result_type = limb_ty_id, |
| 3193 | .id_result = guarded, | 3237 | .id_result = guarded, |
| 3194 | .condition = frac_is_zero, | 3238 | .condition = frac_is_zero, |
| 3195 | .object_1 = zero_id, | 3239 | .object_1 = zero_id, |
| ... | @@ -3199,12 +3243,12 @@ const CompositeInt = struct { | ... | @@ -3199,12 +3243,12 @@ const CompositeInt = struct { |
| 3199 | } else zero_id; | 3243 | } else zero_id; |
| 3200 | | 3244 | |
| 3201 | for (0..ci.n_limbs) |i| { | 3245 | for (0..ci.n_limbs) |i| { |
| 3202 | const i_id = try cg.constInt(.u32, @as(u32, @intCast(i))); | 3246 | const i_id = try cg.constInt(limb_ty, @as(u64, @intCast(i))); |
| 3203 | var main_val = fill_id; | 3247 | var main_val = fill_id; |
| 3204 | var carry_val = arith_carry_init; | 3248 | var carry_val = arith_carry_init; |
| 3205 | | 3249 | |
| 3206 | for (0..ci.n_limbs) |j| { | 3250 | for (0..ci.n_limbs) |j| { |
| 3207 | const j_id = try cg.constInt(.u32, @as(u32, @intCast(j))); | 3251 | const j_id = try cg.constInt(limb_ty, @as(u64, @intCast(j))); |
| 3208 | const i_plus_whole = try ci.limbBinOp(.OpIAdd, i_id, whole); | 3252 | const i_plus_whole = try ci.limbBinOp(.OpIAdd, i_id, whole); |
| 3209 | const is_main = blk: { | 3253 | const is_main = blk: { |
| 3210 | const r = cg.allocId(); | 3254 | const r = cg.allocId(); |
| ... | @@ -3220,7 +3264,7 @@ const CompositeInt = struct { | ... | @@ -3220,7 +3264,7 @@ const CompositeInt = struct { |
| 3220 | main_val = blk: { | 3264 | main_val = blk: { |
| 3221 | const r = cg.allocId(); | 3265 | const r = cg.allocId(); |
| 3222 | try cg.body.emit(gpa, .OpSelect, .{ | 3266 | try cg.body.emit(gpa, .OpSelect, .{ |
| 3223 | .id_result_type = u32_ty_id, | 3267 | .id_result_type = limb_ty_id, |
| 3224 | .id_result = r, | 3268 | .id_result = r, |
| 3225 | .condition = is_main, | 3269 | .condition = is_main, |
| 3226 | .object_1 = shifted, | 3270 | .object_1 = shifted, |
| ... | @@ -3229,7 +3273,7 @@ const CompositeInt = struct { | ... | @@ -3229,7 +3273,7 @@ const CompositeInt = struct { |
| 3229 | break :blk r; | 3273 | break :blk r; |
| 3230 | }; | 3274 | }; |
| 3231 | | 3275 | |
| 3232 | const one_id = try cg.constInt(.u32, @as(u32, 1)); | 3276 | 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); | 3277 | const i_plus_whole_plus_1 = try ci.limbBinOp(.OpIAdd, i_plus_whole, one_id); |
| 3234 | const is_carry = blk: { | 3278 | const is_carry = blk: { |
| 3235 | const r = cg.allocId(); | 3279 | const r = cg.allocId(); |
| ... | @@ -3245,7 +3289,7 @@ const CompositeInt = struct { | ... | @@ -3245,7 +3289,7 @@ const CompositeInt = struct { |
| 3245 | const guarded_carry = blk: { | 3289 | const guarded_carry = blk: { |
| 3246 | const r = cg.allocId(); | 3290 | const r = cg.allocId(); |
| 3247 | try cg.body.emit(gpa, .OpSelect, .{ | 3291 | try cg.body.emit(gpa, .OpSelect, .{ |
| 3248 | .id_result_type = u32_ty_id, | 3292 | .id_result_type = limb_ty_id, |
| 3249 | .id_result = r, | 3293 | .id_result = r, |
| 3250 | .condition = frac_is_zero, | 3294 | .condition = frac_is_zero, |
| 3251 | .object_1 = zero_id, | 3295 | .object_1 = zero_id, |
| ... | @@ -3256,7 +3300,7 @@ const CompositeInt = struct { | ... | @@ -3256,7 +3300,7 @@ const CompositeInt = struct { |
| 3256 | carry_val = blk: { | 3300 | carry_val = blk: { |
| 3257 | const r = cg.allocId(); | 3301 | const r = cg.allocId(); |
| 3258 | try cg.body.emit(gpa, .OpSelect, .{ | 3302 | try cg.body.emit(gpa, .OpSelect, .{ |
| 3259 | .id_result_type = u32_ty_id, | 3303 | .id_result_type = limb_ty_id, |
| 3260 | .id_result = r, | 3304 | .id_result = r, |
| 3261 | .condition = is_carry, | 3305 | .condition = is_carry, |
| 3262 | .object_1 = guarded_carry, | 3306 | .object_1 = guarded_carry, |
| ... | @@ -3284,17 +3328,18 @@ const CompositeInt = struct { | ... | @@ -3284,17 +3328,18 @@ const CompositeInt = struct { |
| 3284 | | 3328 | |
| 3285 | const n: usize = ci.n_limbs; | 3329 | const n: usize = ci.n_limbs; |
| 3286 | const total: usize = if (wide) 2 * n else n; | 3330 | const total: usize = if (wide) 2 * n else n; |
| 3287 | const u32_zig = try pt.intType(.unsigned, 32); | 3331 | const limb_bits = cg.bigIntBits(); |
| 3288 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 3332 | const limb_zig = try pt.intType(.unsigned, limb_bits); |
| | 3333 | const limb_ty_id = try cg.limbTypeId(); |
| 3289 | | 3334 | |
| 3290 | const pair_struct_ty: Type = .fromInterned(try ip.getTupleType(gpa, io, pt.tid, .{ | 3335 | const pair_struct_ty: Type = .fromInterned(try ip.getTupleType(gpa, io, pt.tid, .{ |
| 3291 | .types = &.{ u32_zig.toIntern(), u32_zig.toIntern() }, | 3336 | .types = &.{ limb_zig.toIntern(), limb_zig.toIntern() }, |
| 3292 | .values = &.{ .none, .none }, | 3337 | .values = &.{ .none, .none }, |
| 3293 | })); | 3338 | })); |
| 3294 | const pair_struct_ty_id = try cg.resolveType(pair_struct_ty, .direct); | 3339 | const pair_struct_ty_id = try cg.resolveType(pair_struct_ty, .direct); |
| 3295 | | 3340 | |
| 3296 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, total); | 3341 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, total); |
| 3297 | const zero_id = try cg.constInt(.u32, @as(u32, 0)); | 3342 | const zero_id = try cg.constInt(cg.limbType(), @as(u64, 0)); |
| 3298 | for (result_limbs) |*r| r.* = zero_id; | 3343 | for (result_limbs) |*r| r.* = zero_id; |
| 3299 | | 3344 | |
| 3300 | for (0..n) |i| { | 3345 | for (0..n) |i| { |
| ... | @@ -3309,7 +3354,7 @@ const CompositeInt = struct { | ... | @@ -3309,7 +3354,7 @@ const CompositeInt = struct { |
| 3309 | .opencl => { | 3354 | .opencl => { |
| 3310 | lo = cg.allocId(); | 3355 | lo = cg.allocId(); |
| 3311 | try cg.body.emit(gpa, .OpIMul, .{ | 3356 | try cg.body.emit(gpa, .OpIMul, .{ |
| 3312 | .id_result_type = u32_ty_id, | 3357 | .id_result_type = limb_ty_id, |
| 3313 | .id_result = lo, | 3358 | .id_result = lo, |
| 3314 | .operand_1 = ci.limbs[i], | 3359 | .operand_1 = ci.limbs[i], |
| 3315 | .operand_2 = other.limbs[j], | 3360 | .operand_2 = other.limbs[j], |
| ... | @@ -3318,7 +3363,7 @@ const CompositeInt = struct { | ... | @@ -3318,7 +3363,7 @@ const CompositeInt = struct { |
| 3318 | const set = try cg.importExtendedSet(); | 3363 | const set = try cg.importExtendedSet(); |
| 3319 | hi = cg.allocId(); | 3364 | hi = cg.allocId(); |
| 3320 | try cg.body.emit(gpa, .OpExtInst, .{ | 3365 | try cg.body.emit(gpa, .OpExtInst, .{ |
| 3321 | .id_result_type = u32_ty_id, | 3366 | .id_result_type = limb_ty_id, |
| 3322 | .id_result = hi, | 3367 | .id_result = hi, |
| 3323 | .set = set, | 3368 | .set = set, |
| 3324 | .instruction = .{ .inst = @intFromEnum(spec.OpenClOpcode.u_mul_hi) }, | 3369 | .instruction = .{ .inst = @intFromEnum(spec.OpenClOpcode.u_mul_hi) }, |
| ... | @@ -3336,14 +3381,14 @@ const CompositeInt = struct { | ... | @@ -3336,14 +3381,14 @@ const CompositeInt = struct { |
| 3336 | | 3381 | |
| 3337 | lo = cg.allocId(); | 3382 | lo = cg.allocId(); |
| 3338 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3383 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3339 | .id_result_type = u32_ty_id, | 3384 | .id_result_type = limb_ty_id, |
| 3340 | .id_result = lo, | 3385 | .id_result = lo, |
| 3341 | .composite = mul_result, | 3386 | .composite = mul_result, |
| 3342 | .indexes = &.{0}, | 3387 | .indexes = &.{0}, |
| 3343 | }); | 3388 | }); |
| 3344 | hi = cg.allocId(); | 3389 | hi = cg.allocId(); |
| 3345 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3390 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3346 | .id_result_type = u32_ty_id, | 3391 | .id_result_type = limb_ty_id, |
| 3347 | .id_result = hi, | 3392 | .id_result = hi, |
| 3348 | .composite = mul_result, | 3393 | .composite = mul_result, |
| 3349 | .indexes = &.{1}, | 3394 | .indexes = &.{1}, |
| ... | @@ -3361,14 +3406,14 @@ const CompositeInt = struct { | ... | @@ -3361,14 +3406,14 @@ const CompositeInt = struct { |
| 3361 | | 3406 | |
| 3362 | const sum1 = cg.allocId(); | 3407 | const sum1 = cg.allocId(); |
| 3363 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3408 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3364 | .id_result_type = u32_ty_id, | 3409 | .id_result_type = limb_ty_id, |
| 3365 | .id_result = sum1, | 3410 | .id_result = sum1, |
| 3366 | .composite = add1, | 3411 | .composite = add1, |
| 3367 | .indexes = &.{0}, | 3412 | .indexes = &.{0}, |
| 3368 | }); | 3413 | }); |
| 3369 | const c1 = cg.allocId(); | 3414 | const c1 = cg.allocId(); |
| 3370 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3415 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3371 | .id_result_type = u32_ty_id, | 3416 | .id_result_type = limb_ty_id, |
| 3372 | .id_result = c1, | 3417 | .id_result = c1, |
| 3373 | .composite = add1, | 3418 | .composite = add1, |
| 3374 | .indexes = &.{1}, | 3419 | .indexes = &.{1}, |
| ... | @@ -3384,14 +3429,14 @@ const CompositeInt = struct { | ... | @@ -3384,14 +3429,14 @@ const CompositeInt = struct { |
| 3384 | | 3429 | |
| 3385 | result_limbs[k] = cg.allocId(); | 3430 | result_limbs[k] = cg.allocId(); |
| 3386 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3431 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3387 | .id_result_type = u32_ty_id, | 3432 | .id_result_type = limb_ty_id, |
| 3388 | .id_result = result_limbs[k], | 3433 | .id_result = result_limbs[k], |
| 3389 | .composite = add2, | 3434 | .composite = add2, |
| 3390 | .indexes = &.{0}, | 3435 | .indexes = &.{0}, |
| 3391 | }); | 3436 | }); |
| 3392 | const c2 = cg.allocId(); | 3437 | const c2 = cg.allocId(); |
| 3393 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 3438 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 3394 | .id_result_type = u32_ty_id, | 3439 | .id_result_type = limb_ty_id, |
| 3395 | .id_result = c2, | 3440 | .id_result = c2, |
| 3396 | .composite = add2, | 3441 | .composite = add2, |
| 3397 | .indexes = &.{1}, | 3442 | .indexes = &.{1}, |
| ... | @@ -3412,7 +3457,8 @@ const CompositeInt = struct { | ... | @@ -3412,7 +3457,8 @@ const CompositeInt = struct { |
| 3412 | if (ci.info.bits == ci.info.backing_bits) return ci; | 3457 | if (ci.info.bits == ci.info.backing_bits) return ci; |
| 3413 | const cg = ci.cg; | 3458 | const cg = ci.cg; |
| 3414 | const gpa = cg.gpa; | 3459 | const gpa = cg.gpa; |
| 3415 | const top_bits: u16 = ci.info.bits % big_int_bits; | 3460 | const limb_bits = cg.bigIntBits(); |
| | 3461 | const top_bits: u16 = ci.info.bits % limb_bits; |
| 3416 | assert(top_bits != 0); | 3462 | assert(top_bits != 0); |
| 3417 | | 3463 | |
| 3418 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs); | 3464 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, ci.n_limbs); |
| ... | @@ -3421,41 +3467,43 @@ const CompositeInt = struct { | ... | @@ -3421,41 +3467,43 @@ const CompositeInt = struct { |
| 3421 | } | 3467 | } |
| 3422 | | 3468 | |
| 3423 | const top_limb = ci.limbs[ci.n_limbs - 1]; | 3469 | const top_limb = ci.limbs[ci.n_limbs - 1]; |
| | 3470 | const limb_ty = cg.limbType(); |
| | 3471 | const limb_signed_ty: Type = if (limb_bits == 64) .i64 else .i32; |
| 3424 | switch (ci.info.signedness) { | 3472 | switch (ci.info.signedness) { |
| 3425 | .unsigned => { | 3473 | .unsigned => { |
| 3426 | const mask_val: u32 = (@as(u32, 1) << @as(u5, @intCast(top_bits))) - 1; | 3474 | const mask_val: u64 = (@as(u64, 1) << @as(u6, @intCast(top_bits))) - 1; |
| 3427 | const mask_id = try cg.constInt(.u32, mask_val); | 3475 | 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); | 3476 | result_limbs[ci.n_limbs - 1] = try ci.limbBinOp(.OpBitwiseAnd, top_limb, mask_id); |
| 3429 | }, | 3477 | }, |
| 3430 | .signed => { | 3478 | .signed => { |
| 3431 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 3479 | const limb_ty_id = try cg.limbTypeId(); |
| 3432 | const i32_ty_id = try cg.resolveType(.i32, .direct); | 3480 | const signed_ty_id = try cg.resolveType(limb_signed_ty, .direct); |
| 3433 | const shift_amt: u32 = 32 - top_bits; | 3481 | const shift_amt: u32 = @intCast(limb_bits - top_bits); |
| 3434 | const shift_id = try cg.constInt(.u32, shift_amt); | 3482 | const shift_id = try cg.constInt(limb_ty, shift_amt); |
| 3435 | | 3483 | |
| 3436 | const as_signed = cg.allocId(); | 3484 | const as_signed = cg.allocId(); |
| 3437 | try cg.body.emit(gpa, .OpBitcast, .{ | 3485 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 3438 | .id_result_type = i32_ty_id, | 3486 | .id_result_type = signed_ty_id, |
| 3439 | .id_result = as_signed, | 3487 | .id_result = as_signed, |
| 3440 | .operand = top_limb, | 3488 | .operand = top_limb, |
| 3441 | }); | 3489 | }); |
| 3442 | const shifted_left = cg.allocId(); | 3490 | const shifted_left = cg.allocId(); |
| 3443 | try cg.body.emit(gpa, .OpShiftLeftLogical, .{ | 3491 | try cg.body.emit(gpa, .OpShiftLeftLogical, .{ |
| 3444 | .id_result_type = i32_ty_id, | 3492 | .id_result_type = signed_ty_id, |
| 3445 | .id_result = shifted_left, | 3493 | .id_result = shifted_left, |
| 3446 | .base = as_signed, | 3494 | .base = as_signed, |
| 3447 | .shift = shift_id, | 3495 | .shift = shift_id, |
| 3448 | }); | 3496 | }); |
| 3449 | const shifted_right = cg.allocId(); | 3497 | const shifted_right = cg.allocId(); |
| 3450 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ | 3498 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ |
| 3451 | .id_result_type = i32_ty_id, | 3499 | .id_result_type = signed_ty_id, |
| 3452 | .id_result = shifted_right, | 3500 | .id_result = shifted_right, |
| 3453 | .base = shifted_left, | 3501 | .base = shifted_left, |
| 3454 | .shift = shift_id, | 3502 | .shift = shift_id, |
| 3455 | }); | 3503 | }); |
| 3456 | const back = cg.allocId(); | 3504 | const back = cg.allocId(); |
| 3457 | try cg.body.emit(gpa, .OpBitcast, .{ | 3505 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 3458 | .id_result_type = u32_ty_id, | 3506 | .id_result_type = limb_ty_id, |
| 3459 | .id_result = back, | 3507 | .id_result = back, |
| 3460 | .operand = shifted_right, | 3508 | .operand = shifted_right, |
| 3461 | }); | 3509 | }); |
| ... | @@ -4218,13 +4266,16 @@ const MemoryOptions = struct { | ... | @@ -4218,13 +4266,16 @@ const MemoryOptions = struct { |
| 4218 | fn needsLayout(cg: *CodeGen, as: std.lang.AddressSpace, pointee_ty: Type) bool { | 4266 | fn needsLayout(cg: *CodeGen, as: std.lang.AddressSpace, pointee_ty: Type) bool { |
| 4219 | const target = cg.zcu.getTarget(); | 4267 | const target = cg.zcu.getTarget(); |
| 4220 | if (target.os.tag != .vulkan and target.os.tag != .opengl) return false; | 4268 | if (target.os.tag != .vulkan and target.os.tag != .opengl) return false; |
| 4221 | switch (as) { | 4269 | return switch (as) { |
| 4222 | .uniform, .push_constant, .storage_buffer => {}, | 4270 | .uniform, |
| 4223 | else => return false, | 4271 | .push_constant, |
| 4224 | } | 4272 | .storage_buffer, |
| 4225 | return switch (pointee_ty.zigTypeTag(cg.zcu)) { | 4273 | .physical_storage_buffer, |
| 4226 | .@"struct", .@"union", .array => true, | 4274 | => switch (pointee_ty.zigTypeTag(cg.zcu)) { |
| 4227 | .spirv => pointee_ty.isSpirvRuntimeArray(cg.zcu), | 4275 | .@"struct", .@"union", .array => true, |
| | 4276 | .spirv => pointee_ty.isSpirvRuntimeArray(cg.zcu), |
| | 4277 | else => false, |
| | 4278 | }, |
| 4228 | else => false, | 4279 | else => false, |
| 4229 | }; | 4280 | }; |
| 4230 | } | 4281 | } |
| ... | @@ -4537,10 +4588,6 @@ fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode | ... | @@ -4537,10 +4588,6 @@ fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode |
| 4537 | const zcu = cg.zcu; | 4588 | const zcu = cg.zcu; |
| 4538 | const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 4589 | const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 4539 | | 4590 | |
| 4540 | if (cg.typeOf(bin_op.lhs).isVector(zcu) and !cg.typeOf(bin_op.rhs).isVector(zcu)) { | | |
| 4541 | return cg.fail("vector shift with scalar rhs", .{}); | | |
| 4542 | } | | |
| 4543 | | | |
| 4544 | const base = try cg.temporary(bin_op.lhs); | 4591 | const base = try cg.temporary(bin_op.lhs); |
| 4545 | const shift = try cg.temporary(bin_op.rhs); | 4592 | const shift = try cg.temporary(bin_op.rhs); |
| 4546 | | 4593 | |
| ... | @@ -4550,13 +4597,14 @@ fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode | ... | @@ -4550,13 +4597,14 @@ fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode |
| 4550 | switch (info.class) { | 4597 | switch (info.class) { |
| 4551 | .composite_integer => { | 4598 | .composite_integer => { |
| 4552 | const shift_info = cg.arithmeticTypeInfo(shift.ty); | 4599 | const shift_info = cg.arithmeticTypeInfo(shift.ty); |
| | 4600 | const limb_ty = cg.limbType(); |
| 4553 | const shift_amt_id = switch (shift_info.class) { | 4601 | const shift_amt_id = switch (shift_info.class) { |
| 4554 | .composite_integer => blk: { | 4602 | .composite_integer => blk: { |
| 4555 | const shift_id = try shift.materialize(cg); | 4603 | const shift_id = try shift.materialize(cg); |
| 4556 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 4604 | const limb_ty_id = try cg.limbTypeId(); |
| 4557 | const result_id = cg.allocId(); | 4605 | const result_id = cg.allocId(); |
| 4558 | try cg.body.emit(cg.gpa, .OpCompositeExtract, .{ | 4606 | try cg.body.emit(cg.gpa, .OpCompositeExtract, .{ |
| 4559 | .id_result_type = u32_ty_id, | 4607 | .id_result_type = limb_ty_id, |
| 4560 | .id_result = result_id, | 4608 | .id_result = result_id, |
| 4561 | .composite = shift_id, | 4609 | .composite = shift_id, |
| 4562 | .indexes = &.{@as(u32, 0)}, | 4610 | .indexes = &.{@as(u32, 0)}, |
| ... | @@ -4564,7 +4612,7 @@ fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode | ... | @@ -4564,7 +4612,7 @@ fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode |
| 4564 | break :blk result_id; | 4612 | break :blk result_id; |
| 4565 | }, | 4613 | }, |
| 4566 | else => blk: { | 4614 | else => blk: { |
| 4567 | const converted = try cg.buildConvert(.u32, shift); | 4615 | const converted = try cg.buildConvert(limb_ty, shift); |
| 4568 | break :blk try converted.materialize(cg); | 4616 | break :blk try converted.materialize(cg); |
| 4569 | }, | 4617 | }, |
| 4570 | }; | 4618 | }; |
| ... | @@ -4885,12 +4933,12 @@ fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -4885,12 +4933,12 @@ fn airAbs(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 4885 | const is_neg = try ci.cmp(ci_z, .lt); | 4933 | const is_neg = try ci.cmp(ci_z, .lt); |
| 4886 | const ci_neg = try ci_z.addSub(ci, false); | 4934 | const ci_neg = try ci_z.addSub(ci, false); |
| 4887 | const result_info = cg.arithmeticTypeInfo(result_ty); | 4935 | const result_info = cg.arithmeticTypeInfo(result_ty); |
| 4888 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 4936 | const limb_ty_id = try cg.limbTypeId(); |
| 4889 | const result_limbs = try cg.id_scratch.addManyAsSlice(cg.gpa, ci.n_limbs); | 4937 | const result_limbs = try cg.id_scratch.addManyAsSlice(cg.gpa, ci.n_limbs); |
| 4890 | for (0..ci.n_limbs) |i| { | 4938 | for (0..ci.n_limbs) |i| { |
| 4891 | result_limbs[i] = cg.allocId(); | 4939 | result_limbs[i] = cg.allocId(); |
| 4892 | try cg.body.emit(cg.gpa, .OpSelect, .{ | 4940 | try cg.body.emit(cg.gpa, .OpSelect, .{ |
| 4893 | .id_result_type = u32_ty_id, | 4941 | .id_result_type = limb_ty_id, |
| 4894 | .id_result = result_limbs[i], | 4942 | .id_result = result_limbs[i], |
| 4895 | .condition = is_neg, | 4943 | .condition = is_neg, |
| 4896 | .object_1 = ci_neg.limbs[i], | 4944 | .object_1 = ci_neg.limbs[i], |
| ... | @@ -5064,12 +5112,13 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -5064,12 +5112,13 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 5064 | const high_limbs = wide_limbs[ci_lhs2.n_limbs..]; | 5112 | const high_limbs = wide_limbs[ci_lhs2.n_limbs..]; |
| 5065 | | 5113 | |
| 5066 | const bool_ty_id = try cg.resolveType(.bool, .direct); | 5114 | const bool_ty_id = try cg.resolveType(.bool, .direct); |
| 5067 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 5115 | const limb_ty_id = try cg.limbTypeId(); |
| 5068 | const n: usize = info.backing_bits / big_int_bits; | 5116 | const limb_ty = cg.limbType(); |
| | 5117 | const n: usize = info.backing_bits / cg.bigIntBits(); |
| 5069 | | 5118 | |
| 5070 | const ov_bool = switch (info.signedness) { | 5119 | const ov_bool = switch (info.signedness) { |
| 5071 | .unsigned => blk: { | 5120 | .unsigned => blk: { |
| 5072 | const zero_id = try cg.constInt(.u32, @as(u32, 0)); | 5121 | const zero_id = try cg.constInt(limb_ty, @as(u64, 0)); |
| 5073 | var any_nonzero = cg.allocId(); | 5122 | var any_nonzero = cg.allocId(); |
| 5074 | try cg.body.emit(gpa, .OpINotEqual, .{ | 5123 | try cg.body.emit(gpa, .OpINotEqual, .{ |
| 5075 | .id_result_type = bool_ty_id, | 5124 | .id_result_type = bool_ty_id, |
| ... | @@ -5102,32 +5151,33 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -5102,32 +5151,33 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 5102 | .signed => blk: { | 5151 | .signed => blk: { |
| 5103 | const ci_res = try CompositeInt.init(cg, result_val_id, info); | 5152 | const ci_res = try CompositeInt.init(cg, result_val_id, info); |
| 5104 | const top_limb = ci_res.limbs[n - 1]; | 5153 | const top_limb = ci_res.limbs[n - 1]; |
| 5105 | const i32_ty_id = try cg.resolveType(.i32, .direct); | 5154 | const signed_limb_ty: Type = if (cg.bigIntBits() == 64) .i64 else .i32; |
| | 5155 | const signed_limb_ty_id = try cg.resolveType(signed_limb_ty, .direct); |
| 5106 | | 5156 | |
| 5107 | const top_bits: u16 = if (info.bits % big_int_bits == 0) | 5157 | const top_bits: u16 = if (info.bits % cg.bigIntBits() == 0) |
| 5108 | big_int_bits | 5158 | cg.bigIntBits() |
| 5109 | else | 5159 | else |
| 5110 | info.bits % big_int_bits; | 5160 | info.bits % cg.bigIntBits(); |
| 5111 | | 5161 | |
| 5112 | const shift_amt: u32 = top_bits - 1; | 5162 | const shift_amt: u64 = top_bits - 1; |
| 5113 | const shift_id = try cg.constInt(.u32, shift_amt); | 5163 | const shift_id = try cg.constInt(limb_ty, shift_amt); |
| 5114 | | 5164 | |
| 5115 | const as_signed = cg.allocId(); | 5165 | const as_signed = cg.allocId(); |
| 5116 | try cg.body.emit(gpa, .OpBitcast, .{ | 5166 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 5117 | .id_result_type = i32_ty_id, | 5167 | .id_result_type = signed_limb_ty_id, |
| 5118 | .id_result = as_signed, | 5168 | .id_result = as_signed, |
| 5119 | .operand = top_limb, | 5169 | .operand = top_limb, |
| 5120 | }); | 5170 | }); |
| 5121 | const sign_ext = cg.allocId(); | 5171 | const sign_ext = cg.allocId(); |
| 5122 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ | 5172 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ |
| 5123 | .id_result_type = i32_ty_id, | 5173 | .id_result_type = signed_limb_ty_id, |
| 5124 | .id_result = sign_ext, | 5174 | .id_result = sign_ext, |
| 5125 | .base = as_signed, | 5175 | .base = as_signed, |
| 5126 | .shift = shift_id, | 5176 | .shift = shift_id, |
| 5127 | }); | 5177 | }); |
| 5128 | const expected = cg.allocId(); | 5178 | const expected = cg.allocId(); |
| 5129 | try cg.body.emit(gpa, .OpBitcast, .{ | 5179 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 5130 | .id_result_type = u32_ty_id, | 5180 | .id_result_type = limb_ty_id, |
| 5131 | .id_result = expected, | 5181 | .id_result = expected, |
| 5132 | .operand = sign_ext, | 5182 | .operand = sign_ext, |
| 5133 | }); | 5183 | }); |
| ... | @@ -5160,25 +5210,25 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -5160,25 +5210,25 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 5160 | } | 5210 | } |
| 5161 | | 5211 | |
| 5162 | if (info.bits != info.backing_bits) { | 5212 | if (info.bits != info.backing_bits) { |
| 5163 | const top_bits_s: u16 = info.bits % big_int_bits; | 5213 | const top_bits_s: u16 = info.bits % cg.bigIntBits(); |
| 5164 | const s_shift_id = try cg.constInt(.u32, top_bits_s - 1); | 5214 | const s_shift_id = try cg.constInt(limb_ty, @as(u64, top_bits_s - 1)); |
| 5165 | | 5215 | |
| 5166 | const top_as_signed = cg.allocId(); | 5216 | const top_as_signed = cg.allocId(); |
| 5167 | try cg.body.emit(gpa, .OpBitcast, .{ | 5217 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 5168 | .id_result_type = i32_ty_id, | 5218 | .id_result_type = signed_limb_ty_id, |
| 5169 | .id_result = top_as_signed, | 5219 | .id_result = top_as_signed, |
| 5170 | .operand = top_limb, | 5220 | .operand = top_limb, |
| 5171 | }); | 5221 | }); |
| 5172 | const top_sign_ext = cg.allocId(); | 5222 | const top_sign_ext = cg.allocId(); |
| 5173 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ | 5223 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ |
| 5174 | .id_result_type = i32_ty_id, | 5224 | .id_result_type = signed_limb_ty_id, |
| 5175 | .id_result = top_sign_ext, | 5225 | .id_result = top_sign_ext, |
| 5176 | .base = top_as_signed, | 5226 | .base = top_as_signed, |
| 5177 | .shift = s_shift_id, | 5227 | .shift = s_shift_id, |
| 5178 | }); | 5228 | }); |
| 5179 | const top_expected = cg.allocId(); | 5229 | const top_expected = cg.allocId(); |
| 5180 | try cg.body.emit(gpa, .OpBitcast, .{ | 5230 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 5181 | .id_result_type = u32_ty_id, | 5231 | .id_result_type = limb_ty_id, |
| 5182 | .id_result = top_expected, | 5232 | .id_result = top_expected, |
| 5183 | .operand = top_sign_ext, | 5233 | .operand = top_sign_ext, |
| 5184 | }); | 5234 | }); |
| ... | @@ -5219,7 +5269,7 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -5219,7 +5269,7 @@ fn airMulOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 5219 | // of the result too. | 5269 | // of the result too. |
| 5220 | | 5270 | |
| 5221 | const target = cg.zcu.getTarget(); | 5271 | const target = cg.zcu.getTarget(); |
| 5222 | const largest_int_bits: u16 = if (target.cpu.has(.spirv, .int64) or target.cpu.arch == .spirv64) 64 else 32; | 5272 | const largest_int_bits: u16 = if (hasInt64(target)) 64 else 32; |
| 5223 | // If non-null, the number of bits that the multiplication should be performed in. If | 5273 | // If non-null, the number of bits that the multiplication should be performed in. If |
| 5224 | // null, we have to use wide multiplication. | 5274 | // null, we have to use wide multiplication. |
| 5225 | const maybe_op_ty_bits: ?u16 = switch (info.bits) { | 5275 | const maybe_op_ty_bits: ?u16 = switch (info.bits) { |
| ... | @@ -5368,10 +5418,6 @@ fn airShlOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -5368,10 +5418,6 @@ fn airShlOverflow(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 5368 | const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 5418 | const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 5369 | const extra = cg.air.extraData(Air.Bin, ty_pl.payload).data; | 5419 | const extra = cg.air.extraData(Air.Bin, ty_pl.payload).data; |
| 5370 | | 5420 | |
| 5371 | if (cg.typeOf(extra.lhs).isVector(zcu) and !cg.typeOf(extra.rhs).isVector(zcu)) { | | |
| 5372 | return cg.fail("vector shift with scalar rhs", .{}); | | |
| 5373 | } | | |
| 5374 | | | |
| 5375 | const base = try cg.temporary(extra.lhs); | 5421 | const base = try cg.temporary(extra.lhs); |
| 5376 | const shift = try cg.temporary(extra.rhs); | 5422 | const shift = try cg.temporary(extra.rhs); |
| 5377 | | 5423 | |
| ... | @@ -5964,7 +6010,27 @@ fn bitCast( | ... | @@ -5964,7 +6010,27 @@ fn bitCast( |
| 5964 | | 6010 | |
| 5965 | if (src_ty.toIntern() == dst_ty.toIntern()) return src_id; | 6011 | if (src_ty.toIntern() == dst_ty.toIntern()) return src_id; |
| 5966 | if (src_ty.isPtrAtRuntime(zcu) and dst_ty.isPtrAtRuntime(zcu)) switch (target.os.tag) { | 6012 | if (src_ty.isPtrAtRuntime(zcu) and dst_ty.isPtrAtRuntime(zcu)) switch (target.os.tag) { |
| 5967 | .vulkan, .opengl => if (src_ty.ptrAddressSpace(zcu) != .physical_storage_buffer) return src_id, | 6013 | .vulkan, .opengl => if (src_ty.ptrAddressSpace(zcu) != .physical_storage_buffer) { |
| | 6014 | const src_child = src_ty.childType(zcu); |
| | 6015 | const dst_child = dst_ty.childType(zcu); |
| | 6016 | if (!dst_child.hasRuntimeBits(zcu)) return src_id; |
| | 6017 | if (src_child.toIntern() == dst_child.toIntern()) return src_id; |
| | 6018 | if (src_ty.ptrInfo(zcu).packed_offset.host_size != 0 or |
| | 6019 | dst_ty.ptrInfo(zcu).packed_offset.host_size != 0) return src_id; |
| | 6020 | |
| | 6021 | var indices: std.ArrayList(u32) = .empty; |
| | 6022 | defer indices.deinit(gpa); |
| | 6023 | var cur = src_child; |
| | 6024 | while (cur.toIntern() != dst_child.toIntern()) : (try indices.append(gpa, 0)) { |
| | 6025 | cur = switch (cur.zigTypeTag(zcu)) { |
| | 6026 | .array, .vector => cur.childType(zcu), |
| | 6027 | .@"struct" => cur.fieldType(0, zcu), |
| | 6028 | else => unreachable, |
| | 6029 | }; |
| | 6030 | } |
| | 6031 | const dst_ty_id = try cg.resolveType(dst_ty, .direct); |
| | 6032 | return try cg.accessChain(dst_ty_id, src_id, indices.items); |
| | 6033 | }, |
| 5968 | else => {}, | 6034 | else => {}, |
| 5969 | }; | 6035 | }; |
| 5970 | | 6036 | |
| ... | @@ -6095,15 +6161,17 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -6095,15 +6161,17 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 6095 | | 6161 | |
| 6096 | if (src_composite and dst_composite) { | 6162 | if (src_composite and dst_composite) { |
| 6097 | const src_id = try src.materialize(cg); | 6163 | const src_id = try src.materialize(cg); |
| 6098 | const src_n: u16 = src_info.backing_bits / big_int_bits; | 6164 | const limb_bits = cg.bigIntBits(); |
| 6099 | const dst_n: u16 = dst_info.backing_bits / big_int_bits; | 6165 | const limb_ty = cg.limbType(); |
| | 6166 | const limb_ty_id = try cg.limbTypeId(); |
| | 6167 | const src_n: u16 = src_info.backing_bits / limb_bits; |
| | 6168 | const dst_n: u16 = dst_info.backing_bits / limb_bits; |
| 6100 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, dst_n); | 6169 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, dst_n); |
| 6101 | const min_n = @min(src_n, dst_n); | 6170 | const min_n = @min(src_n, dst_n); |
| 6102 | const u32_ty_id = try cg.resolveType(.u32, .direct); | | |
| 6103 | for (0..min_n) |i| { | 6171 | for (0..min_n) |i| { |
| 6104 | result_limbs[i] = cg.allocId(); | 6172 | result_limbs[i] = cg.allocId(); |
| 6105 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 6173 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 6106 | .id_result_type = u32_ty_id, | 6174 | .id_result_type = limb_ty_id, |
| 6107 | .id_result = result_limbs[i], | 6175 | .id_result = result_limbs[i], |
| 6108 | .composite = src_id, | 6176 | .composite = src_id, |
| 6109 | .indexes = &.{@as(u32, @intCast(i))}, | 6177 | .indexes = &.{@as(u32, @intCast(i))}, |
| ... | @@ -6111,30 +6179,31 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -6111,30 +6179,31 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 6111 | } | 6179 | } |
| 6112 | if (dst_n > src_n) { | 6180 | if (dst_n > src_n) { |
| 6113 | const fill = if (src_info.signedness == .signed) blk: { | 6181 | const fill = if (src_info.signedness == .signed) blk: { |
| 6114 | const i32_ty_id = try cg.resolveType(.i32, .direct); | 6182 | const signed_limb_ty: Type = if (limb_bits == 64) .i64 else .i32; |
| | 6183 | const signed_limb_ty_id = try cg.resolveType(signed_limb_ty, .direct); |
| 6115 | const msb = result_limbs[src_n - 1]; | 6184 | const msb = result_limbs[src_n - 1]; |
| 6116 | const msb_signed = cg.allocId(); | 6185 | const msb_signed = cg.allocId(); |
| 6117 | try cg.body.emit(gpa, .OpBitcast, .{ | 6186 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 6118 | .id_result_type = i32_ty_id, | 6187 | .id_result_type = signed_limb_ty_id, |
| 6119 | .id_result = msb_signed, | 6188 | .id_result = msb_signed, |
| 6120 | .operand = msb, | 6189 | .operand = msb, |
| 6121 | }); | 6190 | }); |
| 6122 | const shift31 = try cg.constInt(.i32, @as(i32, 31)); | 6191 | const shift_amt = try cg.constInt(signed_limb_ty, @as(u64, limb_bits - 1)); |
| 6123 | const sign_ext = cg.allocId(); | 6192 | const sign_ext = cg.allocId(); |
| 6124 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ | 6193 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ |
| 6125 | .id_result_type = i32_ty_id, | 6194 | .id_result_type = signed_limb_ty_id, |
| 6126 | .id_result = sign_ext, | 6195 | .id_result = sign_ext, |
| 6127 | .base = msb_signed, | 6196 | .base = msb_signed, |
| 6128 | .shift = shift31, | 6197 | .shift = shift_amt, |
| 6129 | }); | 6198 | }); |
| 6130 | const back = cg.allocId(); | 6199 | const back = cg.allocId(); |
| 6131 | try cg.body.emit(gpa, .OpBitcast, .{ | 6200 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 6132 | .id_result_type = u32_ty_id, | 6201 | .id_result_type = limb_ty_id, |
| 6133 | .id_result = back, | 6202 | .id_result = back, |
| 6134 | .operand = sign_ext, | 6203 | .operand = sign_ext, |
| 6135 | }); | 6204 | }); |
| 6136 | break :blk back; | 6205 | break :blk back; |
| 6137 | } else try cg.constInt(.u32, @as(u32, 0)); | 6206 | } else try cg.constInt(limb_ty, @as(u64, 0)); |
| 6138 | for (min_n..dst_n) |i| { | 6207 | for (min_n..dst_n) |i| { |
| 6139 | result_limbs[i] = fill; | 6208 | result_limbs[i] = fill; |
| 6140 | } | 6209 | } |
| ... | @@ -6144,16 +6213,18 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -6144,16 +6213,18 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 6144 | return try normalized.materialize(dst_ty); | 6213 | return try normalized.materialize(dst_ty); |
| 6145 | } else if (src_composite and !dst_composite) { | 6214 | } else if (src_composite and !dst_composite) { |
| 6146 | const src_id = try src.materialize(cg); | 6215 | const src_id = try src.materialize(cg); |
| 6147 | const u32_ty_id = try cg.resolveType(.u32, .direct); | 6216 | const limb_bits = cg.bigIntBits(); |
| 6148 | if (dst_info.backing_bits <= 32) { | 6217 | const limb_ty = cg.limbType(); |
| | 6218 | const limb_ty_id = try cg.limbTypeId(); |
| | 6219 | if (dst_info.backing_bits <= limb_bits) { |
| 6149 | const limb0 = cg.allocId(); | 6220 | const limb0 = cg.allocId(); |
| 6150 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 6221 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 6151 | .id_result_type = u32_ty_id, | 6222 | .id_result_type = limb_ty_id, |
| 6152 | .id_result = limb0, | 6223 | .id_result = limb0, |
| 6153 | .composite = src_id, | 6224 | .composite = src_id, |
| 6154 | .indexes = &.{@as(u32, 0)}, | 6225 | .indexes = &.{@as(u32, 0)}, |
| 6155 | }); | 6226 | }); |
| 6156 | const tmp: Temporary = .init(.u32, limb0); | 6227 | const tmp: Temporary = .init(limb_ty, limb0); |
| 6157 | const converted = try cg.buildConvert(dst_ty, tmp); | 6228 | const converted = try cg.buildConvert(dst_ty, tmp); |
| 6158 | const result = if (dst_info.bits < src_info.bits) | 6229 | const result = if (dst_info.bits < src_info.bits) |
| 6159 | try cg.normalize(converted, dst_info) | 6230 | try cg.normalize(converted, dst_info) |
| ... | @@ -6161,16 +6232,17 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -6161,16 +6232,17 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 6161 | converted; | 6232 | converted; |
| 6162 | return try result.materialize(cg); | 6233 | return try result.materialize(cg); |
| 6163 | } else { | 6234 | } else { |
| | 6235 | assert(limb_bits == 32); // dst > 64 while limbs are 64 shouldn't happen — dst fits in one 64-bit limb. |
| 6164 | const limb0 = cg.allocId(); | 6236 | const limb0 = cg.allocId(); |
| 6165 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 6237 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 6166 | .id_result_type = u32_ty_id, | 6238 | .id_result_type = limb_ty_id, |
| 6167 | .id_result = limb0, | 6239 | .id_result = limb0, |
| 6168 | .composite = src_id, | 6240 | .composite = src_id, |
| 6169 | .indexes = &.{@as(u32, 0)}, | 6241 | .indexes = &.{@as(u32, 0)}, |
| 6170 | }); | 6242 | }); |
| 6171 | const limb1 = cg.allocId(); | 6243 | const limb1 = cg.allocId(); |
| 6172 | try cg.body.emit(gpa, .OpCompositeExtract, .{ | 6244 | try cg.body.emit(gpa, .OpCompositeExtract, .{ |
| 6173 | .id_result_type = u32_ty_id, | 6245 | .id_result_type = limb_ty_id, |
| 6174 | .id_result = limb1, | 6246 | .id_result = limb1, |
| 6175 | .composite = src_id, | 6247 | .composite = src_id, |
| 6176 | .indexes = &.{@as(u32, 1)}, | 6248 | .indexes = &.{@as(u32, 1)}, |
| ... | @@ -6212,19 +6284,21 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -6212,19 +6284,21 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 6212 | return try result.materialize(cg); | 6284 | return try result.materialize(cg); |
| 6213 | } | 6285 | } |
| 6214 | } else { | 6286 | } else { |
| 6215 | const dst_n: u16 = dst_info.backing_bits / big_int_bits; | 6287 | const limb_bits = cg.bigIntBits(); |
| | 6288 | const limb_ty = cg.limbType(); |
| | 6289 | const limb_ty_id = try cg.limbTypeId(); |
| | 6290 | const dst_n: u16 = dst_info.backing_bits / limb_bits; |
| 6216 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, dst_n); | 6291 | const result_limbs = try cg.id_scratch.addManyAsSlice(gpa, dst_n); |
| 6217 | const u32_ty_id = try cg.resolveType(.u32, .direct); | | |
| 6218 | | 6292 | |
| 6219 | if (src_info.backing_bits <= 32) { | 6293 | if (src_info.backing_bits <= limb_bits) { |
| 6220 | const converted = try cg.buildConvert(.u32, src); | 6294 | const converted = try cg.buildConvert(limb_ty, src); |
| 6221 | result_limbs[0] = try converted.materialize(cg); | 6295 | result_limbs[0] = try converted.materialize(cg); |
| 6222 | } else { | 6296 | } else { |
| 6223 | const src_as_u64 = try cg.buildConvert(.u64, src); | 6297 | const src_as_u64 = try cg.buildConvert(.u64, src); |
| 6224 | const src_id = try src_as_u64.materialize(cg); | 6298 | const src_id = try src_as_u64.materialize(cg); |
| 6225 | result_limbs[0] = cg.allocId(); | 6299 | result_limbs[0] = cg.allocId(); |
| 6226 | try cg.body.emit(gpa, .OpUConvert, .{ | 6300 | try cg.body.emit(gpa, .OpUConvert, .{ |
| 6227 | .id_result_type = u32_ty_id, | 6301 | .id_result_type = limb_ty_id, |
| 6228 | .id_result = result_limbs[0], | 6302 | .id_result = result_limbs[0], |
| 6229 | .unsigned_value = src_id, | 6303 | .unsigned_value = src_id, |
| 6230 | }); | 6304 | }); |
| ... | @@ -6239,38 +6313,39 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -6239,38 +6313,39 @@ fn airIntCast(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 6239 | }); | 6313 | }); |
| 6240 | result_limbs[1] = cg.allocId(); | 6314 | result_limbs[1] = cg.allocId(); |
| 6241 | try cg.body.emit(gpa, .OpUConvert, .{ | 6315 | try cg.body.emit(gpa, .OpUConvert, .{ |
| 6242 | .id_result_type = u32_ty_id, | 6316 | .id_result_type = limb_ty_id, |
| 6243 | .id_result = result_limbs[1], | 6317 | .id_result = result_limbs[1], |
| 6244 | .unsigned_value = hi, | 6318 | .unsigned_value = hi, |
| 6245 | }); | 6319 | }); |
| 6246 | } | 6320 | } |
| 6247 | // Sign/zero-extend remaining limbs. | 6321 | // Sign/zero-extend remaining limbs. |
| 6248 | const fill_start: u16 = if (src_info.backing_bits <= 32) 1 else 2; | 6322 | const fill_start: u16 = if (src_info.backing_bits <= limb_bits) 1 else 2; |
| 6249 | const fill = if (src_info.signedness == .signed) blk: { | 6323 | const fill = if (src_info.signedness == .signed) blk: { |
| 6250 | const i32_ty_id = try cg.resolveType(.i32, .direct); | 6324 | const signed_limb_ty: Type = if (limb_bits == 64) .i64 else .i32; |
| | 6325 | const signed_limb_ty_id = try cg.resolveType(signed_limb_ty, .direct); |
| 6251 | const msb = result_limbs[fill_start - 1]; | 6326 | const msb = result_limbs[fill_start - 1]; |
| 6252 | const msb_signed = cg.allocId(); | 6327 | const msb_signed = cg.allocId(); |
| 6253 | try cg.body.emit(gpa, .OpBitcast, .{ | 6328 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 6254 | .id_result_type = i32_ty_id, | 6329 | .id_result_type = signed_limb_ty_id, |
| 6255 | .id_result = msb_signed, | 6330 | .id_result = msb_signed, |
| 6256 | .operand = msb, | 6331 | .operand = msb, |
| 6257 | }); | 6332 | }); |
| 6258 | const shift31 = try cg.constInt(.i32, @as(i32, 31)); | 6333 | const shift_amt = try cg.constInt(signed_limb_ty, @as(u64, limb_bits - 1)); |
| 6259 | const sign_ext = cg.allocId(); | 6334 | const sign_ext = cg.allocId(); |
| 6260 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ | 6335 | try cg.body.emit(gpa, .OpShiftRightArithmetic, .{ |
| 6261 | .id_result_type = i32_ty_id, | 6336 | .id_result_type = signed_limb_ty_id, |
| 6262 | .id_result = sign_ext, | 6337 | .id_result = sign_ext, |
| 6263 | .base = msb_signed, | 6338 | .base = msb_signed, |
| 6264 | .shift = shift31, | 6339 | .shift = shift_amt, |
| 6265 | }); | 6340 | }); |
| 6266 | const back = cg.allocId(); | 6341 | const back = cg.allocId(); |
| 6267 | try cg.body.emit(gpa, .OpBitcast, .{ | 6342 | try cg.body.emit(gpa, .OpBitcast, .{ |
| 6268 | .id_result_type = u32_ty_id, | 6343 | .id_result_type = limb_ty_id, |
| 6269 | .id_result = back, | 6344 | .id_result = back, |
| 6270 | .operand = sign_ext, | 6345 | .operand = sign_ext, |
| 6271 | }); | 6346 | }); |
| 6272 | break :blk back; | 6347 | break :blk back; |
| 6273 | } else try cg.constInt(.u32, @as(u32, 0)); | 6348 | } else try cg.constInt(limb_ty, @as(u64, 0)); |
| 6274 | for (fill_start..dst_n) |i| { | 6349 | for (fill_start..dst_n) |i| { |
| 6275 | result_limbs[i] = fill; | 6350 | result_limbs[i] = fill; |
| 6276 | } | 6351 | } |
| ... | @@ -8632,37 +8707,68 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -8632,37 +8707,68 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 8632 | const input_ty = cg.typeOf(in.operand); | 8707 | const input_ty = cg.typeOf(in.operand); |
| 8633 | | 8708 | |
| 8634 | if (std.mem.eql(u8, in.constraint, "c")) { | 8709 | if (std.mem.eql(u8, in.constraint, "c")) { |
| 8635 | // constant | 8710 | const val: Value = .fromInterned(in.operand.toInterned().?); |
| 8636 | const val: Value = .fromInterned(in.operand.toInterned() orelse { | | |
| 8637 | return cg.fail("assembly inputs with 'c' constraint have to be compile-time known", .{}); | | |
| 8638 | }); | | |
| 8639 | | | |
| 8640 | const ip = &zcu.intern_pool; | 8711 | const ip = &zcu.intern_pool; |
| 8641 | switch (ip.indexToKey(val.toIntern())) { | 8712 | const target = cg.pt.zcu.getTarget(); |
| 8642 | .int_type, | 8713 | switch (input_ty.zigTypeTag(zcu)) { |
| 8643 | .ptr_type, | 8714 | .int => { |
| 8644 | .array_type, | 8715 | const bits: u64 = switch (input_ty.intInfo(zcu).signedness) { |
| 8645 | .vector_type, | 8716 | .unsigned => val.toUnsignedInt(zcu), |
| 8646 | .opt_type, | 8717 | .signed => @bitCast(val.toSignedInt(zcu)), |
| 8647 | .anyframe_type, | 8718 | }; |
| 8648 | .error_union_type, | 8719 | try ass.value_map.put(gpa, in.name, .{ .constant = bits }); |
| 8649 | .simple_type, | 8720 | }, |
| 8650 | .struct_type, | 8721 | .float => { |
| 8651 | .union_type, | 8722 | const bits: u64 = switch (input_ty.floatBits(target)) { |
| 8652 | .opaque_type, | 8723 | 16 => @as(u16, @bitCast(val.toFloat(f16, zcu))), |
| 8653 | .spirv_type, | 8724 | 32 => @as(u32, @bitCast(val.toFloat(f32, zcu))), |
| 8654 | .enum_type, | 8725 | 64 => @bitCast(val.toFloat(f64, zcu)), |
| 8655 | .func_type, | 8726 | else => unreachable, // Sema rejects unsupported float widths. |
| 8656 | .error_set_type, | 8727 | }; |
| 8657 | .inferred_error_set_type, | 8728 | try ass.value_map.put(gpa, in.name, .{ .constant = bits }); |
| 8658 | => unreachable, // types, not values | 8729 | }, |
| 8659 | | 8730 | .vector => { |
| 8660 | .undef => return cg.fail("assembly input with 'c' constraint cannot be undefined", .{}), | 8731 | const child_ty = input_ty.childType(zcu); |
| 8661 | | 8732 | const child_kind = child_ty.zigTypeTag(zcu); |
| 8662 | .int => try ass.value_map.put(gpa, in.name, .{ .constant = @intCast(val.toUnsignedInt(zcu)) }), | 8733 | const child_bit_width: u16 = switch (child_kind) { |
| 8663 | .enum_literal => |str| try ass.value_map.put(gpa, in.name, .{ .string = str.toSlice(ip) }), | 8734 | .bool => 0, |
| 8664 | | 8735 | .int => @intCast(child_ty.intInfo(zcu).bits), |
| 8665 | else => unreachable, // TODO | 8736 | .float => child_ty.floatBits(target), |
| | 8737 | else => unreachable, // Sema rejects unsupported vector element types. |
| | 8738 | }; |
| | 8739 | const vec_len: usize = @intCast(input_ty.vectorLen(zcu)); |
| | 8740 | const values = try gpa.alloc(u64, vec_len); |
| | 8741 | errdefer gpa.free(values); |
| | 8742 | for (values, 0..) |*out, i| { |
| | 8743 | const elem: Value = try val.elemValue(cg.pt, i); |
| | 8744 | out.* = switch (child_kind) { |
| | 8745 | .bool => @intFromBool(elem.toBool()), |
| | 8746 | .int => switch (child_ty.intInfo(zcu).signedness) { |
| | 8747 | .unsigned => elem.toUnsignedInt(zcu), |
| | 8748 | .signed => @bitCast(elem.toSignedInt(zcu)), |
| | 8749 | }, |
| | 8750 | .float => switch (child_bit_width) { |
| | 8751 | 16 => @as(u16, @bitCast(elem.toFloat(f16, zcu))), |
| | 8752 | 32 => @as(u32, @bitCast(elem.toFloat(f32, zcu))), |
| | 8753 | 64 => @bitCast(elem.toFloat(f64, zcu)), |
| | 8754 | else => unreachable, |
| | 8755 | }, |
| | 8756 | else => unreachable, |
| | 8757 | }; |
| | 8758 | } |
| | 8759 | const child_ty_id = try cg.resolveType(child_ty, .direct); |
| | 8760 | try ass.value_map.put(gpa, in.name, .{ .constant_composite = .{ |
| | 8761 | .child = child_ty_id, |
| | 8762 | .child_kind = child_kind, |
| | 8763 | .child_bit_width = child_bit_width, |
| | 8764 | .values = values, |
| | 8765 | } }); |
| | 8766 | }, |
| | 8767 | .@"enum" => switch (ip.indexToKey(val.toIntern())) { |
| | 8768 | .enum_literal => |str| try ass.value_map.put(gpa, in.name, .{ .string = str.toSlice(ip) }), |
| | 8769 | else => unreachable, |
| | 8770 | }, |
| | 8771 | else => unreachable, // Sema rejects unsupported types. |
| 8666 | } | 8772 | } |
| 8667 | } else if (std.mem.eql(u8, in.constraint, "t")) { | 8773 | } else if (std.mem.eql(u8, in.constraint, "t")) { |
| 8668 | // type | 8774 | // type |
| ... | @@ -8729,7 +8835,7 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id { | ... | @@ -8729,7 +8835,7 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id { |
| 8729 | .just_declared, .unresolved_forward_reference => unreachable, | 8835 | .just_declared, .unresolved_forward_reference => unreachable, |
| 8730 | .ty => return cg.fail("cannot return spir-v type as value from assembly", .{}), | 8836 | .ty => return cg.fail("cannot return spir-v type as value from assembly", .{}), |
| 8731 | .value => |ref| return ref, | 8837 | .value => |ref| return ref, |
| 8732 | .constant, .string => return cg.fail("cannot return constant from assembly", .{}), | 8838 | .constant, .constant_composite, .string => return cg.fail("cannot return constant from assembly", .{}), |
| 8733 | } | 8839 | } |
| 8734 | // TODO: Multiple results | 8840 | // TODO: Multiple results |
| 8735 | // TODO: Check that the output type from assembly is the same as the type actually expected by Zig. | 8841 | // TODO: Check that the output type from assembly is the same as the type actually expected by Zig. |
| ... | @@ -8749,8 +8855,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier) | ... | @@ -8749,8 +8855,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier) |
| 8749 | const callee_ty = cg.typeOf(air_call.callee); | 8855 | const callee_ty = cg.typeOf(air_call.callee); |
| 8750 | const zig_fn_ty = switch (callee_ty.zigTypeTag(zcu)) { | 8856 | const zig_fn_ty = switch (callee_ty.zigTypeTag(zcu)) { |
| 8751 | .@"fn" => callee_ty, | 8857 | .@"fn" => callee_ty, |
| 8752 | .pointer => return cg.fail("cannot call function pointers", .{}), | 8858 | else => unreachable, // rejected by Sema for SPIR-V |
| 8753 | else => unreachable, | | |
| 8754 | }; | 8859 | }; |
| 8755 | const fn_info = zcu.typeToFunc(zig_fn_ty).?; | 8860 | const fn_info = zcu.typeToFunc(zig_fn_ty).?; |
| 8756 | const return_type = fn_info.return_type; | 8861 | const return_type = fn_info.return_type; |