| ... | @@ -1500,52 +1500,60 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi | ... | @@ -1500,52 +1500,60 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi |
| 1500 | return reg; | 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 | fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | 1547 | fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1504 | const is_volatile = false; // TODO | 1548 | const is_volatile = false; // TODO |
| 1505 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1549 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1506 | const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .dead else result: { | 1550 | const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .dead else result: { |
| 1507 | const slice_ty = self.air.typeOf(bin_op.lhs); | 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 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | 1552 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 1515 | const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf); | 1553 | const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf); |
| 1516 | | 1554 | const elem_ptr = try self.genSliceElemPtr(bin_op.lhs, bin_op.rhs); |
| 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. | | |
| 1544 | const dst_mcv = try self.allocRegOrMem(inst, false); | 1555 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 1545 | try self.genBinMathOpMir(.add, slice_ptr_field_type, .{ .register = addr_reg.to64() }, .{ | 1556 | try self.load(dst_mcv, elem_ptr, slice_ptr_field_type); |
| 1546 | .register = offset_reg.to64(), | | |
| 1547 | }); | | |
| 1548 | try self.load(dst_mcv, .{ .register = addr_reg.to64() }, slice_ptr_field_type); | | |
| 1549 | break :result dst_mcv; | 1557 | break :result dst_mcv; |
| 1550 | }; | 1558 | }; |
| 1551 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 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,7 +1565,7 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1557 | const result: MCValue = if (self.liveness.isUnused(inst)) | 1565 | const result: MCValue = if (self.liveness.isUnused(inst)) |
| 1558 | .dead | 1566 | .dead |
| 1559 | else | 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 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); | 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,6 +1579,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1571 | | 1579 | |
| 1572 | const elem_ty = array_ty.childType(); | 1580 | const elem_ty = array_ty.childType(); |
| 1573 | const elem_abi_size = elem_ty.abiSize(self.target.*); | 1581 | const elem_abi_size = elem_ty.abiSize(self.target.*); |
| | 1582 | |
| 1574 | const index_ty = self.air.typeOf(bin_op.rhs); | 1583 | const index_ty = self.air.typeOf(bin_op.rhs); |
| 1575 | const index = try self.resolveInst(bin_op.rhs); | 1584 | const index = try self.resolveInst(bin_op.rhs); |
| 1576 | index.freezeIfRegister(&self.register_manager); | 1585 | index.freezeIfRegister(&self.register_manager); |