diff options
| author | joachimschmidt557 <joachim.schmidt557@outlook.com> | 2021-12-30 14:39:06 +0100 |
|---|---|---|
| committer | joachimschmidt557 <joachim.schmidt557@outlook.com> | 2021-12-30 14:39:06 +0100 |
| commit | 69d03d3a297809d1bc91ed5848501c64666244a1 (patch) | |
| tree | 05d08dc6e88e0d3ace9f2626b764a64c32c90624 /src | |
| parent | ac7fa95af471304c270a4ae1da4fe074610854d1 (diff) | |
| download | zig-69d03d3a297809d1bc91ed5848501c64666244a1.tar.gz zig-69d03d3a297809d1bc91ed5848501c64666244a1.zip | |
stage2 ARM: implement struct_field_ptr and struct_field_val
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/arm/CodeGen.zig | 72 | ||||
| -rw-r--r-- | src/codegen.zig | 23 | ||||
| -rw-r--r-- | src/register_manager.zig | 6 |
3 files changed, 79 insertions, 22 deletions
diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index fa40bc0c5a..7765064634 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -783,7 +783,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void { const stack_mcv = try self.allocRegOrMem(inst, false); - log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv }); + log.debug("spilling {} (%{d}) to stack mcv {any}", .{ reg, inst, stack_mcv }); const reg_mcv = self.getResolvedInstValue(inst); assert(reg == reg_mcv.register); 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 { fn airStructFieldPtr(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; - return self.structFieldPtr(extra.struct_operand, ty_pl.ty, extra.field_index); + const result = try self.structFieldPtr(inst, extra.struct_operand, extra.field_index); + return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none }); } fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void { const ty_op = self.air.instructions.items(.data)[inst].ty_op; - return self.structFieldPtr(ty_op.operand, ty_op.ty, index); + const result = try self.structFieldPtr(inst, ty_op.operand, index); + return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); } -fn structFieldPtr(self: *Self, operand: Air.Inst.Ref, ty: Air.Inst.Ref, index: u32) !void { - _ = self; - _ = operand; - _ = ty; - _ = index; - return self.fail("TODO implement codegen struct_field_ptr", .{}); - //return self.finishAir(inst, result, .{ extra.struct_ptr, .none, .none }); + +fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue { + return if (self.liveness.isUnused(inst)) .dead else result: { + const mcv = try self.resolveInst(operand); + const struct_ty = self.air.typeOf(operand).childType(); + const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*)); + const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); + const struct_field_ty = struct_ty.structFieldType(index); + const struct_field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*)); + switch (mcv) { + .ptr_stack_offset => |off| { + break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size }; + }, + else => return self.fail("TODO implement codegen struct_field_ptr for {}", .{mcv}), + } + }; } 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; - _ = extra; - return self.fail("TODO implement codegen struct_field_val", .{}); - //return self.finishAir(inst, result, .{ extra.struct_ptr, .none, .none }); + 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_size = @intCast(u32, struct_ty.abiSize(self.target.*)); + const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); + const struct_field_ty = struct_ty.structFieldType(index); + const struct_field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*)); + switch (mcv) { + .stack_offset => |off| { + break :result MCValue{ .stack_offset = off + struct_size - struct_field_offset - struct_field_size }; + }, + else => return self.fail("TODO implement codegen struct_field_val for {}", .{mcv}), + } + }; + + return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none }); } fn armOperandShouldBeRegister(self: *Self, mcv: MCValue) !bool { @@ -1985,11 +2011,11 @@ fn genArmMulConstant(self: *Self, inst: Air.Inst.Index, op: Air.Inst.Ref, op_ind // Allocate 1 or 2 registers if (lhs_is_register) { // Move RHS to register - dst_mcv = MCValue{ .register = try self.register_manager.allocReg(inst, &.{mcv.register}) }; + dst_mcv = MCValue{ .register = try self.register_manager.allocReg(null, &.{mcv.register}) }; rhs_mcv = dst_mcv; } else { // Move LHS and RHS to register - const regs = try self.register_manager.allocRegs(2, .{ inst, null }, &.{}); + const regs = try self.register_manager.allocRegs(2, .{ null, null }, &.{}); lhs_mcv = MCValue{ .register = regs[0] }; rhs_mcv = MCValue{ .register = regs[1] }; dst_mcv = lhs_mcv; @@ -2401,16 +2427,22 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { if (rhs_should_be_register) { if (!lhs_is_register and !rhs_is_register) { const regs = try self.register_manager.allocRegs(2, .{ - Air.refToIndex(bin_op.rhs).?, Air.refToIndex(bin_op.lhs).?, + Air.refToIndex(bin_op.lhs).?, Air.refToIndex(bin_op.rhs).?, }, &.{}); lhs_mcv = MCValue{ .register = regs[0] }; rhs_mcv = MCValue{ .register = regs[1] }; } else if (!rhs_is_register) { - rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(bin_op.rhs).?, &.{}) }; + const track_inst = if (self.liveness.operandDies(inst, 1)) null else Air.refToIndex(bin_op.rhs).?; + rhs_mcv = MCValue{ .register = try self.register_manager.allocReg(track_inst, &.{}) }; + } else if (!lhs_is_register) { + const track_inst = if (self.liveness.operandDies(inst, 0)) null else Air.refToIndex(bin_op.lhs).?; + lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(track_inst, &.{}) }; + } + } else { + if (!lhs_is_register) { + const track_inst = if (self.liveness.operandDies(inst, 0)) null else Air.refToIndex(bin_op.lhs).?; + lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(track_inst, &.{}) }; } - } - if (!lhs_is_register) { - lhs_mcv = MCValue{ .register = try self.register_manager.allocReg(Air.refToIndex(bin_op.lhs).?, &.{}) }; } // Move the operands to the newly allocated registers diff --git a/src/codegen.zig b/src/codegen.zig index f93c53804b..fdbdb7d5c1 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -372,11 +372,32 @@ pub fn generateSymbol( return Result{ .appended = {} }; }, .Struct => { + // TODO debug info + // TODO padding of struct members const field_vals = typed_value.val.castTag(.@"struct").?.data; - _ = field_vals; // TODO write the fields for real + for (field_vals) |field_val, index| { + const field_ty = typed_value.ty.structFieldType(index); + if (!field_ty.hasCodeGenBits()) continue; + switch (try generateSymbol(bin_file, src_loc, .{ + .ty = field_ty, + .val = field_val, + }, code, debug_output)) { + .appended => {}, + .externally_managed => |external_slice| { + code.appendSliceAssumeCapacity(external_slice); + }, + .fail => |em| return Result{ .fail = em }, + } + } + + return Result{ .appended = {} }; + }, + .Union => { + // TODO generateSymbol for unions const target = bin_file.options.target; const abi_size = try math.cast(usize, typed_value.ty.abiSize(target)); try code.writer().writeByteNTimes(0xaa, abi_size); + return Result{ .appended = {} }; }, else => |t| { diff --git a/src/register_manager.zig b/src/register_manager.zig index 43e19e2ca3..add0335374 100644 --- a/src/register_manager.zig +++ b/src/register_manager.zig @@ -129,7 +129,7 @@ pub fn RegisterManager( comptime assert(count > 0 and count <= callee_preserved_regs.len); assert(count + exceptions.len <= callee_preserved_regs.len); - return self.tryAllocRegs(count, insts, exceptions) orelse blk: { + const result = self.tryAllocRegs(count, insts, exceptions) orelse blk: { // We'll take over the first count registers. Spill // the instructions that were previously there to a // stack allocations. @@ -164,6 +164,9 @@ pub fn RegisterManager( break :blk regs; }; + + log.debug("allocated registers {any} for insts {any}", .{ result, insts }); + return result; } /// Allocates a register and optionally tracks it with a @@ -213,6 +216,7 @@ pub fn RegisterManager( /// Marks the specified register as free pub fn freeReg(self: *Self, reg: Register) void { const index = reg.allocIndex() orelse return; + log.debug("freeing register {}", .{reg}); self.registers[index] = null; self.markRegFree(reg); |
