authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-17 17:32:23+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-18 09:14:15+01:00
log085c606b8739fac707e842069010661ed2ec8249
treea18c9bfc5a11d2def8aebf939e17a918e88cf494
parent6d3c7bd4362b8f2415bc1b0d7fee6b30668bdfcd

x64: implement slice_elem_ptr


2 files changed, 48 insertions(+), 42 deletions(-)

src/arch/x86_64/CodeGen.zig+48-39
......@@ -1500,52 +1500,60 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi
15001500 return reg;
15011501}
15021502
1503fn 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
15031547fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
15041548 const is_volatile = false; // TODO
15051549 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
15061550 const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .dead else result: {
15071551 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.*);
15141552 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
15151553 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);
15441555 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);
15491557 break :result dst_mcv;
15501558 };
15511559 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 {
15571565 const result: MCValue = if (self.liveness.isUnused(inst))
15581566 .dead
15591567 else
1560 return self.fail("TODO implement slice_elem_ptr for {}", .{self.target.cpu.arch});
1568 try self.genSliceElemPtr(extra.lhs, extra.rhs);
15611569 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
15621570}
15631571
......@@ -1571,6 +1579,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
15711579
15721580 const elem_ty = array_ty.childType();
15731581 const elem_abi_size = elem_ty.abiSize(self.target.*);
1582
15741583 const index_ty = self.air.typeOf(bin_op.rhs);
15751584 const index = try self.resolveInst(bin_op.rhs);
15761585 index.freezeIfRegister(&self.register_manager);
test/behavior/slice.zig-3
......@@ -261,7 +261,6 @@ fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
261261test "C pointer" {
262262 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
263263 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
264 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
265264
266265 var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
267266 var len: u32 = 10;
......@@ -302,7 +301,6 @@ fn sliceSum(comptime q: []const u8) i32 {
302301test "slice type with custom alignment" {
303302 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
304303 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
305 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
306304
307305 const LazilyResolvedType = struct {
308306 anything: i32,
......@@ -317,7 +315,6 @@ test "slice type with custom alignment" {
317315test "obtaining a null terminated slice" {
318316 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
319317 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
320 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
321318 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
322319
323320 // here we have a normal array