| ... | @@ -438,6 +438,8 @@ pub const DeclGen = struct { | ... | @@ -438,6 +438,8 @@ pub const DeclGen = struct { |
| 438 | | 438 | |
| 439 | /// Construct a struct at runtime. | 439 | /// Construct a struct at runtime. |
| 440 | /// result_ty_ref must be a struct type. | 440 | /// result_ty_ref must be a struct type. |
| | 441 | /// Constituents should be in `indirect` representation (as the elements of a struct should be). |
| | 442 | /// Result is in `direct` representation. |
| 441 | fn constructStruct(self: *DeclGen, result_ty_ref: CacheRef, constituents: []const IdRef) !IdRef { | 443 | fn constructStruct(self: *DeclGen, result_ty_ref: CacheRef, constituents: []const IdRef) !IdRef { |
| 442 | // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which' | 444 | // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which' |
| 443 | // operands are not constant. | 445 | // operands are not constant. |
| ... | @@ -474,6 +476,8 @@ pub const DeclGen = struct { | ... | @@ -474,6 +476,8 @@ pub const DeclGen = struct { |
| 474 | | 476 | |
| 475 | /// Construct a struct at runtime. | 477 | /// Construct a struct at runtime. |
| 476 | /// result_ty_ref must be an array type. | 478 | /// result_ty_ref must be an array type. |
| | 479 | /// Constituents should be in `indirect` representation (as the elements of an array should be). |
| | 480 | /// Result is in `direct` representation. |
| 477 | fn constructArray(self: *DeclGen, result_ty_ref: CacheRef, constituents: []const IdRef) !IdRef { | 481 | fn constructArray(self: *DeclGen, result_ty_ref: CacheRef, constituents: []const IdRef) !IdRef { |
| 478 | // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which' | 482 | // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which' |
| 479 | // operands are not constant. | 483 | // operands are not constant. |
| ... | @@ -1682,6 +1686,7 @@ pub const DeclGen = struct { | ... | @@ -1682,6 +1686,7 @@ pub const DeclGen = struct { |
| 1682 | .not => try self.airNot(inst), | 1686 | .not => try self.airNot(inst), |
| 1683 | | 1687 | |
| 1684 | .array_to_slice => try self.airArrayToSlice(inst), | 1688 | .array_to_slice => try self.airArrayToSlice(inst), |
| | 1689 | .aggregate_init => try self.airAggregateInit(inst), |
| 1685 | | 1690 | |
| 1686 | .slice_ptr => try self.airSliceField(inst, 0), | 1691 | .slice_ptr => try self.airSliceField(inst, 0), |
| 1687 | .slice_len => try self.airSliceField(inst, 1), | 1692 | .slice_len => try self.airSliceField(inst, 1), |
| ... | @@ -2430,6 +2435,8 @@ pub const DeclGen = struct { | ... | @@ -2430,6 +2435,8 @@ pub const DeclGen = struct { |
| 2430 | } | 2435 | } |
| 2431 | | 2436 | |
| 2432 | fn airArrayToSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 2437 | fn airArrayToSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| | 2438 | if (self.liveness.isUnused(inst)) return null; |
| | 2439 | |
| 2433 | const mod = self.module; | 2440 | const mod = self.module; |
| 2434 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2441 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2435 | const array_ptr_ty = self.typeOf(ty_op.operand); | 2442 | const array_ptr_ty = self.typeOf(ty_op.operand); |
| ... | @@ -2453,6 +2460,40 @@ pub const DeclGen = struct { | ... | @@ -2453,6 +2460,40 @@ pub const DeclGen = struct { |
| 2453 | return try self.constructStruct(slice_ty_ref, &.{ elem_ptr_id, len_id }); | 2460 | return try self.constructStruct(slice_ty_ref, &.{ elem_ptr_id, len_id }); |
| 2454 | } | 2461 | } |
| 2455 | | 2462 | |
| | 2463 | fn airAggregateInit(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| | 2464 | if (self.liveness.isUnused(inst)) return null; |
| | 2465 | |
| | 2466 | const mod = self.module; |
| | 2467 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| | 2468 | const result_ty = self.typeOfIndex(inst); |
| | 2469 | const result_ty_ref = try self.resolveType(result_ty, .direct); |
| | 2470 | const len: usize = @intCast(result_ty.arrayLen(mod)); |
| | 2471 | const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra[ty_pl.payload..][0..len]); |
| | 2472 | |
| | 2473 | switch (result_ty.zigTypeTag(mod)) { |
| | 2474 | .Vector => unreachable, // TODO |
| | 2475 | .Struct => unreachable, // TODO |
| | 2476 | .Array => { |
| | 2477 | const array_info = result_ty.arrayInfo(mod); |
| | 2478 | const n_elems: usize = @intCast(result_ty.arrayLenIncludingSentinel(mod)); |
| | 2479 | const elem_ids = try self.gpa.alloc(IdRef, n_elems); |
| | 2480 | defer self.gpa.free(elem_ids); |
| | 2481 | |
| | 2482 | for (elements, 0..) |elem_inst, i| { |
| | 2483 | const id = try self.resolve(elem_inst); |
| | 2484 | elem_ids[i] = try self.convertToIndirect(array_info.elem_type, id); |
| | 2485 | } |
| | 2486 | |
| | 2487 | if (array_info.sentinel) |sentinel_val| { |
| | 2488 | elem_ids[n_elems - 1] = try self.constant(array_info.elem_type, sentinel_val, .indirect); |
| | 2489 | } |
| | 2490 | |
| | 2491 | return try self.constructArray(result_ty_ref, elem_ids); |
| | 2492 | }, |
| | 2493 | else => unreachable, |
| | 2494 | } |
| | 2495 | } |
| | 2496 | |
| 2456 | fn airSliceField(self: *DeclGen, inst: Air.Inst.Index, field: u32) !?IdRef { | 2497 | fn airSliceField(self: *DeclGen, inst: Air.Inst.Index, field: u32) !?IdRef { |
| 2457 | if (self.liveness.isUnused(inst)) return null; | 2498 | if (self.liveness.isUnused(inst)) return null; |
| 2458 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2499 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |