authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2022-11-27 14:50:20+01:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-04-09 01:51:50+02:00
logea97966c9e76727e7f7e4c0a2c4578f64b608001
tree9086e7f22f00be7153b0b392be8f245c7e4e694a
parent8608d6e23573a6d7d4d1ce92bf461b035970c592
signaturelock-open Commit is signed but in an unrecognized format.

spirv: struct field ptr index, ptr elem ptr

Implements the ptr_elem_ptr and struct_field_ptr_index_* AIR instructions for the SPIR-V backend.

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

src/codegen/spirv.zig+74
......@@ -858,9 +858,15 @@ pub const DeclGen = struct {
858858 .slice_len => try self.airSliceField(inst, 1),
859859 .slice_elem_ptr => try self.airSliceElemPtr(inst),
860860 .slice_elem_val => try self.airSliceElemVal(inst),
861 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
861862
862863 .struct_field_val => try self.airStructFieldVal(inst),
863864
865 .struct_field_ptr_index_0 => try self.airStructFieldPtrIndex(inst, 0),
866 .struct_field_ptr_index_1 => try self.airStructFieldPtrIndex(inst, 1),
867 .struct_field_ptr_index_2 => try self.airStructFieldPtrIndex(inst, 2),
868 .struct_field_ptr_index_3 => try self.airStructFieldPtrIndex(inst, 3),
869
864870 .cmp_eq => try self.airCmp(inst, .OpFOrdEqual, .OpLogicalEqual, .OpIEqual),
865871 .cmp_neq => try self.airCmp(inst, .OpFOrdNotEqual, .OpLogicalNotEqual, .OpINotEqual),
866872 .cmp_gt => try self.airCmp(inst, .OpFOrdGreaterThan, .OpSGreaterThan, .OpUGreaterThan),
......@@ -1337,6 +1343,31 @@ pub const DeclGen = struct {
13371343 return result_id.toRef();
13381344 }
13391345
1346 fn airPtrElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
1347 if (self.liveness.isUnused(inst)) return null;
1348
1349 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1350 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
1351 const ptr_ty = self.air.typeOf(bin_op.lhs);
1352 const result_ty = self.air.typeOfIndex(inst);
1353 const elem_ty = ptr_ty.childType();
1354 // TODO: Make this return a null ptr or something
1355 if (!elem_ty.hasRuntimeBitsIgnoreComptime()) return null;
1356
1357 const result_type_id = try self.resolveTypeId(result_ty);
1358 const base_ptr = try self.resolve(bin_op.lhs);
1359 const rhs = try self.resolve(bin_op.rhs);
1360
1361 const result_id = self.spv.allocId();
1362 try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{
1363 .id_result_type = result_type_id,
1364 .id_result = result_id,
1365 .base = base_ptr,
1366 .indexes = &.{rhs},
1367 });
1368 return result_id.toRef();
1369 }
1370
13401371 fn airStructFieldVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
13411372 if (self.liveness.isUnused(inst)) return null;
13421373
......@@ -1363,6 +1394,49 @@ pub const DeclGen = struct {
13631394 return result_id.toRef();
13641395 }
13651396
1397 fn structFieldPtr(
1398 self: *DeclGen,
1399 result_ptr_ty: Type,
1400 object_ptr_ty: Type,
1401 object_ptr: IdRef,
1402 field_index: u32,
1403 ) !?IdRef {
1404 const object_ty = object_ptr_ty.childType();
1405 switch (object_ty.zigTypeTag()) {
1406 .Struct => switch (object_ty.containerLayout()) {
1407 .Packed => unreachable, // TODO
1408 else => {
1409 const field_index_id = self.spv.allocId();
1410 const u32_ty_id = self.spv.typeResultId(try self.intType(.unsigned, 32));
1411 try self.func.body.emit(self.spv.gpa, .OpConstant, .{
1412 .id_result_type = u32_ty_id,
1413 .id_result = field_index_id,
1414 .value = .{ .uint32 = field_index },
1415 });
1416 const result_id = self.spv.allocId();
1417 const result_type_id = try self.resolveTypeId(result_ptr_ty);
1418 try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{
1419 .id_result_type = result_type_id,
1420 .id_result = result_id,
1421 .base = object_ptr,
1422 .indexes = &.{field_index_id.toRef()},
1423 });
1424 return result_id.toRef();
1425 },
1426 },
1427 else => unreachable, // TODO
1428 }
1429 }
1430
1431 fn airStructFieldPtrIndex(self: *DeclGen, inst: Air.Inst.Index, field_index: u32) !?IdRef {
1432 if (self.liveness.isUnused(inst)) return null;
1433 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1434 const struct_ptr = try self.resolve(ty_op.operand);
1435 const struct_ptr_ty = self.air.typeOf(ty_op.operand);
1436 const result_ptr_ty = self.air.typeOfIndex(inst);
1437 return try self.structFieldPtr(result_ptr_ty, struct_ptr_ty, struct_ptr, field_index);
1438 }
1439
13661440 fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
13671441 if (self.liveness.isUnused(inst)) return null;
13681442 const ty = self.air.typeOfIndex(inst);