diff options
| author | David Rubin <daviru007@icloud.com> | 2024-09-01 02:49:47 -0700 |
|---|---|---|
| committer | mlugg <mlugg@mlugg.co.uk> | 2024-09-01 17:34:06 +0100 |
| commit | fbac7afa0f280eb271e802046ae1f3f836a9f6b2 (patch) | |
| tree | 51c47833f3ec9c98f474cd61f0d4e2e3840d9df7 /src | |
| parent | 28383d4d985cd04c897f6b6a63bd2107d8e2a8e9 (diff) | |
| download | zig-fbac7afa0f280eb271e802046ae1f3f836a9f6b2.tar.gz zig-fbac7afa0f280eb271e802046ae1f3f836a9f6b2.zip | |
riscv: implement `errunion_payload_ptr_set`
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/riscv64/CodeGen.zig | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index a70618a394..1934cee7f5 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -3471,9 +3471,48 @@ fn airUnwrapErrPayloadPtr(func: *Func, inst: Air.Inst.Index) !void { return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); } +// *(E!T) => *T fn airErrUnionPayloadPtrSet(func: *Func, inst: Air.Inst.Index) !void { const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; - const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement .errunion_payload_ptr_set for {}", .{func.target.cpu.arch}); + const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: { + const zcu = func.pt.zcu; + const src_ty = func.typeOf(ty_op.operand); + const src_mcv = try func.resolveInst(ty_op.operand); + + // `src_reg` contains the pointer to the error union + const src_reg = switch (src_mcv) { + .register => |reg| reg, + else => try func.copyToTmpRegister(src_ty, src_mcv), + }; + const src_lock = func.register_manager.lockRegAssumeUnused(src_reg); + defer func.register_manager.unlockReg(src_lock); + + // we set the place of where the error would have been to 0 + const eu_ty = src_ty.childType(zcu); + const pl_ty = eu_ty.errorUnionPayload(zcu); + const err_ty = eu_ty.errorUnionSet(zcu); + const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, zcu)); + try func.genSetMem(.{ .reg = src_reg }, err_off, err_ty, .{ .immediate = 0 }); + + const dst_reg, const dst_lock = if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) + .{ src_reg, null } + else + try func.allocReg(.int); + defer if (dst_lock) |lock| func.register_manager.unlockReg(lock); + + // move the pointer to be at the payload + const pl_off = errUnionPayloadOffset(pl_ty, zcu); + try func.genBinOp( + .add, + .{ .register = src_reg }, + Type.u64, + .{ .immediate = pl_off }, + Type.u64, + dst_reg, + ); + + break :result .{ .register = dst_reg }; + }; return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); } |
