diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-03-21 23:54:17 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-03-21 23:54:17 +0100 |
| commit | a9b6de693ce04f73f8aecce91e8033951024c123 (patch) | |
| tree | a4600da1abaa7a18f3af1595dbb38b09d10955f4 | |
| parent | 916a65cb7bc96e5faa9337ab541d1ae230b48259 (diff) | |
| parent | 00e2113c8b07f9d1c67c7c70b69e7b9e6343b2d9 (diff) | |
| download | zig-a9b6de693ce04f73f8aecce91e8033951024c123.tar.gz zig-a9b6de693ce04f73f8aecce91e8033951024c123.zip | |
Merge pull request #11223 from mparadinha/ptr-elem-val
stage2: x86_64: implement `ptr_elem_val`
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 52 | ||||
| -rw-r--r-- | test/behavior/basic.zig | 7 | ||||
| -rw-r--r-- | test/behavior/eval.zig | 1 |
3 files changed, 44 insertions, 16 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 37d93f870c..ce049a4541 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -2174,10 +2174,44 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { const is_volatile = false; // TODO const bin_op = self.air.instructions.items(.data)[inst].bin_op; - const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) - .dead - else - return self.fail("TODO implement ptr_elem_val for {}", .{self.target.cpu.arch}); + const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .dead else result: { + // this is identical to the `airPtrElemPtr` codegen expect here an + // additional `mov` is needed at the end to get the actual value + + const ptr_ty = self.air.typeOf(bin_op.lhs); + const ptr = try self.resolveInst(bin_op.lhs); + ptr.freezeIfRegister(&self.register_manager); + defer ptr.unfreezeIfRegister(&self.register_manager); + + const elem_ty = ptr_ty.elemType2(); + const elem_abi_size = elem_ty.abiSize(self.target.*); + const index_ty = self.air.typeOf(bin_op.rhs); + const index = try self.resolveInst(bin_op.rhs); + index.freezeIfRegister(&self.register_manager); + defer index.unfreezeIfRegister(&self.register_manager); + + const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size); + self.register_manager.freezeRegs(&.{offset_reg}); + defer self.register_manager.unfreezeRegs(&.{offset_reg}); + + const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr); + try self.genBinMathOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg }); + if (elem_abi_size > 8) { + return self.fail("TODO copy value with size {} from pointer", .{elem_abi_size}); + } else { + // mov dst_mcv, [dst_mcv] + _ = try self.addInst(.{ + .tag = .mov, + .ops = (Mir.Ops{ + .flags = 0b01, + .reg1 = registerAlias(dst_mcv.register, @intCast(u32, elem_abi_size)), + .reg2 = dst_mcv.register, + }).encode(), + .data = .{ .imm = 0 }, + }); + break :result .{ .register = registerAlias(dst_mcv.register, @intCast(u32, elem_abi_size)) }; + } + }; return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); } @@ -5166,7 +5200,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void if (!self.wantSafety()) return; // The already existing value will do just fine. // Write the debug undefined value. - switch (reg.size()) { + switch (registerAlias(reg, abi_size).size()) { 8 => return self.genSetReg(ty, reg, .{ .immediate = 0xaa }), 16 => return self.genSetReg(ty, reg, .{ .immediate = 0xaaaa }), 32 => return self.genSetReg(ty, reg, .{ .immediate = 0xaaaaaaaa }), @@ -5303,7 +5337,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void _ = try self.addInst(.{ .tag = .mov, .ops = (Mir.Ops{ - .reg1 = reg.to64(), + .reg1 = registerAlias(reg, abi_size), .reg2 = reg.to64(), .flags = 0b01, }).encode(), @@ -5316,7 +5350,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void _ = try self.addInst(.{ .tag = .mov, .ops = (Mir.Ops{ - .reg1 = reg, + .reg1 = registerAlias(reg, abi_size), .flags = 0b01, }).encode(), .data = .{ .imm = @truncate(u32, x) }, @@ -5343,8 +5377,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void _ = try self.addInst(.{ .tag = .mov, .ops = (Mir.Ops{ - .reg1 = reg, - .reg2 = reg, + .reg1 = registerAlias(reg, abi_size), + .reg2 = reg.to64(), .flags = 0b01, }).encode(), .data = .{ .imm = 0 }, diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index bee68d675c..9931c10f9a 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -382,7 +382,6 @@ fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA { test "take address of parameter" { 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; try testTakeAddressOfParameter(12.34); } @@ -408,7 +407,6 @@ fn testPointerToVoidReturnType2() *const void { test "array 2D const double ptr" { 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; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO const rect_2d_vertexes = [_][1]f32{ @@ -421,7 +419,6 @@ test "array 2D const double ptr" { test "array 2D const double ptr with offset" { 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; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; const rect_2d_vertexes = [_][2]f32{ @@ -434,7 +431,6 @@ test "array 2D const double ptr with offset" { test "array 3D const double ptr with offset" { 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; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO const rect_3d_vertexes = [_][2][2]f32{ @@ -519,7 +515,6 @@ var global_foo: *i32 = undefined; test "peer result location with typed parent, runtime condition, comptime prongs" { 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 S = struct { fn doTheTest(arg: i32) i32 { @@ -620,7 +615,6 @@ test "self reference through fn ptr field" { test "global variable initialized to global variable array element" { 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; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; @@ -655,7 +649,6 @@ test "global constant is loaded with a runtime-known index" { test "multiline string literal is null terminated" { 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 s1 = \\one diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig index c02bb9daa9..cce78b1944 100644 --- a/test/behavior/eval.zig +++ b/test/behavior/eval.zig @@ -424,6 +424,7 @@ test "f64 at compile time is lossy" { } test { + if (builtin.zig_backend != .stage1 and builtin.os.tag == .macos) return error.SkipZigTest; comptime try expect(@as(f128, 1 << 113) == 10384593717069655257060992658440192); } |
