| ... | @@ -2025,16 +2025,35 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2025,16 +2025,35 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2025 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 2025 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2026 | const mcv = try self.resolveInst(operand); | 2026 | const mcv = try self.resolveInst(operand); |
| 2027 | const struct_ty = self.air.typeOf(operand); | 2027 | const struct_ty = self.air.typeOf(operand); |
| 2028 | const struct_size = @intCast(i32, struct_ty.abiSize(self.target.*)); | 2028 | const struct_size = struct_ty.abiSize(self.target.*); |
| 2029 | const struct_field_offset = @intCast(i32, struct_ty.structFieldOffset(index, self.target.*)); | 2029 | const struct_field_offset = struct_ty.structFieldOffset(index, self.target.*); |
| 2030 | const struct_field_ty = struct_ty.structFieldType(index); | 2030 | const struct_field_ty = struct_ty.structFieldType(index); |
| 2031 | const struct_field_size = @intCast(i32, struct_field_ty.abiSize(self.target.*)); | 2031 | const struct_field_size = struct_field_ty.abiSize(self.target.*); |
| 2032 | | 2032 | |
| 2033 | switch (mcv) { | 2033 | switch (mcv) { |
| 2034 | .stack_offset => |off| { | 2034 | .stack_offset => |off| { |
| 2035 | const stack_offset = off + struct_size - struct_field_offset - struct_field_size; | 2035 | const offset_to_field = struct_size - struct_field_offset - struct_field_size; |
| | 2036 | const stack_offset = off + @intCast(i32, offset_to_field); |
| 2036 | break :result MCValue{ .stack_offset = stack_offset }; | 2037 | break :result MCValue{ .stack_offset = stack_offset }; |
| 2037 | }, | 2038 | }, |
| | 2039 | .register => |reg| { |
| | 2040 | // 1. Shift by struct_field_offset. |
| | 2041 | // 2. Mask with reg.size() - struct_field_size |
| | 2042 | // 3. Return in register |
| | 2043 | |
| | 2044 | // TODO check if register can be re-used |
| | 2045 | self.register_manager.freezeRegs(&.{reg}); |
| | 2046 | defer self.register_manager.unfreezeRegs(&.{reg}); |
| | 2047 | const dst_mcv = try self.copyToNewRegister(inst, Type.usize, .{ .register = reg.to64() }); |
| | 2048 | |
| | 2049 | // TODO shift here |
| | 2050 | |
| | 2051 | const mask_shift = @intCast(u6, (64 - struct_field_ty.bitSize(self.target.*))); |
| | 2052 | const mask = (~@as(u64, 0)) >> mask_shift; |
| | 2053 | try self.genBinMathOpMir(.@"and", Type.usize, dst_mcv, .{ .immediate = mask }); |
| | 2054 | |
| | 2055 | break :result dst_mcv; |
| | 2056 | }, |
| 2038 | else => return self.fail("TODO implement codegen struct_field_val for {}", .{mcv}), | 2057 | else => return self.fail("TODO implement codegen struct_field_val for {}", .{mcv}), |
| 2039 | } | 2058 | } |
| 2040 | }; | 2059 | }; |