authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-06-14 18:10:47+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-15 02:43:06-07:00
log11d0dfb8829f7a247b21b417157bafeebd6a2a90
treef78e3fe50d8d691196cfdddc11a7f8988c5cc3c0
parentce88c43a4ee94d82a64e7580885dc6693cc6120c

Sema: fix @intToPtr of zero value to optional pointer

Calling into coercion logic here is a little opaque, and more to the point wholly unnecessary. Instead, the (very short) logic is now implemented directly in Sema. Resolves: #16033

3 files changed, 31 insertions(+), 8 deletions(-)

src/Module.zig+2-7
...@@ -6817,17 +6817,12 @@ pub fn errorSetFromUnsortedNames(...@@ -6817,17 +6817,12 @@ pub fn errorSetFromUnsortedNames(
6817 return new_ty.toType();6817 return new_ty.toType();
6818}6818}
68196819
6820/// Supports optionals in addition to pointers.6820/// Supports only pointers, not pointer-like optionals.
6821pub fn ptrIntValue(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {6821pub fn ptrIntValue(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {
6822 return mod.getCoerced(try mod.intValue_u64(Type.usize, x), ty);
6823}
6824
6825/// Supports only pointers. See `ptrIntValue` for pointer-like optional support.
6826pub fn ptrIntValue_ptronly(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {
6827 assert(ty.zigTypeTag(mod) == .Pointer);6822 assert(ty.zigTypeTag(mod) == .Pointer);
6828 const i = try intern(mod, .{ .ptr = .{6823 const i = try intern(mod, .{ .ptr = .{
6829 .ty = ty.toIntern(),6824 .ty = ty.toIntern(),
6830 .addr = .{ .int = try mod.intValue_u64(Type.usize, x) },6825 .addr = .{ .int = (try mod.intValue_u64(Type.usize, x)).toIntern() },
6831 } });6826 } });
6832 return i.toValue();6827 return i.toValue();
6833}6828}
src/Sema.zig+9-1
...@@ -20846,7 +20846,15 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -20846,7 +20846,15 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
20846 if (addr != 0 and ptr_align != 0 and addr % ptr_align != 0)20846 if (addr != 0 and ptr_align != 0 and addr % ptr_align != 0)
20847 return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(sema.mod)});20847 return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(sema.mod)});
2084820848
20849 return sema.addConstant(ptr_ty, try mod.ptrIntValue(ptr_ty, addr));20849 const ptr_val = switch (ptr_ty.zigTypeTag(mod)) {
20850 .Optional => (try mod.intern(.{ .opt = .{
20851 .ty = ptr_ty.toIntern(),
20852 .val = if (addr == 0) .none else (try mod.ptrIntValue(ptr_ty.childType(mod), addr)).toIntern(),
20853 } })).toValue(),
20854 .Pointer => try mod.ptrIntValue(ptr_ty, addr),
20855 else => unreachable,
20856 };
20857 return sema.addConstant(ptr_ty, ptr_val);
20850 }20858 }
2085120859
20852 try sema.requireRuntimeBlock(block, src, operand_src);20860 try sema.requireRuntimeBlock(block, src, operand_src);
test/behavior/inttoptr.zig+20
...@@ -1,4 +1,6 @@...@@ -1,4 +1,6 @@
1const std = @import("std");
1const builtin = @import("builtin");2const builtin = @import("builtin");
3const expectEqual = std.testing.expectEqual;
24
3test "casting integer address to function pointer" {5test "casting integer address to function pointer" {
4 addressToFunction();6 addressToFunction();
...@@ -26,3 +28,21 @@ fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void {...@@ -26,3 +28,21 @@ fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void {
26 return;28 return;
27 }29 }
28}30}
31
32test "@intToPtr creates null pointer" {
33 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
34 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
35 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
36
37 const ptr = @intToPtr(?*u32, 0);
38 try expectEqual(@as(?*u32, null), ptr);
39}
40
41test "@intToPtr creates allowzero zero pointer" {
42 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
43 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
44 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
45
46 const ptr = @intToPtr(*allowzero u32, 0);
47 try expectEqual(@as(usize, 0), @ptrToInt(ptr));
48}