| ... | ... | @@ -1306,12 +1306,11 @@ pub const DeclGen = struct { |
| 1306 | 1306 | }; |
| 1307 | 1307 | |
| 1308 | 1308 | const result_id = self.spv.allocId(); |
| 1309 | | const indexes = [_]IdRef{index}; |
| 1310 | | try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ |
| 1309 | try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{ |
| 1311 | 1310 | .id_result_type = spv_ptr_ty, |
| 1312 | 1311 | .id_result = result_id, |
| 1313 | 1312 | .base = slice_ptr, |
| 1314 | | .indexes = &indexes, |
| 1313 | .element = index, |
| 1315 | 1314 | }); |
| 1316 | 1315 | return result_id; |
| 1317 | 1316 | } |
| ... | ... | @@ -1340,12 +1339,11 @@ pub const DeclGen = struct { |
| 1340 | 1339 | |
| 1341 | 1340 | const elem_ptr = blk: { |
| 1342 | 1341 | const result_id = self.spv.allocId(); |
| 1343 | | const indexes = [_]IdRef{index}; |
| 1344 | | try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ |
| 1342 | try self.func.body.emit(self.spv.gpa, .OpInBoundsPtrAccessChain, .{ |
| 1345 | 1343 | .id_result_type = ptr_ty_id, |
| 1346 | 1344 | .id_result = result_id, |
| 1347 | 1345 | .base = slice_ptr, |
| 1348 | | .indexes = &indexes, |
| 1346 | .element = index, |
| 1349 | 1347 | }); |
| 1350 | 1348 | break :blk result_id; |
| 1351 | 1349 | }; |
| ... | ... | @@ -1448,22 +1446,45 @@ pub const DeclGen = struct { |
| 1448 | 1446 | fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 1449 | 1447 | if (self.liveness.isUnused(inst)) return null; |
| 1450 | 1448 | const ty = self.air.typeOfIndex(inst); |
| 1451 | | const result_type_id = try self.resolveTypeId(ty); |
| 1449 | const result_ty_ref = try self.resolveType(ty, .direct); |
| 1450 | const result_ty_id = self.typeId(result_ty_ref); |
| 1452 | 1451 | const result_id = self.spv.allocId(); |
| 1453 | 1452 | |
| 1454 | | // Rather than generating into code here, we're just going to generate directly into the functions section so that |
| 1455 | | // variable declarations appear in the first block of the function. |
| 1456 | 1453 | const storage_class = spirvStorageClass(ty.ptrAddressSpace()); |
| 1457 | | const section = if (storage_class == .Function or storage_class == .Generic) |
| 1458 | | &self.func.prologue |
| 1459 | | else |
| 1460 | | &self.spv.sections.types_globals_constants; |
| 1461 | 1454 | |
| 1455 | const ptr_ty_id = switch (storage_class) { |
| 1456 | .Generic => blk: { |
| 1457 | const payload = try self.spv.arena.create(SpvType.Payload.Pointer); |
| 1458 | payload.* = self.spv.typeRefType(result_ty_ref).payload(.pointer).*; |
| 1459 | payload.storage_class = .Function; |
| 1460 | break :blk try self.spv.resolveTypeId(SpvType.initPayload(&payload.base)); |
| 1461 | }, |
| 1462 | else => result_ty_id, |
| 1463 | }; |
| 1464 | const actual_storage_class = switch (storage_class) { |
| 1465 | .Generic, .Function => .Function, |
| 1466 | else => storage_class, |
| 1467 | }; |
| 1468 | const section = switch (storage_class) { |
| 1469 | // SPIR-V requires that OpVariable declarations for locals go into the first block, so we are just going to |
| 1470 | // directly generate them into func.prologue instead of the body. |
| 1471 | .Generic, .Function => &self.func.prologue, |
| 1472 | else => &self.spv.sections.types_globals_constants, |
| 1473 | }; |
| 1462 | 1474 | try section.emit(self.spv.gpa, .OpVariable, .{ |
| 1463 | | .id_result_type = result_type_id, |
| 1475 | .id_result_type = ptr_ty_id, |
| 1464 | 1476 | .id_result = result_id, |
| 1465 | | .storage_class = storage_class, |
| 1477 | .storage_class = actual_storage_class, |
| 1466 | 1478 | }); |
| 1479 | if (storage_class == .Generic) { |
| 1480 | const casted_result_id = self.spv.allocId(); |
| 1481 | try self.func.body.emit(self.spv.gpa, .OpPtrCastToGeneric, .{ |
| 1482 | .id_result_type = result_ty_id, |
| 1483 | .id_result = casted_result_id, |
| 1484 | .pointer = result_id, |
| 1485 | }); |
| 1486 | return casted_result_id; |
| 1487 | } |
| 1467 | 1488 | return result_id; |
| 1468 | 1489 | } |
| 1469 | 1490 | |