authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-09-18 20:28:17+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-23 12:36:56-07:00
log26c279cca2e9b9d93c2d8744ba45c49076ff4a32
treee67aad2b0875c0fec1cefa0bf7c4879b275f6e95
parent8d49b2ef4ef0682d1c258a5270f0646f85d7fe63

spirv: air aggregate_init for array


1 files changed, 41 insertions(+), 0 deletions(-)

src/codegen/spirv.zig+41
......@@ -438,6 +438,8 @@ pub const DeclGen = struct {
438438
439439 /// Construct a struct at runtime.
440440 /// 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.
441443 fn constructStruct(self: *DeclGen, result_ty_ref: CacheRef, constituents: []const IdRef) !IdRef {
442444 // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which'
443445 // operands are not constant.
......@@ -474,6 +476,8 @@ pub const DeclGen = struct {
474476
475477 /// Construct a struct at runtime.
476478 /// 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.
477481 fn constructArray(self: *DeclGen, result_ty_ref: CacheRef, constituents: []const IdRef) !IdRef {
478482 // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which'
479483 // operands are not constant.
......@@ -1682,6 +1686,7 @@ pub const DeclGen = struct {
16821686 .not => try self.airNot(inst),
16831687
16841688 .array_to_slice => try self.airArrayToSlice(inst),
1689 .aggregate_init => try self.airAggregateInit(inst),
16851690
16861691 .slice_ptr => try self.airSliceField(inst, 0),
16871692 .slice_len => try self.airSliceField(inst, 1),
......@@ -2430,6 +2435,8 @@ pub const DeclGen = struct {
24302435 }
24312436
24322437 fn airArrayToSlice(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2438 if (self.liveness.isUnused(inst)) return null;
2439
24332440 const mod = self.module;
24342441 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
24352442 const array_ptr_ty = self.typeOf(ty_op.operand);
......@@ -2453,6 +2460,40 @@ pub const DeclGen = struct {
24532460 return try self.constructStruct(slice_ty_ref, &.{ elem_ptr_id, len_id });
24542461 }
24552462
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
24562497 fn airSliceField(self: *DeclGen, inst: Air.Inst.Index, field: u32) !?IdRef {
24572498 if (self.liveness.isUnused(inst)) return null;
24582499 const ty_op = self.air.instructions.items(.data)[inst].ty_op;