authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-16 16:29:08-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-16 16:29:08-07:00
logcdeb1fb88157130ba1260e6c2d4ef5a20df0c493
treed510a7942f92292839be15c7bc7e883e8dae428a
parent418197b6c51b99ee2a0be5e394753868f7dbf982

Sema: different solution to elemVal

I think that reusing the ComptimePtrLoad infrastructure is ultimately less logic and more robust than adding a `direct` flag to elem_ptr. * Some code in zirTypeInfo needed to be fixed to create proper Type/Value encodings. * comptime elemVal works by constructing an elem_ptr Value and then using the already existing pointerDeref function. There are some remaining calls to Value.elemValue which should be considered code smells at this point.

2 files changed, 64 insertions(+), 42 deletions(-)

src/Sema.zig+63-15
......@@ -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);
......@@ -16739,7 +16787,7 @@ fn elemPtrArray(
1673916787 const index_u64 = index_val.toUnsignedInt();
1674016788 // @intCast here because it would have been impossible to construct a value that
1674116789 // required a larger index.
16742 const elem_ptr = try array_ptr_val.elemPtrDirect(array_ptr_ty, sema.arena, @intCast(usize, index_u64));
16790 const elem_ptr = try array_ptr_val.elemPtr(array_ptr_ty, sema.arena, @intCast(usize, index_u64));
1674316791 return sema.addConstant(result_ty, elem_ptr);
1674416792 }
1674516793 }
src/value.zig+1-27
......@@ -505,7 +505,6 @@ pub const Value = extern union {
505505 .array_ptr = try payload.data.array_ptr.copy(arena),
506506 .elem_ty = try payload.data.elem_ty.copy(arena),
507507 .index = payload.data.index,
508 .direct = payload.data.direct,
509508 },
510509 };
511510 return Value{ .ptr_otherwise = &new_payload.base };
......@@ -2403,11 +2402,7 @@ pub const Value = extern union {
24032402 .decl_ref_mut => return val.castTag(.decl_ref_mut).?.data.decl.val.elemValueAdvanced(index, arena, buffer),
24042403 .elem_ptr => {
24052404 const data = val.castTag(.elem_ptr).?.data;
2406 if (!data.direct)
2407 return data.array_ptr.elemValueAdvanced(index + data.index, arena, buffer);
2408
2409 const underlying = try data.array_ptr.elemValueAdvanced(data.index, arena, buffer);
2410 return underlying.elemValueAdvanced(index, arena, buffer);
2405 return data.array_ptr.elemValueAdvanced(index + data.index, arena, buffer);
24112406 },
24122407
24132408 // The child type of arrays which have only one possible value need
......@@ -2470,25 +2465,12 @@ pub const Value = extern union {
24702465
24712466 /// Returns a pointer to the element value at the index.
24722467 pub fn elemPtr(val: Value, ty: Type, arena: Allocator, index: usize) Allocator.Error!Value {
2473 return val.elemPtrAdvanced(ty, arena, index, false);
2474 }
2475
2476 /// Returns a pointer to the element value at the index. The behavior
2477 /// of this is slightly different for comptime; the "direct" means that
2478 /// indexing indexes the referenced child value, not the parent array.
2479 pub fn elemPtrDirect(val: Value, ty: Type, arena: Allocator, index: usize) Allocator.Error!Value {
2480 return val.elemPtrAdvanced(ty, arena, index, true);
2481 }
2482
2483 pub fn elemPtrAdvanced(val: Value, ty: Type, arena: Allocator, index: usize, direct: bool) Allocator.Error!Value {
24842468 const elem_ty = ty.elemType2();
24852469 const ptr_val = switch (val.tag()) {
24862470 .slice => val.castTag(.slice).?.data.ptr,
24872471 else => val,
24882472 };
24892473
2490 // If the val is already an elem ptr, then we do ptr arithmetic logic
2491 // and just move the index.
24922474 if (ptr_val.tag() == .elem_ptr) {
24932475 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
24942476 if (elem_ptr.elem_ty.eql(elem_ty)) {
......@@ -2496,12 +2478,6 @@ pub const Value = extern union {
24962478 .array_ptr = elem_ptr.array_ptr,
24972479 .elem_ty = elem_ptr.elem_ty,
24982480 .index = elem_ptr.index + index,
2499
2500 // Retain the direct preference. This enables a direct
2501 // elem ptr (i.e. &arr[0]) to be bitcasted to a many-pointer
2502 // with pointer arithmetic then casted back to a single
2503 // pointer.
2504 .direct = elem_ptr.direct,
25052481 });
25062482 }
25072483 }
......@@ -2509,7 +2485,6 @@ pub const Value = extern union {
25092485 .array_ptr = ptr_val,
25102486 .elem_ty = elem_ty,
25112487 .index = index,
2512 .direct = direct,
25132488 });
25142489 }
25152490
......@@ -4219,7 +4194,6 @@ pub const Value = extern union {
42194194 array_ptr: Value,
42204195 elem_ty: Type,
42214196 index: usize,
4222 direct: bool,
42234197 },
42244198 };
42254199