| ... | ... | @@ -1358,24 +1358,28 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 1358 | 1358 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1359 | 1359 | } |
| 1360 | 1360 | |
| 1361 | fn slicePtr(self: *Self, mcv: MCValue) !MCValue { |
| 1362 | switch (mcv) { |
| 1363 | .dead, .unreach => unreachable, |
| 1364 | .register => unreachable, // a slice doesn't fit in one register |
| 1365 | .stack_argument_offset => |off| { |
| 1366 | return MCValue{ .stack_argument_offset = off + 4 }; |
| 1367 | }, |
| 1368 | .stack_offset => |off| { |
| 1369 | return MCValue{ .stack_offset = off + 4 }; |
| 1370 | }, |
| 1371 | .memory => |addr| { |
| 1372 | return MCValue{ .memory = addr }; |
| 1373 | }, |
| 1374 | else => return self.fail("TODO implement slice_ptr for {}", .{mcv}), |
| 1375 | } |
| 1376 | } |
| 1377 | |
| 1361 | 1378 | fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1362 | 1379 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1363 | 1380 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1364 | 1381 | const mcv = try self.resolveInst(ty_op.operand); |
| 1365 | | switch (mcv) { |
| 1366 | | .dead, .unreach => unreachable, |
| 1367 | | .register => unreachable, // a slice doesn't fit in one register |
| 1368 | | .stack_argument_offset => |off| { |
| 1369 | | break :result MCValue{ .stack_argument_offset = off + 4 }; |
| 1370 | | }, |
| 1371 | | .stack_offset => |off| { |
| 1372 | | break :result MCValue{ .stack_offset = off + 4 }; |
| 1373 | | }, |
| 1374 | | .memory => |addr| { |
| 1375 | | break :result MCValue{ .memory = addr }; |
| 1376 | | }, |
| 1377 | | else => return self.fail("TODO implement slice_ptr for {}", .{mcv}), |
| 1378 | | } |
| 1382 | break :result try self.slicePtr(mcv); |
| 1379 | 1383 | }; |
| 1380 | 1384 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1381 | 1385 | } |
| ... | ... | @@ -1409,7 +1413,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1409 | 1413 | switch (mcv) { |
| 1410 | 1414 | .dead, .unreach => unreachable, |
| 1411 | 1415 | .ptr_stack_offset => |off| { |
| 1412 | | break :result MCValue{ .ptr_stack_offset = off + 4 }; |
| 1416 | break :result MCValue{ .ptr_stack_offset = off }; |
| 1413 | 1417 | }, |
| 1414 | 1418 | else => return self.fail("TODO implement ptr_slice_len_ptr for {}", .{mcv}), |
| 1415 | 1419 | } |
| ... | ... | @@ -1424,7 +1428,7 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1424 | 1428 | switch (mcv) { |
| 1425 | 1429 | .dead, .unreach => unreachable, |
| 1426 | 1430 | .ptr_stack_offset => |off| { |
| 1427 | | break :result MCValue{ .ptr_stack_offset = off }; |
| 1431 | break :result MCValue{ .ptr_stack_offset = off + 4 }; |
| 1428 | 1432 | }, |
| 1429 | 1433 | else => return self.fail("TODO implement ptr_slice_ptr_ptr for {}", .{mcv}), |
| 1430 | 1434 | } |
| ... | ... | @@ -1455,15 +1459,17 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1455 | 1459 | if (index_is_register) self.register_manager.freezeRegs(&.{index_mcv.register}); |
| 1456 | 1460 | defer if (index_is_register) self.register_manager.unfreezeRegs(&.{index_mcv.register}); |
| 1457 | 1461 | |
| 1458 | | const base_mcv: MCValue = switch (slice_mcv) { |
| 1459 | | .stack_offset => |off| .{ .register = try self.copyToTmpRegister(slice_ptr_field_type, .{ .stack_offset = off + 4 }) }, |
| 1460 | | .stack_argument_offset => |off| .{ .register = try self.copyToTmpRegister(slice_ptr_field_type, .{ .stack_argument_offset = off + 4 }) }, |
| 1461 | | else => return self.fail("TODO slice_elem_val when slice is {}", .{slice_mcv}), |
| 1462 | | }; |
| 1463 | | self.register_manager.freezeRegs(&.{base_mcv.register}); |
| 1462 | const base_mcv = try self.slicePtr(slice_mcv); |
| 1464 | 1463 | |
| 1465 | 1464 | switch (elem_size) { |
| 1466 | 1465 | 1, 4 => { |
| 1466 | const base_reg = switch (base_mcv) { |
| 1467 | .register => |r| r, |
| 1468 | else => try self.copyToTmpRegister(slice_ptr_field_type, base_mcv), |
| 1469 | }; |
| 1470 | self.register_manager.freezeRegs(&.{base_reg}); |
| 1471 | defer self.register_manager.unfreezeRegs(&.{base_reg}); |
| 1472 | |
| 1467 | 1473 | const dst_reg = try self.register_manager.allocReg(inst); |
| 1468 | 1474 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 1469 | 1475 | self.register_manager.freezeRegs(&.{dst_reg}); |
| ... | ... | @@ -1491,13 +1497,11 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1491 | 1497 | .tag = tag, |
| 1492 | 1498 | .data = .{ .rr_offset = .{ |
| 1493 | 1499 | .rt = dst_reg, |
| 1494 | | .rn = base_mcv.register, |
| 1500 | .rn = base_reg, |
| 1495 | 1501 | .offset = .{ .offset = Instruction.Offset.reg(index_reg, .{ .lsl = shift }) }, |
| 1496 | 1502 | } }, |
| 1497 | 1503 | }); |
| 1498 | 1504 | |
| 1499 | | self.register_manager.unfreezeRegs(&.{base_mcv.register}); |
| 1500 | | |
| 1501 | 1505 | break :result dst_mcv; |
| 1502 | 1506 | }, |
| 1503 | 1507 | else => { |
| ... | ... | @@ -1515,7 +1519,16 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1515 | 1519 | fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1516 | 1520 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1517 | 1521 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 1518 | | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice_elem_ptr for {}", .{self.target.cpu.arch}); |
| 1522 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1523 | const slice_mcv = try self.resolveInst(extra.lhs); |
| 1524 | const index_mcv = try self.resolveInst(extra.rhs); |
| 1525 | const base_mcv = try self.slicePtr(slice_mcv); |
| 1526 | |
| 1527 | const slice_ty = self.air.typeOf(extra.lhs); |
| 1528 | |
| 1529 | const addr = try self.binOp(.ptr_add, null, base_mcv, index_mcv, slice_ty, Type.usize); |
| 1530 | break :result addr; |
| 1531 | }; |
| 1519 | 1532 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); |
| 1520 | 1533 | } |
| 1521 | 1534 | |
| ... | ... | @@ -1535,7 +1548,15 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1535 | 1548 | fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1536 | 1549 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1537 | 1550 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 1538 | | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement ptr_elem_ptr for {}", .{self.target.cpu.arch}); |
| 1551 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1552 | const ptr_mcv = try self.resolveInst(extra.lhs); |
| 1553 | const index_mcv = try self.resolveInst(extra.rhs); |
| 1554 | |
| 1555 | const ptr_ty = self.air.typeOf(extra.lhs); |
| 1556 | |
| 1557 | const addr = try self.binOp(.ptr_add, null, ptr_mcv, index_mcv, ptr_ty, Type.usize); |
| 1558 | break :result addr; |
| 1559 | }; |
| 1539 | 1560 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); |
| 1540 | 1561 | } |
| 1541 | 1562 | |
| ... | ... | @@ -1760,7 +1781,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1760 | 1781 | try self.genStrRegister(value_reg, addr_reg, value_ty); |
| 1761 | 1782 | }, |
| 1762 | 1783 | else => { |
| 1763 | | if (value_ty.abiSize(self.target.*) <= 4) { |
| 1784 | if (elem_size <= 4) { |
| 1764 | 1785 | const tmp_reg = try self.register_manager.allocReg(null); |
| 1765 | 1786 | self.register_manager.freezeRegs(&.{tmp_reg}); |
| 1766 | 1787 | defer self.register_manager.unfreezeRegs(&.{tmp_reg}); |
| ... | ... | @@ -1784,6 +1805,17 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1784 | 1805 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); |
| 1785 | 1806 | }, |
| 1786 | 1807 | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }), |
| 1808 | .stack_argument_offset => |unadjusted_off| { |
| 1809 | const adj_off = unadjusted_off + elem_size; |
| 1810 | |
| 1811 | _ = try self.addInst(.{ |
| 1812 | .tag = .ldr_ptr_stack_argument, |
| 1813 | .data = .{ .r_stack_offset = .{ |
| 1814 | .rt = src_reg, |
| 1815 | .stack_offset = adj_off, |
| 1816 | } }, |
| 1817 | }); |
| 1818 | }, |
| 1787 | 1819 | else => return self.fail("TODO store {} to register", .{value}), |
| 1788 | 1820 | } |
| 1789 | 1821 | |