| author | |
| committer | |
| log | 11d0dfb8829f7a247b21b417157bafeebd6a2a90 |
| tree | f78e3fe50d8d691196cfdddc11a7f8988c5cc3c0 |
| parent | ce88c43a4ee94d82a64e7580885dc6693cc6120c |
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: #160333 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 | } |
| 6819 | 6819 | ||
| 6820 | /// Supports optionals in addition to pointers. | 6820 | /// Supports only pointers, not pointer-like optionals. |
| 6821 | pub fn ptrIntValue(mod: *Module, ty: Type, x: u64) Allocator.Error!Value { | 6821 | pub 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. | ||
| 6826 | pub 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)}); |
| 20848 | 20848 | ||
| 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 | } |
| 20851 | 20859 | ||
| 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 @@ |
| 1 | const std = @import("std"); | ||
| 1 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const expectEqual = std.testing.expectEqual; | ||
| 2 | 4 | ||
| 3 | test "casting integer address to function pointer" { | 5 | test "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 | |||
| 32 | test "@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 | |||
| 41 | test "@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 | } |