| ... | ... | @@ -2882,10 +2882,42 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2882 | 2882 | |
| 2883 | 2883 | fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 2884 | 2884 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2885 | | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement .optional_payload for {}", .{self.target.cpu.arch}); |
| 2885 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 2886 | const optional_ty = self.air.typeOf(ty_op.operand); |
| 2887 | const mcv = try self.resolveInst(ty_op.operand); |
| 2888 | break :result try self.optionalPayload(inst, mcv, optional_ty); |
| 2889 | }; |
| 2886 | 2890 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 2887 | 2891 | } |
| 2888 | 2892 | |
| 2893 | fn optionalPayload(self: *Self, inst: Air.Inst.Index, mcv: MCValue, optional_ty: Type) !MCValue { |
| 2894 | var opt_buf: Type.Payload.ElemType = undefined; |
| 2895 | const payload_ty = optional_ty.optionalChild(&opt_buf); |
| 2896 | if (!payload_ty.hasRuntimeBits()) return MCValue.none; |
| 2897 | if (optional_ty.isPtrLikeOptional()) { |
| 2898 | // TODO should we reuse the operand here? |
| 2899 | const raw_reg = try self.register_manager.allocReg(inst, gp); |
| 2900 | const reg = self.registerAlias(raw_reg, payload_ty); |
| 2901 | try self.genSetReg(payload_ty, reg, mcv); |
| 2902 | return MCValue{ .register = reg }; |
| 2903 | } |
| 2904 | |
| 2905 | const offset = @intCast(u32, optional_ty.abiSize(self.target.*) - payload_ty.abiSize(self.target.*)); |
| 2906 | switch (mcv) { |
| 2907 | .register => return self.fail("TODO optionalPayload for registers", .{}), |
| 2908 | .stack_argument_offset => |off| { |
| 2909 | return MCValue{ .stack_argument_offset = off + offset }; |
| 2910 | }, |
| 2911 | .stack_offset => |off| { |
| 2912 | return MCValue{ .stack_offset = off - offset }; |
| 2913 | }, |
| 2914 | .memory => |addr| { |
| 2915 | return MCValue{ .memory = addr + offset }; |
| 2916 | }, |
| 2917 | else => unreachable, // invalid MCValue for an error union |
| 2918 | } |
| 2919 | } |
| 2920 | |
| 2889 | 2921 | fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 2890 | 2922 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2891 | 2923 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement .optional_payload_ptr for {}", .{self.target.cpu.arch}); |