diff options
| author | Koakuma <koachan@protonmail.com> | 2022-05-27 23:00:11 +0700 |
|---|---|---|
| committer | Koakuma <koachan@protonmail.com> | 2022-06-06 20:34:53 +0700 |
| commit | 9db81fee5df6abcf1eb1212ecc005d22f7b2ca32 (patch) | |
| tree | e7c6bbf98437642e2480b869bafc1b8b810f8894 /src/arch/sparc64/CodeGen.zig | |
| parent | 3d662cfaf4579cb01546c3e5123eece70fd60b9a (diff) | |
| download | zig-9db81fee5df6abcf1eb1212ecc005d22f7b2ca32.tar.gz zig-9db81fee5df6abcf1eb1212ecc005d22f7b2ca32.zip | |
stage2: sparc64: Implement airStructFieldVal
Diffstat (limited to 'src/arch/sparc64/CodeGen.zig')
| -rw-r--r-- | src/arch/sparc64/CodeGen.zig | 92 |
1 files changed, 85 insertions, 7 deletions
diff --git a/src/arch/sparc64/CodeGen.zig b/src/arch/sparc64/CodeGen.zig index 088ee8dcdb..f63995cf5c 100644 --- a/src/arch/sparc64/CodeGen.zig +++ b/src/arch/sparc64/CodeGen.zig @@ -592,7 +592,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .ret_load => try self.airRetLoad(inst), .store => try self.airStore(inst), .struct_field_ptr=> @panic("TODO try self.airStructFieldPtr(inst)"), - .struct_field_val=> @panic("TODO try self.airStructFieldVal(inst)"), + .struct_field_val=> try self.airStructFieldVal(inst), .array_to_slice => @panic("TODO try self.airArrayToSlice(inst)"), .int_to_float => @panic("TODO try self.airIntToFloat(inst)"), .float_to_int => @panic("TODO try self.airFloatToInt(inst)"), @@ -1598,6 +1598,75 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); } +fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { + const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; + const extra = self.air.extraData(Air.StructField, ty_pl.payload).data; + const operand = extra.struct_operand; + const index = extra.field_index; + const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { + const mcv = try self.resolveInst(operand); + const struct_ty = self.air.typeOf(operand); + const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); + + switch (mcv) { + .dead, .unreach => unreachable, + .stack_offset => |off| { + break :result MCValue{ .stack_offset = off - struct_field_offset }; + }, + .memory => |addr| { + break :result MCValue{ .memory = addr + struct_field_offset }; + }, + .register_with_overflow => |rwo| { + switch (index) { + 0 => { + // get wrapped value: return register + break :result MCValue{ .register = rwo.reg }; + }, + 1 => { + // TODO return special MCValue condition flags + // get overflow bit: set register to C flag + // resp. V flag + const dest_reg = try self.register_manager.allocReg(null, gp); + + // TODO handle floating point CCRs + assert(rwo.flag.ccr == .xcc or rwo.flag.ccr == .icc); + + _ = try self.addInst(.{ + .tag = .mov, + .data = .{ + .arithmetic_2op = .{ + .is_imm = false, + .rs1 = dest_reg, + .rs2_or_imm = .{ .rs2 = .g0 }, + }, + }, + }); + + _ = try self.addInst(.{ + .tag = .movcc, + .data = .{ + .conditional_move = .{ + .ccr = rwo.flag.ccr, + .cond = .{ .icond = rwo.flag.cond }, + .is_imm = true, + .rd = dest_reg, + .rs2_or_imm = .{ .imm = 1 }, + }, + }, + }); + + break :result MCValue{ .register = dest_reg }; + }, + else => unreachable, + } + }, + else => return self.fail("TODO implement codegen struct_field_val for {}", .{mcv}), + } + }; + + return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none }); +} + fn airSwitch(self: *Self, inst: Air.Inst.Index) !void { _ = self; _ = inst; @@ -1664,8 +1733,8 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u if (abi_align > self.stack_align) self.stack_align = abi_align; // TODO find a free slot instead of always appending - const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align); - self.next_stack_offset = offset + abi_size; + const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size; + self.next_stack_offset = offset; if (self.next_stack_offset > self.max_end_stack) self.max_end_stack = self.next_stack_offset; try self.stack.putNoClobber(self.gpa, offset, .{ @@ -2436,8 +2505,9 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void return self.genSetReg(ty, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa }); }, .ptr_stack_offset => |off| { - const simm13 = math.cast(u12, off + abi.stack_bias + abi.stack_reserved_area) orelse - return self.fail("TODO larger stack offsets", .{}); + const real_offset = off + abi.stack_bias + abi.stack_reserved_area; + const simm13 = math.cast(i13, real_offset) orelse + return self.fail("TODO larger stack offsets: {}", .{real_offset}); _ = try self.addInst(.{ .tag = .add, @@ -2571,7 +2641,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void .stack_offset => |off| { const real_offset = off + abi.stack_bias + abi.stack_reserved_area; const simm13 = math.cast(i13, real_offset) orelse - return self.fail("TODO larger stack offsets", .{}); + return self.fail("TODO larger stack offsets: {}", .{real_offset}); try self.genLoad(reg, .sp, i13, simm13, ty.abiSize(self.target.*)); }, } @@ -2605,7 +2675,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro .register => |reg| { const real_offset = stack_offset + abi.stack_bias + abi.stack_reserved_area; const simm13 = math.cast(i13, real_offset) orelse - return self.fail("TODO larger stack offsets", .{}); + return self.fail("TODO larger stack offsets: {}", .{real_offset}); return self.genStore(reg, .sp, i13, simm13, abi_size); }, .register_with_overflow => |rwo| { @@ -3198,6 +3268,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void { .compare_flags_signed, .compare_flags_unsigned, => try self.allocRegOrMem(inst_to_save, true), + .register_with_overflow => try self.allocRegOrMem(inst_to_save, false), else => unreachable, // mcv doesn't occupy the compare flags }; @@ -3208,6 +3279,13 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void { try branch.inst_table.put(self.gpa, inst_to_save, new_mcv); self.compare_flags_inst = null; + + // TODO consolidate with register manager and spillInstruction + // this call should really belong in the register manager! + switch (mcv) { + .register_with_overflow => |rwo| self.register_manager.freeReg(rwo.reg), + else => {}, + } } } |
