diff options
| author | Robin Voetter <robin@voetter.nl> | 2023-09-18 20:28:17 +0200 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-09-23 12:36:56 -0700 |
| commit | 26c279cca2e9b9d93c2d8744ba45c49076ff4a32 (patch) | |
| tree | e67aad2b0875c0fec1cefa0bf7c4879b275f6e95 /src/codegen/spirv.zig | |
| parent | 8d49b2ef4ef0682d1c258a5270f0646f85d7fe63 (diff) | |
| download | zig-26c279cca2e9b9d93c2d8744ba45c49076ff4a32.tar.gz zig-26c279cca2e9b9d93c2d8744ba45c49076ff4a32.zip | |
spirv: air aggregate_init for array
Diffstat (limited to 'src/codegen/spirv.zig')
| -rw-r--r-- | src/codegen/spirv.zig | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 962310f28a..e05c8142db 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -438,6 +438,8 @@ pub const DeclGen = struct { /// Construct a struct at runtime. /// result_ty_ref must be a struct type. + /// Constituents should be in `indirect` representation (as the elements of a struct should be). + /// Result is in `direct` representation. fn constructStruct(self: *DeclGen, result_ty_ref: CacheRef, constituents: []const IdRef) !IdRef { // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which' // operands are not constant. @@ -474,6 +476,8 @@ pub const DeclGen = struct { /// Construct a struct at runtime. /// result_ty_ref must be an array type. + /// Constituents should be in `indirect` representation (as the elements of an array should be). + /// Result is in `direct` representation. fn constructArray(self: *DeclGen, result_ty_ref: CacheRef, constituents: []const IdRef) !IdRef { // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which' // operands are not constant. @@ -1682,6 +1686,7 @@ pub const DeclGen = struct { .not => try self.airNot(inst), .array_to_slice => try self.airArrayToSlice(inst), + .aggregate_init => try self.airAggregateInit(inst), .slice_ptr => try self.airSliceField(inst, 0), .slice_len => try self.airSliceField(inst, 1), @@ -2430,6 +2435,8 @@ pub const DeclGen = struct { } fn airArrayToSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { + if (self.liveness.isUnused(inst)) return null; + const mod = self.module; const ty_op = self.air.instructions.items(.data)[inst].ty_op; const array_ptr_ty = self.typeOf(ty_op.operand); @@ -2453,6 +2460,40 @@ pub const DeclGen = struct { return try self.constructStruct(slice_ty_ref, &.{ elem_ptr_id, len_id }); } + fn airAggregateInit(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { + if (self.liveness.isUnused(inst)) return null; + + const mod = self.module; + const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; + const result_ty = self.typeOfIndex(inst); + const result_ty_ref = try self.resolveType(result_ty, .direct); + const len: usize = @intCast(result_ty.arrayLen(mod)); + const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra[ty_pl.payload..][0..len]); + + switch (result_ty.zigTypeTag(mod)) { + .Vector => unreachable, // TODO + .Struct => unreachable, // TODO + .Array => { + const array_info = result_ty.arrayInfo(mod); + const n_elems: usize = @intCast(result_ty.arrayLenIncludingSentinel(mod)); + const elem_ids = try self.gpa.alloc(IdRef, n_elems); + defer self.gpa.free(elem_ids); + + for (elements, 0..) |elem_inst, i| { + const id = try self.resolve(elem_inst); + elem_ids[i] = try self.convertToIndirect(array_info.elem_type, id); + } + + if (array_info.sentinel) |sentinel_val| { + elem_ids[n_elems - 1] = try self.constant(array_info.elem_type, sentinel_val, .indirect); + } + + return try self.constructArray(result_ty_ref, elem_ids); + }, + else => unreachable, + } + } + fn airSliceField(self: *DeclGen, inst: Air.Inst.Index, field: u32) !?IdRef { if (self.liveness.isUnused(inst)) return null; const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
