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...@@ -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}
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
1503fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {1547fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
1504 const is_volatile = false; // TODO1548 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);
15161554 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 .dead1566 .dead
1559 else1567 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}
15631571
...@@ -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 {
15711579
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);
test/behavior/slice.zig-3
...@@ -261,7 +261,6 @@ fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {...@@ -261,7 +261,6 @@ fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
261test "C pointer" {261test "C pointer" {
262 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;262 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
263 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;263 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
264 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
265264
266 var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";265 var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
267 var len: u32 = 10;266 var len: u32 = 10;
...@@ -302,7 +301,6 @@ fn sliceSum(comptime q: []const u8) i32 {...@@ -302,7 +301,6 @@ fn sliceSum(comptime q: []const u8) i32 {
302test "slice type with custom alignment" {301test "slice type with custom alignment" {
303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;302 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
304 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;303 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
305 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
306304
307 const LazilyResolvedType = struct {305 const LazilyResolvedType = struct {
308 anything: i32,306 anything: i32,
...@@ -317,7 +315,6 @@ test "slice type with custom alignment" {...@@ -317,7 +315,6 @@ test "slice type with custom alignment" {
317test "obtaining a null terminated slice" {315test "obtaining a null terminated slice" {
318 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;316 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
319 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;317 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
320 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
321 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO318 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
322319
323 // here we have a normal array320 // here we have a normal array