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
1038810388 )).?;
1038910389 try sema.mod.declareDeclDependency(sema.owner_decl, fn_info_decl);
1039010390 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);
1039110393 const param_info_decl = (try sema.namespaceLookup(
1039210394 block,
1039310395 src,
10394 fn_info_decl.val.castTag(.ty).?.data.getNamespace().?,
10396 fn_ty.getNamespace().?,
1039510397 "Param",
1039610398 )).?;
1039710399 try sema.mod.declareDeclDependency(sema.owner_decl, param_info_decl);
1039810400 try sema.ensureDeclAnalyzed(param_info_decl);
10401 var param_buffer: Value.ToTypeBuffer = undefined;
10402 const param_ty = param_info_decl.val.toType(&param_buffer);
1039910403 const new_decl = try params_anon_decl.finish(
1040010404 try Type.Tag.array.create(params_anon_decl.arena(), .{
1040110405 .len = param_vals.len,
10402 .elem_type = param_info_decl.ty,
10406 .elem_type = try param_ty.copy(params_anon_decl.arena()),
1040310407 }),
1040410408 try Value.Tag.aggregate.create(
1040510409 params_anon_decl.arena(),
1040610410 param_vals,
1040710411 ),
1040810412 );
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 });
1041010417 };
1041110418
1041210419 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
1082310830 try fields_anon_decl.arena().dupe(Value, union_field_vals),
1082410831 ),
1082510832 );
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 });
1082710837 };
1082810838
1082910839 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
1089710907 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
1089810908 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
1089910909 );
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 });
1090110914 };
1090210915
1090310916 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
1093710950 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
1093810951 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
1093910952 );
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 });
1094110957 };
1094210958
1094310959 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
1097910995 try fields_anon_decl.arena().dupe(Value, struct_field_vals),
1098010996 ),
1098110997 );
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 });
1098311002 };
1098411003
1098511004 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, struct_ty.getNamespace());
......@@ -11048,7 +11067,7 @@ fn typeInfoDecls(
1104811067 block,
1104911068 src,
1105011069 type_info_ty.getNamespace().?,
11051 "EnumField",
11070 "Declaration",
1105211071 )).?;
1105311072 try sema.mod.declareDeclDependency(sema.owner_decl, declaration_ty_decl);
1105411073 try sema.ensureDeclAnalyzed(declaration_ty_decl);
......@@ -11069,7 +11088,10 @@ fn typeInfoDecls(
1106911088 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
1107011089 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
1107111090 );
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 });
1107311095 };
1107411096
1107511097 const fields = try decls_anon_decl.arena().create([2]Value);
......@@ -11092,7 +11114,10 @@ fn typeInfoDecls(
1109211114 try decls_anon_decl.arena().dupe(Value, decls_vals),
1109311115 ),
1109411116 );
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 });
1109611121}
1109711122
1109811123fn zirTypeof(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -16574,8 +16599,20 @@ fn elemVal(
1657416599 const runtime_src = if (maybe_slice_val) |slice_val| rs: {
1657516600 const index_val = maybe_index_val orelse break :rs elem_index_src;
1657616601 const index = @intCast(usize, index_val.toUnsignedInt());
16577 const elem_val = try slice_val.elemValue(sema.arena, index);
16578 return sema.addConstant(array_ty.elemType2(), elem_val);
16602
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;
1657916616 } else array_src;
1658016617
1658116618 try sema.requireRuntimeBlock(block, runtime_src);
......@@ -16589,8 +16626,19 @@ fn elemVal(
1658916626 const array_val = maybe_array_val orelse break :rs array_src;
1659016627 const index_val = maybe_index_val orelse break :rs elem_index_src;
1659116628 const index = @intCast(usize, index_val.toUnsignedInt());
16592 const elem_val = try array_val.elemValue(sema.arena, index);
16593 return sema.addConstant(array_ty.elemType2(), elem_val);
16629 const elem_ty = array_ty.elemType2();
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;
1659416642 };
1659516643
1659616644 try sema.requireRuntimeBlock(block, runtime_src);
test/behavior/pointers.zig+68
......@@ -437,3 +437,71 @@ test "indexing array with sentinel returns correct type" {
437437 var s: [:0]const u8 = "abc";
438438 try testing.expectEqualSlices(u8, "*const u8", @typeName(@TypeOf(&s[0])));
439439}
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}