| ... | @@ -17646,12 +17646,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -17646,12 +17646,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17646 | struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len); | 17646 | struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len); |
| 17647 | | 17647 | |
| 17648 | for (struct_field_vals, 0..) |*field_val, i| { | 17648 | for (struct_field_vals, 0..) |*field_val, i| { |
| 17649 | const name_nts = struct_type.fieldName(ip, i).unwrap().?; | 17649 | // TODO: write something like getCoercedInts to avoid needing to dupe |
| | 17650 | const name = if (struct_type.fieldName(ip, i).unwrap()) |name_nts| |
| | 17651 | try sema.arena.dupe(u8, ip.stringToSlice(name_nts)) |
| | 17652 | else |
| | 17653 | try std.fmt.allocPrintZ(gpa, "{d}", .{i}); |
| 17650 | const field_ty = struct_type.field_types.get(ip)[i].toType(); | 17654 | const field_ty = struct_type.field_types.get(ip)[i].toType(); |
| 17651 | const field_init = struct_type.fieldInit(ip, i); | 17655 | const field_init = struct_type.fieldInit(ip, i); |
| 17652 | const field_is_comptime = struct_type.fieldIsComptime(ip, i); | 17656 | const field_is_comptime = struct_type.fieldIsComptime(ip, i); |
| 17653 | // TODO: write something like getCoercedInts to avoid needing to dupe | | |
| 17654 | const name = try sema.arena.dupe(u8, ip.stringToSlice(name_nts)); | | |
| 17655 | const name_val = v: { | 17657 | const name_val = v: { |
| 17656 | var anon_decl = try block.startAnonDecl(); | 17658 | var anon_decl = try block.startAnonDecl(); |
| 17657 | defer anon_decl.deinit(); | 17659 | defer anon_decl.deinit(); |
| ... | @@ -17676,11 +17678,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -17676,11 +17678,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17676 | | 17678 | |
| 17677 | const opt_default_val = if (field_init == .none) null else field_init.toValue(); | 17679 | const opt_default_val = if (field_init == .none) null else field_init.toValue(); |
| 17678 | const default_val_ptr = try sema.optRefValue(block, field_ty, opt_default_val); | 17680 | const default_val_ptr = try sema.optRefValue(block, field_ty, opt_default_val); |
| 17679 | const alignment = mod.structFieldAlignment( | 17681 | const alignment = switch (struct_type.layout) { |
| 17680 | struct_type.field_aligns.get(ip)[i], | 17682 | .Packed => .none, |
| 17681 | field_ty, | 17683 | else => try sema.structFieldAlignment( |
| 17682 | struct_type.layout, | 17684 | struct_type.fieldAlign(ip, i), |
| 17683 | ); | 17685 | field_ty, |
| | 17686 | struct_type.layout, |
| | 17687 | ), |
| | 17688 | }; |
| 17684 | | 17689 | |
| 17685 | const struct_field_fields = .{ | 17690 | const struct_field_fields = .{ |
| 17686 | // name: []const u8, | 17691 | // name: []const u8, |
| ... | @@ -19291,7 +19296,7 @@ fn finishStructInit( | ... | @@ -19291,7 +19296,7 @@ fn finishStructInit( |
| 19291 | for (0..struct_type.field_types.len) |i| { | 19296 | for (0..struct_type.field_types.len) |i| { |
| 19292 | if (field_inits[i] != .none) continue; | 19297 | if (field_inits[i] != .none) continue; |
| 19293 | | 19298 | |
| 19294 | const field_init = struct_type.field_inits.get(ip)[i]; | 19299 | const field_init = struct_type.fieldInit(ip, i); |
| 19295 | if (field_init == .none) { | 19300 | if (field_init == .none) { |
| 19296 | const field_name = struct_type.field_names.get(ip)[i]; | 19301 | const field_name = struct_type.field_names.get(ip)[i]; |
| 19297 | const template = "missing struct field: {}"; | 19302 | const template = "missing struct field: {}"; |
| ... | @@ -20995,9 +21000,10 @@ fn reifyStruct( | ... | @@ -20995,9 +21000,10 @@ fn reifyStruct( |
| 20995 | .fields_len = fields_len, | 21000 | .fields_len = fields_len, |
| 20996 | .requires_comptime = .unknown, | 21001 | .requires_comptime = .unknown, |
| 20997 | .is_tuple = is_tuple, | 21002 | .is_tuple = is_tuple, |
| 20998 | // So that we don't have to scan ahead, we allocate space in the struct for | 21003 | // So that we don't have to scan ahead, we allocate space in the struct |
| 20999 | // alignments, comptime fields, and default inits. This might result in wasted | 21004 | // type for alignments, comptime fields, and default inits. This might |
| 21000 | // space, however, this is a permitted encoding of struct types. | 21005 | // result in wasted space, however, this is a permitted encoding of |
| | 21006 | // struct types. |
| 21001 | .any_comptime_fields = true, | 21007 | .any_comptime_fields = true, |
| 21002 | .any_default_inits = true, | 21008 | .any_default_inits = true, |
| 21003 | .any_aligned_fields = true, | 21009 | .any_aligned_fields = true, |
| ... | @@ -21042,6 +21048,8 @@ fn reifyStruct( | ... | @@ -21042,6 +21048,8 @@ fn reifyStruct( |
| 21042 | if (layout == .Packed) { | 21048 | if (layout == .Packed) { |
| 21043 | if (abi_align != 0) return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{}); | 21049 | if (abi_align != 0) return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{}); |
| 21044 | if (is_comptime_val.toBool()) return sema.fail(block, src, "packed struct fields cannot be marked comptime", .{}); | 21050 | if (is_comptime_val.toBool()) return sema.fail(block, src, "packed struct fields cannot be marked comptime", .{}); |
| | 21051 | } else { |
| | 21052 | struct_type.field_aligns.get(ip)[i] = Alignment.fromByteUnits(abi_align); |
| 21045 | } | 21053 | } |
| 21046 | if (layout == .Extern and is_comptime_val.toBool()) { | 21054 | if (layout == .Extern and is_comptime_val.toBool()) { |
| 21047 | return sema.fail(block, src, "extern struct fields cannot be marked comptime", .{}); | 21055 | return sema.fail(block, src, "extern struct fields cannot be marked comptime", .{}); |
| ... | @@ -21065,8 +21073,7 @@ fn reifyStruct( | ... | @@ -21065,8 +21073,7 @@ fn reifyStruct( |
| 21065 | .{field_index}, | 21073 | .{field_index}, |
| 21066 | ); | 21074 | ); |
| 21067 | } | 21075 | } |
| 21068 | } | 21076 | } else if (struct_type.addFieldName(ip, field_name)) |prev_index| { |
| 21069 | if (struct_type.addFieldName(ip, field_name)) |prev_index| { | | |
| 21070 | _ = prev_index; // TODO: better source location | 21077 | _ = prev_index; // TODO: better source location |
| 21071 | return sema.fail(block, src, "duplicate struct field {}", .{field_name.fmt(ip)}); | 21078 | return sema.fail(block, src, "duplicate struct field {}", .{field_name.fmt(ip)}); |
| 21072 | } | 21079 | } |
| ... | @@ -21084,7 +21091,6 @@ fn reifyStruct( | ... | @@ -21084,7 +21091,6 @@ fn reifyStruct( |
| 21084 | } | 21091 | } |
| 21085 | | 21092 | |
| 21086 | struct_type.field_types.get(ip)[i] = field_ty.toIntern(); | 21093 | struct_type.field_types.get(ip)[i] = field_ty.toIntern(); |
| 21087 | struct_type.field_aligns.get(ip)[i] = Alignment.fromByteUnits(abi_align); | | |
| 21088 | struct_type.field_inits.get(ip)[i] = default_val; | 21094 | struct_type.field_inits.get(ip)[i] = default_val; |
| 21089 | if (is_comptime_val.toBool()) | 21095 | if (is_comptime_val.toBool()) |
| 21090 | struct_type.setFieldComptime(ip, i); | 21096 | struct_type.setFieldComptime(ip, i); |
| ... | @@ -23772,7 +23778,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr | ... | @@ -23772,7 +23778,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr |
| 23772 | } else { | 23778 | } else { |
| 23773 | ptr_ty_data.flags.alignment = blk: { | 23779 | ptr_ty_data.flags.alignment = blk: { |
| 23774 | if (mod.typeToStruct(parent_ty)) |struct_type| { | 23780 | if (mod.typeToStruct(parent_ty)) |struct_type| { |
| 23775 | break :blk struct_type.field_aligns.get(ip)[field_index]; | 23781 | break :blk struct_type.fieldAlign(ip, field_index); |
| 23776 | } else if (mod.typeToUnion(parent_ty)) |union_obj| { | 23782 | } else if (mod.typeToUnion(parent_ty)) |union_obj| { |
| 23777 | break :blk union_obj.fieldAlign(ip, field_index); | 23783 | break :blk union_obj.fieldAlign(ip, field_index); |
| 23778 | } else { | 23784 | } else { |
| ... | @@ -26670,7 +26676,7 @@ fn structFieldPtrByIndex( | ... | @@ -26670,7 +26676,7 @@ fn structFieldPtrByIndex( |
| 26670 | if (parent_align != .none and ptr_ty_data.packed_offset.bit_offset % 8 == 0 and | 26676 | if (parent_align != .none and ptr_ty_data.packed_offset.bit_offset % 8 == 0 and |
| 26671 | target.cpu.arch.endian() == .Little) | 26677 | target.cpu.arch.endian() == .Little) |
| 26672 | { | 26678 | { |
| 26673 | const elem_size_bytes = ptr_ty_data.child.toType().abiSize(mod); | 26679 | const elem_size_bytes = try sema.typeAbiSize(ptr_ty_data.child.toType()); |
| 26674 | const elem_size_bits = ptr_ty_data.child.toType().bitSize(mod); | 26680 | const elem_size_bits = ptr_ty_data.child.toType().bitSize(mod); |
| 26675 | if (elem_size_bytes * 8 == elem_size_bits) { | 26681 | if (elem_size_bytes * 8 == elem_size_bits) { |
| 26676 | const byte_offset = ptr_ty_data.packed_offset.bit_offset / 8; | 26682 | const byte_offset = ptr_ty_data.packed_offset.bit_offset / 8; |
| ... | @@ -26691,7 +26697,7 @@ fn structFieldPtrByIndex( | ... | @@ -26691,7 +26697,7 @@ fn structFieldPtrByIndex( |
| 26691 | } else { | 26697 | } else { |
| 26692 | // Our alignment is capped at the field alignment | 26698 | // Our alignment is capped at the field alignment |
| 26693 | const field_align = try sema.structFieldAlignment( | 26699 | const field_align = try sema.structFieldAlignment( |
| 26694 | struct_type.field_aligns.get(ip)[field_index], | 26700 | struct_type.fieldAlign(ip, field_index), |
| 26695 | field_ty.toType(), | 26701 | field_ty.toType(), |
| 26696 | struct_type.layout, | 26702 | struct_type.layout, |
| 26697 | ); | 26703 | ); |
| ... | @@ -26700,7 +26706,7 @@ fn structFieldPtrByIndex( | ... | @@ -26700,7 +26706,7 @@ fn structFieldPtrByIndex( |
| 26700 | | 26706 | |
| 26701 | const ptr_field_ty = try mod.ptrType(ptr_ty_data); | 26707 | const ptr_field_ty = try mod.ptrType(ptr_ty_data); |
| 26702 | | 26708 | |
| 26703 | if (struct_type.comptime_bits.getBit(ip, field_index)) { | 26709 | if (struct_type.fieldIsComptime(ip, field_index)) { |
| 26704 | const val = try mod.intern(.{ .ptr = .{ | 26710 | const val = try mod.intern(.{ .ptr = .{ |
| 26705 | .ty = ptr_field_ty.toIntern(), | 26711 | .ty = ptr_field_ty.toIntern(), |
| 26706 | .addr = .{ .comptime_field = struct_type.field_inits.get(ip)[field_index] }, | 26712 | .addr = .{ .comptime_field = struct_type.field_inits.get(ip)[field_index] }, |
| ... | @@ -26744,7 +26750,7 @@ fn structFieldVal( | ... | @@ -26744,7 +26750,7 @@ fn structFieldVal( |
| 26744 | | 26750 | |
| 26745 | const field_index = struct_type.nameIndex(ip, field_name) orelse | 26751 | const field_index = struct_type.nameIndex(ip, field_name) orelse |
| 26746 | return sema.failWithBadStructFieldAccess(block, struct_type, field_name_src, field_name); | 26752 | return sema.failWithBadStructFieldAccess(block, struct_type, field_name_src, field_name); |
| 26747 | if (struct_type.comptime_bits.getBit(ip, field_index)) { | 26753 | if (struct_type.fieldIsComptime(ip, field_index)) { |
| 26748 | return Air.internedToRef(struct_type.field_inits.get(ip)[field_index]); | 26754 | return Air.internedToRef(struct_type.field_inits.get(ip)[field_index]); |
| 26749 | } | 26755 | } |
| 26750 | | 26756 | |
| ... | @@ -29199,12 +29205,12 @@ fn coerceInMemoryAllowedPtrs( | ... | @@ -29199,12 +29205,12 @@ fn coerceInMemoryAllowedPtrs( |
| 29199 | const src_align = if (src_info.flags.alignment != .none) | 29205 | const src_align = if (src_info.flags.alignment != .none) |
| 29200 | src_info.flags.alignment | 29206 | src_info.flags.alignment |
| 29201 | else | 29207 | else |
| 29202 | src_info.child.toType().abiAlignment(mod); | 29208 | try sema.typeAbiAlignment(src_info.child.toType()); |
| 29203 | | 29209 | |
| 29204 | const dest_align = if (dest_info.flags.alignment != .none) | 29210 | const dest_align = if (dest_info.flags.alignment != .none) |
| 29205 | dest_info.flags.alignment | 29211 | dest_info.flags.alignment |
| 29206 | else | 29212 | else |
| 29207 | dest_info.child.toType().abiAlignment(mod); | 29213 | try sema.typeAbiAlignment(dest_info.child.toType()); |
| 29208 | | 29214 | |
| 29209 | if (dest_align.compare(.gt, src_align)) { | 29215 | if (dest_align.compare(.gt, src_align)) { |
| 29210 | return InMemoryCoercionResult{ .ptr_alignment = .{ | 29216 | return InMemoryCoercionResult{ .ptr_alignment = .{ |
| ... | @@ -30969,7 +30975,7 @@ fn coerceTupleToStruct( | ... | @@ -30969,7 +30975,7 @@ fn coerceTupleToStruct( |
| 30969 | const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i); | 30975 | const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i); |
| 30970 | const coerced = try sema.coerce(block, field_ty, elem_ref, field_src); | 30976 | const coerced = try sema.coerce(block, field_ty, elem_ref, field_src); |
| 30971 | field_refs[field_index] = coerced; | 30977 | field_refs[field_index] = coerced; |
| 30972 | if (struct_type.comptime_bits.getBit(ip, field_index)) { | 30978 | if (struct_type.fieldIsComptime(ip, field_index)) { |
| 30973 | const init_val = (try sema.resolveMaybeUndefVal(coerced)) orelse { | 30979 | const init_val = (try sema.resolveMaybeUndefVal(coerced)) orelse { |
| 30974 | return sema.failWithNeededComptime(block, field_src, .{ | 30980 | return sema.failWithNeededComptime(block, field_src, .{ |
| 30975 | .needed_comptime_reason = "value stored in comptime field must be comptime-known", | 30981 | .needed_comptime_reason = "value stored in comptime field must be comptime-known", |
| ... | @@ -30998,7 +31004,7 @@ fn coerceTupleToStruct( | ... | @@ -30998,7 +31004,7 @@ fn coerceTupleToStruct( |
| 30998 | if (field_ref.* != .none) continue; | 31004 | if (field_ref.* != .none) continue; |
| 30999 | | 31005 | |
| 31000 | const field_name = struct_type.field_names.get(ip)[i]; | 31006 | const field_name = struct_type.field_names.get(ip)[i]; |
| 31001 | const field_default_val = struct_type.field_inits.get(ip)[i]; | 31007 | const field_default_val = struct_type.fieldInit(ip, i); |
| 31002 | const field_src = inst_src; // TODO better source location | 31008 | const field_src = inst_src; // TODO better source location |
| 31003 | if (field_default_val == .none) { | 31009 | if (field_default_val == .none) { |
| 31004 | const template = "missing struct field: {}"; | 31010 | const template = "missing struct field: {}"; |
| ... | @@ -31088,7 +31094,7 @@ fn coerceTupleToTuple( | ... | @@ -31088,7 +31094,7 @@ fn coerceTupleToTuple( |
| 31088 | }; | 31094 | }; |
| 31089 | const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) { | 31095 | const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) { |
| 31090 | .anon_struct_type => |anon_struct_type| anon_struct_type.values.get(ip)[field_index_usize], | 31096 | .anon_struct_type => |anon_struct_type| anon_struct_type.values.get(ip)[field_index_usize], |
| 31091 | .struct_type => |struct_type| struct_type.field_inits.get(ip)[field_index_usize], | 31097 | .struct_type => |struct_type| struct_type.fieldInit(ip, field_index_usize), |
| 31092 | else => unreachable, | 31098 | else => unreachable, |
| 31093 | }; | 31099 | }; |
| 31094 | | 31100 | |
| ... | @@ -31126,7 +31132,7 @@ fn coerceTupleToTuple( | ... | @@ -31126,7 +31132,7 @@ fn coerceTupleToTuple( |
| 31126 | | 31132 | |
| 31127 | const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) { | 31133 | const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) { |
| 31128 | .anon_struct_type => |anon_struct_type| anon_struct_type.values.get(ip)[i], | 31134 | .anon_struct_type => |anon_struct_type| anon_struct_type.values.get(ip)[i], |
| 31129 | .struct_type => |struct_type| struct_type.field_inits.get(ip)[i], | 31135 | .struct_type => |struct_type| struct_type.fieldInit(ip, i), |
| 31130 | else => unreachable, | 31136 | else => unreachable, |
| 31131 | }; | 31137 | }; |
| 31132 | | 31138 | |
| ... | @@ -33332,12 +33338,12 @@ fn resolvePeerTypesInner( | ... | @@ -33332,12 +33338,12 @@ fn resolvePeerTypesInner( |
| 33332 | if (ptr_info.flags.alignment != .none) | 33338 | if (ptr_info.flags.alignment != .none) |
| 33333 | ptr_info.flags.alignment | 33339 | ptr_info.flags.alignment |
| 33334 | else | 33340 | else |
| 33335 | ptr_info.child.toType().abiAlignment(mod), | 33341 | try sema.typeAbiAlignment(ptr_info.child.toType()), |
| 33336 | | 33342 | |
| 33337 | if (peer_info.flags.alignment != .none) | 33343 | if (peer_info.flags.alignment != .none) |
| 33338 | peer_info.flags.alignment | 33344 | peer_info.flags.alignment |
| 33339 | else | 33345 | else |
| 33340 | peer_info.child.toType().abiAlignment(mod), | 33346 | try sema.typeAbiAlignment(peer_info.child.toType()), |
| 33341 | ); | 33347 | ); |
| 33342 | | 33348 | |
| 33343 | if (ptr_info.flags.address_space != peer_info.flags.address_space) { | 33349 | if (ptr_info.flags.address_space != peer_info.flags.address_space) { |
| ... | @@ -34288,14 +34294,16 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -34288,14 +34294,16 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 34288 | return sema.failWithOwnedErrorMsg(null, msg); | 34294 | return sema.failWithOwnedErrorMsg(null, msg); |
| 34289 | } | 34295 | } |
| 34290 | | 34296 | |
| 34291 | if (try sema.typeRequiresComptime(ty)) | | |
| 34292 | return; | | |
| 34293 | | | |
| 34294 | const aligns = try sema.arena.alloc(Alignment, struct_type.field_types.len); | 34297 | const aligns = try sema.arena.alloc(Alignment, struct_type.field_types.len); |
| 34295 | const sizes = try sema.arena.alloc(u64, struct_type.field_types.len); | 34298 | const sizes = try sema.arena.alloc(u64, struct_type.field_types.len); |
| 34296 | | 34299 | |
| 34297 | for (aligns, sizes, 0..) |*field_align, *field_size, i| { | 34300 | for (aligns, sizes, 0..) |*field_align, *field_size, i| { |
| 34298 | const field_ty = struct_type.field_types.get(ip)[i].toType(); | 34301 | const field_ty = struct_type.field_types.get(ip)[i].toType(); |
| | 34302 | if (struct_type.fieldIsComptime(ip, i) or !(try sema.typeHasRuntimeBits(field_ty))) { |
| | 34303 | field_size.* = 0; |
| | 34304 | field_align.* = .none; |
| | 34305 | continue; |
| | 34306 | } |
| 34299 | field_size.* = sema.typeAbiSize(field_ty) catch |err| switch (err) { | 34307 | field_size.* = sema.typeAbiSize(field_ty) catch |err| switch (err) { |
| 34300 | error.AnalysisFail => { | 34308 | error.AnalysisFail => { |
| 34301 | const msg = sema.err orelse return err; | 34309 | const msg = sema.err orelse return err; |
| ... | @@ -34322,7 +34330,9 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -34322,7 +34330,9 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 34322 | } | 34330 | } |
| 34323 | | 34331 | |
| 34324 | if (struct_type.hasReorderedFields()) { | 34332 | if (struct_type.hasReorderedFields()) { |
| 34325 | for (sizes, struct_type.runtime_order.get(ip), 0..) |size, *ro, i| { | 34333 | const runtime_order = struct_type.runtime_order.get(ip); |
| | 34334 | |
| | 34335 | for (sizes, runtime_order, 0..) |size, *ro, i| { |
| 34326 | ro.* = if (size != 0) @enumFromInt(i) else .omitted; | 34336 | ro.* = if (size != 0) @enumFromInt(i) else .omitted; |
| 34327 | } | 34337 | } |
| 34328 | | 34338 | |
| ... | @@ -34339,7 +34349,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -34339,7 +34349,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 34339 | return a_align.compare(.gt, b_align); | 34349 | return a_align.compare(.gt, b_align); |
| 34340 | } | 34350 | } |
| 34341 | }; | 34351 | }; |
| 34342 | mem.sortUnstable(RuntimeOrder, struct_type.runtime_order.get(ip), AlignSortContext{ | 34352 | mem.sortUnstable(RuntimeOrder, runtime_order, AlignSortContext{ |
| 34343 | .aligns = aligns, | 34353 | .aligns = aligns, |
| 34344 | }, AlignSortContext.lessThan); | 34354 | }, AlignSortContext.lessThan); |
| 34345 | } | 34355 | } |
| ... | @@ -34348,7 +34358,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -34348,7 +34358,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 34348 | const offsets = struct_type.offsets.get(ip); | 34358 | const offsets = struct_type.offsets.get(ip); |
| 34349 | var it = struct_type.iterateRuntimeOrder(ip); | 34359 | var it = struct_type.iterateRuntimeOrder(ip); |
| 34350 | var offset: u64 = 0; | 34360 | var offset: u64 = 0; |
| 34351 | var big_align: Alignment = .none; | 34361 | var big_align: Alignment = .@"1"; |
| 34352 | while (it.next()) |i| { | 34362 | while (it.next()) |i| { |
| 34353 | big_align = big_align.max(aligns[i]); | 34363 | big_align = big_align.max(aligns[i]); |
| 34354 | offsets[i] = @intCast(aligns[i].forward(offset)); | 34364 | offsets[i] = @intCast(aligns[i].forward(offset)); |
| ... | @@ -34358,22 +34368,61 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -34358,22 +34368,61 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { |
| 34358 | const flags = struct_type.flagsPtr(ip); | 34368 | const flags = struct_type.flagsPtr(ip); |
| 34359 | flags.alignment = big_align; | 34369 | flags.alignment = big_align; |
| 34360 | flags.layout_resolved = true; | 34370 | flags.layout_resolved = true; |
| | 34371 | _ = try sema.typeRequiresComptime(ty); |
| 34361 | } | 34372 | } |
| 34362 | | 34373 | |
| 34363 | fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) CompileError!void { | 34374 | fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) CompileError!void { |
| 34364 | const gpa = mod.gpa; | 34375 | const gpa = mod.gpa; |
| 34365 | const ip = &mod.intern_pool; | 34376 | const ip = &mod.intern_pool; |
| 34366 | | 34377 | |
| 34367 | var fields_bit_sum: u64 = 0; | | |
| 34368 | for (0..struct_type.field_types.len) |i| { | | |
| 34369 | const field_ty = struct_type.field_types.get(ip)[i].toType(); | | |
| 34370 | fields_bit_sum += field_ty.bitSize(mod); | | |
| 34371 | } | | |
| 34372 | | | |
| 34373 | const decl_index = struct_type.decl.unwrap().?; | 34378 | const decl_index = struct_type.decl.unwrap().?; |
| 34374 | const decl = mod.declPtr(decl_index); | 34379 | const decl = mod.declPtr(decl_index); |
| 34375 | | 34380 | |
| 34376 | const zir = mod.namespacePtr(struct_type.namespace.unwrap().?).file_scope.zir; | 34381 | const zir = mod.namespacePtr(struct_type.namespace.unwrap().?).file_scope.zir; |
| | 34382 | |
| | 34383 | var analysis_arena = std.heap.ArenaAllocator.init(gpa); |
| | 34384 | defer analysis_arena.deinit(); |
| | 34385 | |
| | 34386 | var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa); |
| | 34387 | defer comptime_mutable_decls.deinit(); |
| | 34388 | |
| | 34389 | var sema: Sema = .{ |
| | 34390 | .mod = mod, |
| | 34391 | .gpa = gpa, |
| | 34392 | .arena = analysis_arena.allocator(), |
| | 34393 | .code = zir, |
| | 34394 | .owner_decl = decl, |
| | 34395 | .owner_decl_index = decl_index, |
| | 34396 | .func_index = .none, |
| | 34397 | .func_is_naked = false, |
| | 34398 | .fn_ret_ty = Type.void, |
| | 34399 | .fn_ret_ty_ies = null, |
| | 34400 | .owner_func_index = .none, |
| | 34401 | .comptime_mutable_decls = &comptime_mutable_decls, |
| | 34402 | }; |
| | 34403 | defer sema.deinit(); |
| | 34404 | |
| | 34405 | var block: Block = .{ |
| | 34406 | .parent = null, |
| | 34407 | .sema = &sema, |
| | 34408 | .src_decl = decl_index, |
| | 34409 | .namespace = struct_type.namespace.unwrap() orelse decl.src_namespace, |
| | 34410 | .wip_capture_scope = try mod.createCaptureScope(decl.src_scope), |
| | 34411 | .instructions = .{}, |
| | 34412 | .inlining = null, |
| | 34413 | .is_comptime = true, |
| | 34414 | }; |
| | 34415 | defer assert(block.instructions.items.len == 0); |
| | 34416 | |
| | 34417 | const fields_bit_sum = blk: { |
| | 34418 | var accumulator: u64 = 0; |
| | 34419 | for (0..struct_type.field_types.len) |i| { |
| | 34420 | const field_ty = struct_type.field_types.get(ip)[i].toType(); |
| | 34421 | accumulator += try field_ty.bitSizeAdvanced(mod, &sema); |
| | 34422 | } |
| | 34423 | break :blk accumulator; |
| | 34424 | }; |
| | 34425 | |
| 34377 | const extended = zir.instructions.items(.data)[struct_type.zir_index].extended; | 34426 | const extended = zir.instructions.items(.data)[struct_type.zir_index].extended; |
| 34378 | assert(extended.opcode == .struct_decl); | 34427 | assert(extended.opcode == .struct_decl); |
| 34379 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); | 34428 | const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small); |
| ... | @@ -34387,40 +34436,6 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp | ... | @@ -34387,40 +34436,6 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp |
| 34387 | const backing_int_body_len = zir.extra[extra_index]; | 34436 | const backing_int_body_len = zir.extra[extra_index]; |
| 34388 | extra_index += 1; | 34437 | extra_index += 1; |
| 34389 | | 34438 | |
| 34390 | var analysis_arena = std.heap.ArenaAllocator.init(gpa); | | |
| 34391 | defer analysis_arena.deinit(); | | |
| 34392 | | | |
| 34393 | var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa); | | |
| 34394 | defer comptime_mutable_decls.deinit(); | | |
| 34395 | | | |
| 34396 | var sema: Sema = .{ | | |
| 34397 | .mod = mod, | | |
| 34398 | .gpa = gpa, | | |
| 34399 | .arena = analysis_arena.allocator(), | | |
| 34400 | .code = zir, | | |
| 34401 | .owner_decl = decl, | | |
| 34402 | .owner_decl_index = decl_index, | | |
| 34403 | .func_index = .none, | | |
| 34404 | .func_is_naked = false, | | |
| 34405 | .fn_ret_ty = Type.void, | | |
| 34406 | .fn_ret_ty_ies = null, | | |
| 34407 | .owner_func_index = .none, | | |
| 34408 | .comptime_mutable_decls = &comptime_mutable_decls, | | |
| 34409 | }; | | |
| 34410 | defer sema.deinit(); | | |
| 34411 | | | |
| 34412 | var block: Block = .{ | | |
| 34413 | .parent = null, | | |
| 34414 | .sema = &sema, | | |
| 34415 | .src_decl = decl_index, | | |
| 34416 | .namespace = struct_type.namespace.unwrap() orelse decl.src_namespace, | | |
| 34417 | .wip_capture_scope = try mod.createCaptureScope(decl.src_scope), | | |
| 34418 | .instructions = .{}, | | |
| 34419 | .inlining = null, | | |
| 34420 | .is_comptime = true, | | |
| 34421 | }; | | |
| 34422 | defer assert(block.instructions.items.len == 0); | | |
| 34423 | | | |
| 34424 | const backing_int_src: LazySrcLoc = .{ .node_offset_container_tag = 0 }; | 34439 | const backing_int_src: LazySrcLoc = .{ .node_offset_container_tag = 0 }; |
| 34425 | const backing_int_ty = blk: { | 34440 | const backing_int_ty = blk: { |
| 34426 | if (backing_int_body_len == 0) { | 34441 | if (backing_int_body_len == 0) { |
| ... | @@ -34435,44 +34450,18 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp | ... | @@ -34435,44 +34450,18 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.Key.StructType) Comp |
| 34435 | | 34450 | |
| 34436 | try sema.checkBackingIntType(&block, backing_int_src, backing_int_ty, fields_bit_sum); | 34451 | try sema.checkBackingIntType(&block, backing_int_src, backing_int_ty, fields_bit_sum); |
| 34437 | struct_type.backingIntType(ip).* = backing_int_ty.toIntern(); | 34452 | struct_type.backingIntType(ip).* = backing_int_ty.toIntern(); |
| 34438 | for (comptime_mutable_decls.items) |ct_decl_index| { | | |
| 34439 | const ct_decl = mod.declPtr(ct_decl_index); | | |
| 34440 | _ = try ct_decl.internValue(mod); | | |
| 34441 | } | | |
| 34442 | } else { | 34453 | } else { |
| 34443 | if (fields_bit_sum > std.math.maxInt(u16)) { | 34454 | if (fields_bit_sum > std.math.maxInt(u16)) { |
| 34444 | var sema: Sema = .{ | | |
| 34445 | .mod = mod, | | |
| 34446 | .gpa = gpa, | | |
| 34447 | .arena = undefined, | | |
| 34448 | .code = zir, | | |
| 34449 | .owner_decl = decl, | | |
| 34450 | .owner_decl_index = decl_index, | | |
| 34451 | .func_index = .none, | | |
| 34452 | .func_is_naked = false, | | |
| 34453 | .fn_ret_ty = Type.void, | | |
| 34454 | .fn_ret_ty_ies = null, | | |
| 34455 | .owner_func_index = .none, | | |
| 34456 | .comptime_mutable_decls = undefined, | | |
| 34457 | }; | | |
| 34458 | defer sema.deinit(); | | |
| 34459 | | | |
| 34460 | var block: Block = .{ | | |
| 34461 | .parent = null, | | |
| 34462 | .sema = &sema, | | |
| 34463 | .src_decl = decl_index, | | |
| 34464 | .namespace = struct_type.namespace.unwrap() orelse | | |
| 34465 | mod.declPtr(struct_type.decl.unwrap().?).src_namespace, | | |
| 34466 | .wip_capture_scope = undefined, | | |
| 34467 | .instructions = .{}, | | |
| 34468 | .inlining = null, | | |
| 34469 | .is_comptime = true, | | |
| 34470 | }; | | |
| 34471 | return sema.fail(&block, LazySrcLoc.nodeOffset(0), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum}); | 34455 | return sema.fail(&block, LazySrcLoc.nodeOffset(0), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum}); |
| 34472 | } | 34456 | } |
| 34473 | const backing_int_ty = try mod.intType(.unsigned, @intCast(fields_bit_sum)); | 34457 | const backing_int_ty = try mod.intType(.unsigned, @intCast(fields_bit_sum)); |
| 34474 | struct_type.backingIntType(ip).* = backing_int_ty.toIntern(); | 34458 | struct_type.backingIntType(ip).* = backing_int_ty.toIntern(); |
| 34475 | } | 34459 | } |
| | 34460 | |
| | 34461 | for (comptime_mutable_decls.items) |ct_decl_index| { |
| | 34462 | const ct_decl = mod.declPtr(ct_decl_index); |
| | 34463 | _ = try ct_decl.internValue(mod); |
| | 34464 | } |
| 34476 | } | 34465 | } |
| 34477 | | 34466 | |
| 34478 | fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_ty: Type, fields_bit_sum: u64) CompileError!void { | 34467 | fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_ty: Type, fields_bit_sum: u64) CompileError!void { |
| ... | @@ -34813,10 +34802,9 @@ fn resolveTypeFieldsStruct( | ... | @@ -34813,10 +34802,9 @@ fn resolveTypeFieldsStruct( |
| 34813 | else => {}, | 34802 | else => {}, |
| 34814 | } | 34803 | } |
| 34815 | | 34804 | |
| 34816 | if (struct_type.haveFieldTypes(ip)) | 34805 | if (struct_type.haveFieldTypes(ip)) return; |
| 34817 | return; | | |
| 34818 | | 34806 | |
| 34819 | if (struct_type.flagsPtr(ip).field_types_wip) { | 34807 | if (struct_type.setTypesWip(ip)) { |
| 34820 | const msg = try Module.ErrorMsg.create( | 34808 | const msg = try Module.ErrorMsg.create( |
| 34821 | sema.gpa, | 34809 | sema.gpa, |
| 34822 | mod.declPtr(owner_decl).srcLoc(mod), | 34810 | mod.declPtr(owner_decl).srcLoc(mod), |
| ... | @@ -34825,9 +34813,7 @@ fn resolveTypeFieldsStruct( | ... | @@ -34825,9 +34813,7 @@ fn resolveTypeFieldsStruct( |
| 34825 | ); | 34813 | ); |
| 34826 | return sema.failWithOwnedErrorMsg(null, msg); | 34814 | return sema.failWithOwnedErrorMsg(null, msg); |
| 34827 | } | 34815 | } |
| 34828 | | 34816 | errdefer struct_type.clearTypesWip(ip); |
| 34829 | struct_type.flagsPtr(ip).field_types_wip = true; | | |
| 34830 | errdefer struct_type.flagsPtr(ip).field_types_wip = false; | | |
| 34831 | | 34817 | |
| 34832 | try semaStructFields(mod, sema.arena, struct_type); | 34818 | try semaStructFields(mod, sema.arena, struct_type); |
| 34833 | } | 34819 | } |
| ... | @@ -36175,7 +36161,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -36175,7 +36161,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 36175 | struct_type.field_types.len, | 36161 | struct_type.field_types.len, |
| 36176 | ); | 36162 | ); |
| 36177 | for (field_vals, 0..) |*field_val, i| { | 36163 | for (field_vals, 0..) |*field_val, i| { |
| 36178 | if (struct_type.comptime_bits.getBit(ip, i)) { | 36164 | if (struct_type.fieldIsComptime(ip, i)) { |
| 36179 | field_val.* = struct_type.field_inits.get(ip)[i]; | 36165 | field_val.* = struct_type.field_inits.get(ip)[i]; |
| 36180 | continue; | 36166 | continue; |
| 36181 | } | 36167 | } |
| ... | @@ -36679,7 +36665,11 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | ... | @@ -36679,7 +36665,11 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { |
| 36679 | if (struct_type.fieldIsComptime(ip, i)) continue; | 36665 | if (struct_type.fieldIsComptime(ip, i)) continue; |
| 36680 | const field_ty = struct_type.field_types.get(ip)[i]; | 36666 | const field_ty = struct_type.field_types.get(ip)[i]; |
| 36681 | if (try sema.typeRequiresComptime(field_ty.toType())) { | 36667 | if (try sema.typeRequiresComptime(field_ty.toType())) { |
| 36682 | struct_type.setRequiresComptime(ip); | 36668 | // Note that this does not cause the layout to |
| | 36669 | // be considered resolved. Comptime-only types |
| | 36670 | // still maintain a layout of their |
| | 36671 | // runtime-known fields. |
| | 36672 | struct_type.flagsPtr(ip).requires_comptime = .yes; |
| 36683 | return true; | 36673 | return true; |
| 36684 | } | 36674 | } |
| 36685 | } | 36675 | } |