Commit cdeb1fb881

Andrew Kelley <andrew@ziglang.org>
2022-03-17 00:29:08
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.
1 parent 418197b
Changed files (2)
src/Sema.zig
@@ -10388,25 +10388,32 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
                 )).?;
                 try sema.mod.declareDeclDependency(sema.owner_decl, fn_info_decl);
                 try sema.ensureDeclAnalyzed(fn_info_decl);
+                var fn_ty_buffer: Value.ToTypeBuffer = undefined;
+                const fn_ty = fn_info_decl.val.toType(&fn_ty_buffer);
                 const param_info_decl = (try sema.namespaceLookup(
                     block,
                     src,
-                    fn_info_decl.val.castTag(.ty).?.data.getNamespace().?,
+                    fn_ty.getNamespace().?,
                     "Param",
                 )).?;
                 try sema.mod.declareDeclDependency(sema.owner_decl, param_info_decl);
                 try sema.ensureDeclAnalyzed(param_info_decl);
+                var param_buffer: Value.ToTypeBuffer = undefined;
+                const param_ty = param_info_decl.val.toType(&param_buffer);
                 const new_decl = try params_anon_decl.finish(
                     try Type.Tag.array.create(params_anon_decl.arena(), .{
                         .len = param_vals.len,
-                        .elem_type = param_info_decl.ty,
+                        .elem_type = try param_ty.copy(params_anon_decl.arena()),
                     }),
                     try Value.Tag.aggregate.create(
                         params_anon_decl.arena(),
                         param_vals,
                     ),
                 );
-                break :v try Value.Tag.decl_ref.create(sema.arena, new_decl);
+                break :v try Value.Tag.slice.create(sema.arena, .{
+                    .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
+                    .len = try Value.Tag.int_u64.create(sema.arena, param_vals.len),
+                });
             };
 
             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
                         try fields_anon_decl.arena().dupe(Value, union_field_vals),
                     ),
                 );
-                break :v try Value.Tag.decl_ref.create(sema.arena, new_decl);
+                break :v try Value.Tag.slice.create(sema.arena, .{
+                    .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
+                    .len = try Value.Tag.int_u64.create(sema.arena, union_field_vals.len),
+                });
             };
 
             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
                                 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
                                 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
                             );
-                            break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);
+                            break :v try Value.Tag.slice.create(sema.arena, .{
+                                .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),
+                                .len = try Value.Tag.int_u64.create(sema.arena, bytes.len),
+                            });
                         };
 
                         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
                             try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
                             try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
                         );
-                        break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);
+                        break :v try Value.Tag.slice.create(sema.arena, .{
+                            .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),
+                            .len = try Value.Tag.int_u64.create(sema.arena, bytes.len),
+                        });
                     };
 
                     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
                         try fields_anon_decl.arena().dupe(Value, struct_field_vals),
                     ),
                 );
-                break :v try Value.Tag.decl_ref.create(sema.arena, new_decl);
+                break :v try Value.Tag.slice.create(sema.arena, .{
+                    .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
+                    .len = try Value.Tag.int_u64.create(sema.arena, struct_field_vals.len),
+                });
             };
 
             const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, struct_ty.getNamespace());
@@ -11048,7 +11067,7 @@ fn typeInfoDecls(
             block,
             src,
             type_info_ty.getNamespace().?,
-            "EnumField",
+            "Declaration",
         )).?;
         try sema.mod.declareDeclDependency(sema.owner_decl, declaration_ty_decl);
         try sema.ensureDeclAnalyzed(declaration_ty_decl);
@@ -11069,7 +11088,10 @@ fn typeInfoDecls(
                 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
                 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
             );
-            break :v try Value.Tag.decl_ref.create(decls_anon_decl.arena(), new_decl);
+            break :v try Value.Tag.slice.create(decls_anon_decl.arena(), .{
+                .ptr = try Value.Tag.decl_ref.create(decls_anon_decl.arena(), new_decl),
+                .len = try Value.Tag.int_u64.create(decls_anon_decl.arena(), bytes.len),
+            });
         };
 
         const fields = try decls_anon_decl.arena().create([2]Value);
@@ -11092,7 +11114,10 @@ fn typeInfoDecls(
             try decls_anon_decl.arena().dupe(Value, decls_vals),
         ),
     );
-    return try Value.Tag.decl_ref.create(sema.arena, new_decl);
+    return try Value.Tag.slice.create(sema.arena, .{
+        .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
+        .len = try Value.Tag.int_u64.create(sema.arena, decls_vals.len),
+    });
 }
 
 fn zirTypeof(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -16574,8 +16599,20 @@ fn elemVal(
                 const runtime_src = if (maybe_slice_val) |slice_val| rs: {
                     const index_val = maybe_index_val orelse break :rs elem_index_src;
                     const index = @intCast(usize, index_val.toUnsignedInt());
-                    const elem_val = try slice_val.elemValue(sema.arena, index);
-                    return sema.addConstant(array_ty.elemType2(), elem_val);
+
+                    const elem_ty = array_ty.elemType2();
+
+                    var payload: Value.Payload.ElemPtr = .{ .data = .{
+                        .array_ptr = slice_val.slicePtr(),
+                        .elem_ty = elem_ty,
+                        .index = index,
+                    } };
+                    const elem_ptr_val = Value.initPayload(&payload.base);
+
+                    if (try sema.pointerDeref(block, array_src, elem_ptr_val, array_ty)) |elem_val| {
+                        return sema.addConstant(elem_ty, elem_val);
+                    }
+                    break :rs array_src;
                 } else array_src;
 
                 try sema.requireRuntimeBlock(block, runtime_src);
@@ -16589,8 +16626,19 @@ fn elemVal(
                     const array_val = maybe_array_val orelse break :rs array_src;
                     const index_val = maybe_index_val orelse break :rs elem_index_src;
                     const index = @intCast(usize, index_val.toUnsignedInt());
-                    const elem_val = try array_val.elemValue(sema.arena, index);
-                    return sema.addConstant(array_ty.elemType2(), elem_val);
+                    const elem_ty = array_ty.elemType2();
+
+                    var payload: Value.Payload.ElemPtr = .{ .data = .{
+                        .array_ptr = array_val,
+                        .elem_ty = elem_ty,
+                        .index = index,
+                    } };
+                    const elem_ptr_val = Value.initPayload(&payload.base);
+
+                    if (try sema.pointerDeref(block, array_src, elem_ptr_val, array_ty)) |elem_val| {
+                        return sema.addConstant(elem_ty, elem_val);
+                    }
+                    break :rs array_src;
                 };
 
                 try sema.requireRuntimeBlock(block, runtime_src);
@@ -16739,7 +16787,7 @@ fn elemPtrArray(
             const index_u64 = index_val.toUnsignedInt();
             // @intCast here because it would have been impossible to construct a value that
             // required a larger index.
-            const elem_ptr = try array_ptr_val.elemPtrDirect(array_ptr_ty, sema.arena, @intCast(usize, index_u64));
+            const elem_ptr = try array_ptr_val.elemPtr(array_ptr_ty, sema.arena, @intCast(usize, index_u64));
             return sema.addConstant(result_ty, elem_ptr);
         }
     }
src/value.zig
@@ -505,7 +505,6 @@ pub const Value = extern union {
                         .array_ptr = try payload.data.array_ptr.copy(arena),
                         .elem_ty = try payload.data.elem_ty.copy(arena),
                         .index = payload.data.index,
-                        .direct = payload.data.direct,
                     },
                 };
                 return Value{ .ptr_otherwise = &new_payload.base };
@@ -2403,11 +2402,7 @@ pub const Value = extern union {
             .decl_ref_mut => return val.castTag(.decl_ref_mut).?.data.decl.val.elemValueAdvanced(index, arena, buffer),
             .elem_ptr => {
                 const data = val.castTag(.elem_ptr).?.data;
-                if (!data.direct)
-                    return data.array_ptr.elemValueAdvanced(index + data.index, arena, buffer);
-
-                const underlying = try data.array_ptr.elemValueAdvanced(data.index, arena, buffer);
-                return underlying.elemValueAdvanced(index, arena, buffer);
+                return data.array_ptr.elemValueAdvanced(index + data.index, arena, buffer);
             },
 
             // The child type of arrays which have only one possible value need
@@ -2470,25 +2465,12 @@ pub const Value = extern union {
 
     /// Returns a pointer to the element value at the index.
     pub fn elemPtr(val: Value, ty: Type, arena: Allocator, index: usize) Allocator.Error!Value {
-        return val.elemPtrAdvanced(ty, arena, index, false);
-    }
-
-    /// Returns a pointer to the element value at the index. The behavior
-    /// of this is slightly different for comptime; the "direct" means that
-    /// indexing indexes the referenced child value, not the parent array.
-    pub fn elemPtrDirect(val: Value, ty: Type, arena: Allocator, index: usize) Allocator.Error!Value {
-        return val.elemPtrAdvanced(ty, arena, index, true);
-    }
-
-    pub fn elemPtrAdvanced(val: Value, ty: Type, arena: Allocator, index: usize, direct: bool) Allocator.Error!Value {
         const elem_ty = ty.elemType2();
         const ptr_val = switch (val.tag()) {
             .slice => val.castTag(.slice).?.data.ptr,
             else => val,
         };
 
-        // If the val is already an elem ptr, then we do ptr arithmetic logic
-        // and just move the index.
         if (ptr_val.tag() == .elem_ptr) {
             const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
             if (elem_ptr.elem_ty.eql(elem_ty)) {
@@ -2496,12 +2478,6 @@ pub const Value = extern union {
                     .array_ptr = elem_ptr.array_ptr,
                     .elem_ty = elem_ptr.elem_ty,
                     .index = elem_ptr.index + index,
-
-                    // Retain the direct preference. This enables a direct
-                    // elem ptr (i.e. &arr[0]) to be bitcasted to a many-pointer
-                    // with pointer arithmetic then casted back to a single
-                    // pointer.
-                    .direct = elem_ptr.direct,
                 });
             }
         }
@@ -2509,7 +2485,6 @@ pub const Value = extern union {
             .array_ptr = ptr_val,
             .elem_ty = elem_ty,
             .index = index,
-            .direct = direct,
         });
     }
 
@@ -4219,7 +4194,6 @@ pub const Value = extern union {
                 array_ptr: Value,
                 elem_ty: Type,
                 index: usize,
-                direct: bool,
             },
         };