| ... | ... | @@ -744,6 +744,30 @@ const DeclGen = struct { |
| 744 | 744 | return try self.load(ty, ptr_composite_id, .{}); |
| 745 | 745 | } |
| 746 | 746 | |
| 747 | /// Construct a vector at runtime. |
| 748 | /// ty must be an vector type. |
| 749 | /// Constituents should be in `indirect` representation (as the elements of an vector should be). |
| 750 | /// Result is in `direct` representation. |
| 751 | fn constructVector(self: *DeclGen, ty: Type, constituents: []const IdRef) !IdRef { |
| 752 | // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which' |
| 753 | // operands are not constant. |
| 754 | // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349 |
| 755 | // For now, just initialize the struct by setting the fields manually... |
| 756 | // TODO: Make this OpCompositeConstruct when we can |
| 757 | const mod = self.module; |
| 758 | const ptr_composite_id = try self.alloc(ty, .{ .storage_class = .Function }); |
| 759 | const ptr_elem_ty_ref = try self.ptrType(ty.elemType2(mod), .Function); |
| 760 | for (constituents, 0..) |constitent_id, index| { |
| 761 | const ptr_id = try self.accessChain(ptr_elem_ty_ref, ptr_composite_id, &.{@as(u32, @intCast(index))}); |
| 762 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ |
| 763 | .pointer = ptr_id, |
| 764 | .object = constitent_id, |
| 765 | }); |
| 766 | } |
| 767 | |
| 768 | return try self.load(ty, ptr_composite_id, .{}); |
| 769 | } |
| 770 | |
| 747 | 771 | /// Construct an array at runtime. |
| 748 | 772 | /// ty must be an array type. |
| 749 | 773 | /// Constituents should be in `indirect` representation (as the elements of an array should be). |
| ... | ... | @@ -963,13 +987,16 @@ const DeclGen = struct { |
| 963 | 987 | } |
| 964 | 988 | |
| 965 | 989 | switch (tag) { |
| 966 | | inline .array_type => if (array_type.sentinel != .none) { |
| 967 | | constituents[constituents.len - 1] = try self.constant(elem_ty, Value.fromInterned(array_type.sentinel), .indirect); |
| 990 | inline .array_type => { |
| 991 | if (array_type.sentinel != .none) { |
| 992 | const sentinel = Value.fromInterned(array_type.sentinel); |
| 993 | constituents[constituents.len - 1] = try self.constant(elem_ty, sentinel, .indirect); |
| 994 | } |
| 995 | return self.constructArray(ty, constituents); |
| 968 | 996 | }, |
| 969 | | else => {}, |
| 997 | inline .vector_type => return self.constructVector(ty, constituents), |
| 998 | else => unreachable, |
| 970 | 999 | } |
| 971 | | |
| 972 | | return try self.constructArray(ty, constituents); |
| 973 | 1000 | }, |
| 974 | 1001 | .struct_type => { |
| 975 | 1002 | const struct_type = mod.typeToStruct(ty).?; |
| ... | ... | @@ -1492,8 +1519,14 @@ const DeclGen = struct { |
| 1492 | 1519 | |
| 1493 | 1520 | const elem_ty = ty.childType(mod); |
| 1494 | 1521 | const elem_ty_ref = try self.resolveType(elem_ty, .indirect); |
| 1522 | const len = ty.vectorLen(mod); |
| 1523 | const is_scalar = elem_ty.isNumeric(mod) or elem_ty.toIntern() == .bool_type; |
| 1524 | |
| 1525 | const ty_ref = if (is_scalar and len > 1 and len <= 4) |
| 1526 | try self.spv.vectorType(ty.vectorLen(mod), elem_ty_ref) |
| 1527 | else |
| 1528 | try self.spv.arrayType(ty.vectorLen(mod), elem_ty_ref); |
| 1495 | 1529 | |
| 1496 | | const ty_ref = try self.spv.arrayType(ty.vectorLen(mod), elem_ty_ref); |
| 1497 | 1530 | try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref }); |
| 1498 | 1531 | return ty_ref; |
| 1499 | 1532 | }, |
| ... | ... | @@ -3688,7 +3721,19 @@ const DeclGen = struct { |
| 3688 | 3721 | constituents[0..index], |
| 3689 | 3722 | ); |
| 3690 | 3723 | }, |
| 3691 | | .Vector, .Array => { |
| 3724 | .Vector => { |
| 3725 | const n_elems = result_ty.vectorLen(mod); |
| 3726 | const elem_ids = try self.gpa.alloc(IdRef, n_elems); |
| 3727 | defer self.gpa.free(elem_ids); |
| 3728 | |
| 3729 | for (elements, 0..) |element, i| { |
| 3730 | const id = try self.resolve(element); |
| 3731 | elem_ids[i] = try self.convertToIndirect(result_ty.childType(mod), id); |
| 3732 | } |
| 3733 | |
| 3734 | return try self.constructVector(result_ty, elem_ids); |
| 3735 | }, |
| 3736 | .Array => { |
| 3692 | 3737 | const array_info = result_ty.arrayInfo(mod); |
| 3693 | 3738 | const n_elems: usize = @intCast(result_ty.arrayLenIncludingSentinel(mod)); |
| 3694 | 3739 | const elem_ids = try self.gpa.alloc(IdRef, n_elems); |