authorgravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-05-27 23:00:11+07:00
committergravatar for koachan@protonmail.comKoakuma <koachan@protonmail.com> 2022-06-06 20:34:53+07:00
log9db81fee5df6abcf1eb1212ecc005d22f7b2ca32
treee7c6bbf98437642e2480b869bafc1b8b810f8894
parent3d662cfaf4579cb01546c3e5123eece70fd60b9a

stage2: sparc64: Implement airStructFieldVal


1 files changed, 85 insertions(+), 7 deletions(-)

src/arch/sparc64/CodeGen.zig+85-7
......@@ -592,7 +592,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
592592 .ret_load => try self.airRetLoad(inst),
593593 .store => try self.airStore(inst),
594594 .struct_field_ptr=> @panic("TODO try self.airStructFieldPtr(inst)"),
595 .struct_field_val=> @panic("TODO try self.airStructFieldVal(inst)"),
595 .struct_field_val=> try self.airStructFieldVal(inst),
596596 .array_to_slice => @panic("TODO try self.airArrayToSlice(inst)"),
597597 .int_to_float => @panic("TODO try self.airIntToFloat(inst)"),
598598 .float_to_int => @panic("TODO try self.airFloatToInt(inst)"),
......@@ -1598,6 +1598,75 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
15981598 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
15991599}
16001600
1601fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
1602 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1603 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
1604 const operand = extra.struct_operand;
1605 const index = extra.field_index;
1606 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1607 const mcv = try self.resolveInst(operand);
1608 const struct_ty = self.air.typeOf(operand);
1609 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));
1610
1611 switch (mcv) {
1612 .dead, .unreach => unreachable,
1613 .stack_offset => |off| {
1614 break :result MCValue{ .stack_offset = off - struct_field_offset };
1615 },
1616 .memory => |addr| {
1617 break :result MCValue{ .memory = addr + struct_field_offset };
1618 },
1619 .register_with_overflow => |rwo| {
1620 switch (index) {
1621 0 => {
1622 // get wrapped value: return register
1623 break :result MCValue{ .register = rwo.reg };
1624 },
1625 1 => {
1626 // TODO return special MCValue condition flags
1627 // get overflow bit: set register to C flag
1628 // resp. V flag
1629 const dest_reg = try self.register_manager.allocReg(null, gp);
1630
1631 // TODO handle floating point CCRs
1632 assert(rwo.flag.ccr == .xcc or rwo.flag.ccr == .icc);
1633
1634 _ = try self.addInst(.{
1635 .tag = .mov,
1636 .data = .{
1637 .arithmetic_2op = .{
1638 .is_imm = false,
1639 .rs1 = dest_reg,
1640 .rs2_or_imm = .{ .rs2 = .g0 },
1641 },
1642 },
1643 });
1644
1645 _ = try self.addInst(.{
1646 .tag = .movcc,
1647 .data = .{
1648 .conditional_move = .{
1649 .ccr = rwo.flag.ccr,
1650 .cond = .{ .icond = rwo.flag.cond },
1651 .is_imm = true,
1652 .rd = dest_reg,
1653 .rs2_or_imm = .{ .imm = 1 },
1654 },
1655 },
1656 });
1657
1658 break :result MCValue{ .register = dest_reg };
1659 },
1660 else => unreachable,
1661 }
1662 },
1663 else => return self.fail("TODO implement codegen struct_field_val for {}", .{mcv}),
1664 }
1665 };
1666
1667 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
1668}
1669
16011670fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
16021671 _ = self;
16031672 _ = inst;
......@@ -1664,8 +1733,8 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u
16641733 if (abi_align > self.stack_align)
16651734 self.stack_align = abi_align;
16661735 // TODO find a free slot instead of always appending
1667 const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align);
1668 self.next_stack_offset = offset + abi_size;
1736 const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size;
1737 self.next_stack_offset = offset;
16691738 if (self.next_stack_offset > self.max_end_stack)
16701739 self.max_end_stack = self.next_stack_offset;
16711740 try self.stack.putNoClobber(self.gpa, offset, .{
......@@ -2436,8 +2505,9 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
24362505 return self.genSetReg(ty, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa });
24372506 },
24382507 .ptr_stack_offset => |off| {
2439 const simm13 = math.cast(u12, off + abi.stack_bias + abi.stack_reserved_area) orelse
2440 return self.fail("TODO larger stack offsets", .{});
2508 const real_offset = off + abi.stack_bias + abi.stack_reserved_area;
2509 const simm13 = math.cast(i13, real_offset) orelse
2510 return self.fail("TODO larger stack offsets: {}", .{real_offset});
24412511
24422512 _ = try self.addInst(.{
24432513 .tag = .add,
......@@ -2571,7 +2641,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
25712641 .stack_offset => |off| {
25722642 const real_offset = off + abi.stack_bias + abi.stack_reserved_area;
25732643 const simm13 = math.cast(i13, real_offset) orelse
2574 return self.fail("TODO larger stack offsets", .{});
2644 return self.fail("TODO larger stack offsets: {}", .{real_offset});
25752645 try self.genLoad(reg, .sp, i13, simm13, ty.abiSize(self.target.*));
25762646 },
25772647 }
......@@ -2605,7 +2675,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
26052675 .register => |reg| {
26062676 const real_offset = stack_offset + abi.stack_bias + abi.stack_reserved_area;
26072677 const simm13 = math.cast(i13, real_offset) orelse
2608 return self.fail("TODO larger stack offsets", .{});
2678 return self.fail("TODO larger stack offsets: {}", .{real_offset});
26092679 return self.genStore(reg, .sp, i13, simm13, abi_size);
26102680 },
26112681 .register_with_overflow => |rwo| {
......@@ -3198,6 +3268,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
31983268 .compare_flags_signed,
31993269 .compare_flags_unsigned,
32003270 => try self.allocRegOrMem(inst_to_save, true),
3271 .register_with_overflow => try self.allocRegOrMem(inst_to_save, false),
32013272 else => unreachable, // mcv doesn't occupy the compare flags
32023273 };
32033274
......@@ -3208,6 +3279,13 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
32083279 try branch.inst_table.put(self.gpa, inst_to_save, new_mcv);
32093280
32103281 self.compare_flags_inst = null;
3282
3283 // TODO consolidate with register manager and spillInstruction
3284 // this call should really belong in the register manager!
3285 switch (mcv) {
3286 .register_with_overflow => |rwo| self.register_manager.freeReg(rwo.reg),
3287 else => {},
3288 }
32113289 }
32123290}
32133291