Commit bbd750ff05

Cody Tapscott <topolarity@tapscott.me>
2022-03-11 02:10:41
stage2: Add container_ty/elem_ty to elem_ptr, field_ptr, *_payload_ptr Values
1 parent a2a5d3c
Changed files (3)
src/codegen/llvm.zig
@@ -2901,7 +2901,7 @@ pub const DeclGen = struct {
             },
             .opt_payload_ptr => {
                 const opt_payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
-                const parent = try dg.lowerParentPtr(opt_payload_ptr, base_ty);
+                const parent = try dg.lowerParentPtr(opt_payload_ptr.container_ptr, base_ty);
                 var buf: Type.Payload.ElemType = undefined;
                 const payload_ty = parent.ty.optionalChild(&buf);
                 if (!payload_ty.hasRuntimeBitsIgnoreComptime() or parent.ty.isPtrLikeOptional()) {
@@ -2925,7 +2925,7 @@ pub const DeclGen = struct {
             },
             .eu_payload_ptr => {
                 const eu_payload_ptr = ptr_val.castTag(.eu_payload_ptr).?.data;
-                const parent = try dg.lowerParentPtr(eu_payload_ptr, base_ty);
+                const parent = try dg.lowerParentPtr(eu_payload_ptr.container_ptr, base_ty);
                 const payload_ty = parent.ty.errorUnionPayload();
                 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
                     // In this case, we represent pointer to error union the same as pointer
src/Sema.zig
@@ -5568,7 +5568,10 @@ fn analyzeOptionalPayloadPtr(
             }
             return sema.addConstant(
                 child_pointer,
-                try Value.Tag.opt_payload_ptr.create(sema.arena, ptr_val),
+                try Value.Tag.opt_payload_ptr.create(sema.arena, .{
+                    .container_ptr = ptr_val,
+                    .container_ty = optional_ptr_ty.childType(),
+                }),
             );
         }
         if (try sema.pointerDeref(block, src, ptr_val, optional_ptr_ty)) |val| {
@@ -5578,7 +5581,10 @@ fn analyzeOptionalPayloadPtr(
             // The same Value represents the pointer to the optional and the payload.
             return sema.addConstant(
                 child_pointer,
-                try Value.Tag.opt_payload_ptr.create(sema.arena, ptr_val),
+                try Value.Tag.opt_payload_ptr.create(sema.arena, .{
+                    .container_ptr = ptr_val,
+                    .container_ty = optional_ptr_ty.childType(),
+                }),
             );
         }
     }
@@ -5733,7 +5739,10 @@ fn analyzeErrUnionPayloadPtr(
             }
             return sema.addConstant(
                 operand_pointer_ty,
-                try Value.Tag.eu_payload_ptr.create(sema.arena, ptr_val),
+                try Value.Tag.eu_payload_ptr.create(sema.arena, .{
+                    .container_ptr = ptr_val,
+                    .container_ty = operand_ty.elemType(),
+                }),
             );
         }
         if (try sema.pointerDeref(block, src, ptr_val, operand_ty)) |val| {
@@ -5743,7 +5752,10 @@ fn analyzeErrUnionPayloadPtr(
 
             return sema.addConstant(
                 operand_pointer_ty,
-                try Value.Tag.eu_payload_ptr.create(sema.arena, ptr_val),
+                try Value.Tag.eu_payload_ptr.create(sema.arena, .{
+                    .container_ptr = ptr_val,
+                    .container_ty = operand_ty.elemType(),
+                }),
             );
         }
     }
@@ -6652,6 +6664,7 @@ fn zirSwitchCapture(
                         field_ty_ptr,
                         try Value.Tag.field_ptr.create(sema.arena, .{
                             .container_ptr = op_ptr_val,
+                            .container_ty = operand_ty,
                             .field_index = field_index,
                         }),
                     );
@@ -9638,7 +9651,7 @@ fn analyzePtrArithmetic(
                 if (air_tag == .ptr_sub) {
                     return sema.fail(block, op_src, "TODO implement Sema comptime pointer subtraction", .{});
                 }
-                const new_ptr_val = try ptr_val.elemPtr(sema.arena, offset_int);
+                const new_ptr_val = try ptr_val.elemPtr(ptr_ty, sema.arena, offset_int);
                 return sema.addConstant(new_ptr_ty, new_ptr_val);
             } else break :rs offset_src;
         } else break :rs ptr_src;
@@ -15903,6 +15916,7 @@ fn finishFieldCallBind(
             ptr_field_ty,
             try Value.Tag.field_ptr.create(arena, .{
                 .container_ptr = struct_ptr_val,
+                .container_ty = ptr_ty.childType(),
                 .field_index = field_index,
             }),
         );
@@ -16065,6 +16079,7 @@ fn structFieldPtrByIndex(
             ptr_field_ty,
             try Value.Tag.field_ptr.create(sema.arena, .{
                 .container_ptr = struct_ptr_val,
+                .container_ty = struct_ptr_ty.childType(),
                 .field_index = field_index,
             }),
         );
@@ -16241,6 +16256,7 @@ fn unionFieldPtr(
             ptr_field_ty,
             try Value.Tag.field_ptr.create(arena, .{
                 .container_ptr = union_ptr_val,
+                .container_ty = union_ty,
                 .field_index = field_index,
             }),
         );
@@ -16333,7 +16349,7 @@ fn elemPtr(
                     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_ptr = try slice_val.elemPtr(sema.arena, index);
+                        const elem_ptr = try slice_val.elemPtr(array_ty, sema.arena, index);
                         return sema.addConstant(result_ty, elem_ptr);
                     } else array_ptr_src;
 
@@ -16348,7 +16364,7 @@ fn elemPtr(
                         const ptr_val = maybe_ptr_val orelse break :rs array_ptr_src;
                         const index_val = maybe_index_val orelse break :rs elem_index_src;
                         const index = @intCast(usize, index_val.toUnsignedInt());
-                        const elem_ptr = try ptr_val.elemPtr(sema.arena, index);
+                        const elem_ptr = try ptr_val.elemPtr(array_ty, sema.arena, index);
                         return sema.addConstant(result_ty, elem_ptr);
                     };
 
@@ -16473,6 +16489,7 @@ fn tupleFieldPtr(
             ptr_field_ty,
             try Value.Tag.field_ptr.create(sema.arena, .{
                 .container_ptr = tuple_ptr_val,
+                .container_ty = tuple_ty,
                 .field_index = field_index,
             }),
         );
@@ -16563,7 +16580,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.elemPtr(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);
         }
     }
@@ -17757,8 +17774,8 @@ fn beginComptimePtrMutation(
             }
         },
         .eu_payload_ptr => {
-            const eu_ptr_val = ptr_val.castTag(.eu_payload_ptr).?.data;
-            var parent = try beginComptimePtrMutation(sema, block, src, eu_ptr_val);
+            const eu_ptr = ptr_val.castTag(.eu_payload_ptr).?.data;
+            var parent = try beginComptimePtrMutation(sema, block, src, eu_ptr.container_ptr);
             const payload_ty = parent.ty.errorUnionPayload();
             switch (parent.val.tag()) {
                 else => {
@@ -17790,8 +17807,8 @@ fn beginComptimePtrMutation(
             }
         },
         .opt_payload_ptr => {
-            const opt_ptr_val = ptr_val.castTag(.opt_payload_ptr).?.data;
-            var parent = try beginComptimePtrMutation(sema, block, src, opt_ptr_val);
+            const opt_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
+            var parent = try beginComptimePtrMutation(sema, block, src, opt_ptr.container_ptr);
             const payload_ty = try parent.ty.optionalChildAlloc(sema.arena);
             switch (parent.val.tag()) {
                 .undef, .null_value => {
@@ -17965,7 +17982,7 @@ fn beginComptimePtrLoad(
         },
         .eu_payload_ptr => {
             const err_union_ptr = ptr_val.castTag(.eu_payload_ptr).?.data;
-            const parent = try beginComptimePtrLoad(sema, block, src, err_union_ptr);
+            const parent = try beginComptimePtrLoad(sema, block, src, err_union_ptr.container_ptr);
             return ComptimePtrLoadKit{
                 .root_val = parent.root_val,
                 .root_ty = parent.root_ty,
@@ -17977,7 +17994,7 @@ fn beginComptimePtrLoad(
         },
         .opt_payload_ptr => {
             const opt_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
-            const parent = try beginComptimePtrLoad(sema, block, src, opt_ptr);
+            const parent = try beginComptimePtrLoad(sema, block, src, opt_ptr.container_ptr);
             return ComptimePtrLoadKit{
                 .root_val = parent.root_val,
                 .root_ty = parent.root_ty,
src/value.zig
@@ -268,12 +268,14 @@ pub const Value = extern union {
 
                 .repeated,
                 .eu_payload,
-                .eu_payload_ptr,
                 .opt_payload,
-                .opt_payload_ptr,
                 .empty_array_sentinel,
                 => Payload.SubValue,
 
+                .eu_payload_ptr,
+                .opt_payload_ptr,
+                => Payload.PayloadPtr,
+
                 .bytes,
                 .enum_literal,
                 => Payload.Bytes,
@@ -479,6 +481,20 @@ pub const Value = extern union {
             .variable => return self.copyPayloadShallow(arena, Payload.Variable),
             .decl_ref => return self.copyPayloadShallow(arena, Payload.Decl),
             .decl_ref_mut => return self.copyPayloadShallow(arena, Payload.DeclRefMut),
+            .eu_payload_ptr,
+            .opt_payload_ptr,
+            => {
+                const payload = self.cast(Payload.PayloadPtr).?;
+                const new_payload = try arena.create(Payload.PayloadPtr);
+                new_payload.* = .{
+                    .base = payload.base,
+                    .data = .{
+                        .container_ptr = try payload.data.container_ptr.copy(arena),
+                        .container_ty = try payload.data.container_ty.copy(arena),
+                    },
+                };
+                return Value{ .ptr_otherwise = &new_payload.base };
+            },
             .elem_ptr => {
                 const payload = self.castTag(.elem_ptr).?;
                 const new_payload = try arena.create(Payload.ElemPtr);
@@ -486,6 +502,7 @@ pub const Value = extern union {
                     .base = payload.base,
                     .data = .{
                         .array_ptr = try payload.data.array_ptr.copy(arena),
+                        .elem_ty = try payload.data.elem_ty.copy(arena),
                         .index = payload.data.index,
                     },
                 };
@@ -498,6 +515,7 @@ pub const Value = extern union {
                     .base = payload.base,
                     .data = .{
                         .container_ptr = try payload.data.container_ptr.copy(arena),
+                        .container_ty = try payload.data.container_ty.copy(arena),
                         .field_index = payload.data.field_index,
                     },
                 };
@@ -506,9 +524,7 @@ pub const Value = extern union {
             .bytes => return self.copyPayloadShallow(arena, Payload.Bytes),
             .repeated,
             .eu_payload,
-            .eu_payload_ptr,
             .opt_payload,
-            .opt_payload_ptr,
             .empty_array_sentinel,
             => {
                 const payload = self.cast(Payload.SubValue).?;
@@ -740,11 +756,11 @@ pub const Value = extern union {
             .inferred_alloc_comptime => return out_stream.writeAll("(inferred comptime allocation value)"),
             .eu_payload_ptr => {
                 try out_stream.writeAll("(eu_payload_ptr)");
-                val = val.castTag(.eu_payload_ptr).?.data;
+                val = val.castTag(.eu_payload_ptr).?.data.container_ptr;
             },
             .opt_payload_ptr => {
                 try out_stream.writeAll("(opt_payload_ptr)");
-                val = val.castTag(.opt_payload_ptr).?.data;
+                val = val.castTag(.opt_payload_ptr).?.data.container_ptr;
             },
             .bound_fn => {
                 const bound_func = val.castTag(.bound_fn).?.data;
@@ -2162,8 +2178,8 @@ pub const Value = extern union {
             .decl_ref_mut => true,
             .elem_ptr => isComptimeMutablePtr(val.castTag(.elem_ptr).?.data.array_ptr),
             .field_ptr => isComptimeMutablePtr(val.castTag(.field_ptr).?.data.container_ptr),
-            .eu_payload_ptr => isComptimeMutablePtr(val.castTag(.eu_payload_ptr).?.data),
-            .opt_payload_ptr => isComptimeMutablePtr(val.castTag(.opt_payload_ptr).?.data),
+            .eu_payload_ptr => isComptimeMutablePtr(val.castTag(.eu_payload_ptr).?.data.container_ptr),
+            .opt_payload_ptr => isComptimeMutablePtr(val.castTag(.opt_payload_ptr).?.data.container_ptr),
 
             else => false,
         };
@@ -2174,9 +2190,9 @@ pub const Value = extern union {
         switch (val.tag()) {
             .repeated => return val.castTag(.repeated).?.data.canMutateComptimeVarState(),
             .eu_payload => return val.castTag(.eu_payload).?.data.canMutateComptimeVarState(),
-            .eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.canMutateComptimeVarState(),
+            .eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.container_ptr.canMutateComptimeVarState(),
             .opt_payload => return val.castTag(.opt_payload).?.data.canMutateComptimeVarState(),
-            .opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.canMutateComptimeVarState(),
+            .opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.container_ptr.canMutateComptimeVarState(),
             .aggregate => {
                 const fields = val.castTag(.aggregate).?.data;
                 for (fields) |field| {
@@ -2239,12 +2255,12 @@ pub const Value = extern union {
             .eu_payload_ptr => {
                 const err_union_ptr = ptr_val.castTag(.eu_payload_ptr).?.data;
                 std.hash.autoHash(hasher, Value.Tag.eu_payload_ptr);
-                hashPtr(err_union_ptr, hasher);
+                hashPtr(err_union_ptr.container_ptr, hasher);
             },
             .opt_payload_ptr => {
                 const opt_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
                 std.hash.autoHash(hasher, Value.Tag.opt_payload_ptr);
-                hashPtr(opt_ptr, hasher);
+                hashPtr(opt_ptr.container_ptr, hasher);
             },
 
             .zero,
@@ -2272,12 +2288,14 @@ pub const Value = extern union {
 
             .repeated,
             .eu_payload,
-            .eu_payload_ptr,
             .opt_payload,
-            .opt_payload_ptr,
             .empty_array_sentinel,
             => return markReferencedDeclsAlive(val.cast(Payload.SubValue).?.data),
 
+            .eu_payload_ptr,
+            .opt_payload_ptr,
+            => return markReferencedDeclsAlive(val.cast(Payload.PayloadPtr).?.data.container_ptr),
+
             .slice => {
                 const slice = val.cast(Payload.Slice).?.data;
                 markReferencedDeclsAlive(slice.ptr);
@@ -2422,36 +2440,28 @@ pub const Value = extern union {
     }
 
     /// Returns a pointer to the element value at the index.
-    pub fn elemPtr(val: Value, arena: Allocator, index: usize) Allocator.Error!Value {
-        switch (val.tag()) {
-            .elem_ptr => {
-                const elem_ptr = val.castTag(.elem_ptr).?.data;
+    pub fn elemPtr(val: Value, ty: Type, arena: Allocator, index: usize) Allocator.Error!Value {
+        const elem_ty = ty.elemType2();
+        const ptr_val = switch (val.tag()) {
+            .slice => val.slicePtr(),
+            else => val,
+        };
+
+        if (ptr_val.tag() == .elem_ptr) {
+            const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
+            if (elem_ptr.elem_ty.eql(elem_ty)) {
                 return Tag.elem_ptr.create(arena, .{
                     .array_ptr = elem_ptr.array_ptr,
+                    .elem_ty = elem_ptr.elem_ty,
                     .index = elem_ptr.index + index,
                 });
-            },
-            .slice => {
-                const ptr_val = val.castTag(.slice).?.data.ptr;
-                switch (ptr_val.tag()) {
-                    .elem_ptr => {
-                        const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
-                        return Tag.elem_ptr.create(arena, .{
-                            .array_ptr = elem_ptr.array_ptr,
-                            .index = elem_ptr.index + index,
-                        });
-                    },
-                    else => return Tag.elem_ptr.create(arena, .{
-                        .array_ptr = ptr_val,
-                        .index = index,
-                    }),
-                }
-            },
-            else => return Tag.elem_ptr.create(arena, .{
-                .array_ptr = val,
-                .index = index,
-            }),
+            }
         }
+        return Tag.elem_ptr.create(arena, .{
+            .array_ptr = ptr_val,
+            .elem_ty = elem_ty,
+            .index = index,
+        });
     }
 
     pub fn isUndef(self: Value) bool {
@@ -4144,12 +4154,21 @@ pub const Value = extern union {
             };
         };
 
+        pub const PayloadPtr = struct {
+            base: Payload,
+            data: struct {
+                container_ptr: Value,
+                container_ty: Type,
+            },
+        };
+
         pub const ElemPtr = struct {
             pub const base_tag = Tag.elem_ptr;
 
             base: Payload = Payload{ .tag = base_tag },
             data: struct {
                 array_ptr: Value,
+                elem_ty: Type,
                 index: usize,
             },
         };
@@ -4160,6 +4179,7 @@ pub const Value = extern union {
             base: Payload = Payload{ .tag = base_tag },
             data: struct {
                 container_ptr: Value,
+                container_ty: Type,
                 field_index: usize,
             },
         };