| ... | ... | @@ -1500,52 +1500,60 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi |
| 1500 | 1500 | return reg; |
| 1501 | 1501 | } |
| 1502 | 1502 | |
| 1503 | fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { |
| 1504 | const slice_ty = self.air.typeOf(lhs); |
| 1505 | const slice_mcv = try self.resolveInst(lhs); |
| 1506 | slice_mcv.freezeIfRegister(&self.register_manager); |
| 1507 | defer slice_mcv.unfreezeIfRegister(&self.register_manager); |
| 1508 | |
| 1509 | const elem_ty = slice_ty.childType(); |
| 1510 | const elem_size = elem_ty.abiSize(self.target.*); |
| 1511 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 1512 | const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf); |
| 1513 | |
| 1514 | const index_ty = self.air.typeOf(rhs); |
| 1515 | const index_mcv = try self.resolveInst(rhs); |
| 1516 | index_mcv.freezeIfRegister(&self.register_manager); |
| 1517 | defer index_mcv.unfreezeIfRegister(&self.register_manager); |
| 1518 | |
| 1519 | const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_size); |
| 1520 | self.register_manager.freezeRegs(&.{offset_reg}); |
| 1521 | defer self.register_manager.unfreezeRegs(&.{offset_reg}); |
| 1522 | |
| 1523 | const addr_reg = try self.register_manager.allocReg(null); |
| 1524 | switch (slice_mcv) { |
| 1525 | .stack_offset => |off| { |
| 1526 | // mov reg, [rbp - 8] |
| 1527 | _ = try self.addInst(.{ |
| 1528 | .tag = .mov, |
| 1529 | .ops = (Mir.Ops{ |
| 1530 | .reg1 = addr_reg.to64(), |
| 1531 | .reg2 = .rbp, |
| 1532 | .flags = 0b01, |
| 1533 | }).encode(), |
| 1534 | .data = .{ .imm = @bitCast(u32, -@intCast(i32, off)) }, |
| 1535 | }); |
| 1536 | }, |
| 1537 | else => return self.fail("TODO implement slice_elem_ptr when slice is {}", .{slice_mcv}), |
| 1538 | } |
| 1539 | // TODO we could allocate register here, but need to expect addr register and potentially |
| 1540 | // offset register. |
| 1541 | try self.genBinMathOpMir(.add, slice_ptr_field_type, .{ .register = addr_reg.to64() }, .{ |
| 1542 | .register = offset_reg.to64(), |
| 1543 | }); |
| 1544 | return MCValue{ .register = addr_reg.to64() }; |
| 1545 | } |
| 1546 | |
| 1503 | 1547 | fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1504 | 1548 | const is_volatile = false; // TODO |
| 1505 | 1549 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1506 | 1550 | const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .dead else result: { |
| 1507 | 1551 | const slice_ty = self.air.typeOf(bin_op.lhs); |
| 1508 | | const slice_mcv = try self.resolveInst(bin_op.lhs); |
| 1509 | | slice_mcv.freezeIfRegister(&self.register_manager); |
| 1510 | | defer slice_mcv.unfreezeIfRegister(&self.register_manager); |
| 1511 | | |
| 1512 | | const elem_ty = slice_ty.childType(); |
| 1513 | | const elem_size = elem_ty.abiSize(self.target.*); |
| 1514 | 1552 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 1515 | 1553 | const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf); |
| 1516 | | |
| 1517 | | const index_ty = self.air.typeOf(bin_op.rhs); |
| 1518 | | const index_mcv = try self.resolveInst(bin_op.rhs); |
| 1519 | | index_mcv.freezeIfRegister(&self.register_manager); |
| 1520 | | defer index_mcv.unfreezeIfRegister(&self.register_manager); |
| 1521 | | |
| 1522 | | const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_size); |
| 1523 | | self.register_manager.freezeRegs(&.{offset_reg}); |
| 1524 | | defer self.register_manager.unfreezeRegs(&.{offset_reg}); |
| 1525 | | |
| 1526 | | const addr_reg = try self.register_manager.allocReg(null); |
| 1527 | | switch (slice_mcv) { |
| 1528 | | .stack_offset => |off| { |
| 1529 | | // mov reg, [rbp - 8] |
| 1530 | | _ = try self.addInst(.{ |
| 1531 | | .tag = .mov, |
| 1532 | | .ops = (Mir.Ops{ |
| 1533 | | .reg1 = addr_reg.to64(), |
| 1534 | | .reg2 = .rbp, |
| 1535 | | .flags = 0b01, |
| 1536 | | }).encode(), |
| 1537 | | .data = .{ .imm = @bitCast(u32, -@intCast(i32, off)) }, |
| 1538 | | }); |
| 1539 | | }, |
| 1540 | | else => return self.fail("TODO implement slice_elem_val when slice is {}", .{slice_mcv}), |
| 1541 | | } |
| 1542 | | // TODO we could allocate register here, but need to expect addr register and potentially |
| 1543 | | // offset register. |
| 1554 | const elem_ptr = try self.genSliceElemPtr(bin_op.lhs, bin_op.rhs); |
| 1544 | 1555 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 1545 | | try self.genBinMathOpMir(.add, slice_ptr_field_type, .{ .register = addr_reg.to64() }, .{ |
| 1546 | | .register = offset_reg.to64(), |
| 1547 | | }); |
| 1548 | | try self.load(dst_mcv, .{ .register = addr_reg.to64() }, slice_ptr_field_type); |
| 1556 | try self.load(dst_mcv, elem_ptr, slice_ptr_field_type); |
| 1549 | 1557 | break :result dst_mcv; |
| 1550 | 1558 | }; |
| 1551 | 1559 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| ... | ... | @@ -1557,7 +1565,7 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1557 | 1565 | const result: MCValue = if (self.liveness.isUnused(inst)) |
| 1558 | 1566 | .dead |
| 1559 | 1567 | else |
| 1560 | | return self.fail("TODO implement slice_elem_ptr for {}", .{self.target.cpu.arch}); |
| 1568 | try self.genSliceElemPtr(extra.lhs, extra.rhs); |
| 1561 | 1569 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); |
| 1562 | 1570 | } |
| 1563 | 1571 | |
| ... | ... | @@ -1571,6 +1579,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1571 | 1579 | |
| 1572 | 1580 | const elem_ty = array_ty.childType(); |
| 1573 | 1581 | const elem_abi_size = elem_ty.abiSize(self.target.*); |
| 1582 | |
| 1574 | 1583 | const index_ty = self.air.typeOf(bin_op.rhs); |
| 1575 | 1584 | const index = try self.resolveInst(bin_op.rhs); |
| 1576 | 1585 | index.freezeIfRegister(&self.register_manager); |