| ... | @@ -880,7 +880,9 @@ pub const DeclGen = struct { | ... | @@ -880,7 +880,9 @@ pub const DeclGen = struct { |
| 880 | // TODO: We probably need to have a special implementation of this for the C abi. | 880 | // TODO: We probably need to have a special implementation of this for the C abi. |
| 881 | .ret_ptr => try self.airAlloc(inst), | 881 | .ret_ptr => try self.airAlloc(inst), |
| 882 | .block => try self.airBlock(inst), | 882 | .block => try self.airBlock(inst), |
| | 883 | |
| 883 | .load => try self.airLoad(inst), | 884 | .load => try self.airLoad(inst), |
| | 885 | .store => return self.airStore(inst), |
| 884 | | 886 | |
| 885 | .br => return self.airBr(inst), | 887 | .br => return self.airBr(inst), |
| 886 | .breakpoint => return, | 888 | .breakpoint => return, |
| ... | @@ -891,7 +893,6 @@ pub const DeclGen = struct { | ... | @@ -891,7 +893,6 @@ pub const DeclGen = struct { |
| 891 | .loop => return self.airLoop(inst), | 893 | .loop => return self.airLoop(inst), |
| 892 | .ret => return self.airRet(inst), | 894 | .ret => return self.airRet(inst), |
| 893 | .ret_load => return self.airRetLoad(inst), | 895 | .ret_load => return self.airRetLoad(inst), |
| 894 | .store => return self.airStore(inst), | | |
| 895 | .switch_br => return self.airSwitchBr(inst), | 896 | .switch_br => return self.airSwitchBr(inst), |
| 896 | .unreach => return self.airUnreach(), | 897 | .unreach => return self.airUnreach(), |
| 897 | | 898 | |
| ... | @@ -964,13 +965,8 @@ pub const DeclGen = struct { | ... | @@ -964,13 +965,8 @@ pub const DeclGen = struct { |
| 964 | 33...64 => .{ .uint64 = mask_value }, | 965 | 33...64 => .{ .uint64 = mask_value }, |
| 965 | else => unreachable, | 966 | else => unreachable, |
| 966 | }; | 967 | }; |
| 967 | // TODO: We should probably optimize these constants a bit. | 968 | // TODO: We should probably optimize the amount of these constants a bit. |
| 968 | const mask_id = self.spv.allocId(); | 969 | const mask_id = try self.spv.emitConstant(ty_id, mask_lit); |
| 969 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpConstant, .{ | | |
| 970 | .id_result_type = ty_id, | | |
| 971 | .id_result = mask_id, | | |
| 972 | .value = mask_lit, | | |
| 973 | }); | | |
| 974 | const result_id = self.spv.allocId(); | 970 | const result_id = self.spv.allocId(); |
| 975 | try self.func.body.emit(self.spv.gpa, .OpBitwiseAnd, .{ | 971 | try self.func.body.emit(self.spv.gpa, .OpBitwiseAnd, .{ |
| 976 | .id_result_type = ty_id, | 972 | .id_result_type = ty_id, |
| ... | @@ -1119,13 +1115,11 @@ pub const DeclGen = struct { | ... | @@ -1119,13 +1115,11 @@ pub const DeclGen = struct { |
| 1119 | // Finally, construct the Zig type. | 1115 | // Finally, construct the Zig type. |
| 1120 | // Layout is result, overflow. | 1116 | // Layout is result, overflow. |
| 1121 | const result_id = self.spv.allocId(); | 1117 | const result_id = self.spv.allocId(); |
| | 1118 | const constituents = [_]IdRef{ result, casted_overflow }; |
| 1122 | try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ | 1119 | try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ |
| 1123 | .id_result_type = result_type_id, | 1120 | .id_result_type = result_type_id, |
| 1124 | .id_result = result_id, | 1121 | .id_result = result_id, |
| 1125 | .constituents = &.{ | 1122 | .constituents = &constituents, |
| 1126 | result, | | |
| 1127 | casted_overflow, | | |
| 1128 | }, | | |
| 1129 | }); | 1123 | }); |
| 1130 | return result_id; | 1124 | return result_id; |
| 1131 | } | 1125 | } |
| ... | @@ -1277,11 +1271,12 @@ pub const DeclGen = struct { | ... | @@ -1277,11 +1271,12 @@ pub const DeclGen = struct { |
| 1277 | | 1271 | |
| 1278 | fn extractField(self: *DeclGen, result_ty: IdResultType, object: IdRef, field: u32) !IdRef { | 1272 | fn extractField(self: *DeclGen, result_ty: IdResultType, object: IdRef, field: u32) !IdRef { |
| 1279 | const result_id = self.spv.allocId(); | 1273 | const result_id = self.spv.allocId(); |
| | 1274 | const indexes = [_]u32{field}; |
| 1280 | try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{ | 1275 | try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{ |
| 1281 | .id_result_type = result_ty, | 1276 | .id_result_type = result_ty, |
| 1282 | .id_result = result_id, | 1277 | .id_result = result_id, |
| 1283 | .composite = object, | 1278 | .composite = object, |
| 1284 | .indexes = &.{field}, | 1279 | .indexes = &indexes, |
| 1285 | }); | 1280 | }); |
| 1286 | return result_id; | 1281 | return result_id; |
| 1287 | } | 1282 | } |
| ... | @@ -1318,11 +1313,12 @@ pub const DeclGen = struct { | ... | @@ -1318,11 +1313,12 @@ pub const DeclGen = struct { |
| 1318 | }; | 1313 | }; |
| 1319 | | 1314 | |
| 1320 | const result_id = self.spv.allocId(); | 1315 | const result_id = self.spv.allocId(); |
| | 1316 | const indexes = [_]IdRef{index}; |
| 1321 | try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ | 1317 | try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ |
| 1322 | .id_result_type = spv_ptr_ty, | 1318 | .id_result_type = spv_ptr_ty, |
| 1323 | .id_result = result_id, | 1319 | .id_result = result_id, |
| 1324 | .base = slice_ptr, | 1320 | .base = slice_ptr, |
| 1325 | .indexes = &.{index}, | 1321 | .indexes = &indexes, |
| 1326 | }); | 1322 | }); |
| 1327 | return result_id; | 1323 | return result_id; |
| 1328 | } | 1324 | } |
| ... | @@ -1335,14 +1331,13 @@ pub const DeclGen = struct { | ... | @@ -1335,14 +1331,13 @@ pub const DeclGen = struct { |
| 1335 | const slice = try self.resolve(bin_op.lhs); | 1331 | const slice = try self.resolve(bin_op.lhs); |
| 1336 | const index = try self.resolve(bin_op.rhs); | 1332 | const index = try self.resolve(bin_op.rhs); |
| 1337 | | 1333 | |
| 1338 | const spv_elem_ty = try self.resolveTypeId(self.air.typeOfIndex(inst)); | | |
| 1339 | var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined; | 1334 | var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 1340 | const spv_ptr_ty = try self.resolveTypeId(slice_ty.slicePtrFieldType(&slice_buf)); | 1335 | const ptr_ty_id = try self.resolveTypeId(slice_ty.slicePtrFieldType(&slice_buf)); |
| 1341 | | 1336 | |
| 1342 | const slice_ptr = blk: { | 1337 | const slice_ptr = blk: { |
| 1343 | const result_id = self.spv.allocId(); | 1338 | const result_id = self.spv.allocId(); |
| 1344 | try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{ | 1339 | try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{ |
| 1345 | .id_result_type = spv_ptr_ty, | 1340 | .id_result_type = ptr_ty_id, |
| 1346 | .id_result = result_id, | 1341 | .id_result = result_id, |
| 1347 | .composite = slice, | 1342 | .composite = slice, |
| 1348 | .indexes = &.{0}, | 1343 | .indexes = &.{0}, |
| ... | @@ -1352,22 +1347,17 @@ pub const DeclGen = struct { | ... | @@ -1352,22 +1347,17 @@ pub const DeclGen = struct { |
| 1352 | | 1347 | |
| 1353 | const elem_ptr = blk: { | 1348 | const elem_ptr = blk: { |
| 1354 | const result_id = self.spv.allocId(); | 1349 | const result_id = self.spv.allocId(); |
| | 1350 | const indexes = [_]IdRef{index}; |
| 1355 | try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ | 1351 | try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ |
| 1356 | .id_result_type = spv_ptr_ty, | 1352 | .id_result_type = ptr_ty_id, |
| 1357 | .id_result = result_id, | 1353 | .id_result = result_id, |
| 1358 | .base = slice_ptr, | 1354 | .base = slice_ptr, |
| 1359 | .indexes = &.{index}, | 1355 | .indexes = &indexes, |
| 1360 | }); | 1356 | }); |
| 1361 | break :blk result_id; | 1357 | break :blk result_id; |
| 1362 | }; | 1358 | }; |
| 1363 | | 1359 | |
| 1364 | const result_id = self.spv.allocId(); | 1360 | return try self.load(slice_ty, elem_ptr); |
| 1365 | try self.func.body.emit(self.spv.gpa, .OpLoad, .{ | | |
| 1366 | .id_result_type = spv_elem_ty, | | |
| 1367 | .id_result = result_id, | | |
| 1368 | .pointer = elem_ptr, | | |
| 1369 | }); | | |
| 1370 | return result_id; | | |
| 1371 | } | 1361 | } |
| 1372 | | 1362 | |
| 1373 | fn airPtrElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 1363 | fn airPtrElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| ... | @@ -1386,11 +1376,12 @@ pub const DeclGen = struct { | ... | @@ -1386,11 +1376,12 @@ pub const DeclGen = struct { |
| 1386 | const rhs = try self.resolve(bin_op.rhs); | 1376 | const rhs = try self.resolve(bin_op.rhs); |
| 1387 | | 1377 | |
| 1388 | const result_id = self.spv.allocId(); | 1378 | const result_id = self.spv.allocId(); |
| | 1379 | const indexes = [_]IdRef{rhs}; |
| 1389 | try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ | 1380 | try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ |
| 1390 | .id_result_type = result_type_id, | 1381 | .id_result_type = result_type_id, |
| 1391 | .id_result = result_id, | 1382 | .id_result = result_id, |
| 1392 | .base = base_ptr, | 1383 | .base = base_ptr, |
| 1393 | .indexes = &.{rhs}, | 1384 | .indexes = &indexes, |
| 1394 | }); | 1385 | }); |
| 1395 | return result_id; | 1386 | return result_id; |
| 1396 | } | 1387 | } |
| ... | @@ -1412,11 +1403,12 @@ pub const DeclGen = struct { | ... | @@ -1412,11 +1403,12 @@ pub const DeclGen = struct { |
| 1412 | assert(struct_ty.zigTypeTag() == .Struct); // Cannot do unions yet. | 1403 | assert(struct_ty.zigTypeTag() == .Struct); // Cannot do unions yet. |
| 1413 | | 1404 | |
| 1414 | const result_id = self.spv.allocId(); | 1405 | const result_id = self.spv.allocId(); |
| | 1406 | const indexes = [_]u32{field_index}; |
| 1415 | try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{ | 1407 | try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{ |
| 1416 | .id_result_type = field_ty_id, | 1408 | .id_result_type = field_ty_id, |
| 1417 | .id_result = result_id, | 1409 | .id_result = result_id, |
| 1418 | .composite = object, | 1410 | .composite = object, |
| 1419 | .indexes = &.{field_index}, | 1411 | .indexes = &indexes, |
| 1420 | }); | 1412 | }); |
| 1421 | return result_id; | 1413 | return result_id; |
| 1422 | } | 1414 | } |
| ... | @@ -1433,20 +1425,16 @@ pub const DeclGen = struct { | ... | @@ -1433,20 +1425,16 @@ pub const DeclGen = struct { |
| 1433 | .Struct => switch (object_ty.containerLayout()) { | 1425 | .Struct => switch (object_ty.containerLayout()) { |
| 1434 | .Packed => unreachable, // TODO | 1426 | .Packed => unreachable, // TODO |
| 1435 | else => { | 1427 | else => { |
| 1436 | const field_index_id = self.spv.allocId(); | | |
| 1437 | const u32_ty_id = self.spv.typeResultId(try self.intType(.unsigned, 32)); | 1428 | const u32_ty_id = self.spv.typeResultId(try self.intType(.unsigned, 32)); |
| 1438 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpConstant, .{ | 1429 | const field_index_id = try self.spv.emitConstant(u32_ty_id, .{ .uint32 = field_index }); |
| 1439 | .id_result_type = u32_ty_id, | | |
| 1440 | .id_result = field_index_id, | | |
| 1441 | .value = .{ .uint32 = field_index }, | | |
| 1442 | }); | | |
| 1443 | const result_id = self.spv.allocId(); | 1430 | const result_id = self.spv.allocId(); |
| 1444 | const result_type_id = try self.resolveTypeId(result_ptr_ty); | 1431 | const result_type_id = try self.resolveTypeId(result_ptr_ty); |
| | 1432 | const indexes = [_]IdRef{field_index_id}; |
| 1445 | try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ | 1433 | try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{ |
| 1446 | .id_result_type = result_type_id, | 1434 | .id_result_type = result_type_id, |
| 1447 | .id_result = result_id, | 1435 | .id_result = result_id, |
| 1448 | .base = object_ptr, | 1436 | .base = object_ptr, |
| 1449 | .indexes = &.{field_index_id}, | 1437 | .indexes = &indexes, |
| 1450 | }); | 1438 | }); |
| 1451 | return result_id; | 1439 | return result_id; |
| 1452 | }, | 1440 | }, |
| ... | @@ -1591,28 +1579,51 @@ pub const DeclGen = struct { | ... | @@ -1591,28 +1579,51 @@ pub const DeclGen = struct { |
| 1591 | }); | 1579 | }); |
| 1592 | } | 1580 | } |
| 1593 | | 1581 | |
| 1594 | fn airLoad(self: *DeclGen, inst: Air.Inst.Index) !IdRef { | 1582 | fn airLoad(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 1595 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1583 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1596 | const operand_id = try self.resolve(ty_op.operand); | 1584 | const ptr_ty = self.air.typeOf(ty_op.operand); |
| 1597 | const ty = self.air.typeOfIndex(inst); | 1585 | const operand = try self.resolve(ty_op.operand); |
| | 1586 | if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null; |
| 1598 | | 1587 | |
| 1599 | const result_type_id = try self.resolveTypeId(ty); | 1588 | return try self.load(ptr_ty, operand); |
| 1600 | const result_id = self.spv.allocId(); | 1589 | } |
| 1601 | | 1590 | |
| | 1591 | fn load(self: *DeclGen, ptr_ty: Type, ptr: IdRef) !IdRef { |
| | 1592 | const value_ty = ptr_ty.childType(); |
| | 1593 | const result_type_id = try self.resolveTypeId(value_ty); |
| | 1594 | const result_id = self.spv.allocId(); |
| 1602 | const access = spec.MemoryAccess.Extended{ | 1595 | const access = spec.MemoryAccess.Extended{ |
| 1603 | .Volatile = ty.isVolatilePtr(), | 1596 | .Volatile = ptr_ty.isVolatilePtr(), |
| 1604 | }; | 1597 | }; |
| 1605 | | | |
| 1606 | try self.func.body.emit(self.spv.gpa, .OpLoad, .{ | 1598 | try self.func.body.emit(self.spv.gpa, .OpLoad, .{ |
| 1607 | .id_result_type = result_type_id, | 1599 | .id_result_type = result_type_id, |
| 1608 | .id_result = result_id, | 1600 | .id_result = result_id, |
| 1609 | .pointer = operand_id, | 1601 | .pointer = ptr, |
| 1610 | .memory_access = access, | 1602 | .memory_access = access, |
| 1611 | }); | 1603 | }); |
| 1612 | | | |
| 1613 | return result_id; | 1604 | return result_id; |
| 1614 | } | 1605 | } |
| 1615 | | 1606 | |
| | 1607 | fn airStore(self: *DeclGen, inst: Air.Inst.Index) !void { |
| | 1608 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| | 1609 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| | 1610 | const ptr = try self.resolve(bin_op.lhs); |
| | 1611 | const value = try self.resolve(bin_op.rhs); |
| | 1612 | |
| | 1613 | try self.store(ptr_ty, ptr, value); |
| | 1614 | } |
| | 1615 | |
| | 1616 | fn store(self: *DeclGen, ptr_ty: Type, ptr: IdRef, value: IdRef) !void { |
| | 1617 | const access = spec.MemoryAccess.Extended{ |
| | 1618 | .Volatile = ptr_ty.isVolatilePtr(), |
| | 1619 | }; |
| | 1620 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ |
| | 1621 | .pointer = ptr, |
| | 1622 | .object = value, |
| | 1623 | .memory_access = access, |
| | 1624 | }); |
| | 1625 | } |
| | 1626 | |
| 1616 | fn airLoop(self: *DeclGen, inst: Air.Inst.Index) !void { | 1627 | fn airLoop(self: *DeclGen, inst: Air.Inst.Index) !void { |
| 1617 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 1628 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1618 | const loop = self.air.extraData(Air.Block, ty_pl.payload); | 1629 | const loop = self.air.extraData(Air.Block, ty_pl.payload); |
| ... | @@ -1644,7 +1655,6 @@ pub const DeclGen = struct { | ... | @@ -1644,7 +1655,6 @@ pub const DeclGen = struct { |
| 1644 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 1655 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 1645 | const ptr_ty = self.air.typeOf(un_op); | 1656 | const ptr_ty = self.air.typeOf(un_op); |
| 1646 | const ret_ty = ptr_ty.childType(); | 1657 | const ret_ty = ptr_ty.childType(); |
| 1647 | const ret_ty_id = try self.resolveTypeId(ret_ty); | | |
| 1648 | | 1658 | |
| 1649 | if (!ret_ty.hasRuntimeBitsIgnoreComptime()) { | 1659 | if (!ret_ty.hasRuntimeBitsIgnoreComptime()) { |
| 1650 | try self.func.body.emit(self.spv.gpa, .OpReturn, {}); | 1660 | try self.func.body.emit(self.spv.gpa, .OpReturn, {}); |
| ... | @@ -1652,29 +1662,9 @@ pub const DeclGen = struct { | ... | @@ -1652,29 +1662,9 @@ pub const DeclGen = struct { |
| 1652 | } | 1662 | } |
| 1653 | | 1663 | |
| 1654 | const ptr = try self.resolve(un_op); | 1664 | const ptr = try self.resolve(un_op); |
| 1655 | const result_id = self.spv.allocId(); | 1665 | const value = try self.load(ptr_ty, ptr); |
| 1656 | try self.func.body.emit(self.spv.gpa, .OpLoad, .{ | 1666 | try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ |
| 1657 | .id_result_type = ret_ty_id, | 1667 | .value = value, |
| 1658 | .id_result = result_id, | | |
| 1659 | .pointer = ptr, | | |
| 1660 | }); | | |
| 1661 | try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = result_id }); | | |
| 1662 | } | | |
| 1663 | | | |
| 1664 | fn airStore(self: *DeclGen, inst: Air.Inst.Index) !void { | | |
| 1665 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | | |
| 1666 | const dst_ptr_id = try self.resolve(bin_op.lhs); | | |
| 1667 | const src_val_id = try self.resolve(bin_op.rhs); | | |
| 1668 | const lhs_ty = self.air.typeOf(bin_op.lhs); | | |
| 1669 | | | |
| 1670 | const access = spec.MemoryAccess.Extended{ | | |
| 1671 | .Volatile = lhs_ty.isVolatilePtr(), | | |
| 1672 | }; | | |
| 1673 | | | |
| 1674 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ | | |
| 1675 | .pointer = dst_ptr_id, | | |
| 1676 | .object = src_val_id, | | |
| 1677 | .memory_access = access, | | |
| 1678 | }); | 1668 | }); |
| 1679 | } | 1669 | } |
| 1680 | | 1670 | |
| ... | @@ -1691,7 +1681,7 @@ pub const DeclGen = struct { | ... | @@ -1691,7 +1681,7 @@ pub const DeclGen = struct { |
| 1691 | const backing_bits = self.backingIntBits(bits) orelse { | 1681 | const backing_bits = self.backingIntBits(bits) orelse { |
| 1692 | return self.todo("implement composite int switch", .{}); | 1682 | return self.todo("implement composite int switch", .{}); |
| 1693 | }; | 1683 | }; |
| 1694 | break :blk if (backing_bits <= 32) 1 else 2; | 1684 | break :blk if (backing_bits <= 32) @as(u32, 1) else 2; |
| 1695 | }, | 1685 | }, |
| 1696 | .Enum => blk: { | 1686 | .Enum => blk: { |
| 1697 | var buffer: Type.Payload.Bits = undefined; | 1687 | var buffer: Type.Payload.Bits = undefined; |
| ... | @@ -1700,7 +1690,7 @@ pub const DeclGen = struct { | ... | @@ -1700,7 +1690,7 @@ pub const DeclGen = struct { |
| 1700 | const backing_bits = self.backingIntBits(int_info.bits) orelse { | 1690 | const backing_bits = self.backingIntBits(int_info.bits) orelse { |
| 1701 | return self.todo("implement composite int switch", .{}); | 1691 | return self.todo("implement composite int switch", .{}); |
| 1702 | }; | 1692 | }; |
| 1703 | break :blk if (backing_bits <= 32) 1 else 2; | 1693 | break :blk if (backing_bits <= 32) @as(u32, 1) else 2; |
| 1704 | }, | 1694 | }, |
| 1705 | else => return self.todo("implement switch for type {s}", .{@tagName(cond_ty.zigTypeTag())}), // TODO: Figure out which types apply here, and work around them as we can only do integers. | 1695 | else => return self.todo("implement switch for type {s}", .{@tagName(cond_ty.zigTypeTag())}), // TODO: Figure out which types apply here, and work around them as we can only do integers. |
| 1706 | }; | 1696 | }; |