diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-02-28 17:48:38 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-02-28 23:20:05 +0100 |
| commit | 05431d7c4a8cb20a3a70553ef0d0f8ed00a05402 (patch) | |
| tree | 39b2c28cad28f68af5c92a9e3ede7284110faeb2 | |
| parent | a7ca40b2817dbf3f2085141f32f20f431707391b (diff) | |
| download | zig-05431d7c4a8cb20a3a70553ef0d0f8ed00a05402.tar.gz zig-05431d7c4a8cb20a3a70553ef0d0f8ed00a05402.zip | |
x64: impl unwrap_errunion_payload and unwrap_errunion_err for register
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 66 | ||||
| -rw-r--r-- | test/behavior/error.zig | 4 |
2 files changed, 44 insertions, 26 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index f423671dcf..6bfea043c6 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -1738,14 +1738,22 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none }); } const err_union_ty = self.air.typeOf(ty_op.operand); + const err_ty = err_union_ty.errorUnionSet(); const payload_ty = err_union_ty.errorUnionPayload(); const operand = try self.resolveInst(ty_op.operand); + operand.freezeIfRegister(&self.register_manager); + defer operand.unfreezeIfRegister(&self.register_manager); + const result: MCValue = result: { if (!payload_ty.hasRuntimeBits()) break :result operand; switch (operand) { .stack_offset => |off| { break :result MCValue{ .stack_offset = off }; }, + .register => { + // TODO reuse operand + break :result try self.copyToRegisterWithInstTracking(inst, err_ty, operand); + }, else => return self.fail("TODO implement unwrap_err_err for {}", .{operand}), } }; @@ -1763,13 +1771,24 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void { if (!payload_ty.hasRuntimeBits()) break :result MCValue.none; const operand = try self.resolveInst(ty_op.operand); + operand.freezeIfRegister(&self.register_manager); + defer operand.unfreezeIfRegister(&self.register_manager); + const err_ty = err_union_ty.errorUnionSet(); - const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*)); switch (operand) { .stack_offset => |off| { + const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*)); const offset = off - @intCast(i32, err_abi_size); break :result MCValue{ .stack_offset = offset }; }, + .register => { + // TODO reuse operand + const result = try self.copyToRegisterWithInstTracking(inst, err_union_ty, operand); + try self.shiftRegister(result.register.to64(), @intCast(u6, err_ty.bitSize(self.target.*))); + break :result MCValue{ + .register = registerAlias(result.register, @intCast(u32, payload_ty.abiSize(self.target.*))), + }; + }, else => return self.fail("TODO implement unwrap_err_payload for {}", .{operand}), } }; @@ -2686,27 +2705,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { }; // Shift by struct_field_offset. - const shift_amount = @intCast(u8, struct_field_offset * 8); - if (shift_amount > 0) { - if (shift_amount == 1) { - _ = try self.addInst(.{ - .tag = .shr, - .ops = (Mir.Ops{ - .reg1 = dst_mcv.register, - }).encode(), - .data = undefined, - }); - } else { - _ = try self.addInst(.{ - .tag = .shr, - .ops = (Mir.Ops{ - .reg1 = dst_mcv.register, - .flags = 0b10, - }).encode(), - .data = .{ .imm = shift_amount }, - }); - } - } + const shift = @intCast(u8, struct_field_offset * 8); + try self.shiftRegister(dst_mcv.register, shift); // Mask with reg.size() - struct_field_size const mask_shift = @intCast(u6, (64 - struct_field_ty.bitSize(self.target.*))); @@ -5768,3 +5768,25 @@ fn registerAlias(reg: Register, size_bytes: u32) Register { unreachable; // TODO handle floating-point registers } } + +fn shiftRegister(self: *Self, reg: Register, shift: u8) !void { + if (shift == 0) return; + if (shift == 1) { + _ = try self.addInst(.{ + .tag = .shr, + .ops = (Mir.Ops{ + .reg1 = reg, + }).encode(), + .data = undefined, + }); + } else { + _ = try self.addInst(.{ + .tag = .shr, + .ops = (Mir.Ops{ + .reg1 = reg, + .flags = 0b10, + }).encode(), + .data = .{ .imm = shift }, + }); + } +} diff --git a/test/behavior/error.zig b/test/behavior/error.zig index ab58874c34..8e7ed3607e 100644 --- a/test/behavior/error.zig +++ b/test/behavior/error.zig @@ -78,7 +78,6 @@ fn unwrapSimpleValueFromErrorDo() anyerror!isize { } test "error return in assignment" { - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; @@ -121,7 +120,6 @@ test "widen cast integer payload of error union function call" { } test "debug info for optional error set" { - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; @@ -173,7 +171,6 @@ fn bar2() (error{}!void) {} test "error union type " { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO try testErrorUnionType(); @@ -191,7 +188,6 @@ fn testErrorUnionType() !void { test "error set type" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO try testErrorSetType(); |
