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 {...@@ -858,9 +858,15 @@ pub const DeclGen = struct {
858 .slice_len => try self.airSliceField(inst, 1),858 .slice_len => try self.airSliceField(inst, 1),
859 .slice_elem_ptr => try self.airSliceElemPtr(inst),859 .slice_elem_ptr => try self.airSliceElemPtr(inst),
860 .slice_elem_val => try self.airSliceElemVal(inst),860 .slice_elem_val => try self.airSliceElemVal(inst),
861 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
861862
862 .struct_field_val => try self.airStructFieldVal(inst),863 .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
864 .cmp_eq => try self.airCmp(inst, .OpFOrdEqual, .OpLogicalEqual, .OpIEqual),870 .cmp_eq => try self.airCmp(inst, .OpFOrdEqual, .OpLogicalEqual, .OpIEqual),
865 .cmp_neq => try self.airCmp(inst, .OpFOrdNotEqual, .OpLogicalNotEqual, .OpINotEqual),871 .cmp_neq => try self.airCmp(inst, .OpFOrdNotEqual, .OpLogicalNotEqual, .OpINotEqual),
866 .cmp_gt => try self.airCmp(inst, .OpFOrdGreaterThan, .OpSGreaterThan, .OpUGreaterThan),872 .cmp_gt => try self.airCmp(inst, .OpFOrdGreaterThan, .OpSGreaterThan, .OpUGreaterThan),
...@@ -1337,6 +1343,31 @@ pub const DeclGen = struct {...@@ -1337,6 +1343,31 @@ pub const DeclGen = struct {
1337 return result_id.toRef();1343 return result_id.toRef();
1338 }1344 }
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
1340 fn airStructFieldVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {1371 fn airStructFieldVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
1341 if (self.liveness.isUnused(inst)) return null;1372 if (self.liveness.isUnused(inst)) return null;
13421373
...@@ -1363,6 +1394,49 @@ pub const DeclGen = struct {...@@ -1363,6 +1394,49 @@ pub const DeclGen = struct {
1363 return result_id.toRef();1394 return result_id.toRef();
1364 }1395 }
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
1366 fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {1440 fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
1367 if (self.liveness.isUnused(inst)) return null;1441 if (self.liveness.isUnused(inst)) return null;
1368 const ty = self.air.typeOfIndex(inst);1442 const ty = self.air.typeOfIndex(inst);