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 /src | |
| parent | a7ca40b2817dbf3f2085141f32f20f431707391b (diff) | |
| download | zig-05431d7c4a8cb20a3a70553ef0d0f8ed00a05402.tar.gz zig-05431d7c4a8cb20a3a70553ef0d0f8ed00a05402.zip | |
x64: impl unwrap_errunion_payload and unwrap_errunion_err for register
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 66 |
1 files changed, 44 insertions, 22 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 }, + }); + } +} |
