authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-16 19:36:54-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-03-16 19:36:54-04:00
log942f8d07d152eb0420419c89b5c9a3110151b873
treed510a7942f92292839be15c7bc7e883e8dae428a
parent94672dfb1941289eb65fdeab2e1dcc39ca70c3b7
parentcdeb1fb88157130ba1260e6c2d4ef5a20df0c493
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11193 from mitchellh/b-elem-ptr

stage2: elem_ptr needs to know if slice or direct access

2 files changed, 130 insertions(+), 14 deletions(-)

src/Sema.zig+62-14
...@@ -10388,25 +10388,32 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -10388,25 +10388,32 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
10388 )).?;10388 )).?;
10389 try sema.mod.declareDeclDependency(sema.owner_decl, fn_info_decl);10389 try sema.mod.declareDeclDependency(sema.owner_decl, fn_info_decl);
10390 try sema.ensureDeclAnalyzed(fn_info_decl);10390 try sema.ensureDeclAnalyzed(fn_info_decl);
10391 var fn_ty_buffer: Value.ToTypeBuffer = undefined;
10392 const fn_ty = fn_info_decl.val.toType(&fn_ty_buffer);
10391 const param_info_decl = (try sema.namespaceLookup(10393 const param_info_decl = (try sema.namespaceLookup(
10392 block,10394 block,
10393 src,10395 src,
10394 fn_info_decl.val.castTag(.ty).?.data.getNamespace().?,10396 fn_ty.getNamespace().?,
10395 "Param",10397 "Param",
10396 )).?;10398 )).?;
10397 try sema.mod.declareDeclDependency(sema.owner_decl, param_info_decl);10399 try sema.mod.declareDeclDependency(sema.owner_decl, param_info_decl);
10398 try sema.ensureDeclAnalyzed(param_info_decl);10400 try sema.ensureDeclAnalyzed(param_info_decl);
10401 var param_buffer: Value.ToTypeBuffer = undefined;
10402 const param_ty = param_info_decl.val.toType(&param_buffer);
10399 const new_decl = try params_anon_decl.finish(10403 const new_decl = try params_anon_decl.finish(
10400 try Type.Tag.array.create(params_anon_decl.arena(), .{10404 try Type.Tag.array.create(params_anon_decl.arena(), .{
10401 .len = param_vals.len,10405 .len = param_vals.len,
10402 .elem_type = param_info_decl.ty,10406 .elem_type = try param_ty.copy(params_anon_decl.arena()),
10403 }),10407 }),
10404 try Value.Tag.aggregate.create(10408 try Value.Tag.aggregate.create(
10405 params_anon_decl.arena(),10409 params_anon_decl.arena(),
10406 param_vals,10410 param_vals,
10407 ),10411 ),
10408 );10412 );
10409 break :v try Value.Tag.decl_ref.create(sema.arena, new_decl);10413 break :v try Value.Tag.slice.create(sema.arena, .{
10414 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
10415 .len = try Value.Tag.int_u64.create(sema.arena, param_vals.len),
10416 });
10410 };10417 };
1041110418
10412 const ret_ty_opt = if (info.return_type.tag() != .generic_poison)10419 const ret_ty_opt = if (info.return_type.tag() != .generic_poison)
...@@ -10823,7 +10830,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -10823,7 +10830,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
10823 try fields_anon_decl.arena().dupe(Value, union_field_vals),10830 try fields_anon_decl.arena().dupe(Value, union_field_vals),
10824 ),10831 ),
10825 );10832 );
10826 break :v try Value.Tag.decl_ref.create(sema.arena, new_decl);10833 break :v try Value.Tag.slice.create(sema.arena, .{
10834 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
10835 .len = try Value.Tag.int_u64.create(sema.arena, union_field_vals.len),
10836 });
10827 };10837 };
1082810838
10829 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, union_ty.getNamespace());10839 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, union_ty.getNamespace());
...@@ -10897,7 +10907,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -10897,7 +10907,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
10897 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),10907 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
10898 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),10908 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
10899 );10909 );
10900 break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);10910 break :v try Value.Tag.slice.create(sema.arena, .{
10911 .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),
10912 .len = try Value.Tag.int_u64.create(sema.arena, bytes.len),
10913 });
10901 };10914 };
1090210915
10903 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);10916 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
...@@ -10937,7 +10950,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -10937,7 +10950,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
10937 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),10950 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
10938 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),10951 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
10939 );10952 );
10940 break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);10953 break :v try Value.Tag.slice.create(sema.arena, .{
10954 .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),
10955 .len = try Value.Tag.int_u64.create(sema.arena, bytes.len),
10956 });
10941 };10957 };
1094210958
10943 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);10959 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
...@@ -10979,7 +10995,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -10979,7 +10995,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
10979 try fields_anon_decl.arena().dupe(Value, struct_field_vals),10995 try fields_anon_decl.arena().dupe(Value, struct_field_vals),
10980 ),10996 ),
10981 );10997 );
10982 break :v try Value.Tag.decl_ref.create(sema.arena, new_decl);10998 break :v try Value.Tag.slice.create(sema.arena, .{
10999 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
11000 .len = try Value.Tag.int_u64.create(sema.arena, struct_field_vals.len),
11001 });
10983 };11002 };
1098411003
10985 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, struct_ty.getNamespace());11004 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, struct_ty.getNamespace());
...@@ -11048,7 +11067,7 @@ fn typeInfoDecls(...@@ -11048,7 +11067,7 @@ fn typeInfoDecls(
11048 block,11067 block,
11049 src,11068 src,
11050 type_info_ty.getNamespace().?,11069 type_info_ty.getNamespace().?,
11051 "EnumField",11070 "Declaration",
11052 )).?;11071 )).?;
11053 try sema.mod.declareDeclDependency(sema.owner_decl, declaration_ty_decl);11072 try sema.mod.declareDeclDependency(sema.owner_decl, declaration_ty_decl);
11054 try sema.ensureDeclAnalyzed(declaration_ty_decl);11073 try sema.ensureDeclAnalyzed(declaration_ty_decl);
...@@ -11069,7 +11088,10 @@ fn typeInfoDecls(...@@ -11069,7 +11088,10 @@ fn typeInfoDecls(
11069 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),11088 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
11070 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),11089 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
11071 );11090 );
11072 break :v try Value.Tag.decl_ref.create(decls_anon_decl.arena(), new_decl);11091 break :v try Value.Tag.slice.create(decls_anon_decl.arena(), .{
11092 .ptr = try Value.Tag.decl_ref.create(decls_anon_decl.arena(), new_decl),
11093 .len = try Value.Tag.int_u64.create(decls_anon_decl.arena(), bytes.len),
11094 });
11073 };11095 };
1107411096
11075 const fields = try decls_anon_decl.arena().create([2]Value);11097 const fields = try decls_anon_decl.arena().create([2]Value);
...@@ -11092,7 +11114,10 @@ fn typeInfoDecls(...@@ -11092,7 +11114,10 @@ fn typeInfoDecls(
11092 try decls_anon_decl.arena().dupe(Value, decls_vals),11114 try decls_anon_decl.arena().dupe(Value, decls_vals),
11093 ),11115 ),
11094 );11116 );
11095 return try Value.Tag.decl_ref.create(sema.arena, new_decl);11117 return try Value.Tag.slice.create(sema.arena, .{
11118 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
11119 .len = try Value.Tag.int_u64.create(sema.arena, decls_vals.len),
11120 });
11096}11121}
1109711122
11098fn zirTypeof(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {11123fn zirTypeof(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -16574,8 +16599,20 @@ fn elemVal(...@@ -16574,8 +16599,20 @@ fn elemVal(
16574 const runtime_src = if (maybe_slice_val) |slice_val| rs: {16599 const runtime_src = if (maybe_slice_val) |slice_val| rs: {
16575 const index_val = maybe_index_val orelse break :rs elem_index_src;16600 const index_val = maybe_index_val orelse break :rs elem_index_src;
16576 const index = @intCast(usize, index_val.toUnsignedInt());16601 const index = @intCast(usize, index_val.toUnsignedInt());
16577 const elem_val = try slice_val.elemValue(sema.arena, index);16602
16578 return sema.addConstant(array_ty.elemType2(), elem_val);16603 const elem_ty = array_ty.elemType2();
16604
16605 var payload: Value.Payload.ElemPtr = .{ .data = .{
16606 .array_ptr = slice_val.slicePtr(),
16607 .elem_ty = elem_ty,
16608 .index = index,
16609 } };
16610 const elem_ptr_val = Value.initPayload(&payload.base);
16611
16612 if (try sema.pointerDeref(block, array_src, elem_ptr_val, array_ty)) |elem_val| {
16613 return sema.addConstant(elem_ty, elem_val);
16614 }
16615 break :rs array_src;
16579 } else array_src;16616 } else array_src;
1658016617
16581 try sema.requireRuntimeBlock(block, runtime_src);16618 try sema.requireRuntimeBlock(block, runtime_src);
...@@ -16589,8 +16626,19 @@ fn elemVal(...@@ -16589,8 +16626,19 @@ fn elemVal(
16589 const array_val = maybe_array_val orelse break :rs array_src;16626 const array_val = maybe_array_val orelse break :rs array_src;
16590 const index_val = maybe_index_val orelse break :rs elem_index_src;16627 const index_val = maybe_index_val orelse break :rs elem_index_src;
16591 const index = @intCast(usize, index_val.toUnsignedInt());16628 const index = @intCast(usize, index_val.toUnsignedInt());
16592 const elem_val = try array_val.elemValue(sema.arena, index);16629 const elem_ty = array_ty.elemType2();
16593 return sema.addConstant(array_ty.elemType2(), elem_val);16630
16631 var payload: Value.Payload.ElemPtr = .{ .data = .{
16632 .array_ptr = array_val,
16633 .elem_ty = elem_ty,
16634 .index = index,
16635 } };
16636 const elem_ptr_val = Value.initPayload(&payload.base);
16637
16638 if (try sema.pointerDeref(block, array_src, elem_ptr_val, array_ty)) |elem_val| {
16639 return sema.addConstant(elem_ty, elem_val);
16640 }
16641 break :rs array_src;
16594 };16642 };
1659516643
16596 try sema.requireRuntimeBlock(block, runtime_src);16644 try sema.requireRuntimeBlock(block, runtime_src);
test/behavior/pointers.zig+68
...@@ -437,3 +437,71 @@ test "indexing array with sentinel returns correct type" {...@@ -437,3 +437,71 @@ test "indexing array with sentinel returns correct type" {
437 var s: [:0]const u8 = "abc";437 var s: [:0]const u8 = "abc";
438 try testing.expectEqualSlices(u8, "*const u8", @typeName(@TypeOf(&s[0])));438 try testing.expectEqualSlices(u8, "*const u8", @typeName(@TypeOf(&s[0])));
439}439}
440
441test "element pointer to slice" {
442 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
443 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
444 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
445
446 const S = struct {
447 fn doTheTest() !void {
448 var cases: [2][2]i32 = [_][2]i32{
449 [_]i32{ 0, 1 },
450 [_]i32{ 2, 3 },
451 };
452
453 const items: []i32 = &cases[0]; // *[2]i32
454 try testing.expect(items.len == 2);
455 try testing.expect(items[1] == 1);
456 try testing.expect(items[0] == 0);
457 }
458 };
459
460 try S.doTheTest();
461 comptime try S.doTheTest();
462}
463
464test "element pointer arithmetic to slice" {
465 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
466 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
467 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
468
469 const S = struct {
470 fn doTheTest() !void {
471 var cases: [2][2]i32 = [_][2]i32{
472 [_]i32{ 0, 1 },
473 [_]i32{ 2, 3 },
474 };
475
476 const elem_ptr = &cases[0]; // *[2]i32
477 const many = @ptrCast([*][2]i32, elem_ptr);
478 const many_elem = @ptrCast(*[2]i32, &many[1]);
479 const items: []i32 = many_elem;
480 try testing.expect(items.len == 2);
481 try testing.expect(items[1] == 3);
482 try testing.expect(items[0] == 2);
483 }
484 };
485
486 try S.doTheTest();
487 comptime try S.doTheTest();
488}
489
490test "array slicing to slice" {
491 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
492 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
493 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
494
495 const S = struct {
496 fn doTheTest() !void {
497 var str: [5]i32 = [_]i32{ 1, 2, 3, 4, 5 };
498 var sub: *[2]i32 = str[1..3];
499 var slice: []i32 = sub; // used to cause failures
500 try testing.expect(slice.len == 2);
501 try testing.expect(slice[0] == 2);
502 }
503 };
504
505 try S.doTheTest();
506 comptime try S.doTheTest();
507}