zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 78e6f9c44c054b922ed1eaafcc4534edcf2dc9ba (tree)
parent c7775a9f628a7fa971e85dec65e1400866ad012c
Author: Jakub Konka <kubkon@jakubkonka.com>
Date:   Fri, 11 Feb 2022 16:13:05 +0100

x64: fix ptr_add

However, still missing is taking into account pointer alignment
when performing arithmetic.

Diffstat:
Msrc/arch/x86_64/CodeGen.zig | 28+++++++++++++++++++++++++---
Mtest/behavior/align.zig | 1+
Mtest/behavior/array.zig | 1+
3 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig @@ -2217,7 +2217,26 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: // Now for step 2, we assing an MIR instruction const air_tags = self.air.instructions.items(.tag); switch (air_tags[inst]) { - .add, .addwrap, .ptr_add => try self.genBinMathOpMir(.add, dst_ty, dst_mcv, src_mcv), + .ptr_add => { + // TODO clean this up + // TODO take into account alignment + const elem_size = dst_ty.elemType2().abiSize(self.target.*); + const dst_reg = blk: { + switch (dst_mcv) { + .register => |reg| break :blk reg, + else => { + src_mcv.freezeIfRegister(&self.register_manager); + defer src_mcv.freezeIfRegister(&self.register_manager); + const reg = try self.copyToTmpRegister(dst_ty, dst_mcv); + break :blk reg; + }, + } + }; + try self.genIMulOpMir(dst_ty, .{ .register = dst_reg }, .{ .immediate = elem_size }); + dst_mcv = MCValue{ .register = dst_reg }; + try self.genBinMathOpMir(.add, dst_ty, dst_mcv, src_mcv); + }, + .add, .addwrap => try self.genBinMathOpMir(.add, dst_ty, dst_mcv, src_mcv), .bool_or, .bit_or => try self.genBinMathOpMir(.@"or", dst_ty, dst_mcv, src_mcv), .bool_and, .bit_and => try self.genBinMathOpMir(.@"and", dst_ty, dst_mcv, src_mcv), .sub, .subwrap => try self.genBinMathOpMir(.sub, dst_ty, dst_mcv, src_mcv), @@ -2244,8 +2263,11 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC .none => unreachable, .undef => try self.genSetReg(dst_ty, dst_reg, .undef), .dead, .unreach => unreachable, - .ptr_stack_offset => |off| { - return self.genBinMathOpMir(mir_tag, dst_ty, dst_mcv, .{ .immediate = @bitCast(u32, off) }); + .ptr_stack_offset => { + self.register_manager.freezeRegs(&.{dst_reg}); + defer self.register_manager.unfreezeRegs(&.{dst_reg}); + const reg = try self.copyToTmpRegister(dst_ty, src_mcv); + return self.genBinMathOpMir(mir_tag, dst_ty, dst_mcv, .{ .register = reg }); }, .ptr_embedded_in_code => unreachable, .register => |src_reg| { diff --git a/test/behavior/align.zig b/test/behavior/align.zig @@ -106,6 +106,7 @@ fn fnWithAlignedStack() i32 { test "implicitly decreasing slice alignment" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; const a: u32 align(4) = 3; const b: u32 align(8) = 4; diff --git a/test/behavior/array.zig b/test/behavior/array.zig @@ -8,6 +8,7 @@ const expectEqual = testing.expectEqual; test "array to slice" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; const a: u32 align(4) = 3; const b: u32 align(8) = 4;