authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-12-30 14:39:06+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-12-30 14:39:06+01:00
log69d03d3a297809d1bc91ed5848501c64666244a1
tree05d08dc6e88e0d3ace9f2626b764a64c32c90624
parentac7fa95af471304c270a4ae1da4fe074610854d1
signaturelock-open Commit is signed but in an unrecognized format.

stage2 ARM: implement struct_field_ptr and struct_field_val


4 files changed, 125 insertions(+), 22 deletions(-)

src/arch/arm/CodeGen.zig+52-20
......@@ -783,7 +783,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
783783
784784pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void {
785785 const stack_mcv = try self.allocRegOrMem(inst, false);
786 log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv });
786 log.debug("spilling {} (%{d}) to stack mcv {any}", .{ reg, inst, stack_mcv });
787787 const reg_mcv = self.getResolvedInstValue(inst);
788788 assert(reg == reg_mcv.register);
789789 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
......@@ -1591,28 +1591,54 @@ fn airStore(self: *Self, inst: Air.Inst.Index) !void {
15911591fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void {
15921592 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
15931593 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
1594 return self.structFieldPtr(extra.struct_operand, ty_pl.ty, extra.field_index);
1594 const result = try self.structFieldPtr(inst, extra.struct_operand, extra.field_index);
1595 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
15951596}
15961597
15971598fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
15981599 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1599 return self.structFieldPtr(ty_op.operand, ty_op.ty, index);
1600 const result = try self.structFieldPtr(inst, ty_op.operand, index);
1601 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
16001602}
1601fn structFieldPtr(self: *Self, operand: Air.Inst.Ref, ty: Air.Inst.Ref, index: u32) !void {
1602 _ = self;
1603 _ = operand;
1604 _ = ty;
1605 _ = index;
1606 return self.fail("TODO implement codegen struct_field_ptr", .{});
1607 //return self.finishAir(inst, result, .{ extra.struct_ptr, .none, .none });
1603
1604fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
1605 return if (self.liveness.isUnused(inst)) .dead else result: {
1606 const mcv = try self.resolveInst(operand);
1607 const struct_ty = self.air.typeOf(operand).childType();
1608 const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*));
1609 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));
1610 const struct_field_ty = struct_ty.structFieldType(index);
1611 const struct_field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*));
1612 switch (mcv) {
1613 .ptr_stack_offset => |off| {
1614 break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size };
1615 },
1616 else => return self.fail("TODO implement codegen struct_field_ptr for {}", .{mcv}),
1617 }
1618 };
16081619}
16091620
16101621fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
16111622 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
16121623 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
1613 _ = extra;
1614 return self.fail("TODO implement codegen struct_field_val", .{});
1615 //return self.finishAir(inst, result, .{ extra.struct_ptr, .none, .none });
1624 const operand = extra.struct_operand;
1625 const index = extra.field_index;
1626 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1627 const mcv = try self.resolveInst(operand);
1628 const struct_ty = self.air.typeOf(operand);
1629 const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*));
1630 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));
1631 const struct_field_ty = struct_ty.structFieldType(index);
1632 const struct_field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*));
1633 switch (mcv) {
1634 .stack_offset => |off| {
1635 break :result MCValue{ .stack_offset = off + struct_size - struct_field_offset - struct_field_size };
1636 },
1637 else => return self.fail("TODO implement codegen struct_field_val for {}", .{mcv}),
1638 }
1639 };
1640
1641 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
16161642}
16171643
16181644fn armOperandShouldBeRegister(self: *Self, mcv: MCValue) !bool {
......@@ -1985,11 +2011,11 @@ fn genArmMulConstant(self: *Self, inst: Air.Inst.Index, op: Air.Inst.Ref, op_ind
19852011 // Allocate 1 or 2 registers
19862012 if (lhs_is_register) {
19872013 // Move RHS to register
1988 dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{mcv.register}) };
2014 dst_mcv = MCValue{ .register = try self.register_manager.allocReg(null, &.{mcv.register}) };
19892015 rhs_mcv = dst_mcv;
19902016 } else {
19912017 // Move LHS and RHS to register
1992 const regs = try self.register_manager.allocRegs(2, .{ inst, null }, &.{});
2018 const regs = try self.register_manager.allocRegs(2, .{ null, null }, &.{});
19932019 lhs_mcv = MCValue{ .register = regs[0] };
19942020 rhs_mcv = MCValue{ .register = regs[1] };
19952021 dst_mcv = lhs_mcv;
......@@ -2401,16 +2427,22 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
24012427 if (rhs_should_be_register) {
24022428 if (!lhs_is_register and !rhs_is_register) {
24032429 const regs = try self.register_manager.allocRegs(2, .{
2404 Air.refToIndex(bin_op.rhs).?, Air.refToIndex(bin_op.lhs).?,
2430 Air.refToIndex(bin_op.lhs).?, Air.refToIndex(bin_op.rhs).?,
24052431 }, &.{});
24062432 lhs_mcv = MCValue{ .register = regs[0] };
24072433 rhs_mcv = MCValue{ .register = regs[1] };
24082434 } else if (!rhs_is_register) {
2409 rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(bin_op.rhs).?, &.{}) };
2435 const track_inst = if (self.liveness.operandDies(inst, 1)) null else Air.refToIndex(bin_op.rhs).?;
2436 rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(track_inst, &.{}) };
2437 } else if (!lhs_is_register) {
2438 const track_inst = if (self.liveness.operandDies(inst, 0)) null else Air.refToIndex(bin_op.lhs).?;
2439 lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(track_inst, &.{}) };
2440 }
2441 } else {
2442 if (!lhs_is_register) {
2443 const track_inst = if (self.liveness.operandDies(inst, 0)) null else Air.refToIndex(bin_op.lhs).?;
2444 lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(track_inst, &.{}) };
24102445 }
2411 }
2412 if (!lhs_is_register) {
2413 lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(bin_op.lhs).?, &.{}) };
24142446 }
24152447
24162448 // Move the operands to the newly allocated registers
src/codegen.zig+22-1
......@@ -372,11 +372,32 @@ pub fn generateSymbol(
372372 return Result{ .appended = {} };
373373 },
374374 .Struct => {
375 // TODO debug info
376 // TODO padding of struct members
375377 const field_vals = typed_value.val.castTag(.@"struct").?.data;
376 _ = field_vals; // TODO write the fields for real
378 for (field_vals) |field_val, index| {
379 const field_ty = typed_value.ty.structFieldType(index);
380 if (!field_ty.hasCodeGenBits()) continue;
381 switch (try generateSymbol(bin_file, src_loc, .{
382 .ty = field_ty,
383 .val = field_val,
384 }, code, debug_output)) {
385 .appended => {},
386 .externally_managed => |external_slice| {
387 code.appendSliceAssumeCapacity(external_slice);
388 },
389 .fail => |em| return Result{ .fail = em },
390 }
391 }
392
393 return Result{ .appended = {} };
394 },
395 .Union => {
396 // TODO generateSymbol for unions
377397 const target = bin_file.options.target;
378398 const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));
379399 try code.writer().writeByteNTimes(0xaa, abi_size);
400
380401 return Result{ .appended = {} };
381402 },
382403 else => |t| {
src/register_manager.zig+5-1
......@@ -129,7 +129,7 @@ pub fn RegisterManager(
129129 comptime assert(count > 0 and count <= callee_preserved_regs.len);
130130 assert(count + exceptions.len <= callee_preserved_regs.len);
131131
132 return self.tryAllocRegs(count, insts, exceptions) orelse blk: {
132 const result = self.tryAllocRegs(count, insts, exceptions) orelse blk: {
133133 // We'll take over the first count registers. Spill
134134 // the instructions that were previously there to a
135135 // stack allocations.
......@@ -164,6 +164,9 @@ pub fn RegisterManager(
164164
165165 break :blk regs;
166166 };
167
168 log.debug("allocated registers {any} for insts {any}", .{ result, insts });
169 return result;
167170 }
168171
169172 /// Allocates a register and optionally tracks it with a
......@@ -213,6 +216,7 @@ pub fn RegisterManager(
213216 /// Marks the specified register as free
214217 pub fn freeReg(self: *Self, reg: Register) void {
215218 const index = reg.allocIndex() orelse return;
219 log.debug("freeing register {}", .{reg});
216220
217221 self.registers[index] = null;
218222 self.markRegFree(reg);
test/stage2/arm.zig+46
......@@ -658,4 +658,50 @@ pub fn addCases(ctx: *TestContext) !void {
658658 "",
659659 );
660660 }
661
662 {
663 var case = ctx.exe("structs", linux_arm);
664 case.addCompareOutput(
665 \\var array = [_]SomeStruct{
666 \\ .{ .a = 0, .b = 42, .c = 69 },
667 \\ .{ .a = 1, .b = 2, .c = 3 },
668 \\ .{ .a = 123, .b = 456, .c = 789 },
669 \\};
670 \\var s: []const SomeStruct = &array;
671 \\
672 \\var some_struct: SomeStruct = .{
673 \\ .a = 0,
674 \\ .b = 42,
675 \\ .c = 69,
676 \\};
677 \\
678 \\const SomeStruct = struct {
679 \\ a: u32,
680 \\ b: u32,
681 \\ c: u32,
682 \\};
683 \\
684 \\pub fn main() void {
685 \\ assert(some_struct.a == 0);
686 \\ assert(some_struct.b == 42);
687 \\ assert(some_struct.c == 69);
688 \\
689 \\ assert(s[0].a == 0);
690 \\ assert(s[0].b == 42);
691 \\ assert(s[0].c == 69);
692 \\ assert(s[1].a == 1);
693 \\ assert(s[1].b == 2);
694 \\ assert(s[1].c == 3);
695 \\ assert(s[2].a == 123);
696 \\ assert(s[2].b == 456);
697 \\ assert(s[2].c == 789);
698 \\}
699 \\
700 \\fn assert(ok: bool) void {
701 \\ if (!ok) unreachable;
702 \\}
703 ,
704 "",
705 );
706 }
661707}