Commit d89f39d719

Andrew Kelley <andrew@ziglang.org>
2019-11-14 02:43:32
rework layout of struct type fields
This removes the remaining hack in the implementation of anonymous struct literals, and they can now therefore now have greater than 16 fields/elements.
1 parent f2f698a
src/all_types.hpp
@@ -1279,7 +1279,7 @@ struct RootStruct {
 
 struct ZigTypeStruct {
     AstNode *decl_node;
-    TypeStructField *fields;
+    TypeStructField **fields;
     ScopeDecls *decls_scope;
     HashMap<Buf *, TypeStructField *, buf_hash, buf_eql_buf> fields_by_name;
     RootStruct *root_struct;
src/analyze.cpp
@@ -803,19 +803,19 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
     entry->data.structure.is_slice = true;
     entry->data.structure.src_field_count = element_count;
     entry->data.structure.gen_field_count = element_count;
-    entry->data.structure.fields = allocate<TypeStructField>(element_count);
+    entry->data.structure.fields = alloc_type_struct_fields(element_count);
     entry->data.structure.fields_by_name.init(element_count);
-    entry->data.structure.fields[slice_ptr_index].name = ptr_field_name;
-    entry->data.structure.fields[slice_ptr_index].type_entry = ptr_type;
-    entry->data.structure.fields[slice_ptr_index].src_index = slice_ptr_index;
-    entry->data.structure.fields[slice_ptr_index].gen_index = 0;
-    entry->data.structure.fields[slice_len_index].name = len_field_name;
-    entry->data.structure.fields[slice_len_index].type_entry = g->builtin_types.entry_usize;
-    entry->data.structure.fields[slice_len_index].src_index = slice_len_index;
-    entry->data.structure.fields[slice_len_index].gen_index = 1;
-
-    entry->data.structure.fields_by_name.put(ptr_field_name, &entry->data.structure.fields[slice_ptr_index]);
-    entry->data.structure.fields_by_name.put(len_field_name, &entry->data.structure.fields[slice_len_index]);
+    entry->data.structure.fields[slice_ptr_index]->name = ptr_field_name;
+    entry->data.structure.fields[slice_ptr_index]->type_entry = ptr_type;
+    entry->data.structure.fields[slice_ptr_index]->src_index = slice_ptr_index;
+    entry->data.structure.fields[slice_ptr_index]->gen_index = 0;
+    entry->data.structure.fields[slice_len_index]->name = len_field_name;
+    entry->data.structure.fields[slice_len_index]->type_entry = g->builtin_types.entry_usize;
+    entry->data.structure.fields[slice_len_index]->src_index = slice_len_index;
+    entry->data.structure.fields[slice_len_index]->gen_index = 1;
+
+    entry->data.structure.fields_by_name.put(ptr_field_name, entry->data.structure.fields[slice_ptr_index]);
+    entry->data.structure.fields_by_name.put(len_field_name, entry->data.structure.fields[slice_len_index]);
 
     switch (type_requires_comptime(g, ptr_type)) {
         case ReqCompTimeInvalid:
@@ -828,8 +828,8 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
 
     if (!type_has_bits(ptr_type)) {
         entry->data.structure.gen_field_count = 1;
-        entry->data.structure.fields[slice_ptr_index].gen_index = SIZE_MAX;
-        entry->data.structure.fields[slice_len_index].gen_index = 0;
+        entry->data.structure.fields[slice_ptr_index]->gen_index = SIZE_MAX;
+        entry->data.structure.fields[slice_len_index]->gen_index = 0;
     }
 
     ZigType *child_type = ptr_type->data.pointer.child_type;
@@ -1984,12 +1984,12 @@ static ZigType *get_struct_type(CodeGen *g, const char *type_name, SrcField fiel
     struct_type->data.structure.src_field_count = field_count;
     struct_type->data.structure.gen_field_count = 0;
     struct_type->data.structure.resolve_status = ResolveStatusSizeKnown;
-    struct_type->data.structure.fields = allocate<TypeStructField>(field_count);
+    struct_type->data.structure.fields = alloc_type_struct_fields(field_count);
     struct_type->data.structure.fields_by_name.init(field_count);
 
     size_t abi_align = min_abi_align;
     for (size_t i = 0; i < field_count; i += 1) {
-        TypeStructField *field = &struct_type->data.structure.fields[i];
+        TypeStructField *field = struct_type->data.structure.fields[i];
         field->name = buf_create_from_str(fields[i].name);
         field->type_entry = fields[i].ty;
         field->src_index = i;
@@ -2009,7 +2009,7 @@ static ZigType *get_struct_type(CodeGen *g, const char *type_name, SrcField fiel
 
     size_t next_offset = 0;
     for (size_t i = 0; i < field_count; i += 1) {
-        TypeStructField *field = &struct_type->data.structure.fields[i];
+        TypeStructField *field = struct_type->data.structure.fields[i];
         if (!type_has_bits(field->type_entry))
             continue;
 
@@ -2018,7 +2018,7 @@ static ZigType *get_struct_type(CodeGen *g, const char *type_name, SrcField fiel
         // find the next non-zero-byte field for offset calculations
         size_t next_src_field_index = i + 1;
         for (; next_src_field_index < field_count; next_src_field_index += 1) {
-            if (type_has_bits(struct_type->data.structure.fields[next_src_field_index].type_entry))
+            if (type_has_bits(struct_type->data.structure.fields[next_src_field_index]->type_entry))
                 break;
         }
         size_t next_abi_align;
@@ -2026,7 +2026,7 @@ static ZigType *get_struct_type(CodeGen *g, const char *type_name, SrcField fiel
             next_abi_align = abi_align;
         } else {
             next_abi_align = max(fields[next_src_field_index].align,
-                    struct_type->data.structure.fields[next_src_field_index].type_entry->abi_align);
+                    struct_type->data.structure.fields[next_src_field_index]->type_entry->abi_align);
         }
         next_offset = next_field_offset(next_offset, abi_align, field->type_entry->abi_size, next_abi_align);
     }
@@ -2109,7 +2109,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
 
     // Calculate offsets
     for (size_t i = 0; i < field_count; i += 1) {
-        TypeStructField *field = &struct_type->data.structure.fields[i];
+        TypeStructField *field = struct_type->data.structure.fields[i];
         if (field->gen_index == SIZE_MAX)
             continue;
 
@@ -2178,12 +2178,12 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
             gen_field_index += 1;
             size_t next_src_field_index = i + 1;
             for (; next_src_field_index < field_count; next_src_field_index += 1) {
-                if (struct_type->data.structure.fields[next_src_field_index].gen_index != SIZE_MAX) {
+                if (struct_type->data.structure.fields[next_src_field_index]->gen_index != SIZE_MAX) {
                     break;
                 }
             }
             size_t next_align = (next_src_field_index == field_count) ?
-                abi_align : struct_type->data.structure.fields[next_src_field_index].align;
+                abi_align : struct_type->data.structure.fields[next_src_field_index]->align;
             next_offset = next_field_offset(next_offset, abi_align, field_abi_size, next_align);
             size_in_bits = next_offset * 8;
         }
@@ -2206,7 +2206,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
 
     // Resolve types for fields
     for (size_t i = 0; i < field_count; i += 1) {
-        TypeStructField *field = &struct_type->data.structure.fields[i];
+        TypeStructField *field = struct_type->data.structure.fields[i];
         ZigType *field_type = resolve_struct_field_type(g, field);
         if (field_type == nullptr) {
             struct_type->data.structure.resolve_status = ResolveStatusInvalid;
@@ -2697,7 +2697,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
         struct_type->data.structure.src_field_count = (uint32_t)field_count;
 
         src_assert(struct_type->data.structure.fields == nullptr, decl_node);
-        struct_type->data.structure.fields = allocate<TypeStructField>(field_count);
+        struct_type->data.structure.fields = alloc_type_struct_fields(field_count);
     } else if (decl_node->type == NodeTypeContainerInitExpr) {
         src_assert(struct_type->data.structure.is_inferred, decl_node);
         src_assert(struct_type->data.structure.fields != nullptr, decl_node);
@@ -2711,7 +2711,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
 
     size_t gen_field_index = 0;
     for (size_t i = 0; i < field_count; i += 1) {
-        TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
+        TypeStructField *type_struct_field = struct_type->data.structure.fields[i];
 
         AstNode *field_node;
         if (decl_node->type == NodeTypeContainerDecl) {
@@ -2843,7 +2843,7 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
     bool packed = struct_type->data.structure.layout == ContainerLayoutPacked;
 
     for (size_t i = 0; i < field_count; i += 1) {
-        TypeStructField *field = &struct_type->data.structure.fields[i];
+        TypeStructField *field = struct_type->data.structure.fields[i];
         if (field->gen_index == SIZE_MAX)
             continue;
 
@@ -5506,7 +5506,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
             return type_has_one_possible_value(g, type_entry->data.array.child_type);
         case ZigTypeIdStruct:
             for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
-                TypeStructField *field = &type_entry->data.structure.fields[i];
+                TypeStructField *field = type_entry->data.structure.fields[i];
                 OnePossibleValue opv = (field->type_entry != nullptr) ?
                     type_has_one_possible_value(g, field->type_entry) :
                     type_val_resolve_has_one_possible_value(g, field->type_val);
@@ -5902,6 +5902,21 @@ ConstExprValue **realloc_const_vals_ptrs(ConstExprValue **ptr, size_t old_count,
     return result;
 }
 
+TypeStructField **alloc_type_struct_fields(size_t count) {
+    return realloc_type_struct_fields(nullptr, 0, count);
+}
+
+TypeStructField **realloc_type_struct_fields(TypeStructField **ptr, size_t old_count, size_t new_count) {
+    assert(new_count >= old_count);
+
+    size_t new_item_count = new_count - old_count;
+    TypeStructField **result = reallocate(ptr, old_count, new_count, "TypeStructField*");
+    TypeStructField *vals = allocate<TypeStructField>(new_item_count, "TypeStructField");
+    for (size_t i = old_count; i < new_count; i += 1) {
+        result[i] = &vals[i - old_count];
+    }
+    return result;
+}
 
 static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) {
     if (orig_fn_type->data.fn.fn_type_id.cc == CallingConventionAsync)
@@ -7176,7 +7191,7 @@ static void init_const_undefined(CodeGen *g, ConstExprValue *const_val) {
         const_val->data.x_struct.fields = alloc_const_vals_ptrs(field_count);
         for (size_t i = 0; i < field_count; i += 1) {
             ConstExprValue *field_val = const_val->data.x_struct.fields[i];
-            field_val->type = resolve_struct_field_type(g, &wanted_type->data.structure.fields[i]);
+            field_val->type = resolve_struct_field_type(g, wanted_type->data.structure.fields[i]);
             assert(field_val->type);
             init_const_undefined(g, field_val);
             field_val->parent.id = ConstParentIdStruct;
@@ -7608,7 +7623,7 @@ static X64CABIClass type_system_V_abi_x86_64_class(CodeGen *g, ZigType *ty, size
             }
             X64CABIClass working_class = X64CABIClass_Unknown;
             for (uint32_t i = 0; i < ty->data.structure.src_field_count; i += 1) {
-                X64CABIClass field_class = type_c_abi_x86_64_class(g, ty->data.structure.fields->type_entry);
+                X64CABIClass field_class = type_c_abi_x86_64_class(g, ty->data.structure.fields[0]->type_entry);
                 if (field_class == X64CABIClass_Unknown)
                     return X64CABIClass_Unknown;
                 if (i == 0 || field_class == X64CABIClass_MEMORY || working_class == X64CABIClass_SSE) {
@@ -7740,7 +7755,7 @@ Buf *type_h_name(ZigType *t) {
 static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {
     if (type->data.structure.resolve_status >= wanted_resolve_status) return;
 
-    ZigType *ptr_type = type->data.structure.fields[slice_ptr_index].type_entry;
+    ZigType *ptr_type = type->data.structure.fields[slice_ptr_index]->type_entry;
     ZigType *child_type = ptr_type->data.pointer.child_type;
     ZigType *usize_type = g->builtin_types.entry_usize;
 
@@ -7762,7 +7777,7 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa
     // If the child type is []const T then we need to make sure the type ref
     // and debug info is the same as if the child type were []T.
     if (is_slice(child_type)) {
-        ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry;
+        ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index]->type_entry;
         assert(child_ptr_type->id == ZigTypeIdPointer);
         if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile ||
             child_ptr_type->data.pointer.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero)
@@ -7939,7 +7954,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
 
     // trigger all the recursive get_llvm_type calls
     for (size_t i = 0; i < field_count; i += 1) {
-        TypeStructField *field = &struct_type->data.structure.fields[i];
+        TypeStructField *field = struct_type->data.structure.fields[i];
         ZigType *field_type = field->type_entry;
         if (!type_has_bits(field_type))
             continue;
@@ -7953,7 +7968,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
     // inserting padding bytes where LLVM would do it automatically.
     size_t llvm_struct_abi_align = 0;
     for (size_t i = 0; i < field_count; i += 1) {
-        ZigType *field_type = struct_type->data.structure.fields[i].type_entry;
+        ZigType *field_type = struct_type->data.structure.fields[i]->type_entry;
         if (!type_has_bits(field_type))
             continue;
         LLVMTypeRef field_llvm_type = get_llvm_type(g, field_type);
@@ -7962,7 +7977,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
     }
 
     for (size_t i = 0; i < field_count; i += 1) {
-        TypeStructField *field = &struct_type->data.structure.fields[i];
+        TypeStructField *field = struct_type->data.structure.fields[i];
         ZigType *field_type = field->type_entry;
 
         if (!type_has_bits(field_type)) {
@@ -8012,23 +8027,23 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
             // find the next non-zero-byte field for offset calculations
             size_t next_src_field_index = i + 1;
             for (; next_src_field_index < field_count; next_src_field_index += 1) {
-                if (type_has_bits(struct_type->data.structure.fields[next_src_field_index].type_entry))
+                if (type_has_bits(struct_type->data.structure.fields[next_src_field_index]->type_entry))
                     break;
             }
             size_t next_abi_align;
             if (next_src_field_index == field_count) {
                 next_abi_align = struct_type->abi_align;
             } else {
-                if (struct_type->data.structure.fields[next_src_field_index].align == 0) {
-                    next_abi_align = struct_type->data.structure.fields[next_src_field_index].type_entry->abi_align;
+                if (struct_type->data.structure.fields[next_src_field_index]->align == 0) {
+                    next_abi_align = struct_type->data.structure.fields[next_src_field_index]->type_entry->abi_align;
                 } else {
-                    next_abi_align = struct_type->data.structure.fields[next_src_field_index].align;
+                    next_abi_align = struct_type->data.structure.fields[next_src_field_index]->align;
                 }
             }
             size_t llvm_next_abi_align = (next_src_field_index == field_count) ?
                 llvm_struct_abi_align :
                 LLVMABIAlignmentOfType(g->target_data_ref,
-                        get_llvm_type(g, struct_type->data.structure.fields[next_src_field_index].type_entry));
+                        get_llvm_type(g, struct_type->data.structure.fields[next_src_field_index]->type_entry));
 
             size_t next_offset = next_field_offset(field->offset, struct_type->abi_align,
                     field_type->abi_size, next_abi_align);
@@ -8067,7 +8082,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
     ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(debug_field_count);
     size_t debug_field_index = 0;
     for (size_t i = 0; i < field_count; i += 1) {
-        TypeStructField *field = &struct_type->data.structure.fields[i];
+        TypeStructField *field = struct_type->data.structure.fields[i];
         size_t gen_field_index = field->gen_index;
         if (gen_field_index == SIZE_MAX) {
             continue;
src/analyze.hpp
@@ -180,6 +180,9 @@ ConstExprValue *create_const_vals(size_t count);
 ConstExprValue **alloc_const_vals_ptrs(size_t count);
 ConstExprValue **realloc_const_vals_ptrs(ConstExprValue **ptr, size_t old_count, size_t new_count);
 
+TypeStructField **alloc_type_struct_fields(size_t count);
+TypeStructField **realloc_type_struct_fields(TypeStructField **ptr, size_t old_count, size_t new_count);
+
 ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
 void expand_undef_array(CodeGen *g, ConstExprValue *const_val);
 void expand_undef_struct(CodeGen *g, ConstExprValue *const_val);
src/codegen.cpp
@@ -1108,15 +1108,15 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
     LLVMValueRef err_ret_trace_ptr = LLVMGetParam(fn_val, 0);
     LLVMValueRef address_value = LLVMGetParam(fn_val, 1);
 
-    size_t index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index;
+    size_t index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index;
     LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, err_ret_trace_ptr, (unsigned)index_field_index, "");
-    size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index;
+    size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index;
     LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, err_ret_trace_ptr, (unsigned)addresses_field_index, "");
 
-    ZigType *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry;
-    size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index;
+    ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry;
+    size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index;
     LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)ptr_field_index, "");
-    size_t len_field_index = slice_type->data.structure.fields[slice_len_index].gen_index;
+    size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index;
     LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)len_field_index, "");
 
     LLVMValueRef len_value = gen_load_untyped(g, len_field_ptr, 0, false, "");
@@ -2176,16 +2176,16 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
     LLVMBuildCondBr(g->builder, null_bit, return_block, non_null_block);
 
     LLVMPositionBuilderAtEnd(g->builder, non_null_block);
-    size_t src_index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index;
-    size_t src_addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index;
+    size_t src_index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index;
+    size_t src_addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index;
     LLVMValueRef src_index_field_ptr = LLVMBuildStructGEP(g->builder, src_stack_trace_ptr,
             (unsigned)src_index_field_index, "");
     LLVMValueRef src_addresses_field_ptr = LLVMBuildStructGEP(g->builder, src_stack_trace_ptr,
             (unsigned)src_addresses_field_index, "");
-    ZigType *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry;
-    size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index;
+    ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry;
+    size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index;
     LLVMValueRef src_ptr_field_ptr = LLVMBuildStructGEP(g->builder, src_addresses_field_ptr, (unsigned)ptr_field_index, "");
-    size_t len_field_index = slice_type->data.structure.fields[slice_len_index].gen_index;
+    size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index;
     LLVMValueRef src_len_field_ptr = LLVMBuildStructGEP(g->builder, src_addresses_field_ptr, (unsigned)len_field_index, "");
     LLVMValueRef src_index_val = LLVMBuildLoad(g->builder, src_index_field_ptr, "");
     LLVMValueRef src_ptr_val = LLVMBuildLoad(g->builder, src_ptr_field_ptr, "");
@@ -3010,21 +3010,21 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable,
     assert(actual_type->id == ZigTypeIdStruct);
     assert(actual_type->data.structure.is_slice);
 
-    ZigType *actual_pointer_type = actual_type->data.structure.fields[0].type_entry;
+    ZigType *actual_pointer_type = actual_type->data.structure.fields[0]->type_entry;
     ZigType *actual_child_type = actual_pointer_type->data.pointer.child_type;
-    ZigType *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry;
+    ZigType *wanted_pointer_type = wanted_type->data.structure.fields[0]->type_entry;
     ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
 
 
-    size_t actual_ptr_index = actual_type->data.structure.fields[slice_ptr_index].gen_index;
-    size_t actual_len_index = actual_type->data.structure.fields[slice_len_index].gen_index;
-    size_t wanted_ptr_index = wanted_type->data.structure.fields[slice_ptr_index].gen_index;
-    size_t wanted_len_index = wanted_type->data.structure.fields[slice_len_index].gen_index;
+    size_t actual_ptr_index = actual_type->data.structure.fields[slice_ptr_index]->gen_index;
+    size_t actual_len_index = actual_type->data.structure.fields[slice_len_index]->gen_index;
+    size_t wanted_ptr_index = wanted_type->data.structure.fields[slice_ptr_index]->gen_index;
+    size_t wanted_len_index = wanted_type->data.structure.fields[slice_len_index]->gen_index;
 
     LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_ptr_index, "");
     LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, "");
     LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr,
-            get_llvm_type(g, wanted_type->data.structure.fields[0].type_entry), "");
+            get_llvm_type(g, wanted_type->data.structure.fields[0]->type_entry), "");
     LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, result_loc,
             (unsigned)wanted_ptr_index, "");
     gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false);
@@ -3140,9 +3140,9 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutable *ex
 {
     ZigType *actual_type = instruction->operand->value.type;
     ZigType *slice_type = instruction->base.value.type;
-    ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index].type_entry;
-    size_t ptr_index = slice_type->data.structure.fields[slice_ptr_index].gen_index;
-    size_t len_index = slice_type->data.structure.fields[slice_len_index].gen_index;
+    ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
+    size_t ptr_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index;
+    size_t len_index = slice_type->data.structure.fields[slice_len_index]->gen_index;
 
     LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc);
 
@@ -3766,14 +3766,14 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
         assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
 
         if (safety_check_on) {
-            size_t len_index = array_type->data.structure.fields[slice_len_index].gen_index;
+            size_t len_index = array_type->data.structure.fields[slice_len_index]->gen_index;
             assert(len_index != SIZE_MAX);
             LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)len_index, "");
             LLVMValueRef len = gen_load_untyped(g, len_ptr, 0, false, "");
             add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, len);
         }
 
-        size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index;
+        size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index;
         assert(ptr_index != SIZE_MAX);
         LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)ptr_index, "");
         LLVMValueRef ptr = gen_load_untyped(g, ptr_ptr, 0, false, "");
@@ -3865,7 +3865,7 @@ static void render_async_spills(CodeGen *g) {
         if (instruction->field_index == SIZE_MAX)
             continue;
 
-        size_t gen_index = frame_type->data.structure.fields[instruction->field_index].gen_index;
+        size_t gen_index = frame_type->data.structure.fields[instruction->field_index]->gen_index;
         instruction->base.llvm_value = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, gen_index,
                 instruction->name_hint);
     }
@@ -4992,10 +4992,10 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
         align_bytes = target_type->data.maybe.child_type->data.fn.fn_type_id.alignment;
         ptr_val = target_val;
     } else if (target_type->id == ZigTypeIdStruct && target_type->data.structure.is_slice) {
-        ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry;
+        ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index]->type_entry;
         align_bytes = get_ptr_align(g, slice_ptr_type);
 
-        size_t ptr_index = target_type->data.structure.fields[slice_ptr_index].gen_index;
+        size_t ptr_index = target_type->data.structure.fields[slice_ptr_index]->gen_index;
         LLVMValueRef ptr_val_ptr = LLVMBuildStructGEP(g->builder, target_val, (unsigned)ptr_index, "");
         ptr_val = gen_load_untyped(g, ptr_val_ptr, 0, false, "");
     } else {
@@ -5240,13 +5240,13 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
         }
 
         if (type_has_bits(array_type)) {
-            size_t gen_ptr_index = instruction->base.value.type->data.structure.fields[slice_ptr_index].gen_index;
+            size_t gen_ptr_index = instruction->base.value.type->data.structure.fields[slice_ptr_index]->gen_index;
             LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_ptr_index, "");
             LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, "");
             gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
         }
 
-        size_t gen_len_index = instruction->base.value.type->data.structure.fields[slice_len_index].gen_index;
+        size_t gen_len_index = instruction->base.value.type->data.structure.fields[slice_len_index]->gen_index;
         LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_len_index, "");
         LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
         gen_store_untyped(g, len_value, len_field_ptr, 0, false);
@@ -5258,9 +5258,9 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
         assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
         assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind);
 
-        size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index;
+        size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index;
         assert(ptr_index != SIZE_MAX);
-        size_t len_index = array_type->data.structure.fields[slice_len_index].gen_index;
+        size_t len_index = array_type->data.structure.fields[slice_len_index]->gen_index;
         assert(len_index != SIZE_MAX);
 
         LLVMValueRef prev_end = nullptr;
@@ -6568,7 +6568,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
                 LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false);
                 size_t used_bits = 0;
                 for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
-                    TypeStructField *field = &type_entry->data.structure.fields[i];
+                    TypeStructField *field = type_entry->data.structure.fields[i];
                     if (field->gen_index == SIZE_MAX) {
                         continue;
                     }
@@ -6647,7 +6647,7 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
                     return const_val->global_refs->llvm_value;
                 }
                 size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index;
-                size_t gen_field_index = struct_const_val->type->data.structure.fields[src_field_index].gen_index;
+                size_t gen_field_index = struct_const_val->type->data.structure.fields[src_field_index]->gen_index;
                 LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val,
                         gen_field_index);
                 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, get_llvm_type(g, const_val->type));
@@ -6826,7 +6826,7 @@ check: switch (const_val->special) {
                 if (type_entry->data.structure.layout == ContainerLayoutPacked) {
                     size_t src_field_index = 0;
                     while (src_field_index < src_field_count) {
-                        TypeStructField *type_struct_field = &type_entry->data.structure.fields[src_field_index];
+                        TypeStructField *type_struct_field = type_entry->data.structure.fields[src_field_index];
                         if (type_struct_field->gen_index == SIZE_MAX) {
                             src_field_index += 1;
                             continue;
@@ -6834,7 +6834,7 @@ check: switch (const_val->special) {
 
                         size_t src_field_index_end = src_field_index + 1;
                         for (; src_field_index_end < src_field_count; src_field_index_end += 1) {
-                            TypeStructField *it_field = &type_entry->data.structure.fields[src_field_index_end];
+                            TypeStructField *it_field = type_entry->data.structure.fields[src_field_index_end];
                             if (it_field->gen_index != type_struct_field->gen_index)
                                 break;
                         }
@@ -6853,7 +6853,7 @@ check: switch (const_val->special) {
                             LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false);
                             size_t used_bits = 0;
                             for (size_t i = src_field_index; i < src_field_index_end; i += 1) {
-                                TypeStructField *it_field = &type_entry->data.structure.fields[i];
+                                TypeStructField *it_field = type_entry->data.structure.fields[i];
                                 if (it_field->gen_index == SIZE_MAX) {
                                     continue;
                                 }
@@ -6893,7 +6893,7 @@ check: switch (const_val->special) {
                     }
                 } else {
                     for (uint32_t i = 0; i < src_field_count; i += 1) {
-                        TypeStructField *type_struct_field = &type_entry->data.structure.fields[i];
+                        TypeStructField *type_struct_field = type_entry->data.structure.fields[i];
                         if (type_struct_field->gen_index == SIZE_MAX) {
                             continue;
                         }
@@ -6910,10 +6910,10 @@ check: switch (const_val->special) {
                         make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, field_val->type, val);
 
                         size_t end_pad_gen_index = (i + 1 < src_field_count) ?
-                            type_entry->data.structure.fields[i + 1].gen_index :
+                            type_entry->data.structure.fields[i + 1]->gen_index :
                             type_entry->data.structure.gen_field_count;
                         size_t next_offset = (i + 1 < src_field_count) ?
-                            type_entry->data.structure.fields[i + 1].offset : type_entry->abi_size;
+                            type_entry->data.structure.fields[i + 1]->offset : type_entry->abi_size;
                         if (end_pad_gen_index != SIZE_MAX) {
                             for (size_t gen_i = type_struct_field->gen_index + 1; gen_i < end_pad_gen_index;
                                     gen_i += 1)
@@ -7576,15 +7576,15 @@ static void do_code_gen(CodeGen *g) {
         // finishing error return trace setup. we have to do this after all the allocas.
         if (have_err_ret_trace_stack) {
             ZigType *usize = g->builtin_types.entry_usize;
-            size_t index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index;
+            size_t index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index;
             LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)index_field_index, "");
             gen_store_untyped(g, LLVMConstNull(usize->llvm_type), index_field_ptr, 0, false);
 
-            size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index;
+            size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index;
             LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)addresses_field_index, "");
 
-            ZigType *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry;
-            size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index;
+            ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry;
+            size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index;
             LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)ptr_field_index, "");
             LLVMValueRef zero = LLVMConstNull(usize->llvm_type);
             LLVMValueRef indices[] = {zero, zero};
@@ -7593,7 +7593,7 @@ static void do_code_gen(CodeGen *g) {
             ZigType *ptr_ptr_usize_type = get_pointer_to_type(g, get_pointer_to_type(g, usize, false), false);
             gen_store(g, err_ret_array_val_elem0_ptr, ptr_field_ptr, ptr_ptr_usize_type);
 
-            size_t len_field_index = slice_type->data.structure.fields[slice_len_index].gen_index;
+            size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index;
             LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)len_field_index, "");
             gen_store(g, LLVMConstInt(usize->llvm_type, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false));
         }
@@ -9508,7 +9508,7 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e
             return;
         case ZigTypeIdStruct:
             for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
-                TypeStructField *field = &type_entry->data.structure.fields[i];
+                TypeStructField *field = type_entry->data.structure.fields[i];
                 prepend_c_type_to_decl_list(g, gen_h, field->type_entry);
             }
             gen_h->types_to_declare.append(type_entry);
@@ -9874,7 +9874,7 @@ static void gen_h_file(CodeGen *g) {
                 if (type_entry->data.structure.layout == ContainerLayoutExtern) {
                     fprintf(out_h, "struct %s {\n", buf_ptr(type_h_name(type_entry)));
                     for (uint32_t field_i = 0; field_i < type_entry->data.structure.src_field_count; field_i += 1) {
-                        TypeStructField *struct_field = &type_entry->data.structure.fields[field_i];
+                        TypeStructField *struct_field = type_entry->data.structure.fields[field_i];
 
                         Buf *type_name_buf = buf_alloc();
                         get_c_type(g, gen_h, struct_field->type_entry, type_name_buf);
src/dump_analysis.cpp
@@ -268,7 +268,7 @@ static void tree_print_struct(FILE *f, ZigType *struct_type, size_t indent) {
     ZigList<ZigType *> children = {};
     uint64_t sum_from_fields = 0;
     for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {
-        TypeStructField *field = &struct_type->data.structure.fields[i];
+        TypeStructField *field = struct_type->data.structure.fields[i];
         children.append(field->type_entry);
         sum_from_fields += field->type_entry->abi_size;
     }
@@ -747,7 +747,7 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {
             if (ty->data.structure.is_slice) {
                 jw_object_field(jw, "len");
                 jw_int(jw, 2);
-                anal_dump_pointer_attrs(ctx, ty->data.structure.fields[slice_ptr_index].type_entry);
+                anal_dump_pointer_attrs(ctx, ty->data.structure.fields[slice_ptr_index]->type_entry);
                 break;
             }
 
@@ -803,7 +803,7 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) {
 
                 for(size_t i = 0; i < ty->data.structure.src_field_count; i += 1) {
                     jw_array_elem(jw);
-                    anal_dump_type_ref(ctx, ty->data.structure.fields[i].type_entry);
+                    anal_dump_type_ref(ctx, ty->data.structure.fields[i]->type_entry);
                 }
                 jw_end_array(jw);
             }
src/ir.cpp
@@ -277,7 +277,7 @@ static bool is_slice(ZigType *type) {
 
 static bool slice_is_const(ZigType *type) {
     assert(is_slice(type));
-    return type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;
+    return type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;
 }
 
 // This function returns true when you can change the type of a ConstExprValue and the
@@ -9858,8 +9858,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
 
     // slice const
     if (is_slice(wanted_type) && is_slice(actual_type)) {
-        ZigType *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry;
-        ZigType *wanted_ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
+        ZigType *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index]->type_entry;
+        ZigType *wanted_ptr_type = wanted_type->data.structure.fields[slice_ptr_index]->type_entry;
         if ((err = type_resolve(g, actual_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
             result.id = ConstCastResultIdInvalid;
             return result;
@@ -10623,7 +10623,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
             ZigType *array_type = cur_type->data.pointer.child_type;
             ZigType *slice_type = (prev_type->id == ZigTypeIdErrorUnion) ?
                 prev_type->data.error_union.payload_type : prev_type;
-            ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index].type_entry;
+            ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
             if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0) &&
                 types_match_const_cast_only(ira,
                     slice_ptr_type->data.pointer.child_type,
@@ -10644,7 +10644,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
             ZigType *array_type = prev_type->data.pointer.child_type;
             ZigType *slice_type = (cur_type->id == ZigTypeIdErrorUnion) ?
                 cur_type->data.error_union.payload_type : cur_type;
-            ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index].type_entry;
+            ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
             if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0) &&
                 types_match_const_cast_only(ira,
                     slice_ptr_type->data.pointer.child_type,
@@ -10658,10 +10658,10 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
 
         // [N]T to []T
         if (cur_type->id == ZigTypeIdArray && is_slice(prev_type) &&
-            (prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
+            (prev_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const ||
             cur_type->data.array.len == 0) &&
             types_match_const_cast_only(ira,
-                prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
+                prev_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.child_type,
                 cur_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
         {
             convert_to_const_slice = false;
@@ -10670,10 +10670,10 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
 
         // [N]T to []T
         if (prev_type->id == ZigTypeIdArray && is_slice(cur_type) &&
-            (cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
+            (cur_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const ||
             prev_type->data.array.len == 0) &&
             types_match_const_cast_only(ira,
-                cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
+                cur_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.child_type,
                 prev_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
         {
             prev_inst = cur_inst;
@@ -10978,7 +10978,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
             assert(value->value.type->id == ZigTypeIdPointer);
             ZigType *array_type = value->value.type->data.pointer.child_type;
             assert(is_slice(wanted_type));
-            bool is_const = wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;
+            bool is_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;
 
             IrInstruction *result = ir_const(ira, source_instr, wanted_type);
             init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const);
@@ -12775,7 +12775,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
     // cast from [N]T to []const T
     // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
     if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) {
-        ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
+        ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index]->type_entry;
         assert(ptr_type->id == ZigTypeIdPointer);
         if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
             types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
@@ -12792,7 +12792,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
         actual_type->id == ZigTypeIdArray)
     {
         ZigType *ptr_type =
-            wanted_type->data.maybe.child_type->data.structure.fields[slice_ptr_index].type_entry;
+            wanted_type->data.maybe.child_type->data.structure.fields[slice_ptr_index]->type_entry;
         assert(ptr_type->id == ZigTypeIdPointer);
         if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
             types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
@@ -12841,7 +12841,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
     {
         ZigType *slice_type = (wanted_type->id == ZigTypeIdErrorUnion) ?
             wanted_type->data.error_union.payload_type : wanted_type;
-        ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index].type_entry;
+        ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
         assert(slice_ptr_type->id == ZigTypeIdPointer);
         ZigType *array_type = actual_type->data.pointer.child_type;
         bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0
@@ -12895,7 +12895,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
         actual_type->data.pointer.child_type->id == ZigTypeIdArray)
     {
         ZigType *slice_type = wanted_type->data.error_union.payload_type;
-        ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index].type_entry;
+        ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
         assert(slice_ptr_type->id == ZigTypeIdPointer);
         ZigType *array_type = actual_type->data.pointer.child_type;
         bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0
@@ -12972,7 +12972,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
         actual_type->id == ZigTypeIdArray)
     {
         ZigType *ptr_type =
-            wanted_type->data.error_union.payload_type->data.structure.fields[slice_ptr_index].type_entry;
+            wanted_type->data.error_union.payload_type->data.structure.fields[slice_ptr_index]->type_entry;
         assert(ptr_type->id == ZigTypeIdPointer);
         if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
             types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
@@ -14817,7 +14817,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
         op1_array_index = op1_val->data.x_ptr.data.base_array.elem_index;
         op1_array_end = op1_array_val->type->data.array.len - 1;
     } else if (is_slice(op1_type)) {
-        ZigType *ptr_type = op1_type->data.structure.fields[slice_ptr_index].type_entry;
+        ZigType *ptr_type = op1_type->data.structure.fields[slice_ptr_index]->type_entry;
         child_type = ptr_type->data.pointer.child_type;
         ConstExprValue *ptr_val = op1_val->data.x_struct.fields[slice_ptr_index];
         assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
@@ -14850,7 +14850,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
         op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index;
         op2_array_end = op2_array_val->type->data.array.len - 1;
     } else if (is_slice(op2_type)) {
-        ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index].type_entry;
+        ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index]->type_entry;
         op2_type_valid = ptr_type->data.pointer.child_type == child_type;
         ConstExprValue *ptr_val = op2_val->data.x_struct.fields[slice_ptr_index];
         assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
@@ -16458,18 +16458,10 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
         uint32_t old_field_count = isf->inferred_struct_type->data.structure.src_field_count;
         uint32_t new_field_count = old_field_count + 1;
         isf->inferred_struct_type->data.structure.src_field_count = new_field_count;
-        if (new_field_count > 16) {
-            // This thing with 16 is a hack to allow this functionality to work without
-            // modifying the ConstExprValue layout of structs. That reworking needs to be
-            // done, but this hack lets us do it separately, in the future.
-            zig_panic("TODO need to rework the layout of ZigTypeStruct. This realloc would have caused invalid pointer references");
-        }
-        if (isf->inferred_struct_type->data.structure.fields == nullptr) {
-            isf->inferred_struct_type->data.structure.fields = allocate<TypeStructField>(16);
-        }
+        isf->inferred_struct_type->data.structure.fields = realloc_type_struct_fields(
+                isf->inferred_struct_type->data.structure.fields, old_field_count, new_field_count);
 
-        // This reference can't live long, don't keep it around outside this block.
-        TypeStructField *field = &isf->inferred_struct_type->data.structure.fields[old_field_count];
+        TypeStructField *field = isf->inferred_struct_type->data.structure.fields[old_field_count];
         field->name = isf->field_name;
         field->type_entry = uncasted_value->value.type;
         field->type_val = create_const_type(ira->codegen, field->type_entry);
@@ -17900,7 +17892,7 @@ static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_ali
 
 static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align) {
     assert(is_slice(slice_type));
-    ZigType *ptr_type = adjust_ptr_align(g, slice_type->data.structure.fields[slice_ptr_index].type_entry,
+    ZigType *ptr_type = adjust_ptr_align(g, slice_type->data.structure.fields[slice_ptr_index]->type_entry,
         new_align);
     return get_slice_type(g, ptr_type);
 }
@@ -17986,7 +17978,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
         }
         return_type = adjust_ptr_len(ira->codegen, array_type, elem_ptr_instruction->ptr_len);
     } else if (is_slice(array_type)) {
-        return_type = adjust_ptr_len(ira->codegen, array_type->data.structure.fields[slice_ptr_index].type_entry,
+        return_type = adjust_ptr_len(ira->codegen, array_type->data.structure.fields[slice_ptr_index]->type_entry,
                 elem_ptr_instruction->ptr_len);
     } else if (array_type->id == ZigTypeIdArgTuple) {
         ConstExprValue *ptr_val = ir_resolve_const(ira, array_ptr, UndefBad);
@@ -18464,7 +18456,7 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
                     ConstExprValue *field_val = struct_val->data.x_struct.fields[i];
                     field_val->special = ConstValSpecialUndef;
                     field_val->type = resolve_struct_field_type(ira->codegen,
-                            &struct_type->data.structure.fields[i]);
+                            struct_type->data.structure.fields[i]);
                     field_val->parent.id = ConstParentIdStruct;
                     field_val->parent.data.p_struct.struct_val = struct_val;
                     field_val->parent.data.p_struct.field_index = i;
@@ -20385,7 +20377,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
         if (field_assign_nodes[i] != nullptr) continue;
 
         // look for a default field value
-        TypeStructField *field = &container_type->data.structure.fields[i];
+        TypeStructField *field = container_type->data.structure.fields[i];
         if (field->init_val == nullptr) {
             // it's not memoized. time to go analyze it
             AstNode *init_node;
@@ -20396,7 +20388,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
             }
             if (init_node == nullptr) {
                 ir_add_error_node(ira, instruction->source_node,
-                    buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name)));
+                    buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i]->name)));
                 any_missing = true;
                 continue;
             }
@@ -21198,7 +21190,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
     ZigType *attrs_type;
     BuiltinPtrSize size_enum_index;
     if (is_slice(ptr_type_entry)) {
-        attrs_type = ptr_type_entry->data.structure.fields[slice_ptr_index].type_entry;
+        attrs_type = ptr_type_entry->data.structure.fields[slice_ptr_index]->type_entry;
         size_enum_index = BuiltinPtrSizeSlice;
     } else if (ptr_type_entry->id == ZigTypeIdPointer) {
         attrs_type = ptr_type_entry;
@@ -21691,7 +21683,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
                 init_const_slice(ira->codegen, fields[1], struct_field_array, 0, struct_field_count, false);
 
                 for (uint32_t struct_field_index = 0; struct_field_index < struct_field_count; struct_field_index++) {
-                    TypeStructField *struct_field = &type_entry->data.structure.fields[struct_field_index];
+                    TypeStructField *struct_field = type_entry->data.structure.fields[struct_field_index];
                     ConstExprValue *struct_field_val = &struct_field_array->data.x_array.data.s_none.elements[struct_field_index];
 
                     struct_field_val->special = ConstValSpecialStatic;
@@ -22647,7 +22639,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
         if ((err = resolve_ptr_align(ira, target->value.type, &src_ptr_align)))
             return ira->codegen->invalid_instruction;
     } else if (is_slice(target->value.type)) {
-        ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;
+        ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index]->type_entry;
         src_ptr_const = src_ptr_type->data.pointer.is_const;
         src_ptr_volatile = src_ptr_type->data.pointer.is_volatile;
 
@@ -22740,7 +22732,7 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
         return ira->codegen->invalid_instruction;
     }
 
-    ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;
+    ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index]->type_entry;
 
     uint32_t alignment;
     if ((err = resolve_ptr_align(ira, src_ptr_type, &alignment)))
@@ -23548,7 +23540,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
             }
         }
     } else if (is_slice(array_type)) {
-        ZigType *ptr_type = array_type->data.structure.fields[slice_ptr_index].type_entry;
+        ZigType *ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry;
         return_type = get_slice_type(ira->codegen, ptr_type);
     } else {
         ir_add_error(ira, &instruction->base,
@@ -23857,7 +23849,7 @@ static IrInstruction *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInstr
                     member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count));
             return ira->codegen->invalid_instruction;
         }
-        TypeStructField *field = &container_type->data.structure.fields[member_index];
+        TypeStructField *field = container_type->data.structure.fields[member_index];
 
         return ir_const_type(ira, &instruction->base, field->type_entry);
     } else if (container_type->id == ZigTypeIdUnion) {
@@ -23899,7 +23891,7 @@ static IrInstruction *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInstr
                     member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count));
             return ira->codegen->invalid_instruction;
         }
-        TypeStructField *field = &container_type->data.structure.fields[member_index];
+        TypeStructField *field = container_type->data.structure.fields[member_index];
 
         IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
         init_const_str_lit(ira->codegen, &result->value, field->name);
@@ -24885,7 +24877,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
         ZigType *fn_type = get_fn_type(ira->codegen, &fn_type_id);
         result_type = get_optional_type(ira->codegen, fn_type);
     } else if (is_slice(target_type)) {
-        ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry;
+        ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index]->type_entry;
         if ((err = resolve_ptr_align(ira, slice_ptr_type, &old_align_bytes)))
             return ira->codegen->invalid_instruction;
         ZigType *result_ptr_type = adjust_ptr_align(ira->codegen, slice_ptr_type, align_bytes);
@@ -25130,7 +25122,7 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
                 case ContainerLayoutExtern: {
                     size_t src_field_count = val->type->data.structure.src_field_count;
                     for (size_t field_i = 0; field_i < src_field_count; field_i += 1) {
-                        TypeStructField *struct_field = &val->type->data.structure.fields[field_i];
+                        TypeStructField *struct_field = val->type->data.structure.fields[field_i];
                         if (struct_field->gen_index == SIZE_MAX)
                             continue;
                         ConstExprValue *field_val = val->data.x_struct.fields[field_i];
@@ -25159,7 +25151,7 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
                         bigint_init_unsigned(&big_int, 0);
                         size_t used_bits = 0;
                         while (src_i < src_field_count) {
-                            TypeStructField *field = &val->type->data.structure.fields[src_i];
+                            TypeStructField *field = val->type->data.structure.fields[src_i];
                             assert(field->gen_index != SIZE_MAX);
                             if (field->gen_index != gen_i)
                                 break;
@@ -25306,7 +25298,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
                     for (size_t field_i = 0; field_i < src_field_count; field_i += 1) {
                         ConstExprValue *field_val = val->data.x_struct.fields[field_i];
                         field_val->special = ConstValSpecialStatic;
-                        TypeStructField *struct_field = &val->type->data.structure.fields[field_i];
+                        TypeStructField *struct_field = val->type->data.structure.fields[field_i];
                         field_val->type = struct_field->type_entry;
                         if (struct_field->gen_index == SIZE_MAX)
                             continue;
@@ -25337,7 +25329,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
                         BigInt big_int;
                         bigint_read_twos_complement(&big_int, buf + offset, big_int_byte_count * 8, is_big_endian, false);
                         while (src_i < src_field_count) {
-                            TypeStructField *field = &val->type->data.structure.fields[src_i];
+                            TypeStructField *field = val->type->data.structure.fields[src_i];
                             src_assert(field->gen_index != SIZE_MAX, source_node);
                             if (field->gen_index != gen_i)
                                 break;
@@ -25600,7 +25592,7 @@ static IrInstruction *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstru
 
     ZigType *elem_type = nullptr;
     if (is_slice(target->value.type)) {
-        ZigType *slice_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;
+        ZigType *slice_ptr_type = target->value.type->data.structure.fields[slice_ptr_index]->type_entry;
         elem_type = slice_ptr_type->data.pointer.child_type;
     } else if (target->value.type->id == ZigTypeIdPointer) {
         elem_type = target->value.type->data.pointer.child_type;