| ... | @@ -1358,24 +1358,28 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1358,24 +1358,28 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 1358 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 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 | fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { | 1378 | fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1362 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1379 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1363 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1380 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1364 | const mcv = try self.resolveInst(ty_op.operand); | 1381 | const mcv = try self.resolveInst(ty_op.operand); |
| 1365 | switch (mcv) { | 1382 | break :result try self.slicePtr(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 | } | | |
| 1379 | }; | 1383 | }; |
| 1380 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 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,7 +1413,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1409 | switch (mcv) { | 1413 | switch (mcv) { |
| 1410 | .dead, .unreach => unreachable, | 1414 | .dead, .unreach => unreachable, |
| 1411 | .ptr_stack_offset => |off| { | 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 | else => return self.fail("TODO implement ptr_slice_len_ptr for {}", .{mcv}), | 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,7 +1428,7 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1424 | switch (mcv) { | 1428 | switch (mcv) { |
| 1425 | .dead, .unreach => unreachable, | 1429 | .dead, .unreach => unreachable, |
| 1426 | .ptr_stack_offset => |off| { | 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 | else => return self.fail("TODO implement ptr_slice_ptr_ptr for {}", .{mcv}), | 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,15 +1459,17 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1455 | if (index_is_register) self.register_manager.freezeRegs(&.{index_mcv.register}); | 1459 | if (index_is_register) self.register_manager.freezeRegs(&.{index_mcv.register}); |
| 1456 | defer if (index_is_register) self.register_manager.unfreezeRegs(&.{index_mcv.register}); | 1460 | defer if (index_is_register) self.register_manager.unfreezeRegs(&.{index_mcv.register}); |
| 1457 | | 1461 | |
| 1458 | const base_mcv: MCValue = switch (slice_mcv) { | 1462 | const base_mcv = try self.slicePtr(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}); | | |
| 1464 | | 1463 | |
| 1465 | switch (elem_size) { | 1464 | switch (elem_size) { |
| 1466 | 1, 4 => { | 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 | const dst_reg = try self.register_manager.allocReg(inst); | 1473 | const dst_reg = try self.register_manager.allocReg(inst); |
| 1468 | const dst_mcv = MCValue{ .register = dst_reg }; | 1474 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 1469 | self.register_manager.freezeRegs(&.{dst_reg}); | 1475 | self.register_manager.freezeRegs(&.{dst_reg}); |
| ... | @@ -1491,13 +1497,11 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1491,13 +1497,11 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1491 | .tag = tag, | 1497 | .tag = tag, |
| 1492 | .data = .{ .rr_offset = .{ | 1498 | .data = .{ .rr_offset = .{ |
| 1493 | .rt = dst_reg, | 1499 | .rt = dst_reg, |
| 1494 | .rn = base_mcv.register, | 1500 | .rn = base_reg, |
| 1495 | .offset = .{ .offset = Instruction.Offset.reg(index_reg, .{ .lsl = shift }) }, | 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 | break :result dst_mcv; | 1505 | break :result dst_mcv; |
| 1502 | }, | 1506 | }, |
| 1503 | else => { | 1507 | else => { |
| ... | @@ -1515,7 +1519,16 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1515,7 +1519,16 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1515 | fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { | 1519 | fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1516 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 1520 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1517 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 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 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); | 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,7 +1548,15 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1535 | fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void { | 1548 | fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1536 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 1549 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1537 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 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 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); | 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,7 +1781,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1760 | try self.genStrRegister(value_reg, addr_reg, value_ty); | 1781 | try self.genStrRegister(value_reg, addr_reg, value_ty); |
| 1761 | }, | 1782 | }, |
| 1762 | else => { | 1783 | else => { |
| 1763 | if (value_ty.abiSize(self.target.*) <= 4) { | 1784 | if (elem_size <= 4) { |
| 1764 | const tmp_reg = try self.register_manager.allocReg(null); | 1785 | const tmp_reg = try self.register_manager.allocReg(null); |
| 1765 | self.register_manager.freezeRegs(&.{tmp_reg}); | 1786 | self.register_manager.freezeRegs(&.{tmp_reg}); |
| 1766 | defer self.register_manager.unfreezeRegs(&.{tmp_reg}); | 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,6 +1805,17 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1784 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); | 1805 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); |
| 1785 | }, | 1806 | }, |
| 1786 | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }), | 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 | else => return self.fail("TODO store {} to register", .{value}), | 1819 | else => return self.fail("TODO store {} to register", .{value}), |
| 1788 | } | 1820 | } |
| 1789 | | 1821 | |