| ... | @@ -408,7 +408,7 @@ pub const DeclGen = struct { | ... | @@ -408,7 +408,7 @@ pub const DeclGen = struct { |
| 408 | switch (repr) { | 408 | switch (repr) { |
| 409 | .indirect => { | 409 | .indirect => { |
| 410 | const int_ty_ref = try self.intType(.unsigned, 1); | 410 | const int_ty_ref = try self.intType(.unsigned, 1); |
| 411 | return self.spv.constInt(int_ty_ref, @intFromBool(value)); | 411 | return self.constInt(int_ty_ref, @intFromBool(value)); |
| 412 | }, | 412 | }, |
| 413 | .direct => { | 413 | .direct => { |
| 414 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); | 414 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); |
| ... | @@ -417,6 +417,25 @@ pub const DeclGen = struct { | ... | @@ -417,6 +417,25 @@ pub const DeclGen = struct { |
| 417 | } | 417 | } |
| 418 | } | 418 | } |
| 419 | | 419 | |
| | 420 | /// Emits an integer constant. |
| | 421 | /// This function, unlike SpvModule.constInt, takes care to bitcast |
| | 422 | /// the value to an unsigned int first for Kernels. |
| | 423 | fn constInt(self: *DeclGen, ty_ref: CacheRef, value: anytype) !IdRef { |
| | 424 | if (value < 0) { |
| | 425 | const ty = self.spv.cache.lookup(ty_ref).int_type; |
| | 426 | // Manually truncate the value so that the resulting value |
| | 427 | // fits within the unsigned type. |
| | 428 | const bits: u64 = @bitCast(@as(i64, @intCast(value))); |
| | 429 | const truncated_bits = if (ty.bits == 64) |
| | 430 | bits |
| | 431 | else |
| | 432 | bits & (@as(u64, 1) << @intCast(ty.bits)) - 1; |
| | 433 | return try self.spv.constInt(ty_ref, truncated_bits); |
| | 434 | } else { |
| | 435 | return try self.spv.constInt(ty_ref, value); |
| | 436 | } |
| | 437 | } |
| | 438 | |
| 420 | /// Construct a struct at runtime. | 439 | /// Construct a struct at runtime. |
| 421 | /// result_ty_ref must be a struct type. | 440 | /// result_ty_ref must be a struct type. |
| 422 | fn constructStruct(self: *DeclGen, result_ty_ref: CacheRef, constituents: []const IdRef) !IdRef { | 441 | fn constructStruct(self: *DeclGen, result_ty_ref: CacheRef, constituents: []const IdRef) !IdRef { |
| ... | @@ -434,7 +453,7 @@ pub const DeclGen = struct { | ... | @@ -434,7 +453,7 @@ pub const DeclGen = struct { |
| 434 | const member_types = spv_composite_ty.member_types; | 453 | const member_types = spv_composite_ty.member_types; |
| 435 | | 454 | |
| 436 | for (constituents, member_types, 0..) |constitent_id, member_ty_ref, index| { | 455 | for (constituents, member_types, 0..) |constitent_id, member_ty_ref, index| { |
| 437 | const index_id = try self.spv.constInt(index_ty_ref, index); | 456 | const index_id = try self.constInt(index_ty_ref, index); |
| 438 | const ptr_member_ty_ref = try self.spv.ptrType(member_ty_ref, .Generic); | 457 | const ptr_member_ty_ref = try self.spv.ptrType(member_ty_ref, .Generic); |
| 439 | const ptr_id = try self.accessChain(ptr_member_ty_ref, ptr_composite_id, &.{index_id}); | 458 | const ptr_id = try self.accessChain(ptr_member_ty_ref, ptr_composite_id, &.{index_id}); |
| 440 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ | 459 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ |
| ... | @@ -469,7 +488,7 @@ pub const DeclGen = struct { | ... | @@ -469,7 +488,7 @@ pub const DeclGen = struct { |
| 469 | const ptr_elem_ty_ref = try self.spv.ptrType(elem_ty_ref, .Generic); | 488 | const ptr_elem_ty_ref = try self.spv.ptrType(elem_ty_ref, .Generic); |
| 470 | | 489 | |
| 471 | for (constituents, 0..) |constitent_id, index| { | 490 | for (constituents, 0..) |constitent_id, index| { |
| 472 | const index_id = try self.spv.constInt(index_ty_ref, index); | 491 | const index_id = try self.constInt(index_ty_ref, index); |
| 473 | const ptr_id = try self.accessChain(ptr_elem_ty_ref, ptr_composite_id, &.{index_id}); | 492 | const ptr_id = try self.accessChain(ptr_elem_ty_ref, ptr_composite_id, &.{index_id}); |
| 474 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ | 493 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ |
| 475 | .pointer = ptr_id, | 494 | .pointer = ptr_id, |
| ... | @@ -580,17 +599,14 @@ pub const DeclGen = struct { | ... | @@ -580,17 +599,14 @@ pub const DeclGen = struct { |
| 580 | .generic_poison, | 599 | .generic_poison, |
| 581 | => unreachable, // non-runtime values | 600 | => unreachable, // non-runtime values |
| 582 | | 601 | |
| 583 | .false, .true => switch (repr) { | 602 | .false, .true => return try self.constBool(val.toBool(), repr), |
| 584 | .direct => return try self.spv.constBool(result_ty_ref, val.toBool()), | | |
| 585 | .indirect => return try self.spv.constInt(result_ty_ref, @intFromBool(val.toBool())), | | |
| 586 | }, | | |
| 587 | }, | 603 | }, |
| 588 | | 604 | |
| 589 | .int => { | 605 | .int => { |
| 590 | if (ty.isSignedInt(mod)) { | 606 | if (ty.isSignedInt(mod)) { |
| 591 | return try self.spv.constInt(result_ty_ref, val.toSignedInt(mod)); | 607 | return try self.constInt(result_ty_ref, val.toSignedInt(mod)); |
| 592 | } else { | 608 | } else { |
| 593 | return try self.spv.constInt(result_ty_ref, val.toUnsignedInt(mod)); | 609 | return try self.constInt(result_ty_ref, val.toUnsignedInt(mod)); |
| 594 | } | 610 | } |
| 595 | }, | 611 | }, |
| 596 | .float => return switch (ty.floatBits(target)) { | 612 | .float => return switch (ty.floatBits(target)) { |
| ... | @@ -602,7 +618,7 @@ pub const DeclGen = struct { | ... | @@ -602,7 +618,7 @@ pub const DeclGen = struct { |
| 602 | }, | 618 | }, |
| 603 | .err => |err| { | 619 | .err => |err| { |
| 604 | const value = try mod.getErrorValue(err.name); | 620 | const value = try mod.getErrorValue(err.name); |
| 605 | return try self.spv.constInt(result_ty_ref, value); | 621 | return try self.constInt(result_ty_ref, value); |
| 606 | }, | 622 | }, |
| 607 | .error_union => |error_union| { | 623 | .error_union => |error_union| { |
| 608 | // TODO: Error unions may be constructed with constant instructions if the payload type | 624 | // TODO: Error unions may be constructed with constant instructions if the payload type |
| ... | @@ -716,7 +732,7 @@ pub const DeclGen = struct { | ... | @@ -716,7 +732,7 @@ pub const DeclGen = struct { |
| 716 | // TODO: This is really space inefficient, perhaps there is a better | 732 | // TODO: This is really space inefficient, perhaps there is a better |
| 717 | // way to do it? | 733 | // way to do it? |
| 718 | for (bytes, 0..) |byte, i| { | 734 | for (bytes, 0..) |byte, i| { |
| 719 | constituents[i] = try self.spv.constInt(elem_ty_ref, byte); | 735 | constituents[i] = try self.constInt(elem_ty_ref, byte); |
| 720 | } | 736 | } |
| 721 | }, | 737 | }, |
| 722 | .elems => |elems| { | 738 | .elems => |elems| { |
| ... | @@ -794,7 +810,7 @@ pub const DeclGen = struct { | ... | @@ -794,7 +810,7 @@ pub const DeclGen = struct { |
| 794 | const index_ty_ref = try self.intType(.unsigned, 32); | 810 | const index_ty_ref = try self.intType(.unsigned, 32); |
| 795 | | 811 | |
| 796 | if (layout.tag_size != 0) { | 812 | if (layout.tag_size != 0) { |
| 797 | const index_id = try self.spv.constInt(index_ty_ref, @as(u32, @intCast(layout.tag_index))); | 813 | const index_id = try self.constInt(index_ty_ref, @as(u32, @intCast(layout.tag_index))); |
| 798 | const tag_ty = ty.unionTagTypeSafety(mod).?; | 814 | const tag_ty = ty.unionTagTypeSafety(mod).?; |
| 799 | const tag_ty_ref = try self.resolveType(tag_ty, .indirect); | 815 | const tag_ty_ref = try self.resolveType(tag_ty, .indirect); |
| 800 | const tag_ptr_ty_ref = try self.spv.ptrType(tag_ty_ref, .Function); | 816 | const tag_ptr_ty_ref = try self.spv.ptrType(tag_ty_ref, .Function); |
| ... | @@ -807,7 +823,7 @@ pub const DeclGen = struct { | ... | @@ -807,7 +823,7 @@ pub const DeclGen = struct { |
| 807 | } | 823 | } |
| 808 | | 824 | |
| 809 | if (layout.active_field_size != 0) { | 825 | if (layout.active_field_size != 0) { |
| 810 | const index_id = try self.spv.constInt(index_ty_ref, @as(u32, @intCast(layout.active_field_index))); | 826 | const index_id = try self.constInt(index_ty_ref, @as(u32, @intCast(layout.active_field_index))); |
| 811 | const active_field_ty_ref = try self.resolveType(layout.active_field_ty, .indirect); | 827 | const active_field_ty_ref = try self.resolveType(layout.active_field_ty, .indirect); |
| 812 | const active_field_ptr_ty_ref = try self.spv.ptrType(active_field_ty_ref, .Function); | 828 | const active_field_ptr_ty_ref = try self.spv.ptrType(active_field_ty_ref, .Function); |
| 813 | const ptr_id = try self.accessChain(active_field_ptr_ty_ref, var_id, &.{index_id}); | 829 | const ptr_id = try self.accessChain(active_field_ptr_ty_ref, var_id, &.{index_id}); |
| ... | @@ -870,7 +886,9 @@ pub const DeclGen = struct { | ... | @@ -870,7 +886,9 @@ pub const DeclGen = struct { |
| 870 | // An array of largestSupportedIntBits. | 886 | // An array of largestSupportedIntBits. |
| 871 | return self.todo("Implement {s} composite int type of {} bits", .{ @tagName(signedness), bits }); | 887 | return self.todo("Implement {s} composite int type of {} bits", .{ @tagName(signedness), bits }); |
| 872 | }; | 888 | }; |
| 873 | return self.spv.intType(signedness, backing_bits); | 889 | // Kernel only supports unsigned ints. |
| | 890 | // TODO: Only do this with Kernels |
| | 891 | return self.spv.intType(.unsigned, backing_bits); |
| 874 | } | 892 | } |
| 875 | | 893 | |
| 876 | /// Create an integer type that represents 'usize'. | 894 | /// Create an integer type that represents 'usize'. |
| ... | @@ -1568,8 +1586,8 @@ pub const DeclGen = struct { | ... | @@ -1568,8 +1586,8 @@ pub const DeclGen = struct { |
| 1568 | } | 1586 | } |
| 1569 | | 1587 | |
| 1570 | fn intFromBool(self: *DeclGen, result_ty_ref: CacheRef, condition_id: IdRef) !IdRef { | 1588 | fn intFromBool(self: *DeclGen, result_ty_ref: CacheRef, condition_id: IdRef) !IdRef { |
| 1571 | const zero_id = try self.spv.constInt(result_ty_ref, 0); | 1589 | const zero_id = try self.constInt(result_ty_ref, 0); |
| 1572 | const one_id = try self.spv.constInt(result_ty_ref, 1); | 1590 | const one_id = try self.constInt(result_ty_ref, 1); |
| 1573 | const result_id = self.spv.allocId(); | 1591 | const result_id = self.spv.allocId(); |
| 1574 | try self.func.body.emit(self.spv.gpa, .OpSelect, .{ | 1592 | try self.func.body.emit(self.spv.gpa, .OpSelect, .{ |
| 1575 | .id_result_type = self.typeId(result_ty_ref), | 1593 | .id_result_type = self.typeId(result_ty_ref), |
| ... | @@ -1589,7 +1607,7 @@ pub const DeclGen = struct { | ... | @@ -1589,7 +1607,7 @@ pub const DeclGen = struct { |
| 1589 | .Bool => blk: { | 1607 | .Bool => blk: { |
| 1590 | const direct_bool_ty_ref = try self.resolveType(ty, .direct); | 1608 | const direct_bool_ty_ref = try self.resolveType(ty, .direct); |
| 1591 | const indirect_bool_ty_ref = try self.resolveType(ty, .indirect); | 1609 | const indirect_bool_ty_ref = try self.resolveType(ty, .indirect); |
| 1592 | const zero_id = try self.spv.constInt(indirect_bool_ty_ref, 0); | 1610 | const zero_id = try self.constInt(indirect_bool_ty_ref, 0); |
| 1593 | const result_id = self.spv.allocId(); | 1611 | const result_id = self.spv.allocId(); |
| 1594 | try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{ | 1612 | try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{ |
| 1595 | .id_result_type = self.typeId(direct_bool_ty_ref), | 1613 | .id_result_type = self.typeId(direct_bool_ty_ref), |
| ... | @@ -1832,7 +1850,7 @@ pub const DeclGen = struct { | ... | @@ -1832,7 +1850,7 @@ pub const DeclGen = struct { |
| 1832 | fn maskStrangeInt(self: *DeclGen, ty_ref: CacheRef, value_id: IdRef, bits: u16) !IdRef { | 1850 | fn maskStrangeInt(self: *DeclGen, ty_ref: CacheRef, value_id: IdRef, bits: u16) !IdRef { |
| 1833 | const mask_value = if (bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(bits))) - 1; | 1851 | const mask_value = if (bits == 64) 0xFFFF_FFFF_FFFF_FFFF else (@as(u64, 1) << @as(u6, @intCast(bits))) - 1; |
| 1834 | const result_id = self.spv.allocId(); | 1852 | const result_id = self.spv.allocId(); |
| 1835 | const mask_id = try self.spv.constInt(ty_ref, mask_value); | 1853 | const mask_id = try self.constInt(ty_ref, mask_value); |
| 1836 | try self.func.body.emit(self.spv.gpa, .OpBitwiseAnd, .{ | 1854 | try self.func.body.emit(self.spv.gpa, .OpBitwiseAnd, .{ |
| 1837 | .id_result_type = self.typeId(ty_ref), | 1855 | .id_result_type = self.typeId(ty_ref), |
| 1838 | .id_result = result_id, | 1856 | .id_result = result_id, |
| ... | @@ -1971,7 +1989,7 @@ pub const DeclGen = struct { | ... | @@ -1971,7 +1989,7 @@ pub const DeclGen = struct { |
| 1971 | // Note that signed overflow is also wrapping in spir-v. | 1989 | // Note that signed overflow is also wrapping in spir-v. |
| 1972 | | 1990 | |
| 1973 | const rhs_lt_zero_id = self.spv.allocId(); | 1991 | const rhs_lt_zero_id = self.spv.allocId(); |
| 1974 | const zero_id = try self.spv.constInt(operand_ty_ref, 0); | 1992 | const zero_id = try self.constInt(operand_ty_ref, 0); |
| 1975 | try self.func.body.emit(self.spv.gpa, .OpSLessThan, .{ | 1993 | try self.func.body.emit(self.spv.gpa, .OpSLessThan, .{ |
| 1976 | .id_result_type = self.typeId(bool_ty_ref), | 1994 | .id_result_type = self.typeId(bool_ty_ref), |
| 1977 | .id_result = rhs_lt_zero_id, | 1995 | .id_result = rhs_lt_zero_id, |
| ... | @@ -2540,7 +2558,7 @@ pub const DeclGen = struct { | ... | @@ -2540,7 +2558,7 @@ pub const DeclGen = struct { |
| 2540 | .Packed => unreachable, // TODO | 2558 | .Packed => unreachable, // TODO |
| 2541 | else => { | 2559 | else => { |
| 2542 | const field_index_ty_ref = try self.intType(.unsigned, 32); | 2560 | const field_index_ty_ref = try self.intType(.unsigned, 32); |
| 2543 | const field_index_id = try self.spv.constInt(field_index_ty_ref, field_index); | 2561 | const field_index_id = try self.constInt(field_index_ty_ref, field_index); |
| 2544 | const result_ty_ref = try self.resolveType(result_ptr_ty, .direct); | 2562 | const result_ty_ref = try self.resolveType(result_ptr_ty, .direct); |
| 2545 | return try self.accessChain(result_ty_ref, object_ptr, &.{field_index_id}); | 2563 | return try self.accessChain(result_ty_ref, object_ptr, &.{field_index_id}); |
| 2546 | }, | 2564 | }, |
| ... | @@ -2822,7 +2840,7 @@ pub const DeclGen = struct { | ... | @@ -2822,7 +2840,7 @@ pub const DeclGen = struct { |
| 2822 | else | 2840 | else |
| 2823 | err_union_id; | 2841 | err_union_id; |
| 2824 | | 2842 | |
| 2825 | const zero_id = try self.spv.constInt(err_ty_ref, 0); | 2843 | const zero_id = try self.constInt(err_ty_ref, 0); |
| 2826 | const is_err_id = self.spv.allocId(); | 2844 | const is_err_id = self.spv.allocId(); |
| 2827 | try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{ | 2845 | try self.func.body.emit(self.spv.gpa, .OpINotEqual, .{ |
| 2828 | .id_result_type = self.typeId(bool_ty_ref), | 2846 | .id_result_type = self.typeId(bool_ty_ref), |