authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-17 19:10:49-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-17 19:10:49-07:00
log40cbf525f7d7b17b0728f835e6f68efe3c2eabf6
tree4533eaccd46b97525f0f9c744216d9353cc2a475
parente5dac0a0b391f227605e496a09f32b453ac3280d

stage2: implement coercion from null to C pointer


4 files changed, 33 insertions(+), 25 deletions(-)

src/Sema.zig+18-11
...@@ -4731,7 +4731,7 @@ fn zirFunc(...@@ -4731,7 +4731,7 @@ fn zirFunc(
4731 body_inst,4731 body_inst,
4732 ret_ty_body,4732 ret_ty_body,
4733 cc,4733 cc,
4734 Value.initTag(.null_value),4734 Value.@"null",
4735 false,4735 false,
4736 inferred_error_set,4736 inferred_error_set,
4737 false,4737 false,
...@@ -8105,7 +8105,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -8105,7 +8105,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
8105 // return_type: ?type,8105 // return_type: ?type,
8106 field_values[4] = try Value.Tag.ty.create(sema.arena, ty.fnReturnType());8106 field_values[4] = try Value.Tag.ty.create(sema.arena, ty.fnReturnType());
8107 // args: []const FnArg,8107 // args: []const FnArg,
8108 field_values[5] = Value.initTag(.null_value); // TODO8108 field_values[5] = Value.@"null"; // TODO
81098109
8110 return sema.addConstant(8110 return sema.addConstant(
8111 type_info_ty,8111 type_info_ty,
...@@ -8163,7 +8163,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -8163,7 +8163,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
8163 // is_allowzero: bool,8163 // is_allowzero: bool,
8164 field_values[5] = if (info.@"allowzero") Value.initTag(.bool_true) else Value.initTag(.bool_false);8164 field_values[5] = if (info.@"allowzero") Value.initTag(.bool_true) else Value.initTag(.bool_false);
8165 // sentinel: anytype,8165 // sentinel: anytype,
8166 field_values[6] = if (info.sentinel) |some| try Value.Tag.opt_payload.create(sema.arena, some) else Value.initTag(.null_value);8166 field_values[6] = if (info.sentinel) |some| try Value.Tag.opt_payload.create(sema.arena, some) else Value.@"null";
81678167
8168 return sema.addConstant(8168 return sema.addConstant(
8169 type_info_ty,8169 type_info_ty,
...@@ -8181,7 +8181,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -8181,7 +8181,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
8181 // child: type,8181 // child: type,
8182 field_values[1] = try Value.Tag.ty.create(sema.arena, info.elem_type);8182 field_values[1] = try Value.Tag.ty.create(sema.arena, info.elem_type);
8183 // sentinel: anytype,8183 // sentinel: anytype,
8184 field_values[2] = if (info.sentinel) |some| try Value.Tag.opt_payload.create(sema.arena, some) else Value.initTag(.null_value);8184 field_values[2] = if (info.sentinel) |some| try Value.Tag.opt_payload.create(sema.arena, some) else Value.@"null";
81858185
8186 return sema.addConstant(8186 return sema.addConstant(
8187 type_info_ty,8187 type_info_ty,
...@@ -9753,7 +9753,7 @@ fn zirCmpxchg(...@@ -9753,7 +9753,7 @@ fn zirCmpxchg(
97539753
9754 // special case zero bit types9754 // special case zero bit types
9755 if ((try sema.typeHasOnePossibleValue(block, elem_ty_src, elem_ty)) != null) {9755 if ((try sema.typeHasOnePossibleValue(block, elem_ty_src, elem_ty)) != null) {
9756 return sema.addConstant(result_ty, Value.initTag(.null_value));9756 return sema.addConstant(result_ty, Value.@"null");
9757 }9757 }
97589758
9759 const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: {9759 const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: {
...@@ -9767,7 +9767,7 @@ fn zirCmpxchg(...@@ -9767,7 +9767,7 @@ fn zirCmpxchg(
9767 const stored_val = (try ptr_val.pointerDeref(sema.arena)) orelse break :rs ptr_src;9767 const stored_val = (try ptr_val.pointerDeref(sema.arena)) orelse break :rs ptr_src;
9768 const result_val = if (stored_val.eql(expected_val, elem_ty)) blk: {9768 const result_val = if (stored_val.eql(expected_val, elem_ty)) blk: {
9769 try sema.storePtr(block, src, ptr, new_value);9769 try sema.storePtr(block, src, ptr, new_value);
9770 break :blk Value.initTag(.null_value);9770 break :blk Value.@"null";
9771 } else try Value.Tag.opt_payload.create(sema.arena, stored_val);9771 } else try Value.Tag.opt_payload.create(sema.arena, stored_val);
97729772
9773 return sema.addConstant(result_ty, result_val);9773 return sema.addConstant(result_ty, result_val);
...@@ -10225,7 +10225,7 @@ fn zirVarExtended(...@@ -10225,7 +10225,7 @@ fn zirVarExtended(
10225 // extra_index += 1;10225 // extra_index += 1;
10226 // const align_tv = try sema.resolveInstConst(block, align_src, align_ref);10226 // const align_tv = try sema.resolveInstConst(block, align_src, align_ref);
10227 // break :blk align_tv.val;10227 // break :blk align_tv.val;
10228 //} else Value.initTag(.null_value);10228 //} else Value.@"null";
1022910229
10230 const uncasted_init: Air.Inst.Ref = if (small.has_init) blk: {10230 const uncasted_init: Air.Inst.Ref = if (small.has_init) blk: {
10231 const init_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);10231 const init_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
...@@ -10307,7 +10307,7 @@ fn zirFuncExtended(...@@ -10307,7 +10307,7 @@ fn zirFuncExtended(
10307 extra_index += 1;10307 extra_index += 1;
10308 const align_tv = try sema.resolveInstConst(block, align_src, align_ref);10308 const align_tv = try sema.resolveInstConst(block, align_src, align_ref);
10309 break :blk align_tv.val;10309 break :blk align_tv.val;
10310 } else Value.initTag(.null_value);10310 } else Value.@"null";
1031110311
10312 const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];10312 const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];
10313 extra_index += ret_ty_body.len;10313 extra_index += ret_ty_body.len;
...@@ -10592,7 +10592,7 @@ fn panicWithMsg(...@@ -10592,7 +10592,7 @@ fn panicWithMsg(
10592 });10592 });
10593 const null_stack_trace = try sema.addConstant(10593 const null_stack_trace = try sema.addConstant(
10594 try Type.optional(arena, ptr_stack_trace_ty),10594 try Type.optional(arena, ptr_stack_trace_ty),
10595 Value.initTag(.null_value),10595 Value.@"null",
10596 );10596 );
10597 const args = try arena.create([2]Air.Inst.Ref);10597 const args = try arena.create([2]Air.Inst.Ref);
10598 args.* = .{ msg_inst, null_stack_trace };10598 args.* = .{ msg_inst, null_stack_trace };
...@@ -11544,7 +11544,7 @@ fn coerce(...@@ -11544,7 +11544,7 @@ fn coerce(
11544 .Optional => {11544 .Optional => {
11545 // null to ?T11545 // null to ?T
11546 if (inst_ty.zigTypeTag() == .Null) {11546 if (inst_ty.zigTypeTag() == .Null) {
11547 return sema.addConstant(dest_ty, Value.initTag(.null_value));11547 return sema.addConstant(dest_ty, Value.@"null");
11548 }11548 }
1154911549
11550 // T to ?T11550 // T to ?T
...@@ -11605,6 +11605,13 @@ fn coerce(...@@ -11605,6 +11605,13 @@ fn coerce(
11605 .One => {},11605 .One => {},
11606 }11606 }
11607 }11607 }
11608
11609 // coercion to C pointer
11610 if (dest_ty.ptrSize() == .C) {
11611 if (inst_ty.zigTypeTag() == .Null) {
11612 return sema.addConstant(dest_ty, Value.@"null");
11613 }
11614 }
11608 },11615 },
11609 .Int => {11616 .Int => {
11610 // integer widening11617 // integer widening
...@@ -13806,7 +13813,7 @@ fn typeHasOnePossibleValue(...@@ -13806,7 +13813,7 @@ fn typeHasOnePossibleValue(
13806 .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),13813 .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),
13807 .void => return Value.void,13814 .void => return Value.void,
13808 .noreturn => return Value.initTag(.unreachable_value),13815 .noreturn => return Value.initTag(.unreachable_value),
13809 .@"null" => return Value.initTag(.null_value),13816 .@"null" => return Value.@"null",
13810 .@"undefined" => return Value.initTag(.undef),13817 .@"undefined" => return Value.initTag(.undef),
1381113818
13812 .int_unsigned, .int_signed => {13819 .int_unsigned, .int_signed => {
src/value.zig+1
...@@ -2824,6 +2824,7 @@ pub const Value = extern union {...@@ -2824,6 +2824,7 @@ pub const Value = extern union {
2824 pub const negative_one: Value = .{ .ptr_otherwise = &negative_one_payload.base };2824 pub const negative_one: Value = .{ .ptr_otherwise = &negative_one_payload.base };
2825 pub const undef = initTag(.undef);2825 pub const undef = initTag(.undef);
2826 pub const @"void" = initTag(.void_value);2826 pub const @"void" = initTag(.void_value);
2827 pub const @"null" = initTag(.null_value);
2827};2828};
28282829
2829var negative_one_payload: Value.Payload.I64 = .{2830var negative_one_payload: Value.Payload.I64 = .{
test/behavior/pointers.zig+14
...@@ -44,3 +44,17 @@ test "double pointer parsing" {...@@ -44,3 +44,17 @@ test "double pointer parsing" {
44fn PtrOf(comptime T: type) type {44fn PtrOf(comptime T: type) type {
45 return *T;45 return *T;
46}46}
47
48test "implicit cast single item pointer to C pointer and back" {
49 var y: u8 = 11;
50 var x: [*c]u8 = &y;
51 var z: *u8 = x;
52 z.* += 1;
53 try expect(y == 12);
54}
55
56test "initialize const optional C pointer to null" {
57 const a: ?[*c]i32 = null;
58 try expect(a == null);
59 comptime try expect(a == null);
60}
test/behavior/pointers_stage1.zig-14
...@@ -29,14 +29,6 @@ test "assigning integer to C pointer" {...@@ -29,14 +29,6 @@ test "assigning integer to C pointer" {
29 }29 }
30}30}
3131
32test "implicit cast single item pointer to C pointer and back" {
33 var y: u8 = 11;
34 var x: [*c]u8 = &y;
35 var z: *u8 = x;
36 z.* += 1;
37 try expect(y == 12);
38}
39
40test "C pointer comparison and arithmetic" {32test "C pointer comparison and arithmetic" {
41 const S = struct {33 const S = struct {
42 fn doTheTest() !void {34 fn doTheTest() !void {
...@@ -103,12 +95,6 @@ test "implicit cast error unions with non-optional to optional pointer" {...@@ -103,12 +95,6 @@ test "implicit cast error unions with non-optional to optional pointer" {
103 comptime try S.doTheTest();95 comptime try S.doTheTest();
104}96}
10597
106test "initialize const optional C pointer to null" {
107 const a: ?[*c]i32 = null;
108 try expect(a == null);
109 comptime try expect(a == null);
110}
111
112test "compare equality of optional and non-optional pointer" {98test "compare equality of optional and non-optional pointer" {
113 const a = @intToPtr(*const usize, 0x12345678);99 const a = @intToPtr(*const usize, 0x12345678);
114 const b = @intToPtr(?*usize, 0x12345678);100 const b = @intToPtr(?*usize, 0x12345678);