| ... | @@ -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), |
| 861 | | 862 | |
| 862 | .struct_field_val => try self.airStructFieldVal(inst), | 863 | .struct_field_val => try self.airStructFieldVal(inst), |
| 863 | | 864 | |
| | 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 | } |
| 1339 | | 1345 | |
| | 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; |
| 1342 | | 1373 | |
| ... | @@ -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 | } |
| 1365 | | 1396 | |
| | 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); |